// $Source: /usr/local/SimSoft/Sfx3D/src/gsl/ereignis.cpp,v $
// $Revision: 1.3 $
// $Author: baum $
// $Date: 2001/12/06 13:26:51 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name:  $
// State assigned to revision
// $State: Exp $
//
//
// $Log: ereignis.cpp,v $
// Revision 1.3  2001/12/06 13:26:51  baum

//
// Revision 1.2  2001/11/29 15:18:09  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//

#include <stdio.h>
#include <string.h>

#include "Kalender.h"

#define _EREIGNIS_CPP
#include "modell.h"
#include "ereignis.h"

#include "sfx.h"
#include "transp.h"
#include "arbplan.h"
#include "baustein.h"
#include "prozess.h"
#include "maschine.h"
#include "vwagen.h"
#include "staufoer.h"
#include "regal.h"
#include "senke.h"
#include "programm.h"
//#include "fts.h"
//#include "kettfoer.h"
//#include "querfoer.h"
#include "realzeit.h"

bool modelOpen = false;

//---------------------------------------------------------
//  System-Prozeduren
//---------------------------------------------------------

int ok_ereignis (int etyp) {
  switch (etyp) {
    case ETatrace          : 
    case ETetrace          : 
    case ETprotokoll       : 
    case ETasperrung       :
    case ETesperrung       :
    case ETastoerung       :
    case ETestoerung       :
    case ETprogramm        :   
    case ETazeitreihe      :
    case ETezeitreihe      :
    case ETstartextprozess : 
    case ETstopextprozess  : 
    case ETexplerzeugen    :
    case ETerzBestellung   :
    case ETloeBestellung   :
    case ETaladen	   :
    case ETeladen	   : return 1;
    default                : return 0;
  }
}

char *ereignisstring (int etyp) {
  static char EreignisString[80];
  switch (etyp) {
    case ETatrace           : return strcpy (EreignisString, "A_TRACE       ");
    case ETetrace           : return strcpy (EreignisString, "E_TRACE       ");
    case ETprotokoll        : return strcpy (EreignisString, "PROTOKOLL     ");
    case ETaaufnehmen	    : return strcpy (EreignisString, "A_AUFNEHMEN   ");
    case ETeaufnehmen	    : return strcpy (EreignisString, "E_AUFNEHMEN   ");
    case ETaarbeiten	    : return strcpy (EreignisString, "A_ARBEITEN    ");
    case ETearbeiten	    : return strcpy (EreignisString, "E_ARBEITEN    ");
    case ETaabgeben         : return strcpy (EreignisString, "A_ABGEBEN     ");
    case ETeabgeben         : return strcpy (EreignisString, "E_ABGEBEN     ");
    case ETafoerdern	    : return strcpy (EreignisString, "A_FOERDERN    ");
    case ETefoerdern	    : return strcpy (EreignisString, "E_FOERDERN    ");
    case ETadrehen          : return strcpy (EreignisString, "A_DREHEN      ");
    case ETedrehen          : return strcpy (EreignisString, "E_DREHEN      ");
    case ETafahren          : return strcpy (EreignisString, "A_FAHREN      ");
    case ETefahren          : return strcpy (EreignisString, "E_FAHREN      ");
    case ETasperrung        : return strcpy (EreignisString, "A_SPERRUNG    ");
    case ETesperrung        : return strcpy (EreignisString, "E_SPERRUNG    ");
    case ETastoerung        : return strcpy (EreignisString, "A_STOERUNG    ");
    case ETestoerung        : return strcpy (EreignisString, "E_STOERUNG    ");
    case ETalagern          : return strcpy (EreignisString, "A_LAGERN      ");
    case ETelagern          : return strcpy (EreignisString, "E_LAGERN      ");
    case ETaheben           : return strcpy (EreignisString, "A_HEBEN       ");
    case ETeheben           : return strcpy (EreignisString, "E_HEBEN       ");
    case ETasenken          : return strcpy (EreignisString, "A_SENKEN      ");
    case ETesenken          : return strcpy (EreignisString, "E_SENKEN      ");
    case ETprogramm         : return strcpy (EreignisString, "PROGRAMM      ");
    case ETazeitreihe       : return strcpy (EreignisString, "A_ZEITREIHE   ");
    case ETezeitreihe       : return strcpy (EreignisString, "E_ZEITREIHE   ");
    case ETstartextprozess  : return strcpy (EreignisString, "STARTPROZESS  ");
    case ETstopextprozess   : return strcpy (EreignisString, "STOPPROZESS   ");
    case ETexplerzeugen     : return strcpy (EreignisString, "EXPL_ERZEUGEN ");
    case ETerzBestellung    : return strcpy (EreignisString, "ERZ_BESTELLUNG");
    case ETloeBestellung    : return strcpy (EreignisString, "LOE_BESTELLUNG");
    case ETfahrTakt         : return strcpy (EreignisString, "FAHRTAKT      ");
    case ETdrehTakt         : return strcpy (EreignisString, "DREHTAKT      ");
    case ETaufnTakt         : return strcpy (EreignisString, "AUFNAHMETAKT  ");
    case ETameldewarten	    : return strcpy (EreignisString, "MELDEWARTEN   ");
    case ETaktivieren	    : return strcpy (EreignisString, "AKTIVIEREN    ");
    case ETwecken           : return strcpy (EreignisString, "WECKEN        ");
    case ETaftsfahren       : return strcpy (EreignisString, "AFTSFAHREN    "); /*FTS*/
    case ETeftsfahren       : return strcpy (EreignisString, "EFTSFAHREN    ");
    case ETakommissionieren : return strcpy (EreignisString, "AKOMMISSION   ");
    case ETekommissionieren : return strcpy (EreignisString, "EKOMMISSION   ");
    case ETinitGrafik       : return strcpy (EreignisString, "INITGRAFIK    ");
    case ETloescheGrafik    : return strcpy (EreignisString, "LOESCHEGRAFIK ");
    case ETeausschl         : return strcpy (EreignisString, "E_AUSSCHLEUSEN");
    case ETaladen	    : return strcpy (EreignisString, "A_LADEN       ");
    case ETeladen	    : return strcpy (EreignisString, "E_LADEN       ");
    case ETbereit           : return strcpy (EreignisString, "ET_BEREIT     "); /*Modelltechnik*/
    default                 : {
                           dprintf ("Info1 = %d, Info2 = %d, Info3 = %d\n",
                                     notiz::AktInfo1 (), notiz::AktInfo2 (), notiz::AktInfo3 ());
                           sim_error ("EREIGNIS", "ereignisstring",
                                     "ungueltiges Ereignis", etyp, FATAL);
                           return NULL;}
  }
}

void sys_trace (ostream& ostrm) {
  SimTime now (SimTime::convertSysClock ());
  ostrm << "ZEIT=";
  Modellzeit ().print (ostrm, SimTime::OutputFormat ());
  ostrm << " TYP=";
  ostrm.width (2);
  ostrm << notiz::AktTyp () << " " << ereignisstring (notiz::AktTyp ()) << " ";
  ostrm.width (4);
  ostrm << notiz::AktInfo1 () << " ";
  ostrm.width (4);
  ostrm << notiz::AktInfo2 () << " ";
  ostrm.width (4);
  ostrm << notiz::AktInfo3 () << " UHRZEIT= ";
  ostrm.width (2);
  ostrm << now.Hours () << ":";
  ostrm.width (2);
  ostrm << now.Minutes () << ":";
  ostrm.width (2);
  ostrm << now.Seconds (); //rei050506 << endl;
  ostrm << (baustein[notiz::AktInfo1()] ? (baustein[notiz::AktInfo1()]->Name()) : Ustring("")) << endl;
}

void sys_protokoll (ostream& ostrm) {
  //LCE
  /*
  if (MySFXModel->zLCE_Kern) {
      MySFXModel->zLCE_Kern->Auswertung(Modellzeit ()); 
  }
  */
  //LCE  
   
  ostrm.precision (2);
  ostrm << endl;
  ostrm << "Protokoll  >" << MySFXModel->ModelName () << "<  zur Modellzeit = ";
  Modellzeit ().print (ostrm, SimTime::OutputFormat ());
  ostrm << endl;
  ostrm << "Arbeitsplaene:                 < DzRegister >" << endl;
  ostrm << "    Nr P.Ein P.Aus P.ImSys    Min   Mittel  Max    Anz" << endl;

  const DynArray<typArbeitsplan>& a (MySFXModel->WorkSchedules ());
  for (a.First (); a (); a++) {
    a ()->schreibeProtokoll (ostrm);
    ostrm << endl;
  }
  ostrm << endl;

  ostrm << "Bausteine:       < BelGeschichte >                  < AuslGeschichte >                 < StoerGeschichte >" << endl;
  ostrm << " Nr Mld   Min Mittel    Max Status  WZeit    Min Mittel    Max Status  WZeit    Min Mittel    Max Status  WZeit" << endl;

  for (unsigned b = 1; b <=  baustein.Count (); b++)
    if (baustein[b] != NULL){
//       baustein[b]->schreibeZustand (ostrm);
       baustein[b]->schreibeProtokoll (ostrm);
    }
  ostrm << endl;
}

//---------------------------------------------------------
// Ereignisse EP<Name>
//---------------------------------------------------------

void EPtrace() {
   if (MySFXModel->Trace ()) MySFXModel->setTrace (0);
   else {
      if (notiz::AktInfo2() == 1)
         MySFXModel->setTrace (1);
      else MySFXModel->setTrace (2);
   }
   if (notiz::AktInfo1() > 0)
      planeein((float)notiz::AktInfo1(),
               ETatrace, 0, notiz::AktInfo2());
} // EPtrace

void EPprotokoll() {
     
  //LCE
  /*
  if (MySFXModel->zLCE_Kern) {
      MySFXModel->zLCE_Kern->Auswertung(Modellzeit ()); 
  }
  */
  //LCE  
   
  if (notiz::AktInfo2() == 0)
     sys_trace(cout);
  else {
     if (notiz::AktInfo2() == 1)
        sys_protokoll(cout);
     else sys_protokoll(clog);
  }
  if ((Modellzeit () < Modellende ()) && (notiz::AktInfo1() > 0)){
    planedelta (notiz::AktInfo1(), ETprotokoll, notiz::AktInfo1(),
                notiz::AktInfo2());
  }
} // EPprotokoll

void EPstartextprozess () {
   double DeltaZeit;
   typProzess *zPr = MySFXModel->findProcess (notiz::AktInfo1 ());
   if (!zPr->isStopped ()) {
     if (zPr->Typ () == typProzess::ANKUNFT) {
       typAnkunftsProzess* zArbPr = (typAnkunftsProzess*) zPr;
       int Menge = zArbPr->ZufMenge ();
       typArbeitsplan *zA = MySFXModel->findWorkSchedule (zPr->Betrifft ());
       zA->Vorgaenge ().First ()->ZielBaustein ()->ArbBestellung (zA->Nummer (), 0, 0, Menge);
       if (Modellzeit () < Modellende ()) {
         DeltaZeit = zArbPr->ZufAbstand ();
         planedelta (DeltaZeit, ETstartextprozess, zPr->Nummer (), Menge);
       }
     }
     else if (zPr->Typ () == typProzess::STOERUNG) {
       typStoerProzess* zStoerPr = (typStoerProzess*) zPr;
       double Dauer = zStoerPr->ZufDauer ();
       if (baustein [zPr->Betrifft ()])
         baustein [zPr->Betrifft ()]->stoerungEinleiten (Dauer * SimTime::SecondsPerMinute ());
       else
         sim_error ("EREIGNIS", "EPstartextprozess",
                  "Baustein fuer Stoerung nicht vorhanden", zPr->Betrifft (),
		  FATAL);
       if (Modellzeit () < Modellende ()) {
         DeltaZeit = zStoerPr->ZufAbstand ();
         planedelta (DeltaZeit, ETstartextprozess, zPr->Nummer (), 0);
       }
     }
   } else {
     zPr->go ();
   }
} // EPstartextprozess

void EPstopextprozess () {
   typAnkunftsProzess *zPr = (typAnkunftsProzess*) MySFXModel->findProcess (notiz::AktInfo1 ());
   if (zPr) zPr->stop ();
} // EPstopextprozess

void EPexplerzeugen () {
  typArbeitsplan *zA = MySFXModel->findWorkSchedule (notiz::AktInfo1 ());
  zA->Vorgaenge ().First ()->ZielBaustein ()->ArbBestellung (zA->Nummer (), 0, 0, notiz::AktInfo2 ());
} // EPdetAnkunft

void EPerzBestellung () {
  baustein [notiz::AktInfo1 ()]->ArbBestellung (notiz::AktInfo2 (), 
                                                0, 0, notiz::AktInfo3 ());
} // EPerzBestellung

void EPloeBestellung () {
  baustein [notiz::AktInfo1 ()]->loescheArbBestellung (notiz::AktInfo2 (), notiz::AktInfo3 ());
} // EPloeBestellung

void EPaaufnehmen () {
  baustein [notiz::AktInfo1 ()]->a_aufnehmen ();
} // EPaaufnehmen

void EPeaufnehmen () {
  baustein [notiz::AktInfo1 ()]->e_aufnehmen ();
} // EPeaufnehmen

void EPeausschl () {
  ((typSenke*) baustein [notiz::AktInfo1 ()])->e_ausschl ();
}

void EPaarbeiten () {
  baustein [notiz::AktInfo1 ()]->a_arbeiten ();
} // EPaarbeiten

void EPearbeiten () {
  baustein [notiz::AktInfo1 ()]->e_arbeiten ();
} // EPearbeiten

void EPakommissionieren () {
  baustein [notiz::AktInfo1 ()]->a_kommissionieren ();
} // EPakommissionieren

void EPekommissionieren () {
  baustein [notiz::AktInfo1 ()]->e_kommissionieren ();
} // EPekommissionieren

void EPameldewarten () {
  baustein [notiz::AktInfo1 ()]->a_meldewarten ();
} // EPaaufnehmen

void EPaabgeben () {
  baustein [notiz::AktInfo1 ()]->a_abgeben ();
} // EPaaufnehmen

void EPeabgeben () {
  baustein [notiz::AktInfo1 ()]->e_abgeben ();
} // EPaaufnehmen

void EPafoerdern () {
  baustein [notiz::AktInfo1 ()]->a_foerdern ();
} // EPafoerdern

void EPefoerdern () {
  baustein [notiz::AktInfo1 ()]->e_foerdern ();
} // EPefoerdern

void EPaheben() {
  baustein [notiz::AktInfo1 ()]->a_heben ();
} // EPaheben

void EPeheben() {
  baustein [notiz::AktInfo1 ()]->e_heben ();
} // EPeheben

void EPasenken () {
  baustein [notiz::AktInfo1 ()]->a_senken ();
} // EPasenken

void EPesenken () {
  baustein [notiz::AktInfo1 ()]->e_senken ();
} // EPesenken

void EPadrehen () {
  baustein [notiz::AktInfo1 ()]->a_drehen ();
} // EPadrehen

void EPedrehen () {
  baustein [notiz::AktInfo1 ()]->e_drehen ();
} // EPedrehen

void EPafahren () {
  ((typVerteilwagen*) baustein [notiz::AktInfo1 ()])->a_fahren ();
} // EPafahren

void EPefahren () {
  ((typVerteilwagen*) baustein [notiz::AktInfo1 ()])->e_fahren ();
} // EPefahren

void EPasperrung () {
  baustein [notiz::AktInfo1 ()]->aSperren ();
}

void EPesperrung () {
  baustein [notiz::AktInfo1 ()]->eSperren ();
}

void EPastoerung () {
  baustein [notiz::AktInfo1 ()]->aStoeren ();
}

void EPestoerung () {
  baustein [notiz::AktInfo1 ()]->eStoeren ();
}

void EPaftsfahren (){
//    ((typFtsWagen *)baustein[notiz::AktInfo1()])->a_ftsfahren();
}

void EPeftsfahren (){
//    ((typFtsWagen *)baustein[notiz::AktInfo1()])->e_ftsfahren();
}

void EPalagern () {
  ((typRegaleinheit*) baustein [notiz::AktInfo1 ()])->a_lagern (notiz::AktInfo2 ());
} // EPalagern

void EPelagern () {
  ((typRegaleinheit*) baustein [notiz::AktInfo1 ()])->e_lagern (notiz::AktInfo2 ());
} // EPelagern

void EPfahrTakt () {
  baustein [notiz::AktInfo1 ()]->fahr_takt ();
} // EPfahrTakt

void EPdrehTakt () {
  baustein [notiz::AktInfo1 ()]->dreh_takt ();
} // EPdrehTakt

void EPaufnTakt () {
  baustein [notiz::AktInfo1 ()]->aufn_takt ();
} // EPaufnTakt

void EPaktivieren (){
  baustein [notiz::AktInfo1 ()]->aktivieren (notiz::AktInfo2 ());
}

void EPwecken (){
  baustein [notiz::AktInfo1 ()]->setZustand (PRGWARTEN);
  planesofort (ETaktivieren, notiz::AktInfo1 (), notiz::AktInfo1 ());
}

void EPaladen (){
  baustein [notiz::AktInfo1 ()]->a_laden ();
}

void EPeladen (){
  baustein [notiz::AktInfo1 ()]->e_laden ();
}

void EPprogramm (char *c) {
  int pnr = notiz::AktInfo2 (), bstnr = notiz::AktInfo1 ();
  if (bstnr > 0) {
    typPrgBaustein* bst = (typPrgBaustein*) baustein [bstnr];
    switch (bst->Basistyp ()) {
      case tQuelle   :
      case tMaschine :
      case tSenke    : if (!bst->hasProgramm ())
                         PrgModul->startProg (bstnr, pnr, c);
                       else 
                         sim_error ("EREIGNIS", "EPprogramm", 
                                    "PrgBaustein hat bereits Programm",
                                    bstnr, FATAL);
                       break;
      default:         sim_error ("EREIGNIS", "EPprogramm",
                                  "Programme nur auf PrgBaustein zulaessig",
                                  pnr, FATAL);
                       break;
    }
  }
  else {
    char pname[50];
    sprintf (pname, "prog_%i", pnr);
    PrgModul->callPrgFunc (pname);
  }
}

SFXViewHandler* EPPoseHandler;
void (*EPPoseFunc)    (SFXViewHandler*);
void (*EPDisposeFunc) (SFXViewHandler*, bool, bool);

void EPinitGrafik () {
  if (EPPoseFunc && EPPoseHandler)
    EPPoseFunc (EPPoseHandler);
  MySFXModel->restoreCycle ();
}

void EPloescheGrafik (){
  if (EPDisposeFunc && EPPoseHandler)
    EPDisposeFunc (EPPoseHandler, true, true);
}

void E_Steuerung () {
  char c;	// Erforderlich fuer C-Schnittstelle
  if (!PrgModul->checkEvent (notiz::AktTyp (), notiz::AktInfo1 (), &c)) {
    if (MySFXModel->Trace ())  
      sys_trace ((MySFXModel->Trace () == 1) ? cout : clog);

    switch (notiz::AktTyp ()) {
      case ETatrace           : EPtrace();           break;
      case ETetrace           : EPtrace();           break;
      case ETprotokoll        : EPprotokoll();       break;
      case ETstartextprozess  : EPstartextprozess(); break;
      case ETstopextprozess   : EPstopextprozess();  break;
      case ETprogramm         : EPprogramm(&c);      break;
      case ETazeitreihe       : break;
      case ETezeitreihe       : break;
      case ETexplerzeugen     : EPexplerzeugen();    break;
      case ETerzBestellung    : EPerzBestellung();   break;
      case ETloeBestellung    : EPloeBestellung();   break;
      case ETaaufnehmen       : EPaaufnehmen();      break;
      case ETeaufnehmen       : EPeaufnehmen();      break;
      case ETameldewarten     : EPameldewarten();    break;
      case ETaabgeben         : EPaabgeben();        break;
      case ETeabgeben         : EPeabgeben();        break;
      case ETafoerdern        : EPafoerdern();       break;
      case ETefoerdern        : EPefoerdern();       break;
      case ETadrehen          : EPadrehen();         break;
      case ETedrehen          : EPedrehen();         break;
      case ETafahren          : EPafahren();         break;
      case ETefahren          : EPefahren();         break;
      case ETasperrung        : EPasperrung();       break;
      case ETesperrung        : EPesperrung();       break;
      case ETastoerung        : EPastoerung();       break;
      case ETestoerung        : EPestoerung();       break;
      case ETaarbeiten        : EPaarbeiten();       break;
      case ETearbeiten        : EPearbeiten();       break;
      case ETakommissionieren : EPakommissionieren();break;
      case ETekommissionieren : EPekommissionieren();break;
      case ETalagern          : EPalagern();         break;
      case ETelagern          : EPelagern();         break;
      case ETaheben           : EPaheben();          break;
      case ETeheben           : EPeheben();          break;
      case ETasenken          : EPasenken();         break;
      case ETesenken          : EPesenken();         break;
      case ETaktivieren       : EPaktivieren();      break;
      case ETwecken           : EPwecken();          break;
      case ETaftsfahren       : EPaftsfahren();      break; /*FTS*/
      case ETeftsfahren       : EPeftsfahren();      break;
      case ETfahrTakt         : EPfahrTakt();        break;
      case ETdrehTakt         : EPdrehTakt();        break;
      case ETaufnTakt         : EPaufnTakt();        break;
      case ETinitGrafik       : EPinitGrafik();      break;
      case ETloescheGrafik    : EPloescheGrafik();   break;
      case ETeausschl         : EPeausschl();	     break;
      case ETaladen	      : EPaladen(); 	     break;
      case ETeladen	      : EPeladen();	     break;
      default                 : sim_error ("EREIGNIS", "E_Steuerung",
                                         "ungueltiges Ereignis",
                                          notiz::AktTyp (), FATAL);
				break;
    } // switch
  }
} // E_Steuerung


