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