4 class ShippingCompany extends BaseSimulator implements Customer, ContractPartner {
6 private $companyName = "Namenlose Reederei";
9 private $shortName = "";
12 private $founderInstance = null;
15 private $employeeList = null;
18 private $hqInstance = null;
21 private $shipyardList = null;
23 // Der Reederei gehoerenden Schiffe
24 private $ownedShips = null;
26 // Bauauftraege als Kunde
27 private $contractList = null;
30 private function __construct () {
31 // Eltern-Konstruktor aufrufen
32 parent::constructor(__CLASS__);
35 if (((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) && (defined('DEBUG_CONSTRUCT'))) {
36 $this->getDebugInstance()->output(sprintf("[%s:%d] Konstruktor erreicht.<br />\n",
42 // Beschreibung setzen
43 $this->setPartDescr("Reederei");
46 $this->createUniqueID();
49 $this->removeSystemArray();
52 // Reederei gruenden (create wegen Namenskonvention)
53 public static function createShippingCompany ($companyName, Harbor $hqInstance) {
55 $companyInstance = new ShippingCompany();
57 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $companyInstance->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> wird gegründet.<br />\n",
64 $companyInstance->setCompanyName($companyName);
67 $companyInstance->createShortName();
70 $companyInstance->setHQInstance($hqInstance);
72 // Werftenliste erstellen
73 $companyInstance->createshipyardList();
75 // Angestellten-Liste erstellen
76 $companyInstance->createEmployeeList();
78 // Auftragsliste erstellen
79 $companyInstance->createContractList();
82 $companyInstance->removeWidth();
83 $companyInstance->removeHeight();
84 $companyInstance->removeLength();
85 $companyInstance->removeDraught();
86 $companyInstance->removePartInstance();
88 // Instanz zurueckgeben
89 return $companyInstance;
92 // Angestellten-Liste erstellen
93 private function createEmployeeList () {
94 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erhält eine Angestelltenliste.<br />\n",
97 $this->getCompanyName()
99 $this->employeeList = new FrameworkArrayObject();
102 // Werftenliste erstellen
103 public function createShipyardList () {
104 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erhält eine Werftsliste.<br />\n",
107 $this->getCompanyName()
109 $this->shipyardList = new FrameworkArrayObject();
112 // Auftragsliste erstellen
113 public function createContractList () {
114 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erhält eine Auftragsliste.<br />\n",
117 $this->getCompanyName()
119 $this->contractList = new FrameworkArrayObject();
122 // Setter-Methode fuer Firmennamen
123 public function setCompanyName ($companyName) {
124 $this->companyName = (string) $companyName;
127 // Getter-Methode fuer Firmennamen
128 public function getCompanyName () {
129 return $this->companyName;
132 // Setter-Methode fuer Firmensitz
133 public function setHQInstance (Harbor $hqInstance) {
134 $this->hqInstance = $hqInstance;
138 private function createShortName () {
139 // Mindestens eine Leerstelle?
140 $dummy = explode(" ", $this->getCompanyName());
141 foreach ($dummy as $part) {
142 $this->shortName .= substr($part, 0, 1);
146 // Reedereien Werften bauen lassen
147 public function createShipyardInHarbor($shipyardName, Harbor $harborInstance) {
148 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> baut im <strong>%s</strong> eine Werft <strong>%s</strong>.<br />\n",
151 $this->getCompanyName(),
152 $harborInstance->getHarborName(),
156 // Wird im HQ gebaut?
157 if ($this->hqInstance->equals($harborInstance)) {
158 // Die neue Werft wird im HQ gebaut!
159 $this->hqInstance->addNewShipyardNotify($shipyardName, $this);
160 // Die Werft drueber in Kenntnis setzen, welcher Reederei sie angehoert
162 // Ausserhalb des Heimathafens soll eine Werft gebaut werden
163 $harborInstance->addNewShipyardNotify($shipyardName, $this);
167 // Setter fuer Reederei-Gruender
168 public function setCompanyFounder(CompanyEmployee $founderInstance) {
169 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> ist von <strong>%s %s</strong> gegründet worden.<br />\n",
172 $this->getCompanyName(),
173 $founderInstance->getSurname(),
174 $founderInstance->getFamily()
176 $this->founderInstance = $founderInstance;
179 // Getter for founder instance
180 public function getFounderInstance () {
181 return $this->founderInstance;
184 // Neue(n) Angestellte(n) in Angestellten-Liste aufnehmen
185 public function addNewEmployee (SimulatorPersonell $employeeInstance) {
186 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] <strong>%s %s</strong> tritt der Reederei <strong>%s</strong> als <strong>%s</strong> bei und erhält ein Gehalt von <strong>%s</strong>.<br />\n",
189 $employeeInstance->getSurname(),
190 $employeeInstance->getFamily(),
191 $this->getCompanyName(),
192 $employeeInstance->getPartDescr(),
193 $this->formatCurrency($employeeInstance->getSalary())
195 $this->employeeList->append($employeeInstance);
198 // Neue Werft in Liste aufnehmen
199 public function addNewShipyard (Shipyard $shipyardInstance) {
200 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erhält die Werft <strong>%s</strong> hinzugefügt.<br />\n",
203 $this->getCompanyName(),
204 $shipyardInstance->getShipyardName()
206 $this->shipyardList->append($shipyardInstance);
209 // Neue Mitarbeiter per Zufall einstellen/rekrutieren
210 public function recruitRandomEmployees($amount, SimulatorPersonell $personellInstance) {
211 // Anzahl Mitarbeiter absichern
212 $amount = (int) $amount;
214 // Debug-Meldung ausgeben
215 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> stellt per Zufall <strong>%d</strong> neue Mitarbeiter ein.<br />\n",
218 $this->getCompanyName(),
222 // Gesamtanzahl verfuegbarer Erwerbsloser holen
223 $totalUnemployed = $personellInstance->getAllUnemployed();
225 // Existiert die gewuenschte Anzahl freier Arbeiter? (doppelt geht derzeit nicht)
226 if ($totalUnemployed < $amount) {
227 // Reichte nicht aus!
228 throw new ToMuchEmployeesException(array($amount, $personellInstance->getAllUnemployed()), self::EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES);
231 // Get list for all unemployed people
232 $list = $personellInstance->getSpecialPersonellList(false); // Should be cached
234 // Get iterator of the list
235 $iterator = $list->getIterator();
237 // Get the requested amount of personell
238 for ($idx = 0; $idx < $amount; $idx++) {
240 // Is this personl unemployed?
241 while (is_null($employee) || $employee->isEmployed()) {
242 // Generate random number
243 $pos = mt_rand(0, ($totalUnemployed - 1)); // Don't remove the -1 here:
244 // E.g. 100 entries means latest position is 99...
246 // Seek for the position
247 $iterator->seek($pos);
249 // Is the current position valid?
250 if ($iterator->valid()) {
252 $employee = $iterator->current();
254 // Should normally not happen... :(
255 throw new StructuresOutOfBoundsException($idx, self::EXCEPTION_INDEX_OUT_OF_BOUNDS);
259 // A dummy just for the description and real class
260 $dummy = CompanyEmployee::createCompanyEmployee("", "", "M", 1970, 1, 1, $employee->isMarried(), 0);
262 // Make this person employed and give him some money to work
263 $employee->setEmployed(true);
264 $employee->setPartDescr($dummy->getPartDescr());
265 $employee->setRealClass($dummy->__toString());
266 $employee->increaseSalary((mt_rand(7, 14) * 100)); // Are 700 to 1400 EUR for the begin okay?
269 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> stellt den/die Angestellte(n) <strong>%s %s</strong> ein.<br />\n",
272 $this->getCompanyName(),
273 $employee->getSurname(),
274 $employee->getFamily()
278 $this->addNewEmployee($employee);
282 $personellInstance->resetCache();
284 // Debug-Meldung ausgeben
285 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat per Zufall <strong>%d</strong> neue Mitarbeiter eingestellt.<br />\n",
288 $this->getCompanyName(),
293 // Distribute all personells on all shipyards
294 public function distributeAllPersonellOnShipyards () {
295 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> verteilt alle ihre <strong>%d</strong> Mitarbeiter auf alle <strong>%d</strong> Werft(en).<br />\n",
298 $this->getCompanyName(),
299 $this->getTotalEmployee(),
300 $this->getTotalShipyards()
303 // Do we have some shipyards?
304 if (is_null($this->shipyardList)) {
305 // No shipyards created
306 throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
309 // Get iterator for shipyards
310 $shipyardIter = $this->shipyardList->getIterator();
312 // Iterate through all employees
313 for ($idx = $this->employeeList->getIterator(); $idx->valid(); $idx->next()) {
314 // Is the shipyard iterator still okay?
315 if (!$shipyardIter->valid()) {
316 // Rewind to first position
317 $shipyardIter->seek(0);
320 // Get Shipyard object
321 $shipyard = $shipyardIter->current();
323 // Is this a Shipyard object?
324 if (is_null($shipyard)) {
326 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
327 } elseif (!is_object($shipyard)) {
328 // Not an object! ;-(
329 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
330 } elseif (!$shipyard->isClass("Shipyard")) {
331 // Nope, so throw exception
332 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
335 // Add employee to the shipyard
336 $shipyard->addNewPersonell($idx->current());
338 // Continue to next shipyard
339 $shipyardIter->next();
343 // Getter for total employees
344 public function getTotalEmployee () {
346 $total = $this->employeeList->count();
349 if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat <strong>%d</strong> Mitarbeiter.<br />\n",
352 $this->getCompanyName(),
360 // Getter for total shipyards
361 public function getTotalShipyards () {
362 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Für die Reederei <strong>%s</strong> werden die Anzahl der Werften in allen Häfen ermittelt.<br />\n",
365 $this->getCompanyName()
368 // Do we have some shipyards?
369 if (is_null($this->shipyardList)) {
370 // No shipyards created
371 throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
375 $total = $this->shipyardList->count();
378 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat <strong>%d</strong> Werft(en).<br />\n",
381 $this->getCompanyName(),
389 // Add a ship type (class) to all shipyards
390 public function addShipTypeToAllShipyards ($shipType) {
392 $shipType = (string) $shipType;
394 // Is the class there?
395 if (!class_exists($shipType)) {
397 throw new ClassNotFoundException($shipType, 0);
401 eval(sprintf("\$shipInstance = %s::create%s(\"M/S Dummy\");",
407 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> baut in allen Werften bald Schiffe vom Typ <strong>%s</strong>.<br />\n",
410 $this->getCompanyName(),
411 $shipInstance->getPartDescr()
414 // Iterate shipyard list
415 for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
416 // Get current element
417 $shipyard = $idx->current();
419 // Is this a shipyard?
420 if (is_null($shipyard)) {
422 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
423 } elseif (!is_object($shipyard)) {
424 // Not an object! ;-(
425 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
426 } elseif (!$shipyard->isClass("Shipyard")) {
427 // Class is not a shipyard
428 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
431 // Add the new ship type to the shipyard
432 $shipyard->addNewConstructableShipType($shipType);
436 // Validate the requested ship type with the company if they can construct it
437 public function validateWorksContractShipType (WorksContract $contractInstance) {
438 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> prüft den Bauauftrag der <strong>%s</strong>.<br />\n",
441 $this->getCompanyName(),
442 $contractInstance->getShipName()
445 // First get the ship type
446 $shipInstance = $contractInstance->getShipInstance();
448 // Ist there a ship instance?
449 if (is_null($shipInstance)) {
450 // Opps! Empty entry?
451 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
452 } elseif (!is_object($shipInstance)) {
453 // Not an object! ;-(
454 throw new NoObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
457 // Get it's real class name
458 $shipType = $shipInstance->__toString();
461 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> prüft, ob die <strong>%s</strong> (Typ:<strong>%s</strong>) gebaut werden kann.<br />\n",
464 $this->getCompanyName(),
465 $contractInstance->getShipName(),
466 $shipInstance->getPartDescr()
469 // Now check if the ship type is in any list and return the result
470 return ($this->isShipTypeConstructable($shipType));
473 // Is the ship type constructable?
474 public function isShipTypeConstructable ($shipType) {
475 // The type must be a string!
476 $shipType = (string) $shipType;
479 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> fragt alle Werften ab, ob diese Schiffe vom Typ <strong>%s</strong> bauen können.<br />\n",
482 $this->getCompanyName(),
486 // First everthing is failed...
489 // Iterate through all shipyards
490 for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
491 // Get current Shipyard instance
492 $shipyard = $idx->current();
494 // Is this a shipyard?
495 if (is_null($shipyard)) {
497 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
498 } elseif (!is_object($shipyard)) {
499 // Not an object! ;-(
500 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
501 } elseif (!$shipyard->isClass("Shipyard")) {
502 // Class is not a shipyard
503 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
506 // Validate if the first found shipyard can construct the requested type
507 $result = $shipyard->isShipTypeConstructable($shipType);
509 // Does this shipyard construct the requested ship type?
510 if ($result) break; // Then abort the search!
514 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat die Suche nach einer Werft beendet, die Schiffe vom Typ <strong>%s</strong> bauen kann.<br />\n",
517 $this->getCompanyName(),
525 // As a customer the shipping company can add new contracts
526 public function addNewWorksContract (WorksContract $contractInstance) {
527 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erstellt einen Bauauftrag für ein <strong>%s</strong> mit dem Namen <strong>%s</strong>.<br />\n",
530 $this->getCompanyName(),
531 $contractInstance->getShipInstance()->getPartDescr(),
532 $contractInstance->getShipInstance()->getShipName()
534 $this->contractList->append($contractInstance);
537 // As a customer the shippng company can withdraw from a contract
538 public function withdrawFromContract (WorksContract $contractInstance) {
539 ApplicationEntryPoint::app_die("WITHDRAW:<pre>".print_r($contractInstance, true)."</pre>");
542 // Get latest added contract instance
543 public function getLastContractInstance () {
545 $iter = $this->contractList->getIterator();
547 // Get latest entry (total - 1)
548 $iter->seek($iter->count() - 1);
551 return $iter->current();
554 // Sign a contract with an other party which must also implement Customer
555 public function signContract (WorksContract $contractInstance, ContractPartner $partnerInstance) {
556 if (!$partnerInstance->isContractPartner($contractInstance)) {
557 // Invalid contract partner!
558 throw new InvalidContractPartnerException($partnerInstance, self::EXCEPTION_CONTRACT_PARTNER_INVALID);
561 // Determine if company "signs" own contract (must be done) or with an other party
562 if ($this->equals($partnerInstance)) {
564 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erteilt an sich selbst einen Bauauftrag für das <strong>%s</strong> "<strong>%s</strong>".<br />\n",
567 $this->getCompanyName(),
568 $contractInstance->getShipInstance()->getPartDescr(),
569 $contractInstance->getShipInstance()->getShipName()
572 // Other external company
573 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> unterzeichnet einen Bauauftrag für das <strong>%s</strong> "<strong>%s</strong>" mit der <strong>%s</strong>.<br />\n",
576 $this->getCompanyName(),
577 $contractInstance->getShipInstance()->getPartDescr(),
578 $contractInstance->getShipInstance()->getShipName(),
579 $partnerInstance->getCompanyName()
584 $contractInstance->signContract($this, $partnerInstance);
587 * @todo Maybe do something more here...
591 // Is this the right contract partner?
592 public function isContractPartner (WorksContract $contractInstance) {
593 // Get contract partner instance and compare it with $this contract partner
594 return ($this->equals($contractInstance->getContractPartner()));
597 // Setter for merchant instance
598 public function setMerchantInstance (Merchant $merchantInstance) {
600 $contractInstance = $this->getLastContractInstance();
602 if (is_null($contractInstance)) {
603 // Opps! Empty contract instance?
604 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
605 } elseif (!is_object($contractInstance)) {
606 // Not an object! ;-(
607 throw new NoObjectException($contractInstance, self::EXCEPTION_IS_NO_OBJECT);
608 } elseif (!$contractInstance->isClass('WorksContract')) {
610 throw new ClassMismatchException(array($contractInstance->__toString(), "WorksContract"), self::EXCEPTION_CLASSES_NOT_MATCHING);
613 // Set the merchant in the contract (for getting prices)
614 $contractInstance->setMerchantInstance($merchantInstance);
620 public function saveObjectToDatabase () {
621 $this->getDebugInstance()->output(sprintf("[%s:] Stub <strong>%s</strong> erreicht.",
628 * Limits this object with an ObjectLimits instance
630 public function limitObject (ObjectLimits $limitInstance) {
631 ApplicationEntryPoint::app_die("".__METHOD__." reached! Stub!");