'final' added to factory methods
[shipsimu.git] / application / ship-simu / main / personell / class_SimulatorPersonell.php
1 <?php
2 /**
3  * The general simulator personell class
4  *
5  * @author              Roland Haeder <webmaster@ship-simu.org>
6  * @version             0.0.0
7  * @copyright   Copyright(c) 2007, 2008 Roland Haeder, this is free software
8  * @license             GNU GPL 3.0 or any newer version
9  * @link                http://www.ship-simu.org
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23  */
24 class SimulatorPersonell extends BasePersonell {
25         // Personell list
26         private $personellList = null;
27
28         // A cache for lists
29         private $cacheList = null;
30
31         // A string for cached conditions
32         private $cacheCond = null;
33
34         /**
35          * Private constructor
36          *
37          * @return      void
38          */
39         private function __construct () {
40                 // Call parent constructor
41                 parent::constructor(__CLASS__);
42
43                 if (((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) && (defined('DEBUG_CONSTRUCT'))) $this->getDebugInstance()->output(sprintf("[%s:] Konstruktor erreicht.<br />\n",
44                         $this->__toString()
45                 ));
46
47                 // Set description
48                 $this->setPartDescr("Simulationspersonal");
49
50                 // Create unique ID
51                 $this->createUniqueID();
52
53                 // Clean-up a little
54                 $this->removeSystemArray();
55         }
56
57         /**
58          * Magic wake-up method called when unserialize() is called. This is
59          * neccessary because in this case a personell does not need to know the
60          * min/max ages range and system classes. This would anyway use more RAM
61          * what is not required.
62          *
63          * @return      void
64          */
65         public function __wakeup () {
66                 // Tidy up a little
67                 $this->removePersonellList();
68                 $this->removeMinMaxAge();
69                 $this->removeCache();
70                 $this->removeSystemArray();
71         }
72
73         /**
74          * Generate a specified amount of personell and return the prepared instance
75          *
76          * @param               $amountPersonell                Number of personell we shall
77          *                                                              generate
78          * @return      $personellInstance              An instance of this object with a
79          *                                                              list of personells
80          */
81         public final static function createSimulatorPersonell ($amountPersonell) {
82                 // Make sure only integer can pass
83                 $amountPersonell = (int) $amountPersonell;
84
85                 // Get a new instance
86                 $personellInstance = new SimulatorPersonell();
87
88                 // Debug message
89                 if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $personellInstance->getDebugInstance()->output(sprintf("[%s:%d] Es werden <strong>%d</strong> Personal bereitgestellt.<br />\n",
90                         __CLASS__,
91                         __LINE__,
92                         $amountPersonell
93                 ));
94
95                 // Initialize the personell list
96                 $personellInstance->createPersonellList();
97
98                 // Create requested amount of personell
99                 for ($idx = 0; $idx < $amountPersonell; $idx++) {
100                         $personellInstance->addRandomPersonell();
101                 }
102
103                 // Debug message
104                 if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $personellInstance->getDebugInstance()->output(sprintf("[%s:%d] <strong>%d</strong> Personal bereitgestellt.<br />\n",
105                         __CLASS__,
106                         __LINE__,
107                         $amountPersonell
108                 ));
109
110                 // Tidy up a little
111                 $personellInstance->removeGender();
112                 $personellInstance->removeNames();
113                 $personellInstance->removeBirthday();
114                 $personellInstance->removeSalary();
115                 $personellInstance->removeEmployed();
116                 $personellInstance->removeMarried();
117                 $personellInstance->removeNumberFormaters();
118                 //$personellInstance->removeCache();
119                 $personellInstance->removeSystemArray();
120
121                 // Instanz zurueckgeben
122                 return $personellInstance;
123         }
124
125         /**
126          * Create a SimulatorPersonell object by loading the specified personell
127          * list from an existing database backend
128          *
129          * @param               $idNumber               The ID number (only right part) of the list
130          * @return      $personellInstance      An instance of
131          * @throws      InvalidIDFormatException                If the given id number
132          *                                                                      $idNumber is invalid
133          * @throws      NullPointerException            If a null pointer (instance)
134          *                                                                      has been returned.
135          * @throws      NoObjectException                       If a non-object has been
136          *                                                                      returned
137          * @throws      MissingMethodException          If a required method is missing
138          * @throws      MissingSimulatorIDException     If an ID number was not found
139          */
140         public final static function createSimulatorPersonellByID ($idNumber) {
141                 // Add the class name if it was not found
142                 if (count(explode("@", $idNumber)) < 2) {
143                         // Add class name in front of the incomplete ID number
144                         $tempID = sprintf("%s@%s", __CLASS__, $idNumber);
145                 } else {
146                         // Use the direct ID number
147                         $tempID = $idNumber;
148                 }
149
150                 // Validate the ID number
151                 if (!preg_match(sprintf("/%s\@([a-f0-9]){32}/i", __CLASS__), $tempID)) {
152                         // Invalid format
153                         throw new InvalidIDFormatException(new SimulatorPersonell(), self::EXCEPTION_ID_IS_INVALID_FORMAT);
154                 }
155
156                 // Get instance
157                 $personellInstance = new SimulatorPersonell(false);
158
159                 // Get database instance
160                 $dbInstance = $personellInstance->getDatabaseInstance();
161
162                 // Is this a valid database instance?
163                 if (is_null($dbInstance)) {
164                         // No class returned
165                         throw new NullPointerException($personellInstance, self::EXCEPTION_IS_NULL_POINTER);
166                 } elseif (!is_object($dbInstance)) {
167                         // Not an object! ;-(
168                         throw new NoObjectException($dbInstance, self::EXCEPTION_IS_NO_OBJECT);
169                 } elseif (!method_exists($dbInstance, 'isUniqueIdUsed')) {
170                         // Required method not found
171                         throw new MissingMethodException(array($dbInstance, 'isUniqueIdUsed'), self::EXCEPTION_MISSING_METHOD);
172                 }
173
174                 // Is the unique ID already used? Then it must be there!
175                 if (!$dbInstance->isUniqueIdUsed($tempID))  {
176                         // Entry not found!
177                         throw new MissingSimulatorIDException(array($personellInstance, $idNumber), self::EXCEPTION_SIMULATOR_ID_INVALID);
178                 }
179
180                 // Load the personell list and add it to this object
181                 $personellInstance->loadPersonellList($tempID);
182
183                 // Clean-up a little
184                 $personellInstance->removeGender();
185                 $personellInstance->removeNames();
186                 $personellInstance->removeBirthday();
187                 $personellInstance->removeSalary();
188                 $personellInstance->removeEmployed();
189                 $personellInstance->removeMarried();
190                 $personellInstance->removeNumberFormaters();
191                 //$personellInstance->removeCache();
192                 $personellInstance->removeSystemArray();
193
194                 // Return instance
195                 return $personellInstance;
196         }
197
198         // Create personell list
199         public function createPersonellList () {
200                 if (is_null($this->personellList)) {
201                         if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Personell-Liste erstellt.<br />\n",
202                                 __CLASS__,
203                                 __LINE__
204                         ));
205                         $this->personellList = new FrameworkArrayObject();
206                 } else {
207                         throw new PersonellListAlreadyCreatedException($this, self::EXCEPTION_DIMENSION_ARRAY_INVALID);
208                 }
209         }
210
211         // Remove the personell list
212         private function removePersonellList () {
213                 if (defined('DEBUG_PERSONELL')) $this->getDebugInstance()->output(sprintf("[%s:%d] Personell-Liste entfernt.<br />\n",
214                         __CLASS__,
215                         __LINE__
216                 ));
217                 unset($this->personellList);
218         }
219
220         // Add new personell object to our list
221         public function addRandomPersonell () {
222                 // Gender list...
223                 $genders = array('M', 'F');
224
225                 // Create new personell members
226                 $personellInstance = new SimulatorPersonell();
227
228                 // Set a randomized gender
229                 $personellInstance->setGender($genders[mt_rand(0, 1)]);
230
231                 // Set a randomized birthday (maximum age required, see const MAX_AGE)
232                 $personellInstance->createBirthday();
233
234                 // Married? Same values means: married
235                 if (mt_rand(0, 5) == mt_rand(0, 5)) $personellInstance->setMarried(true);
236
237                 // Tidy up a little
238                 $personellInstance->removePersonellList();
239                 $personellInstance->removeMinMaxAge();
240                 $personellInstance->removeCache();
241                 $personellInstance->removeSystemArray();
242
243                 // Add new member to the list
244                 $this->personellList->append($personellInstance);
245         }
246
247         /**
248          * Get a specifyable list of our people, null or empty string will be ignored!
249          *
250          * @return      $cacheList      A list of cached personells
251          */
252         function getSpecialPersonellList ($isEmployed = null, $isMarried = null, $hasGender = "") {
253                 // Serialize the conditions for checking if we can take the cache
254                 $serialized = serialize(array($isEmployed, $isMarried, $hasGender));
255
256                 // The same (last) conditions?
257                 if (($serialized == $this->cacheCond) && (!is_null($this->cacheCond))) {
258                         if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Gecachte Liste wird verwendet.<br />\n",
259                                 __CLASS__,
260                                 __LINE__
261                         ));
262
263                         // Return cached list
264                         return $this->cacheList;
265                 }
266
267                 // Output debug message
268                 if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Personalliste wird nach Kriterien durchsucht...<br />\n",
269                         __CLASS__,
270                         __LINE__
271                 ));
272
273                 // Remember the conditions
274                 $this->setCacheCond($serialized);
275
276                 // Create cached list
277                 $this->setAllCacheList(new FrameworkArrayObject());
278
279                 // Search all unemployed personells
280                 for ($idx = $this->personellList->getIterator(); $idx->valid(); $idx->next()) {
281                         // Element holen
282                         $el = $idx->current();
283
284                         // Check currenylt all single conditions (combined conditions are not yet supported)
285                         if ((!is_null($isEmployed)) && ($el->isEmployed() == $isEmployed)) {
286                                 // Add this one (employed status asked)
287                                 $this->cacheList->append($el);
288                         } elseif ((!is_null($isMarried)) && ($el->isMarried() == $isMarried)) {
289                                 // Add this one (marrital status asked)
290                                 $this->cacheList->append($el);
291                         } elseif ((!empty($hasGender)) && ($el->getGender() == $hasGender)) {
292                                 // Add this one (specified gender)
293                                 $this->cacheList->append($el);
294                         }
295                 }
296
297                 // Return the completed list
298                 return $this->cacheList;
299         }
300
301         /**
302          * Get amount of unemployed personell
303          *
304          * @return      $count  Amount of unemployed personell
305          */
306         public final function getAllUnemployed () {
307                 if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Es werden alle erwerbslosen Personen gesucht.<br />\n",
308                         __CLASS__,
309                         __LINE__
310                 ));
311
312                 // Get a temporary list
313                 $list = $this->getSpecialPersonellList(false);
314
315                 // Anzahl zurueckliefern
316                 return $list->count();
317         }
318
319         /**
320          * Remove cache things
321          *
322          * @return      void
323          */
324         private function removeCache () {
325                 if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Cache-Attribute entfernt.<br />\n",
326                         __CLASS__,
327                         __LINE__
328                 ));
329
330                 // Remove cache data
331                 unset($this->cacheList);
332                 unset($this->cacheCond);
333         }
334
335         /**
336          * Setter for cache list
337          *
338          * @param               $cacheList      The new cache list to set or null for initialization/reset
339          * @return      void
340          */
341         private function setAllCacheList (FrameworkArrayObject $cacheList = null) {
342                 $this->cacheList = $cacheList;
343         }
344
345         /**
346          * Setter for cache conditions
347          *
348          * @param               $cacheCond      The new cache conditions to set
349          * @return      void
350          */
351         private function setCacheCond ($cacheCond) {
352                 $this->cacheCond = (string) $cacheCond;
353         }
354
355         /**
356          * Reset cache list
357          *
358          * @return      void
359          */
360         public function resetCache () {
361                 if ((defined('DEBUG_PERSONELL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Cache-Liste zur&uuml;ckgesetzt.<br />\n",
362                         __CLASS__,
363                         __LINE__
364                 ));
365                 $this->setAllCacheList(null);
366                 $this->setCacheCond("");
367         }
368
369         /**
370          * Getter for surname. If no surname is set then default surnames are set
371          * for male and female personells.
372          *
373          * @return      $surname                The personell' surname
374          */
375         public final function getSurname () {
376                 $surname = parent::getSurname();
377                 // Make sure every one has a surname...
378                 if (empty($surname)) {
379                         if ($this->isMale()) {
380                                 // Typical male name
381                                 $surname = "John";
382                         } else {
383                                 // Typical female name
384                                 $surname = "Jennifer";
385                         }
386
387                         // Set typical family name
388                         parent::setFamily("Smith");
389                 }
390                 return $surname;
391         }
392
393         /**
394          * Saves only the personell list to the database
395          *
396          * @return      void
397          */
398         public function saveObjectToDatabase () {
399                 // Get the database
400                 $dbInstance = $this->getDatabaseInstance();
401
402                 // Prepare the limitation object. We just need the personellList array object.
403                 $limitInstance = ObjectLimits::createObjectLimits(array("personellList"));
404
405                 // Limitate the saving amount
406                 $dbInstance->limitObject($limitInstance);
407
408                 // Save this object
409                 $dbInstance->saveObject($this);
410         }
411
412         /**
413          * Getter for personell list
414          *
415          * @return      $personellList          The list of all personells
416          */
417         public final function getPersonellList () {
418                 return $this->personellList;
419         }
420
421         /**
422          * Loads the mostly pre-cached personell list
423          *
424          * @param               $idNumber               The ID number we shall use for looking up
425          *                                              the right data.
426          * @return      void
427          * @throws      ContainerItemIsNullException    If a container item is null
428          * @throws      ContainerItemIsNoArrayException If a container item is
429          *                                                                              not an array
430          * @throws      ContainerMaybeDamagedException  If the container item
431          *                                                                              is missing the indexes
432          *                                                                              'name' and/or 'value'
433          * @see         SerializationContainer  A special container class which
434          *                                                              helps storing only some attributes
435          *                                                              of a class.
436          */
437         public function loadPersonellList ($idNumber) {
438                 // Get database instance
439                 $dbInstance = $this->getDatabaseInstance();
440
441                 // Get the serialization container within the  personell list from
442                 // the database layer
443                 $containerInstance = $dbInstance->getObjectFromCachedData($idNumber);
444
445                 // Iterate through the whole container
446                 for ($idx = $containerInstance->getIterator(); $idx->valid(); $idx->next()) {
447                         // Get current item from container
448                         $item = $idx->current();
449
450                         // Validate it a bit
451                         if (is_null($item)) {
452                                 // Is null
453                                 throw new ContainerItemIsNullException($this, self::EXCEPTION_CONTAINER_ITEM_IS_NULL);
454                         } elseif (!is_array($item)) {
455                                 // Is not an array
456                                 throw new ContainerItemIsNoArrayException($this, self::EXCEPTION_ITEM_IS_NO_ARRAY);
457                         } elseif ((!isset($item['name'])) || (!isset($item['value']))) {
458                                 // Missing elements
459                                 throw new ContainerMaybeDamagedException($this, self::EXCEPTION_CONTAINER_MAYBE_DAMAGED);
460                         }
461
462                         // Okay, now we can get the item and generate a valid command for eval().
463                         // We need to convert the first letter to lower-case but keep all others intact
464                         $eval = sprintf("\$this->%s = \$item['value'];",
465                                 strtolower(substr($item['name'], 0, 1))
466                                 .
467                                 substr($item['name'], 1)
468                         );
469
470                         // Debug message
471                         if ((defined('DEBUG_EVAL')) || (defined('DEBUG_ALL'))) $this->getDebugInstance()->output(sprintf("[%s:%d] Konstruierte PHP-Anweisung: <pre><em>%s</em></pre><br />\n",
472                                 __CLASS__,
473                                 __LINE__,
474                                 htmlentities($eval)
475                         ));
476
477                         // Run the command
478                         @eval($eval);
479                 }
480         }
481 }
482
483 // [EOF]
484 ?>