// $Source: /usr/local/SimSoft/Sfx3D/src/gsl/senke.cpp,v $
// $Revision: 1.2 $
// $Author: baum $
// $Date: 2001/11/29 15:18:10 $
//
// 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: senke.cpp,v $
// Revision 1.2  2001/11/29 15:18:10  baum
// -Realzeitsteuerung eingebaut
// -Handsteuerung eingebaut
//

#define _SENKE_CPP
#include "modell.h"
#include "senke.h"

#include "sfx.h"
#include "transp.h"
#include "baustein.h"
#include "route.h"
#include "regalver.h"
#include "ereignis.h"
#include "programm.h"
#include "arbplan.h"
#include "realzeit.h"

//-----------------------------------------------------
//   Klasse typSenke
//-----------------------------------------------------                      

typSenke::typSenke (unsigned n, unsigned b)
 : typPrgBaustein (n, b),
   ObjBetreuer  (NULL) {
  ObjAvis = new typAvis ();
}

typSenke::~typSenke ()
 { }

// fuer RZS: e_ausschl hat den Sinn, dass die Senke keine weitere Palette
// aufnehmen kann, solange sie nicht tatsaechlich frei gemacht wurde.
void typSenke::e_ausschl () {
  decBelegung ();
  ObjTransportEinheit->AktPlatz ()->setTransportEinheit (NULL);
  delete ObjTransportEinheit;
  ObjTransportEinheit = NULL;
  setZustand (RUHE);
  planesofort (ETaktivieren, ObjNummer, ObjNummer);
  aktiviereEingaenge ();
}

/*virtual*/ void typSenke::a_meldewarten () {
  ObjAvis->decDirIstAnzahl ();
  ObjTransportEinheit->TransportRoute ()->stopBDE (ObjTransportEinheit);

  if (ObjBetreuer)
    ObjBetreuer->Anforderung_naechste_TE (this);

  setZustand (ABGEBEN);
  planesofort (ETeausschl, ObjNummer, 0);
  if (MySFXModel->RealTime ())   RzsSenden (ObjNummer, ETausschl, 1);
}

/*virtual*/ bool typSenke::hasKapazitaet (typTransportEinheit*) const {
  return (ObjBelegung + ObjBuchung) < ObjKapazitaet;
}

/*virtual*/typBaustein* typSenke::setZielBaustein (typTransportEinheit *zTE) {
  typBaustein* ziel;

  if (ObjBetreuer && !(ObjAvis->isDirAvisOk ()))
    ziel = ObjBetreuer->setZielBaustein (zTE);
  else {
    ziel = this;
    ObjAvis->decIndIstAnzahl ();
    ObjAvis->incDirIstAnzahl ();
    (zTE->Baustein ())->Avis ()->decDirIstAnzahl ();
  }
  return ziel;
}

/*virtual*/ typPlatz* typSenke::waehlePlatz (typTransportEinheit* zTE) {
  typPlatz* p (ObjPalPlaetze[0]);
  if (!p->isVerfuegbar ())  
    return (p->Buchung () == zTE) ? p : (typPlatz*) NULL;
  p->setBuchung (zTE);
  ObjBuchung++;
  return p;
}

/*virtual*/ Vec3D typSenke::UebernahmePos (const typBaustein&) const {
  return (ObjPalPlaetze [0]->Position ());
}

/*virtual*/ Vec3D typSenke::UebergabePos (const typBaustein&) const {
  return (ObjPalPlaetze [0]->Position ());
}

/*virtual*/ typRegalverwalter* typSenke::setBetreuer (typRegalverwalter* newBetreuer) {
  return (ObjBetreuer = newBetreuer);
}

/*virtual*/ void typSenke::individuellAktivieren (typBaustein* vonWem) {
  if (!((ObjZustand == RUHE) || ((ObjZustand == WARTEDP) && (ObjZielBaustein == vonWem))
        || (ObjZustand == PRGWARTEN)))
    return;

  if (ObjProgramm)
    if (!PrgModul->continueUserProg (ObjProgramm)) {
      ObjProgramm = NULL;
      if (MySFXModel->PrgDebug ()) dprintf ("Programm geloescht auf Bst = %d\n", ObjNummer);
    }
    else return;

  if (ObjBelegung)  return;
  typMeldung* zM = findeAusfuehrbareMeldung ();
  if (zM) {
    ObjTransportEinheit = zM->TransportEinheit ();
    ObjZielBaustein = zM->VonBaustein ();
    wartenaufnehmen (ObjTransportEinheit, ObjZielBaustein);
  }
}

typMeldung* typSenke::findeAusfuehrbareMeldung () {
  typTransportEinheit* zBuch = ObjPalPlaetze [0]->Buchung ();
  for (LCursor<typMeldung> c (ObjMeldungen); c; c++) {
    typTransportEinheit* zTE = c ()->TransportEinheit ();
    if (!zBuch || (zTE == zBuch)) {
      if (!zBuch)  zTE->setZielPlatz (waehlePlatz (zTE));
      return &(ObjMeldungen.prepend (*(ObjMeldungen.remove (c))));
    }
  }
  return NULL;
}

/*virtual*/ void typSenke::wartenaufnehmen (typTransportEinheit* zTE, typBaustein* vonWem) {
  if (vonWem->isUebergabeBereit (zTE, this)) {
    setZustand (AKTIVIERT);
    planesofort (ETprogramm, ObjNummer, zTE->Vorgang ()->ProgNr ());
  }
  else {
    vonWem->UebergabeVorbereiten (zTE);
    setZustand (WARTEDP);
  }
}

// typSenke
