// $Source: /usr/local/SimSoft/Sfx3D/src/gsl/Sfxhla.cpp,v $
// $Revision: 1.2 $
// $Author: baum $
// $Date: 2001/11/29 15:18:09 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name: Release-14 $
// State assigned to revision
// $State: Exp $
//
//
// $Log: Sfxhla.cpp,v $
// Revision 1.2  2001/11/29 15:18:09  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//


//#include <hla.h>        //---rudi---16.08.01
#include "programm.h"
#include "sfxhla.h"
#define _SFXHLA_CPP
#include "modell.h"
#include "realzeit.h"

//HINSTANCE MyHlaDLL;

typedef void* (*newObject)(const char*, const char*, double, double, double, const char*);
typedef int ( * startCall)(void*, Map<ObjectStructure, DynArray<HlaAttribute> > &pubObjects,
											  Map<ObjectStructure, DynArray<HlaAttribute> > &subObjects,
											  Map<InteractionStructure, DynArray<HlaParameter> > &pubInteractions,
											  Map<InteractionStructure, DynArray<HlaParameter> > &subInteractions);

typedef const char* ( * constCharFunc)(void*);
typedef const char* ( * constCharFunc1)(void*, int);
typedef void ( * voidCall)(void*);
typedef void ( * voidFunc3)(void*,const char*, DynArray<HlaParameter>&);

typedef int ( * intCall)(void*);
typedef int ( * intFunc1)(void*, int);
typedef void ( * neRequest)(void*, double);
typedef void ( * tickFunc)(void*, double, double);

typedef double ( * doubleFunc) (void*);
typedef void ( * objIntAFunc) (void*, const char*, DynArray<char>&);
typedef void ( * objPubFunc) (void*, const char*, int bstNr, DynArray<char>&);
typedef void ( * sendIAWithClassAndPar) (void*, double, const char*, const char*);
typedef void ( * sendIAText) (void*, double, const char*);

char buf[255];

HINSTANCE hlaLibrary;


#ifdef WIN32
#include <windows.h>
#endif

static char Befehl[3];
static char AnBaustein [3];
static char BefehlParameter [4];

SFXHla *MySFXHla;



//---------------------------------------------------------
// class InteractionStructure
//---------------------------------------------------------
InteractionStructure::InteractionStructure (const char* className) {
	interactionClassName = className;
	interactionClassHandle = NULL;
}

InteractionStructure::~InteractionStructure () {}


void InteractionStructure::SetName (const char* className) {
	interactionClassName = className;
}

const char* InteractionStructure::GetName () {
	return interactionClassName;
}

void InteractionStructure::SetOwner (const char* owner) {
	interactionClassOwner = owner;
}

const char* InteractionStructure::GetOwner () {
	return interactionClassOwner;
}

void InteractionStructure::SetClassHandle (unsigned long classHandle) {
	interactionClassHandle = classHandle;
}

unsigned long InteractionStructure::GetClassHandle () {
	return interactionClassHandle;
}

void InteractionStructure::SetTime (double const & time) {
	interactionTime = time;
}

double const & InteractionStructure::GetTime() {
	return interactionTime;
}



//---------------------------------------------------------
// class HlaParameter
//---------------------------------------------------------
HlaParameter::HlaParameter (const char* parName) {
	parameterName = parName;
}


HlaParameter::HlaParameter (const char* parName, const char* textVal) {
	parameterName = parName;	
	AddTextValue(textVal);
}

/**
 * Zunaechst nur fuer den Compiler.
 *
 */
HlaParameter::~HlaParameter () {
	char buf[255];
	sprintf (buf,"Parameter: %s wird geloescht!", parameterName);
	MessageBox(NULL, buf, "HlaParameter::~HlaParameter", MB_OK);
}


const char* HlaParameter::GetName () {
	return parameterName;
}


void HlaParameter::AddTextValue (const char* str) {
	parameterTextList.append(*(strcpy (new char [strlen (str) + 1], str)));;
} 

const char* HlaParameter::GetFirstTextValue () {
	return parameterTextList.removeFirst();
}

int HlaParameter::CountTextValues () {
	return parameterTextList.Count();
}

void HlaParameter::SetParameterRtiId (unsigned long handle) {
	myRTI_ID = handle;
}

unsigned long HlaParameter::GetParameterRtiId() {
	return myRTI_ID; 
}

void HlaParameter::SetOwner (const char* owner) {
	ownerOfParameter = owner;
}

const char* HlaParameter::GetOwner () {
	return ownerOfParameter;
}





// - - - - - - - - - - - - - - - - - - - - - - - - - - -
int HlaZuETyp (int HlaBefehl) {
  switch (HlaBefehl) {
  case  1  : return ETaaufnehmen;
  case  2  :  return ETaktivieren;
  case  3  :  return ETprotokoll;
  case  9  :  return ETaaufnehmen;
  case 10  :  return ETeaufnehmen;
  case 11  :  return ETaabgeben;
  case 12  :  return ETeabgeben;
  case 13  :  return ETadrehen;
  case 14  :  return ETedrehen;
  case 17  :  return ETalagern;
  case 18  :  return ETelagern;
  case 20  :  return ETafahren;
  case 21  :  return ETefahren;
  case 24  :  return ETasperrung;
  case 25  :  return ETesperrung;
  case 27  :  return ETastoerung;
  case 28  :  return ETestoerung;
  case 30  :  return ETaarbeiten;
  case 31  :  return ETearbeiten;
  case 35  :  return ETaladen;
  case 36  :  return ETeladen;
  case 41  :  return ETaftsfahren;
  case 42  :  return ETeftsfahren;
  case 44  :  return ETatrace;
  case 45  :  return ETetrace;
  case 46  :  return ETprogramm;
  case 53  :  return ETazeitreihe;
  case 54  :  return ETezeitreihe;
  case 64  :  return ETstartextprozess;
  case 65  :  return ETstopextprozess;
  case 66  :  return ETexplerzeugen;
  case 67  :  return ETerzBestellung;
  case 68  :  return ETloeBestellung;
  case 72  :  return ETakommissionieren;
  case 73  :  return ETekommissionieren;
  case 75  :  return ETafoerdern;
  case 76  :  return ETefoerdern;
  case 81  :  return ETinitGrafik;
  case 82  :  return ETloescheGrafik;
  case 83  :  return ETaheben;
  case 84  :  return ETeheben;
  case 85  :  return ETasenken;
  case 86  :  return ETesenken;     
  case 91  :  return ETfahrTakt;
  case 92  :  return ETdrehTakt;
  case 93  :  return ETaufnTakt;
  case 95  :  return ETameldewarten;
  case 100 :  return ETwecken;
    
    // Folgende Ereignistypen sind fuer die Realzeitsteuerung benutzbar
    
  case 992 :  return ETdpabgplatz;   // Dem Drehpuffer muss vor dem Abgeben mitge-
    // teilt werden, welcher Platz abgeben soll.
  case 993 :  return ETeausschl;
  case 994 :  return ETausschl;
  case 995 :  return ETaeinschl;
  case 996 :  return ETbereit;
  case 997 :  return ETainit;
  case 998 :  return ETeinit;
  case 999 :  return ETchtyp;
  default           : return 0;
  }
}


// ----------------------------------------------------------
// --- Lokal benutzte Funktion:                           ---
// --- Uebersetzt die Simulatorereignisse in MSPS-Befehle ---
// ----------------------------------------------------------

int ETypZuHla (int EreignisTyp) {
  switch (EreignisTyp) {
     case ETaktivieren      : return  2;
     case ETprotokoll       : return  3;
     case ETaaufnehmen      : return  9;
     case ETeaufnehmen      : return 10;
     case ETaabgeben        : return 11;
     case ETeabgeben        : return 12;
     case ETadrehen         : return 13;
     case ETedrehen         : return 14;
     case ETalagern         : return 17;
     case ETelagern         : return 18;
     case ETafahren         : return 20;
     case ETefahren         : return 21;
     case ETasperrung       : return 24;
     case ETesperrung       : return 25;
     case ETastoerung       : return 27;
     case ETestoerung       : return 28;
     case ETaarbeiten       : return 30;
     case ETearbeiten       : return 31;
     case ETaladen	       : return 35;
     case ETeladen	       : return 36;
     case ETaftsfahren      : return 41;
     case ETeftsfahren      : return 42;
     case ETatrace          : return 44;
     case ETetrace          : return 45;
     case ETprogramm        : return 46;
     case ETazeitreihe      : return 53;
     case ETezeitreihe      : return 54;
     case ETstartextprozess : return 64;
     case ETstopextprozess  : return 65;
     case ETexplerzeugen    : return 66;
     case ETerzBestellung   : return 67;
     case ETloeBestellung   : return 68;
     case ETakommissionieren: return 72;
     case ETekommissionieren: return 73;
     case ETafoerdern       : return 75;
     case ETefoerdern       : return 76;
     case ETinitGrafik      : return 81;
     case ETloescheGrafik   : return 82;
     case ETaheben          : return 83;
     case ETeheben          : return 84;
     case ETasenken         : return 85;
     case ETesenken         : return 86;     
     case ETfahrTakt        : return 91;
     case ETdrehTakt        : return 92;
     case ETaufnTakt        : return 93;
     case ETameldewarten    : return 95;
     case ETwecken          : return 100;
     
     // Folgende Ereignistypen sind fuer die Realzeitsteuerung benutzbar

     case ETdpabgplatz     : return 992;   // Dem Drehpuffer muss vor dem Abgeben mitge-
                               // teilt werden, welcher Platz abgeben soll.
     case ETeausschl       : return 993;
     case ETausschl        : return 994;
     case ETaeinschl       : return 995;
     case ETbereit         : return 996;
     case ETainit          : return 997;
     case ETeinit          : return 998;
     case ETchtyp          : return 999;
     default           : return 0;
  }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - -
int HlaRzsEchoZuETyp (int RzsEchoBefehl) {
  switch (RzsEchoBefehl) {
    case  1 : return ETaaufnehmen;
    case  2 : return ETeaufnehmen;
    case 30 : return ETaarbeiten;
    case 31 : return ETearbeiten;
    case 52 : return ETaabgeben;
    case 53 : return ETeabgeben;
    case 54 : return ETdpabgplatz;
    case  3 : return ETafoerdern;
    case  4 : return ETefoerdern;
    case  5 : return ETadrehen;
    case  6 : return ETedrehen;
    case 14 : return ETafahren;
    case 16 : return ETefahren;
    case 15 : return ETausschl;
    case 17 : return ETeausschl;
    case 36 : return ETaeinschl;
    case 37 : return ETeaufnehmen;
    case 63 : return ETbereit;
    case 60 : return ETainit;
    case 61 : return ETeinit;
    case 80 : return ETchtyp;
    default : return 0;
  }
}


// ----------------------------------------------------------
// --- Lokal benutzte Funktion:                           ---
// --- Uebersetzt die Simulatorereignisse in MSPS-Befehle ---
// ----------------------------------------------------------

int ETypZuHlaRzsEcho (int EreignisTyp) {
  switch (EreignisTyp) {
    case ETaaufnehmen : return 1;
    case ETeaufnehmen : return 2;
    case ETaarbeiten  : return 30;
    case ETearbeiten  : return 31;
    case ETaabgeben   : return 52;
    case ETeabgeben   : return 53;
    case ETdpabgplatz : return 54;
    case ETafoerdern  : return 3;
    case ETefoerdern  : return 4;
    case ETadrehen    : return 5;
    case ETedrehen    : return 6;
    case ETafahren    : return 14;
    case ETefahren    : return 16;
    case ETausschl    : return 15;
    case ETeausschl   : return 17;
    case ETaeinschl   : return 36;
    case ETbereit     : return 63;
    case ETainit      : return 60;
    case ETeinit      : return 61;
    case ETchtyp      : return 80;
    default           : return 0;
  }
}

// -----------------------------------------------------
// -----------------------------------------------------
/**
 * SFXHla ist Konstruktor und initialisiert alle benoetigten Variablen.
 *
 * @param interp Tcl-Interpreter.
 * @param fedName Federatename, mit dem sich ein Objekt anmeldet.
 * @param fedExecName Federationname, an der sich ein Objekt beteiligen moechte.
 * @param lookAhead Vorausschauende Zeit, die in Millisekunden angegeben werden sollte (z.B.: 0.01 = 10 ms).
 * @param pClass Interaction Klassenname, der veroeffentlicht wird.
 * @param pParList Liste der Parameter, die veroeffenlticht werden.
 * @param sClass Interaction Klassenname, der abonniert wird.
 * @param sParList Liste der Parameter, die abonniert werden.
 * @author Rudi
 * @since Release 14.00
 */
SFXHla::SFXHla (    Tcl_Interp* interp,const char* fedName, const char* fExecName, double lookAhead, \
		            double tickMin, double tickMax, const char* fedFileName, const char* pClass, \
		            DynArray<char> &pParList, const char* sClass, DynArray<char> &sParList ) :
  ObjInterp (interp),
  ObjFederateName (fedName),
  ObjFederateExecutionName (fExecName),
  ObjLookAhead (lookAhead),
  ObjTickMin (tickMin),
  ObjTickMax (tickMax),
  ObjFEDFileName (fedFileName),
  ObjPublishInteractionClassName (pClass),
  ObjSubscribeInteractionClassName (sClass),
  PublishedInteractionsMap (1),
  SubscribedInteractionsMap (1),
  PublishedObjectsMap (1),
  SubscribedObjectsMap (1) {

  int intWert;
  
  cout << "Konstruktor" << endl;

  /**< 24-01-03: Rudi: DllTest.*/
  newObject hlaObj;
  voidCall vCall;
  startCall startMe;
  voidCall pubAndSubCall;
  intCall iCall;

  // hLibrary koennte auch  weggelassen werden, oder?
  hlaLibrary = LoadLibrary("hla4sfx.dll");
  
  if (hlaLibrary != NULL) {
    //cout << "hla4sfx.dll geladen" << endl;

    /**< 05-02-03: Rudi: Die Funktion zur Generierung einer Instanz wird ausgeführt.*/
    hlaObj = (newObject)(GetProcAddress( hlaLibrary, "CreateHla4SfxInstance" ) );
    if (hlaObj != NULL){
      // get pointer to object in dll
      myHla4SfxPtr = (hla4sfx*) ( 	hlaObj(ObjFederateName, ObjFederateExecutionName, \
					 							ObjLookAhead, ObjTickMin, ObjTickMax, ObjFEDFileName) );	
    } else {
      sim_error ("HLA", "SFXHla::SFXHla", "Konstruktor der HLA-Objektinstanz konnten nicht aufgerufen werden!", 0, FATAL);
    }
    
     startMe = (startCall) GetProcAddress(hlaLibrary, "hla4sfx_Start");
    if (startMe != NULL) {
      intWert = startMe(myHla4SfxPtr, PublishedObjectsMap, SubscribedObjectsMap, PublishedInteractionsMap, SubscribedInteractionsMap);
  
      if (intWert != 0)
         sim_error ("HLA", "SFXHla::SFXHla", "HLA konnten nicht gestartet werden!", 0, FATAL);
      else
          cout << "HLA gestartet: " << intWert << endl;
    } else {
      sim_error ("HLA", "SFXHla::SFXHla", "HLA konnten nicht gestartet werden!", 0, FATAL);
    }

    /**< Es folgen die Zeiteigenschaften.*/
    if(hlaAsynchronousDelivery) {
      iCall = (intCall) GetProcAddress(hlaLibrary, "hla4sfx_EnableAsynchronousDelivery");
      if (iCall != NULL) {
	intWert = iCall(myHla4SfxPtr);
	cout << "hlaAsynchronousDelivery: " << intWert << endl;
      } else {
	sim_error ("HLA", "SFXHla::SFXHla", "hlaAsynchronousDelivery konnten nicht initialisiert werden!", 0, FATAL);
      }
    }
      
    if(hlaTimeConstrained) {
      iCall = (intCall) GetProcAddress(hlaLibrary, "hla4sfx_EnableTimeConstrained");
      if (iCall != NULL) {
	intWert = iCall(myHla4SfxPtr);
	cout << "hlaTimeConstrained: " << intWert << endl;
      } else {
	sim_error ("HLA", "SFXHla::SFXHla", "hlaTimeConstrained konnten nicht initialisiert werden!", 0, FATAL);
      }
    }

    if(hlaTimeRegulating) {
      iCall = (intCall) GetProcAddress(hlaLibrary, "hla4sfx_EnableTimeRegulation");
      if (iCall != NULL) {
	intWert = iCall(myHla4SfxPtr);
	cout << "hlaTimeRegulating: " << intWert << endl;
      } else {
	sim_error ("HLA", "SFXHla::SFXHla", "hlaTimeRegulating konnten nicht initialisiert werden!", 0, FATAL);
      }
    }

    
    /**< Es folgen die Veröffentlichungen und Abbonements der Objekte und Interactions.*/
    // pParList muss in eine andere Liste umgewandelt werden!
    if (pClass != NULL) {
      pubAndSubCall = (voidCall) GetProcAddress(hlaLibrary, "hla4sfx_PublishInteractions");      
      
      if (pubAndSubCall != NULL) {
      	
      	InteractionStructure *myInteraction = new InteractionStructure (ObjPublishInteractionClassName);
      	// folgende Zeile notwendig, damit Zeiger myAttributes die Adresse in der Map erhaelt
      	DynArray<HlaParameter> *myParams = &PublishedInteractionsMap.insert (*myInteraction, *(new DynArray<HlaParameter> (1)));
      	
      	for (pParList.First(); pParList(); pParList++) {
      		HlaParameter *par = new HlaParameter (pParList());
      		myParams->append(*par);
      	}
      	cout << "Veroeffentliche: "<< ObjPublishInteractionClassName << " Anzahl Paramter: " << myParams->Count() << endl;
      	pubAndSubCall(myHla4SfxPtr);
      	      	
      } else {
			sim_error ("HLA", "SFXHla::SFXHla", "Veröffentlichung einer Interaktionklasse fehlerhaft!", 0, FATAL);
      }
    }

    /**< Klassen, die abonniert werden sollen, sollten nicht mit veroeffentlichten Klassen uebereinstimmen.*/
    if ((sClass != NULL) && (pClass == NULL)) {
      pubAndSubCall = (voidCall) GetProcAddress(hlaLibrary, "hla4sfx_SubscribeInteractions");
      if (pubAndSubCall != NULL) {
   	   InteractionStructure *myInteraction = new InteractionStructure (ObjSubscribeInteractionClassName);
	      // folgende Zeile notwendig, damit Zeiger myAttributes die Adresse in der Map erhaelt
   	   DynArray<HlaParameter> *myParams = &SubscribedInteractionsMap.insert (*myInteraction, *(new DynArray<HlaParameter> (1)));
   	   
      	for (sParList.First(); sParList(); sParList++) {
      		HlaParameter *par = new HlaParameter (sParList());
      		myParams->append(*par);
      	}      		
      	cout << "Abonniere: " << ObjSubscribeInteractionClassName << endl;	
			pubAndSubCall(myHla4SfxPtr);
      } else {
			sim_error ("HLA", "SFXHla::SFXHla", "Abonnement einer Interaktionklasse fehlerhaft!", 0, FATAL);
      }
    } else if ((sClass != NULL) && (strcmp(sClass, pClass))) {
    	
    	InteractionStructure *myInteraction = new InteractionStructure (ObjSubscribeInteractionClassName);
	   DynArray<HlaParameter> *myParams = &SubscribedInteractionsMap.insert (*myInteraction, *(new DynArray<HlaParameter> (1)));
   	   
      for (sParList.First(); sParList(); sParList++) {
      	HlaParameter *par = new HlaParameter (sParList());
      	myParams->append(*par);
      }      		
    	
      cout << "sClass == pClass: " << (sClass == pClass) << " sClass: " << sClass << " pClass: " << pClass << endl;
      pubAndSubCall = (voidCall) GetProcAddress(hlaLibrary, "hla4sfx_SubscribeInteractions");
      if (pubAndSubCall != NULL) {
			pubAndSubCall(myHla4SfxPtr);
      } else {
			sim_error ("HLA", "SFXHla::SFXHla", "Abonnement einer Interaktionklasse fehlerhaft!", 0, FATAL);
      }
    }

  } else {
    /**< Wenn DLL nicht gefunden werden konnte.*/
    sim_error ("HLA", "SFXHla::SFXHla", "hla4sfx.dll konnten nicht geladen werden!", 0, FATAL);
  }
}

SFXHla::~SFXHla () {
  Exit();
  FreeLibrary (hlaLibrary);	
}

void SFXHla::Exit () {
  cout << "hier 1" << endl;
  intCall iCall;
  iCall = (intCall) GetProcAddress(hlaLibrary, "hla4sfx_WaitForProcedures");
  if (iCall != NULL) {
  	cout << "hla4sfx_WaitForProcedures: " << endl;
    iCall(myHla4SfxPtr);
  } else {
    sim_error ("HLA", "SFXHla::SFXHla", "hla4sfx_WaitForProcedures nicht ausführbar!", 0, FATAL);
  }

  cout << "hier 2" << endl;
  constCharFunc ccCall;
  ccCall = (constCharFunc) GetProcAddress(hlaLibrary, "hla4sfx_Stop");
  if (ccCall != NULL) {
  	ccCall(myHla4SfxPtr);
  } else {
    sim_error ("HLA", "SFXHla::SFXHla", "hla4sfx_Stop nicht ausführbar!", 0, FATAL);
  }

  /*
  ccCall;
  ccCall = (constCharFunc) GetProcAddress(hlaLibrary, "Delete_hla4sfx");
  if (ccCall != NULL) {
    cout << ccCall(myHla4SfxPtr) << endl;
  } else {
    sim_error ("HLA", "SFXHla::SFXHla", "Delete_hla4sfx nicht ausführbar!", 0, FATAL);
  }
  */
  delete myHla4SfxPtr;
}

/**
 * Folgende Funktion nur in Verbindung mit Realzeitsteuerung.
 *
 */
void SFXHla::SendUpdate (int BausteinNr, int ETyp, int Parameter) {
  char NText [100];
  sprintf (AnBaustein, "%02i", BausteinNr);

  // --- Befehl vorbereiten ---
  sprintf (Befehl, "%02i", ETypZuHlaRzsEcho (ETyp));
  
  // --- Parameter vorbereiten ---
  sprintf (BefehlParameter, "%03i", Parameter);
  if (Parameter < 0)
    BefehlParameter [0] = '-';
  else
    BefehlParameter [0] = '+';
  
  // --- Befehl senden ---
  sprintf (NText, "%s,00,%s %s", AnBaustein, Befehl, BefehlParameter);

  dprintf ("\nRUDI:: HlaSendUpdate: %s zur ZEIT: %f\n\n",NText,Modellzeit().inSeconds());
}

/**
 * Sendet Interaction in Form eines Kallendereignisses des Simulators.
 *
 * @param bstNr Bausteinnummer, fuer die die Information gilt.
 * @param eTyp Ereignistyp.
 * @param parameter Gibt Parameter an, der geschickt werden soll.
 * @author Rudi
 * @since Release 14.00
 */
void SFXHla::SendInteraction (int bstNr, int eTyp, int parameter) {
  char NText [100];
  sprintf (AnBaustein, "%02i", bstNr);
  // --- Befehl vorbereiten ---
  sprintf (Befehl, "%02i", ETypZuHlaRzsEcho (eTyp));
  // --- Parameter vorbereiten ---
  sprintf (BefehlParameter, "%03i", parameter);
  if (parameter < 0)
    BefehlParameter [0] = '-';
  else
    BefehlParameter [0] = '+';
  // --- Befehl senden ---
  sprintf (NText, "%s,00,%s %s", AnBaustein, Befehl, BefehlParameter);
  
  //hla4sfx_SendInteraction(ObjRti,Modellzeit().inSeconds(),NText);
  
  SendInteractionText (NText);
  dprintf ("\nRUDI:: HlaSendInteraction: %s zur ZEIT: %f\n\n",NText,Modellzeit().inSeconds());
}

/**
 * Folgende Funktion nur in Verbindung mit Realzeitsteuerung.
 *
 */
void SFXHla::SendSfxInteraction (const char* msg) {
  char NText [255];
  sprintf (NText, "%s",msg);
  //dprintf ("\nRUDI:: HlaSendInteraction: %s\n\n",hla4sfx_SendInteraction(ObjRti,Modellzeit().inSeconds(),NText));

  SendInteractionText (NText);
  //hla4sfx_SendInteraction(ObjRti,Modellzeit().inSeconds(),NText);
  dprintf ("\nRUDI:: SendSfxInteraction: %s zur ZEIT: %f \n\n", NText, Modellzeit().inSeconds());
}


/**
 * Sendet Interaction mit Klassen- und Parameternamen in Form eines Kallendereignisses des Simulators.
 *
 * @param ereignisZeit Aktuelle Modellzeit.
 * @param eTyp Ereignistyp.
 * @param bstNr Bausteinnummer, fuer die die Information gilt.
 * @param arbPlNr Arbeitsplannummer.
 * @param menge Menge.
 * @param className Name der Interactionklasse.
 * @param parName Parametername der Interactionklasse.
 * @author Rudi
 * @since Release 14.00
 */
void SFXHla::SendInteractionWithClassAndParName (double ereignisZeit, int eTyp, int bstNr, int arbPlNr, int menge, const char* className, const char* parName) {
	char NText [255];
  	sendIAWithClassAndPar iaMsg;

  	DynArray<HlaParameter> *da;
	for (InteractionStructure *iaClass = PublishedInteractionsMap.First (); (da = PublishedInteractionsMap ()) != NULL; iaClass = PublishedInteractionsMap.Next() ) {
      if (!strcmp(className, iaClass->GetName()) ) {
         
			for (HlaParameter *par = da->First(); (*da)(); par = da->Next()) {
           	if (!strcmp(par->GetName(), parName)) {
           		sprintf (NText, "%f;%02i;%02i;%02i;%02i", ereignisZeit, ETypZuHla(eTyp), bstNr, arbPlNr, menge);
	  					
              	par->AddTextValue(NText);
           		iaMsg = (sendIAWithClassAndPar) GetProcAddress(hlaLibrary, "hla4sfx_SendInteractionWithClassAndParName");

	        		if (iaMsg != NULL) {
	           		iaMsg (myHla4SfxPtr, (Modellzeit().inSeconds() +  ObjLookAhead), className, par->GetName());
           			dprintf ("schicke %s\n",NText);
               } else {
    					sim_error ("HLA", "SFXHla::SendInteractionWithClassAndParName", "HlaSendInteractionWithClassAndParName nicht ausführbar!", 0, FATAL);
   				}                  
               break;
            }
         }
         break;
     }
   }
}


/**
 * Sendet Interactionmitteilung mit Klassen- und Parameternamen in Form eines Kallendereignisses des Simulators.
 *
 * @param iaMessage Die eigentlicht Message, die verschickt wird.
 * @param className Name der Interactionklasse.
 * @param parName Parametername der Interactionklasse.
 * @author Rudi
 * @since Release 14.00
 */
void SFXHla::SendInteractionMessageWithClassAndParName (const char* iaMessage, const char* className, const char* parName) {
	
	// 13-10-03: anpassen!!!
  //char NText [100];
  // --- Befehl senden ---
  //sprintf (NText, "%f;%02i;%02i;%02i;%02i",EreignisZeit,ETypZuHla(ETyp),BausteinNr,ArbPlNr,Menge);
  sendIAWithClassAndPar iaMsg;
  
  iaMsg = (sendIAWithClassAndPar) GetProcAddress(hlaLibrary, "hla4sfx_SendInteractionWithClassAndParName");
  if (iaMsg != NULL)
    iaMsg(myHla4SfxPtr, (Modellzeit().inSeconds() + ObjLookAhead), className, parName);
  else
    sim_error ("HLA", "SFXHla::SendInteractionMessageWithClassAndParName", "SendInteractionMessageWithClassAndParName nicht ausführbar!", 0, FATAL);
}




void SFXHla::SendNextEventRequest (double requestTime) {
  //void HlaSendNextEventRequest (LPVOID requestTime) {
  //while (Tcl_DoOneEvent (TCL_ALL_EVENTS|TCL_DONT_WAIT) != 0);

  neRequest nerCall;

  nerCall = (neRequest) GetProcAddress(hlaLibrary, "hla4sfx_NextEventRequest");
  if (nerCall != NULL)
    nerCall (myHla4SfxPtr, requestTime);
  else
    sim_error ("HLA", "SFXHla::SendNextEventRequest", "hla4sfx_NextEventRequest nicht ausführbar!", 0, FATAL);
}



double SFXHla::GetGrantTime () {
  //while (Tcl_DoOneEvent (TCL_ALL_EVENTS|TCL_DONT_WAIT) != 0);

  doubleFunc dCall;

  dCall = (doubleFunc)GetProcAddress(hlaLibrary, "hla4sfx_GetGrantTime");
  
  if (dCall != NULL)
    return dCall (myHla4SfxPtr);
  else
    sim_error ("HLA", "SFXHla::GetGrantTime", \
    	"hla4sfx_GetGrantTime nicht ausführbar!", 0, FATAL);

  return 0.0; // hierhin sollte die Funktion nicht mehr kommen
}


double SFXHla::meinHlaLesen () {
  int ic;
  double newZeit;
  
  Tick (ObjTickMin, ObjTickMax);
  
  ic = GetInteractionCounter();
  if (ic > 0) {
    const char* imsg = GetInteraction ();
    dprintf ("New Interaction in mein HlaLesen: %s\n", imsg);
    
    char* interaction;
    // Allocate appropriate size string and copy data
    if ( imsg && strlen( imsg ) > 0 ) {
      interaction = new char[ strlen(imsg) + 1 ];
      strcpy( interaction, imsg );
    } else {
      interaction = NULL;
    }

    char seps[] = " ,";
    char* txt[5];
    char *token;
    
    token = strtok (interaction, seps);
    int counter = 0;
    while( token != NULL ) {
      /* While there are tokens in "string" */
      txt[counter] = token;
      /* Get next token: NULL is very important*/
      token = strtok ( NULL,seps);
      counter++;
    }
    newZeit = atof (txt[5]);
  }
  return newZeit;
}


/**
 * Verarbeitet Interaction-Informationen, die in der Liste abgelegt sind.
 *
 * @author Rudi
 * @since Release 14.00
 */
void SFXHla::VerarbeiteInteractions () {
  const char* imsg = GetInteraction ();
  HlaReceivedInteractionList.append(*(strcpy (new char [strlen ((const char*)imsg) + 1], imsg)));
  
  while (imsg) {
    char* interaction;
    /**< Allocate appropriate size string and copy data.*/
    if ( imsg && strlen( imsg ) > 0 ) {
      interaction = new char[ strlen(imsg) + 1 ];
      strcpy( interaction, imsg );
    } else {
      interaction = NULL;
    }
    
    char seps[] = ";"; // TrennZeichen
    char* txt[5];
    char *token;
    
    token = strtok (interaction, seps);
    int counter = 0;
    while( token != NULL ) {
      /* While there are tokens in "string" */
      txt[counter] = token;
      /* Get next token: NULL is very important*/
      token = strtok ( NULL,seps);
      counter++;
    }
    
    double d_EreignisZeit = atof (txt[0]);
    int i_EreignisTyp = HlaZuETyp (atoi(txt[1]));
    int i_BstNr = atoi (txt[2]);
    int i_ArbPlanNr = atoi (txt[3]);
    int i_Menge = atoi (txt[4]);
    
    typArbeitsplan *zA = MySFXModel->findWorkSchedule (i_ArbPlanNr);
    if (zA) {
      /**< Abfangen, wenn Zeit schon weiter als gesendete ist.*/
      if (d_EreignisZeit < Modellzeit().inSeconds()) {
      	d_EreignisZeit = Modellzeit().inSeconds();
      	//planeein (d_EreignisZeit,i_EreignisTyp,i_BstNr,i_ArbPlanNr,i_Menge);
      	planesofort (i_EreignisTyp,i_BstNr,i_ArbPlanNr,i_Menge);
      	dprintf("Zeitkorrektur vorgenommen!\n");
      } else {
      	//dprintf("IA verarbeitet: %f,%i,%i,%i,%i\n",(d_EreignisZeit/60),i_EreignisTyp,i_BstNr,i_ArbPlanNr,i_Menge);
			// die Zeit muss demnaechst in SimTime umgewandelt werden!
			planeein ((d_EreignisZeit/60),i_EreignisTyp,i_BstNr,i_ArbPlanNr,i_Menge);
			cout << "Aktuelle Zeit(s): " << Modellzeit().inSeconds() << endl;
			dprintf("planeein (%f,%i,%i,%i,%i)\n",(d_EreignisZeit/60),i_EreignisTyp,i_BstNr,i_ArbPlanNr,i_Menge);
			//dprintf("planeein (%f,%i,%i,%i,%i)\n",(d_EreignisZeit),i_EreignisTyp,i_BstNr,i_ArbPlanNr,i_Menge);
			//zA->Vorgaenge ().First ()->ZielBaustein ()->ArbBestellung (zA->Nummer (), 0, 0, Menge);
      }
    }
    imsg = GetInteraction ();
  }
}



/**
 * Verarbeitet realzeitgesteuerte Interaction-Informationen, die empfangen werden.
 *
 * @author Rudi
 * @since Release 14.00
 */
void SFXHla::VerarbeiteSfxInteractions () {
  const char* imsg = GetInteraction ();
  
  while (imsg) {
    char* interaction;
    // Allocate appropriate size string and copy data
    if ( imsg && strlen( imsg ) > 0 ) {
      interaction = new char[ strlen(imsg) + 1 ];
      strcpy( interaction, imsg );
    } else {
      interaction = NULL;
    }
    char seps[] = ";"; // TrennZeichen
    char* txt[3];
    char *token;
    
    token = strtok (interaction, seps);
    int counter = 0;
    while( token != NULL ) {
      /* While there are tokens in "string" */
      txt[counter] = token;
      /* Get next token: NULL is very important*/
      token = strtok ( NULL,seps);
      counter++;
    }
    if (txt[0] == "hla_Tcl_Cmd") {
      dprintf("TclDialog von TimeConstrained bekommen!!!");
      if (!strcmp("Stop",txt[2]))
		MySFXModel->stop();
    }
    imsg = GetInteraction();
  }
}


int SFXHla::Lesen (int *VonBausteinNr, int *ETyp, int *Parameter) {
  int NachrichtDa = 0;  
  
  Tick (ObjTickMin, ObjTickMax);
  //hla4sfx_Tick(ObjRti);
  // Dieser Bereich ist zu erweitern
  //dprintf("RUDI:: VonBstNr.: %i, ETyp: %i, Par: %i\n", VonBausteinNr, ETyp, Parameter);
  
  //if (hlaTimeConstrained) 
  //dprintf ("hlaTimeRegulation: %i, hlaTimeConstrained: %i\n",hlaTimeRegulation,hlaTimeConstrained);
  
  //int ant = ETypEcho(atoi (Befehl));
  if (hla && hlaTimeRegulating) {
    if (GetInteractionCounter() > 0) {
      const char* imsg = GetInteraction ();

      char* interaction;
      // Allocate appropriate size string and copy data
      if ( imsg && strlen( imsg ) > 0 ) {
	interaction = new char[ strlen(imsg) + 1 ];
	strcpy( interaction, imsg );
      } else {
	interaction = NULL;
      }
      
      char seps[] = " ,";
      char* txt[4];
      char *token;
      
      token = strtok (interaction, seps);
      int counter = 0;
      while( token != NULL ) {
	/* While there are tokens in "string" */
	txt[counter] = token;
	/* Get next token: NULL is very important*/
	token = strtok ( NULL,seps);
	counter++;
      }
      
      //dprintf("aus while: %s,%s,%s %s\n",txt[0],txt[1],(txt[2]),txt[3]);
      *VonBausteinNr = atoi (txt[1]);
      *ETyp = HlaRzsEchoZuETyp(atoi(txt[2]));
      *Parameter = atoi (txt[3]);
      
      if (atoi(txt[0]) == 0) {
      	//dprintf ("NachrichtDa\n");
	NachrichtDa = 1;
      }
    }
  } else if (hla && hlaTimeConstrained && (GetInteractionCounter() > 0)) {
    
    const char* imsg = GetInteraction ();
      
    char* interaction;
    // Allocate appropriate size string and copy data
    if ( imsg && strlen( imsg ) > 0 ) {
      interaction = new char[ strlen(imsg) + 1 ];
      strcpy( interaction, imsg );
    } else {
      interaction = NULL;
    }
    
    char seps[] = " ,";
    char* txt[4];
    char *token;
    
    token = strtok (interaction, seps);
    int counter = 0;
    while( token != NULL ) {
      /* While there are tokens in "string" */
      txt[counter] = token;
      /* Get next token: NULL is very important*/
      token = strtok ( NULL,seps);
      counter++;
    }
      
    //dprintf("aus while: %s,%s,%s %s\n",txt[0],txt[1],(txt[2]),txt[3]);
    *VonBausteinNr = atoi (txt[0]);
    *ETyp = HlaRzsEchoZuETyp(atoi(txt[2]));
    *Parameter = atoi (txt[3]);
    // im Folgenden wird Abfrage auf zweite Stelle gesetzt!!!
    if (atoi(txt[1]) == 0) {
      NachrichtDa = 1;    
    }
  }
  return NachrichtDa;
}

const char* SFXHla::GetReceivedInteraction () {
  return HlaReceivedInteractionList.First();
}


/**
 * Liefert einen Zaehler, der empfangene Interactions hochzaehlt.
 *
 */
int SFXHla::GetInteractionCounter () {
	int interactions = 0;
	if (SubscribedInteractionsMap.Count() > 0) {
      DynArray<HlaParameter>* da;
      for (InteractionStructure *iaClass = SubscribedInteractionsMap.First (); (da = SubscribedInteractionsMap ()) != NULL; iaClass = SubscribedInteractionsMap.Next() ) {
			for (HlaParameter *par = da->First(); (*da)(); par = da->Next()) {
				interactions += par->CountTextValues();
         }
      }
      return interactions;
	} else {
		return 0;
	}
}

const char* SFXHla::GetInteraction() {
	// muss noch angepasst werden!!!
	// hier wird die erste Interaction zurueckgegeben!!!
	const char* text = NULL;
	if (SubscribedInteractionsMap.Count() > 0) {
      DynArray<HlaParameter>* da;
      for (InteractionStructure *iaClass = SubscribedInteractionsMap.First (); (da = SubscribedInteractionsMap ()) != NULL; iaClass = SubscribedInteractionsMap.Next() ) {
			for (HlaParameter *par = da->First(); (*da)(); par = da->Next()) {
				if (par->CountTextValues() > 0) {
					text = par->GetFirstTextValue();
				}
         }
      }
	} 
	return text;
}
 

void SFXHla::SendInteractionText (const char* nText) {
  sendIAText iaMsg;
  iaMsg = (sendIAText)GetProcAddress(hlaLibrary, "hla4sfx_SendInteraction");
  if (iaMsg != NULL)
    iaMsg(myHla4SfxPtr, (Modellzeit().inSeconds() + ObjLookAhead), nText);
  else
    sim_error ("HLA", "SFXHla::SendInteractionText", "hla4sfx_SendInteraction nicht ausführbar!", 0, FATAL);
}


void SFXHla::Tick (double min, double max) {
  tickFunc tCall;
  tCall = (tickFunc) GetProcAddress(hlaLibrary, "hla4sfx_Tick");
  if (tCall != NULL)
    tCall(myHla4SfxPtr, min, max);
  else
    sim_error ("HLA", "SFXHla::Tick", "hla4sfx_Tick nicht ausführbar!", 0, FATAL);
}

/*
 * Ueber diese Funktion koennen Objekte der HLA-Umgebung veroeffentlicht werden.
 *
 */
void SFXHla::RegisterObject (const char* className, int bstNr, DynArray<char> &attribs) {
  objPubFunc objCall;
  objCall = (objPubFunc) GetProcAddress(hlaLibrary, "hla4sfx_PublishObject");
  if (objCall != NULL)
    objCall(myHla4SfxPtr, className, bstNr, attribs);
  else
    sim_error ("HLA", "SFXHla::RegisterObject", "RegisterObject nicht ausführbar!", 0, FATAL);
}

/*
 * Ueber diese Funktion werden Objekte aus der HLA-Umgebung abonniert.
 *
 */
void SFXHla::SubscribeObject (const char* className, DynArray<char> &attribs) {
  objIntAFunc subCall;
  subCall = (objIntAFunc) GetProcAddress(hlaLibrary, "hla4sfx_SubscribeObject");
  if (subCall != NULL)
    subCall(myHla4SfxPtr, className, attribs);
  else
    sim_error ("HLA", "SFXHla::SubscribeObject", "RegisterObject nicht ausführbar!", 0, FATAL);
}
