4 class ShippingCompany extends BaseSimulator implements Customer, ContractPartner {
6 * Full name of this company
8 private $companyName = "Namenlose Reederei";
11 * Shorted name of this company
13 private $shortName = "";
16 * Instance of the founder
18 private $founderInstance = null;
21 * Employed people by this company
23 private $employeeList = null;
26 * Headquarter harbor instance
28 private $hqInstance = null;
31 * List of all assigned shipyards
33 private $shipyardList = null;
38 private $ownedShips = null;
41 * Work constracts this company is currently working on
43 private $contractList = null;
50 private function __construct () {
51 // Call parent constructor
52 parent::constructor(__CLASS__);
55 if (((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) && (defined('DEBUG_CONSTRUCT'))) {
56 $this->getDebugInstance()->output(sprintf("[%s:%d] Konstruktor erreicht.<br />\n",
63 $this->setPartDescr("Reederei");
65 // Generate unique ID number
66 $this->createUniqueID();
69 $this->removeSystemArray();
72 // Reederei gruenden (create wegen Namenskonvention)
73 public static function createShippingCompany ($companyName, Harbor $hqInstance) {
75 $companyInstance = new ShippingCompany();
77 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $companyInstance->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> wird gegründet.<br />\n",
84 $companyInstance->setCompanyName($companyName);
87 $companyInstance->createShortName();
90 $companyInstance->setHQInstance($hqInstance);
92 // Werftenliste erstellen
93 $companyInstance->createshipyardList();
95 // Angestellten-Liste erstellen
96 $companyInstance->createEmployeeList();
98 // Auftragsliste erstellen
99 $companyInstance->createContractList();
102 $companyInstance->removeWidth();
103 $companyInstance->removeHeight();
104 $companyInstance->removeLength();
105 $companyInstance->removeDraught();
106 $companyInstance->removePartInstance();
108 // Instanz zurueckgeben
109 return $companyInstance;
112 // Angestellten-Liste erstellen
113 private function createEmployeeList () {
114 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",
117 $this->getCompanyName()
119 $this->employeeList = new FrameworkArrayObject();
122 // Werftenliste erstellen
123 public function createShipyardList () {
124 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erhält eine Werftsliste.<br />\n",
127 $this->getCompanyName()
129 $this->shipyardList = new FrameworkArrayObject();
132 // Auftragsliste erstellen
133 public function createContractList () {
134 if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erhält eine Auftragsliste.<br />\n",
137 $this->getCompanyName()
139 $this->contractList = new FrameworkArrayObject();
142 // Setter-Methode fuer Firmennamen
143 public final function setCompanyName ($companyName) {
144 $this->companyName = (string) $companyName;
147 // Getter-Methode fuer Firmennamen
148 public final function getCompanyName () {
149 return $this->companyName;
152 // Setter-Methode fuer Firmensitz
153 public final function setHQInstance (Harbor $hqInstance) {
154 $this->hqInstance = $hqInstance;
158 private function createShortName () {
159 // Mindestens eine Leerstelle?
160 $dummy = explode(" ", $this->getCompanyName());
161 foreach ($dummy as $part) {
162 $this->shortName .= substr($part, 0, 1);
166 // Reedereien Werften bauen lassen
167 public function createShipyardInHarbor($shipyardName, Harbor $harborInstance) {
168 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",
171 $this->getCompanyName(),
172 $harborInstance->getHarborName(),
176 // Wird im HQ gebaut?
177 if ($this->hqInstance->equals($harborInstance)) {
178 // Die neue Werft wird im HQ gebaut!
179 $this->hqInstance->addNewShipyardNotify($shipyardName, $this);
180 // Die Werft drueber in Kenntnis setzen, welcher Reederei sie angehoert
182 // Ausserhalb des Heimathafens soll eine Werft gebaut werden
183 $harborInstance->addNewShipyardNotify($shipyardName, $this);
187 // Setter fuer Reederei-Gruender
188 public final function setCompanyFounder(CompanyEmployee $founderInstance) {
189 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",
192 $this->getCompanyName(),
193 $founderInstance->getSurname(),
194 $founderInstance->getFamily()
196 $this->founderInstance = $founderInstance;
199 // Getter for founder instance
200 public final function getFounderInstance () {
201 return $this->founderInstance;
204 // Neue(n) Angestellte(n) in Angestellten-Liste aufnehmen
205 public function addNewEmployee (SimulatorPersonell $employeeInstance) {
206 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",
209 $employeeInstance->getSurname(),
210 $employeeInstance->getFamily(),
211 $this->getCompanyName(),
212 $employeeInstance->getPartDescr(),
213 $this->formatCurrency($employeeInstance->getSalary())
215 $this->employeeList->append($employeeInstance);
218 // Neue Werft in Liste aufnehmen
219 public function addNewShipyard (Shipyard $shipyardInstance) {
220 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",
223 $this->getCompanyName(),
224 $shipyardInstance->getShipyardName()
226 $this->shipyardList->append($shipyardInstance);
229 // Neue Mitarbeiter per Zufall einstellen/rekrutieren
230 public function recruitRandomEmployees($amount, SimulatorPersonell $personellInstance) {
231 // Anzahl Mitarbeiter absichern
232 $amount = (int) $amount;
234 // Debug-Meldung ausgeben
235 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",
238 $this->getCompanyName(),
242 // Gesamtanzahl verfuegbarer Erwerbsloser holen
243 $totalUnemployed = $personellInstance->getAllUnemployed();
245 // Existiert die gewuenschte Anzahl freier Arbeiter? (doppelt geht derzeit nicht)
246 if ($totalUnemployed < $amount) {
247 // Reichte nicht aus!
248 throw new ToMuchEmployeesException(array($amount, $personellInstance->getAllUnemployed()), self::EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES);
251 // Get list for all unemployed people
252 $list = $personellInstance->getSpecialPersonellList(false); // Should be cached
254 // Get iterator of the list
255 $iterator = $list->getIterator();
257 // Get the requested amount of personell
258 for ($idx = 0; $idx < $amount; $idx++) {
260 // Is this personl unemployed?
261 while (is_null($employee) || $employee->isEmployed()) {
262 // Generate random number
263 $pos = mt_rand(0, ($totalUnemployed - 1)); // Don't remove the -1 here:
264 // E.g. 100 entries means latest position is 99...
266 // Seek for the position
267 $iterator->seek($pos);
269 // Is the current position valid?
270 if ($iterator->valid()) {
272 $employee = $iterator->current();
274 // Should�normally not happen... :(
275 throw new StructuresOutOfBoundsException($idx, self::EXCEPTION_INDEX_OUT_OF_BOUNDS);
279 // A dummy just for the description and real class
280 $dummy = CompanyEmployee::createCompanyEmployee("", "", "M", 1970, 1, 1, $employee->isMarried(), 0);
282 // Make this person employed and give him some money to work
283 $employee->setEmployed(true);
284 $employee->setPartDescr($dummy->getPartDescr());
285 $employee->setRealClass($dummy->__toString());
286 $employee->increaseSalary((mt_rand(7, 14) * 100)); // Are 700 to 1400 EUR for the begin okay?
289 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",
292 $this->getCompanyName(),
293 $employee->getSurname(),
294 $employee->getFamily()
298 $this->addNewEmployee($employee);
302 $personellInstance->resetCache();
304 // Debug-Meldung ausgeben
305 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",
308 $this->getCompanyName(),
313 // Distribute all personells on all shipyards
314 public function distributeAllPersonellOnShipyards () {
315 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",
318 $this->getCompanyName(),
319 $this->getTotalEmployee(),
320 $this->getTotalShipyards()
323 // Do we have some shipyards?
324 if (is_null($this->shipyardList)) {
325 // No shipyards created
326 throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
329 // Get iterator for shipyards
330 $shipyardIter = $this->shipyardList->getIterator();
332 // Iterate through all employees
333 for ($idx = $this->employeeList->getIterator(); $idx->valid(); $idx->next()) {
334 // Is the shipyard iterator still okay?
335 if (!$shipyardIter->valid()) {
336 // Rewind to first position
337 $shipyardIter->seek(0);
340 // Get Shipyard object
341 $shipyard = $shipyardIter->current();
343 // Is this a Shipyard object?
344 if (is_null($shipyard)) {
346 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
347 } elseif (!is_object($shipyard)) {
348 // Not an object! ;-(
349 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
350 } elseif (!$shipyard->isSameClass("Shipyard")) {
351 // Nope, so throw exception
352 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
355 // Add employee to the shipyard
356 $shipyard->addNewPersonell($idx->current());
358 // Continue to next shipyard
359 $shipyardIter->next();
363 // Getter for total employees
364 public final function getTotalEmployee () {
366 $total = $this->employeeList->count();
369 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",
372 $this->getCompanyName(),
380 // Getter for total shipyards
381 public final function getTotalShipyards () {
382 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",
385 $this->getCompanyName()
388 // Do we have some shipyards?
389 if (is_null($this->shipyardList)) {
390 // No shipyards created
391 throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
395 $total = $this->shipyardList->count();
398 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",
401 $this->getCompanyName(),
409 // Add a ship type (class) to all shipyards
410 public function addShipTypeToAllShipyards ($shipType) {
412 $shipType = (string) $shipType;
414 // Is the class there?
415 if (!class_exists($shipType)) {
417 throw new ClassNotFoundException($shipType, 0);
421 eval(sprintf("\$shipInstance = %s::create%s(\"M/S Dummy\");",
427 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",
430 $this->getCompanyName(),
431 $shipInstance->getPartDescr()
434 // Iterate shipyard list
435 for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
436 // Get current element
437 $shipyard = $idx->current();
439 // Is this a shipyard?
440 if (is_null($shipyard)) {
442 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
443 } elseif (!is_object($shipyard)) {
444 // Not an object! ;-(
445 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
446 } elseif (!$shipyard->isSameClass("Shipyard")) {
447 // Class is not a shipyard
448 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
451 // Add the new ship type to the shipyard
452 $shipyard->addNewConstructableShipType($shipType);
456 // Validate the requested ship type with the company if they can construct it
457 public function validateWorksContractShipType (SignableContract $contractInstance) {
458 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",
461 $this->getCompanyName(),
462 $contractInstance->getShipName()
465 // First get the ship type
466 $shipInstance = $contractInstance->getShipInstance();
468 // Ist there a ship instance?
469 if (is_null($shipInstance)) {
470 // Opps! Empty entry?
471 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
472 } elseif (!is_object($shipInstance)) {
473 // Not an object! ;-(
474 throw new NoObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
477 // Get it's real class name
478 $shipType = $shipInstance->__toString();
481 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",
484 $this->getCompanyName(),
485 $contractInstance->getShipName(),
486 $shipInstance->getPartDescr()
489 // Now check if the ship type is in any list and return the result
490 return ($this->isShipTypeConstructable($shipType));
493 // Is the ship type constructable?
494 public function isShipTypeConstructable ($shipType) {
495 // The type must be a string!
496 $shipType = (string) $shipType;
499 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",
502 $this->getCompanyName(),
506 // First everthing is failed...
509 // Iterate through all shipyards
510 for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
511 // Get current Shipyard instance
512 $shipyard = $idx->current();
514 // Is this a shipyard?
515 if (is_null($shipyard)) {
517 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
518 } elseif (!is_object($shipyard)) {
519 // Not an object! ;-(
520 throw new NoObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
521 } elseif (!$shipyard->isSameClass("Shipyard")) {
522 // Class is not a shipyard
523 throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
526 // Validate if the first found shipyard can construct the requested type
527 $result = $shipyard->isShipTypeConstructable($shipType);
529 //�Does this shipyard construct the requested ship type?
530 if ($result) break; // Then abort the search!
534 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",
537 $this->getCompanyName(),
545 // As a customer the shipping company can add new contracts
546 public function addNewWorksContract (SignableContract $contractInstance) {
547 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",
550 $this->getCompanyName(),
551 $contractInstance->getShipInstance()->getPartDescr(),
552 $contractInstance->getShipInstance()->getShipName()
554 $this->contractList->append($contractInstance);
557 // As a customer the shippng company can withdraw from a contract
558 public function withdrawFromContract (SignableContract $contractInstance) {
559 ApplicationEntryPoint::app_die("WITHDRAW:<pre>".print_r($contractInstance, true)."</pre>");
562 // Get latest added contract instance
563 public final function getLastContractInstance () {
565 $iter = $this->contractList->getIterator();
567 // Get latest entry (total - 1)
568 $iter->seek($iter->count() - 1);
571 return $iter->current();
574 // Sign a contract with an other party which must also implement Customer
575 public function signContract (SignableContract $contractInstance, ContractPartner $partnerInstance) {
576 // Check wether the other party is our contract partner
577 if (!$partnerInstance->isContractPartner($contractInstance)) {
578 // Invalid contract partner!
579 throw new InvalidContractPartnerException($partnerInstance, self::EXCEPTION_CONTRACT_PARTNER_INVALID);
582 // Determine if company "signs" own contract (must be done) or with an other party
583 if ($this->equals($partnerInstance)) {
585 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",
588 $this->getCompanyName(),
589 $contractInstance->getShipInstance()->getPartDescr(),
590 $contractInstance->getShipInstance()->getShipName()
593 // Other external company
594 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",
597 $this->getCompanyName(),
598 $contractInstance->getShipInstance()->getPartDescr(),
599 $contractInstance->getShipInstance()->getShipName(),
600 $partnerInstance->getCompanyName()
605 $contractInstance->signContract($this, $partnerInstance);
608 * @todo Maybe do something more here...
612 // Is this the right contract partner?
613 public function isContractPartner (SignableContract $contractInstance) {
614 // Get contract partner instance and compare it with $this contract partner
615 return ($this->equals($contractInstance->getContractPartner()));
618 // Setter for merchant instance
619 public final function setMerchantInstance (Merchant $merchantInstance) {
621 $contractInstance = $this->getLastContractInstance();
623 if (is_null($contractInstance)) {
624 // Opps! Empty contract instance?
625 throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
626 } elseif (!is_object($contractInstance)) {
627 // Not an object! ;-(
628 throw new NoObjectException($contractInstance, self::EXCEPTION_IS_NO_OBJECT);
629 } elseif (!$contractInstance->isSameClass('WorksContract')) {
631 throw new ClassMismatchException(array($contractInstance->__toString(), "WorksContract"), self::EXCEPTION_CLASSES_NOT_MATCHING);
634 // Set the merchant in the contract (for getting prices)
635 $contractInstance->setMerchantInstance($merchantInstance);
641 public function saveObjectToDatabase () {
642 $this->getDebugInstance()->output(sprintf("[%s:] Stub <strong>%s</strong> erreicht.",
649 * Limits this object with an ObjectLimits instance
651 public function limitObject (ObjectLimits $limitInstance) {
652 ApplicationEntryPoint::app_die("".__METHOD__." reached! Stub!");