--- /dev/null
+<?php
+/**
+ * A shipping company may be founded with this class
+ *
+ * @author Roland Haeder <webmaster@shipsimu.org>
+ * @version 0.0.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 Ship-Simu Developer Team
+ * @license GNU GPL 3.0 or any newer version
+ * @link http://www.shipsimu.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+class ShippingCompany extends BaseSimulator implements Customer, ContractPartner {
+ /**
+ * Full name of this company
+ */
+ private $companyName = "Namenlose Reederei";
+
+ /**
+ * Shorted name of this company
+ */
+ private $shortName = "";
+
+ /**
+ * Instance of the founder
+ */
+ private $founderInstance = null;
+
+ /**
+ * Headquarter harbor instance
+ */
+ private $hqInstance = null;
+
+ /**
+ * Employed people by this company
+ */
+ private $employeeList = null;
+
+ /**
+ * List of all assigned shipyards
+ */
+ private $shipyardList = null;
+
+ /**
+ * List of owned ships
+ */
+ private $ownedShips = null;
+
+ /**
+ * Work constracts this company is currently working on
+ */
+ private $contractList = null;
+
+ // Exception constants
+ const EXCEPTION_USER_OWNS_NO_COMPANY = 0x200;
+
+ /**
+ * Protected constructor
+ *
+ * @return void
+ */
+ protected function __construct () {
+ // Call parent constructor
+ parent::__construct(__CLASS__);
+ }
+
+ /**
+ * Creates an instance of this company class or throws an exception if the
+ * given user owns no company.
+ *
+ * @param $userInstance A user class
+ * @return $companyInstance Prepared company instance
+ * @todo Add functionality if user participates in a company
+ */
+ public static final function createShippingCompany (ManageableAccount $userInstance) {
+ // Get new instance
+ $companyInstance = new ShippingCompany();
+
+ // Does the given user owns a company?
+ if ($companyInstance->ifUserParticipatesInCompany($userInstance)) {
+ // Then do some nasty caching here but don't throw an exception
+ // because then you will hurt our web helpers... :/
+ $companyInstance->partialStub("Don't throw exceptions here.");
+ } // END - if
+
+ // Init all lists
+ $companyInstance->initCompanyLists();
+
+ // Return instance
+ return $companyInstance;
+ }
+
+ /**
+ * Checks wether the given user participates in a company
+ *
+ * @param $userInstance An instance of a user class
+ * @return $participates Wether the user participates at lease in one company
+ */
+ protected function ifUserParticipatesInCompany (ManageableAccount $userInstance) {
+ // By default no user owns any company... ;)
+ $participates = false;
+
+ // Get a company database wrapper class
+ $wrapperInstance = ObjectFactory::createObjectByConfiguredName('company_db_wrapper_class', array($this));
+
+ // Ask the wrapper if this user participates
+ $participates = $wrapperInstance->ifUserParticipatesInCompany($userInstance);
+
+ // Get the result instance
+ $resultInstance = $wrapperInstance->getResultInstance();
+
+ // Caches the result instance here, if set (we don't the wrapper anymore!)
+ if ($resultInstance instanceof SearchableResult) {
+ // Set the result instance
+ $this->setResultInstance($resultInstance);
+ } // END - if
+
+ // Return result
+ return $participates;
+ }
+
+ /**
+ * Checks wether the current user in registry is the company founder
+ *
+ * @return $isFounder Wether the current user is the company founder
+ * @todo Check if user is company founder
+ */
+ public function ifUserIsFounder () {
+ // Default is not the founder
+ $isFounder = false;
+
+ // Get result instance
+ $resultInstance = $this->getResultInstance();
+
+ // Is it set?
+ if ($resultInstance instanceof SearchableResult) {
+ // Result found so analyse it
+ $this->partialStub("Check if user is company founder.");
+ } // END - if
+
+ // Return result
+ return $isFounder;
+ }
+
+ /**
+ * Checks wether the current user in registry is the company owner
+ *
+ * @return $isOwner Wether the current user is the company owner
+ * @todo Check if user is company owner
+ */
+ public function ifUserIsOwner () {
+ // Default is not the owner
+ $isOwner = false;
+
+ // Get result instance
+ $resultInstance = $this->getResultInstance();
+
+ // Is it set?
+ if ($resultInstance instanceof SearchableResult) {
+ // Result found so analyse it
+ $this->partialStub("Check if user is company owner.");
+ } // END - if
+
+ // Return result
+ return $isOwner;
+ }
+
+ /**
+ * Checks wether the current user in registry is an employee in this company
+ *
+ * @return $isOwner Wether the current user is an employee in this company
+ */
+ public function ifUserIsEmployee () {
+ // Default is no employee
+ $isEmployee = false;
+
+ // Get result instance
+ $resultInstance = $this->getResultInstance();
+
+ // Is it set?
+ if ($resultInstance instanceof SearchableResult) {
+ // Result found so he is employee
+ $isEmployee = true;
+ } // END - if
+
+ // Return result
+ return $isEmployee;
+ }
+
+ //------------------------------------------------------------------------------\
+ // Below here is very old code which needs to be translated and changed heavily |
+ //------------------------------------------------------------------------------/
+
+ /**
+ * Intialize all lists
+ *
+ * @return void
+ * @todo Maybe we don't need these big lists anymore?! So we can deprecate/remove it
+ */
+ protected function initCompanyLists () {
+ // Employees
+ $this->employeeList = new FrameworkArrayObject("FakedEmployeeList");
+
+ // Ship yards
+ $this->shipyardList = new FrameworkArrayObject("FakedShipyardList");
+
+ // Contracts
+ $this->contractList = new FrameworkArrayObject("FakedContractList");
+ }
+
+ // Setter-Methode fuer Firmennamen
+ public final function setCompanyName ($companyName) {
+ $this->companyName = (string) $companyName;
+ }
+
+ // Getter-Methode fuer Firmennamen
+ public final function getCompanyName () {
+ return $this->companyName;
+ }
+
+ // Setter-Methode fuer Firmensitz
+ public final function setHQInstance (Harbor $hqInstance) {
+ $this->hqInstance = $hqInstance;
+ }
+
+ // Kuerzel setzen
+ private function initShortName () {
+ // Mindestens eine Leerstelle?
+ $dummy = explode(" ", $this->getCompanyName());
+ foreach ($dummy as $part) {
+ $this->shortName .= substr($part, 0, 1);
+ } // END - if
+ }
+
+ // Reedereien Werften bauen lassen
+ public function createShipyardInHarbor($shipyardName, Harbor $harborInstance) {
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> baut im <strong>%s</strong> eine Werft <strong>%s</strong>.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $harborInstance->getHarborName(),
+ $shipyardName
+ ));
+
+ // Wird im HQ gebaut?
+ if ($this->hqInstance->equals($harborInstance)) {
+ // Die neue Werft wird im HQ gebaut!
+ $this->hqInstance->addNewShipyardNotify($shipyardName, $this);
+ // Die Werft drueber in Kenntnis setzen, welcher Reederei sie angehoert
+ } else {
+ // Ausserhalb des Heimathafens soll eine Werft gebaut werden
+ $harborInstance->addNewShipyardNotify($shipyardName, $this);
+ }
+ }
+
+ // Setter fuer Reederei-Gruender
+ public final function setCompanyFounder(CompanyEmployee $founderInstance) {
+ $this->founderInstance = $founderInstance;
+ }
+
+ // Getter for founder instance
+ public final function getFounderInstance () {
+ return $this->founderInstance;
+ }
+
+ // Neue(n) Angestellte(n) in Angestellten-Liste aufnehmen
+ public function addNewEmployee (SimulatorPersonell $employeeInstance) {
+ $this->employeeList->append($employeeInstance);
+ }
+
+ // Neue Werft in Liste aufnehmen
+ public function addNewShipyard (Shipyard $shipyardInstance) {
+ $this->shipyardList->append($shipyardInstance);
+ }
+
+ // Neue Mitarbeiter per Zufall einstellen/rekrutieren
+ public function recruitRandomEmployees($amount, SimulatorPersonell $personellInstance) {
+ // Anzahl Mitarbeiter absichern
+ $amount = (int) $amount;
+
+ // Debug-Meldung ausgeben
+ if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> stellt per Zufall <strong>%d</strong> neue Mitarbeiter ein.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $amount
+ ));
+
+ // Gesamtanzahl verfuegbarer Erwerbsloser holen
+ $totalUnemployed = $personellInstance->getAllUnemployed();
+
+ // Existiert die gewuenschte Anzahl freier Arbeiter? (doppelt geht derzeit nicht)
+ if ($totalUnemployed < $amount) {
+ // Reichte nicht aus!
+ throw new ToMuchEmployeesException(array($amount, $personellInstance->getAllUnemployed()), self::EXCEPTION_NOT_ENOUGTH_UNEMPLOYEES);
+ } // END - if
+
+ // Get list for all unemployed people
+ $list = $personellInstance->getSpecialPersonellList(false); // Should be cached
+
+ // Get iterator of the list
+ $iterator = $list->getIterator();
+
+ // Get the requested amount of personell
+ for ($idx = 0; $idx < $amount; $idx++) {
+ $employee = null;
+ // Is this personl unemployed?
+ while (is_null($employee) || $employee->isEmployed()) {
+ // Generate random number
+ $pos = mt_rand(0, ($totalUnemployed - 1)); // Don't remove the -1 here:
+ // E.g. 100 entries means latest position is 99...
+
+ // Seek for the position
+ $iterator->seek($pos);
+
+ // Is the current position valid?
+ if ($iterator->valid() === false) {
+ // Should normally not happen... :(
+ throw new StructuresOutOfBoundsException($idx, self::EXCEPTION_INDEX_OUT_OF_BOUNDS);
+ } // END - if
+
+ // Get current element
+ $employee = $iterator->current();
+ } // END - while
+
+ // A dummy just for the description and real class
+ $dummy = CompanyEmployee::createCompanyEmployee("", "", "M", 1970, 1, 1, $employee->isMarried(), 0);
+
+ // Make this person employed and give him some money to work
+ $employee->setEmployed(true);
+ $employee->setRealClass($dummy->__toString());
+ $employee->increaseSalary((mt_rand(7, 14) * 100)); // Are 700 to 1400 EUR for the begin okay?
+
+ // Debug message
+ if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> stellt den/die Angestellte(n) <strong>%s %s</strong> ein.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $employee->getSurname(),
+ $employee->getFamily()
+ ));
+
+ // Add this employee
+ $this->addNewEmployee($employee);
+ } // End - for
+
+ // Cache resetten
+ $personellInstance->resetCache();
+
+ // Debug-Meldung ausgeben
+ if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat per Zufall <strong>%d</strong> neue Mitarbeiter eingestellt.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $amount
+ ));
+ } // End - method
+
+ // Distribute all personells on all shipyards
+ public function distributeAllPersonellOnShipyards () {
+ if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> verteilt alle ihre <strong>%d</strong> Mitarbeiter auf alle <strong>%d</strong> Werft(en).",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $this->getTotalEmployee(),
+ $this->getTotalShipyards()
+ ));
+
+ // Do we have some shipyards?
+ if (is_null($this->shipyardList)) {
+ // No shipyards created
+ throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
+ }
+
+ // Get iterator for shipyards
+ $shipyardIter = $this->shipyardList->getIterator();
+
+ // Iterate through all employees
+ for ($idx = $this->employeeList->getIterator(); $idx->valid(); $idx->next()) {
+ // Is the shipyard iterator still okay?
+ if ($shipyardIter->valid() === false) {
+ // Rewind to first position
+ $shipyardIter->seek(0);
+ } // END - if
+
+ // Get Shipyard object
+ $shipyard = $shipyardIter->current();
+
+ // Is this a Shipyard object?
+ if (is_null($shipyard)) {
+ // No class returned
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } elseif (!is_object($shipyard)) {
+ // Not an object! ;-(
+ throw new InvalidObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
+ } elseif ($shipyard->isClass("Shipyard") === false) {
+ // Nope, so throw exception
+ throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
+ }
+
+ // Add employee to the shipyard
+ $shipyard->addNewPersonell($idx->current());
+
+ // Continue to next shipyard
+ $shipyardIter->next();
+ }
+ }
+
+ // Getter for total employees
+ public final function getTotalEmployee () {
+ // Count all...
+ $total = $this->employeeList->count();
+
+ // Debug message
+ if ((defined('DEBUG_COMPANY_EMPLOYEE')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat <strong>%d</strong> Mitarbeiter.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $total
+ ));
+
+ // Return amount
+ return $total;
+ }
+
+ // Getter for total shipyards
+ public final function getTotalShipyards () {
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Für die Reederei <strong>%s</strong> werden die Anzahl der Werften in allen Häfen ermittelt.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName()
+ ));
+
+ // Do we have some shipyards?
+ if (is_null($this->shipyardList)) {
+ // No shipyards created
+ throw new NoShipyardsConstructedException($this, self::EXCEPTION_HARBOR_HAS_NO_SHIPYARDS);
+ }
+
+ // Get iterator
+ $total = $this->shipyardList->count();
+
+ // Debug message
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat <strong>%d</strong> Werft(en).",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $total
+ ));
+
+ // Return amount
+ return $total;
+ }
+
+ // Add a ship type (class) to all shipyards
+ public function addShipTypeToAllShipyards ($shipType) {
+ // Secure strings
+ $shipType = (string) $shipType;
+
+ // Is the class there?
+ if (!class_exists($shipType)) {
+ // Throw exception
+ throw new NoClassException($shipType, self::EXCEPTION_CLASS_NOT_FOUND);
+ }
+
+ // Create dummy ship
+ eval(sprintf("\$shipInstance = %s::create%s(\"M/S Dummy\");",
+ $shipType,
+ $shipType
+ ));
+
+ // Iterate shipyard list
+ for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
+ // Get current element
+ $shipyard = $idx->current();
+
+ // Is this a shipyard?
+ if (is_null($shipyard)) {
+ // Opps! Empty list?
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } elseif (!is_object($shipyard)) {
+ // Not an object! ;-(
+ throw new InvalidObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
+ } elseif ($shipyard->isClass("Shipyard") === false) {
+ // Class is not a shipyard
+ throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
+ }
+
+ // Add the new ship type to the shipyard
+ $shipyard->addNewConstructableShipType($shipType);
+ } // END - for
+ }
+
+ // Validate the requested ship type with the company if they can construct it
+ public function validateWorksContractShipType (SignableContract $contractInstance) {
+ // First get the ship type
+ $shipInstance = $contractInstance->getShipInstance();
+
+ // Ist there a ship instance?
+ if (is_null($shipInstance)) {
+ // Opps! Empty entry?
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } elseif (!is_object($shipInstance)) {
+ // Not an object! ;-(
+ throw new InvalidObjectException($shipInstance, self::EXCEPTION_IS_NO_OBJECT);
+ }
+
+ // Get it's real class name
+ $shipType = $shipInstance->__toString();
+
+ // Now check if ship type is in any list and return the result
+ return ($this->isShipTypeConstructable($shipType));
+ }
+
+ // Is the ship type constructable?
+ public function isShipTypeConstructable ($shipType) {
+ // The type must be a string!
+ $shipType = (string) $shipType;
+
+ // Debug message
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> fragt alle Werften ab, ob diese Schiffe vom Typ <strong>%s</strong> bauen können.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $shipType
+ ));
+
+ // First everthing is failed...
+ $result = false;
+
+ // Iterate through all shipyards
+ for ($idx = $this->shipyardList->getIterator(); $idx->valid(); $idx->next()) {
+ // Get current Shipyard instance
+ $shipyard = $idx->current();
+
+ // Is this a shipyard?
+ if (is_null($shipyard)) {
+ // Opps! Empty list?
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } elseif (!is_object($shipyard)) {
+ // Not an object! ;-(
+ throw new InvalidObjectException($shipyard, self::EXCEPTION_IS_NO_OBJECT);
+ } elseif ($shipyard->isClass("Shipyard") === false) {
+ // Class is not a shipyard
+ throw new ClassMismatchException(array($shipyard->__toString(), "Shipyard"), self::EXCEPTION_CLASSES_NOT_MATCHING);
+ }
+
+ // Validate if first found shipyard can construct the requested type
+ $result = $shipyard->isShipTypeConstructable($shipType);
+
+ // Does this shipyard construct the requested ship type?
+ if ($result) break; // Then abort the search!
+ } // END - for
+
+ // Debug message
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> hat die Suche nach einer Werft beendet, die Schiffe vom Typ <strong>%s</strong> bauen kann.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $shipType
+ ));
+
+ // Return result
+ return $result;
+ }
+
+ // As a customer the shipping company can add new contracts
+ public function addNewWorksContract (SignableContract $contractInstance) {
+ $this->contractList->append($contractInstance);
+ }
+
+ // As a customer the shippng company can withdraw from a contract
+ public function withdrawFromContract (SignableContract $contractInstance) {
+ ApplicationEntryPoint::app_exit("WITHDRAW:<pre>".print_r($contractInstance, true)."</pre>");
+ }
+
+ // Get latest added contract instance
+ public final function getLastContractInstance () {
+ // Get iterator
+ $iter = $this->contractList->getIterator();
+
+ // Get latest entry (total - 1)
+ $iter->seek($iter->count() - 1);
+
+ // Return entry
+ return $iter->current();
+ }
+
+ // Sign a contract with an other party which must also implement Customer
+ public function signContract (SignableContract $contractInstance, ContractPartner $partnerInstance) {
+ // Check wether the other party is our contract partner
+ if ($partnerInstance->isContractPartner($contractInstance) === false) {
+ // Invalid contract partner!
+ throw new InvalidContractPartnerException($partnerInstance, self::EXCEPTION_CONTRACT_PARTNER_INVALID);
+ } // END - if
+
+ // Determine if company "signs" own contract (must be done) or with an other party
+ if ($this->equals($partnerInstance)) {
+ // With itself
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(sprintf("[%s:%d] Die Reederei <strong>%s</strong> erteilt an sich selbst einen Bauauftrag für das <strong>%s</strong> "<strong>%s</strong>".",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $contractInstance->getShipInstance()->getObjectDescription(),
+ $contractInstance->getShipInstance()->getShipName()
+ ));
+ } else {
+ // Other external company
+ if ((defined('DEBUG_COMPANY')) || (defined('DEBUG_ALL'))) $this->debugOutput(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>.",
+ __CLASS__,
+ __LINE__,
+ $this->getCompanyName(),
+ $contractInstance->getShipInstance()->getObjectDescription(),
+ $contractInstance->getShipInstance()->getShipName(),
+ $partnerInstance->getCompanyName()
+ ));
+ }
+
+ // Sign the contract
+ $contractInstance->signContract($this, $partnerInstance);
+
+ /**
+ * @todo Maybe do something more here...
+ */
+ }
+
+ // Is this the right contract partner?
+ public function isContractPartner (SignableContract $contractInstance) {
+ // Get contract partner instance and compare it with $this contract partner
+ return ($this->equals($contractInstance->getContractPartner()));
+ }
+
+ // Setter for merchant instance
+ public final function setMerchantInstance (Merchant $merchantInstance) {
+ // Get contract
+ $contractInstance = $this->getLastContractInstance();
+
+ if (is_null($contractInstance)) {
+ // Opps! Empty contract instance?
+ throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
+ } elseif (!is_object($contractInstance)) {
+ // Not an object! ;-(
+ throw new InvalidObjectException($contractInstance, self::EXCEPTION_IS_NO_OBJECT);
+ } elseif ($contractInstance->isClass("WorksContract") === false) {
+ // Is not a merchant
+ throw new ClassMismatchException(array($contractInstance->__toString(), "WorksContract"), self::EXCEPTION_CLASSES_NOT_MATCHING);
+ }
+
+ // Set the merchant in the contract (for getting prices)
+ $contractInstance->setMerchantInstance($merchantInstance);
+ }
+}
+
+// [EOF]
+?>