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