final added, code clean-ups
[shipsimu.git] / application / ship-simu / main / class_BaseSimulator.php
1 <?php
2 /**
3  * The general simulator 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 BaseSimulator extends BaseFrameworkSystem {
25         // Schiffsteilinstanz
26         private $partInstance = null;
27
28         // Abmasse (Breite/Hoehe/Laenge)
29         private $width  = 0;
30         private $height = 0;
31         private $length = 0;
32
33         // Aktuelles Schiff und Schiffsteil
34         private $currShip = null;
35         private $currPart = null;
36
37         // Faktoren zur Erweiterung der Masse. Beispielsweise soll der Maschinenraum groesser wie der Motor sein
38         private $resizeFactorArray = array(
39                 'width'  => 1,
40                 'height' => 1,
41                 'length' => 1
42         );
43
44         // Konstruktor
45         private function __construct ($class) {
46                 // Call highest constructor
47                 parent::constructor($class);
48
49                 if ((defined('DEBUG_CORE')) && (defined('DEBUG_CONSTRUCT'))) $this->getDebugInstance()->output(sprintf("[%s:] Konstruktor erreicht.<br />\n",
50                         $this->__toString()
51                 ));
52
53                 // Set part description and class name
54                 $this->setPartDescr("Simulator-Basis-Einheit");
55
56                 // Clean up a little, dies sollte ganz zum Schluss erfolgen!
57                 $this->removeResizeFactorArray();
58                 $this->removeCurrPart();
59                 $this->removeCurrShip();
60         }
61
62         // Public constructor
63         public function constructor ($class) {
64                 // Call real constructor
65                 $this->__construct($class);
66         }
67
68         // Magic __isset method
69         private function __isset ($var) {
70                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Checking <strong>%s</strong> in class.<br />\n",
71                         $this->__toString(), $var
72                 ));
73                 return isset($this->$var);
74         }
75
76         // Magic __unset method
77         private function __unset($var) {
78                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Removing <strong>%s</strong> from class.<br />\n",
79                         $this->__toString(), $var
80                 ));
81                 unset($this->$var);
82         }
83
84         // Setter-Methode fuer Laenge
85         public final function setLength ($length) {
86                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] <strong>%dm</strong> L&auml;nge gesetzt.<br />\n",
87                         $this->__toString(),
88                         $length
89                 ));
90                 $this->length = (float) $length;
91         }
92
93         // Setter-Methode fuer Breite
94         public final function setWidth ($width) {
95                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] <strong>%dm</strong> Breite gesetzt.<br />\n",
96                         $this->__toString(),
97                         $width
98                 ));
99                 $this->width = (float) $width;
100         }
101
102         // Setter-Methode fuer Hoehe
103         public final function setHeight ($height) {
104                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] <strong>%dm</strong> H&ouml;he gesetzt.<br />\n",
105                         $this->__toString(),
106                         $height
107                 ));
108                 $this->height = (float) $height;
109         }
110
111         // Getter-Methode fuer Laenge
112         public final function getLength () {
113                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] L&auml;nge angefordert.<br />\n",
114                         $this->__toString()
115                 ));
116                 return $this->length;
117         }
118
119         // Getter-Methode fuer Breite
120         public final function getWidth () {
121                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] L&auml;nge angefordert.<br />\n",
122                         $this->__toString()
123                 ));
124                 return $this->width;
125         }
126
127         // Getter-Methode fuer Hoehe
128         public final function getHeight () {
129                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] H&ouml;he angefordert.<br />\n",
130                         $this->__toString()
131                 ));
132                 return $this->height;
133         }
134
135         // Setter-Methode fuer Teil-Instanz
136         public final function setPartInstance (ConstructableShipPart $partInstance) {
137                 $this->partInstance = $partInstance;
138         }
139
140         // Getter-Methode fuer Teil-Instanz
141         public final function getPartInstance () {
142                 if (!isset($this->partInstance)) {
143                         return null;
144                 }
145                 return $this->partInstance;
146         }
147
148         // Remover-Methode fuer die Teil-Instanz
149         public final function removePartInstance () {
150                 if ($this->getPartInstance() !== null) {
151                         // Warnung ausgeben
152                         if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] partInstance ist nicht null! Instanz-Attribut wird nicht entfernt.<br />\n",
153                                 $this->__toString()
154                         ));
155                 } else {
156                         // Leere Instanz kann entfernt werden
157                         if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] partInstance wurde entfernt.<br />\n",
158                                 $this->__toString()
159                         ));
160                         unset($this->partInstance);
161                 }
162         }
163
164         // Prueft ob all Umberechnungsfaktoren gesetzt sind
165         private function isResizeFactorValid () {
166                 return (($this->getResizeFactorElement('width')  > 1)
167                         || ($this->getResizeFactorElement('height') > 1)
168                         || ($this->getResizeFactorElement('length') > 1)
169                 );
170         }
171
172         // Baut einen Motor in das Schiff ein
173         public function addShipPartToShip (ConstructableShip $shipInstance, ConstructableShipPart $partInstance) {
174                 // Schiff/-steil merken
175                 $this->currShip = $shipInstance;
176                 $this->currPart = $partInstance;
177
178                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Maschinenraum mit Motor <strong>%s</strong> wird fuer das Schiff <strong>%s</strong> konstruiert.<br />\n",
179                         $this->__toString(),
180                         $this->getCurrPart()->getPartDescr(),
181                         $this->currShip->getShipName()
182                 ));
183
184                 // Passt ueberhaupt das Schiffsteil in's Schiff?
185                 if ($this->isShipPartSizeValid()) {
186                         // Berechnungen fuer umliegendes Objekt anpassen
187                         if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Das Schiffsteil <strong>%s</strong> vom Typ <strong>%s</strong> passt in das Schiff <strong>%s</strong> hinein.<br />\n",
188                                 $this->__toString(),
189                                 $this->getCurrPart()->getPartDescr(),
190                                 $this->getCurrPart()->__toString(),
191                                 $this->currShip->getShipName()
192                         ));
193
194                         // Muessen die Masse angepasst werden?
195                         if ($this->isResizeFactorValid()) {
196                                 // Neue Angaben berechnen (wir lassen etwas Lust fuer Kabelbaeume, Roehren, Maschinisten, etc.)
197                                 $this->newWidth  = (float) $this->getCurrPart()->getWidth()  * $this->resizeFactorArray['width'];
198                                 $this->newHeight = (float) $this->getCurrPart()->getHeight() * $this->resizeFactorArray['height'];
199                                 $this->newLength = (float) $this->getCurrPart()->getLength() * $this->resizeFactorArray['length'];
200
201                                 // Passt dies nun immer noch?
202                                 if ($this->isNewSizeValid()) {
203                                         // Das passt auch, dann Werte setzen und Motor-Instanz merken
204                                         if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Das Schiffsteil <strong>%s</strong> passt in das Schiff <strong>%s</strong> hinein.<br />\n",
205                                                 $this->__toString(),
206                                                 $this->getPartDescr(),
207                                                 $this->currShip->getShipName()
208                                         ));
209                                         $this->setWidth($this->newWidth);
210                                         $this->setHeight($this->newHeight);
211                                         $this->setLength($this->newLength);
212
213                                         // Einige Dinge entfernen...
214                                         $this->removeAllNewAttr();
215                                 } else {
216                                         // Passt nicht! Also wieder Exception werfen...
217                                         throw new StructureShipMismatchException(sprintf("[%s:] Das Schiffsteil <strong>%s</strong> vom Typ <strong>%s</strong> ist zu gross f&uuml;r das Schiff!",
218                                                 $this->getCurrPart()->__toString(),
219                                                 $this->getCurrPart()->getPartDescr(),
220                                                 $this->getCurrPart()->__toString()
221                                         ), 2);
222                                 }
223                         } elseif ($this->currPart != null) {
224                                 // Aktuelle Masse setzen
225                                 $this->setWidth($this->getCurrPart()->getWidth());
226                                 $this->setHeight($this->getCurrPart()->getHeight());
227                                 $this->setLength($this->getCurrPart()->getLength());
228                         }
229
230                         // Existiert ein Schiffsteil?
231                         if (!is_null($this->currPart)) {
232                                 // Debug-Meldung ausgeben
233                                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Schiffsteil <strong>%s</strong> gefunden.<br />\n",
234                                         $this->getCurrPart()->realClass,
235                                         $this->getCurrPart()->getPartDescr()
236                                 ));
237
238                                 // Schiffsteil-Instanz setzen
239                                 $this->setPartInstance($this->currPart);
240
241                                 // Instanzen entfernen
242                                 $this->getCurrPart()->removeCurrShip();
243                                 $this->getCurrPart()->removeCurrPart();
244                                 $this->getCurrPart()->removePartInstance();
245                                 $this->getCurrPart()->removeResizeFactorArray();
246                         }
247                 } else {
248                         // Exception werfen!
249                         throw new StructureShipMismatchException(sprintf("[%s:] Das Schiffsteil <u>%s</u> vom Typ <u>%s</u> passt nicht in das Schiff!",
250                                 $this->getCurrPart()->realClass,
251                                 $this->getCurrPart()->getPartDescr(),
252                                 $this->getCurrPart()->__toString()
253                         ), 1);
254                 }
255
256                 // Nochmals Clean up a little
257                 $this->removeResizeFactorArray();
258                 $this->removeCurrShip();
259                 $this->removeCurrPart();
260         }
261
262         // Array fuer Umrechnungstabelle entfernen
263         public final function removeResizeFactorArray () {
264                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] removeResizeFactor erreicht.<br />\n",
265                         $this->__toString()
266                 ));
267                 unset($this->resizeFactorArray);
268         }
269
270         /**
271          * Remove all new*** attributes
272          *
273          * @return      void
274          */
275         public final function removeAllNewAttr () {
276                 unset($this->newWidth);
277                 unset($this->newHeight);
278                 unset($this->newLength);
279         }
280
281         /**
282          * Remove current ship instance
283          *
284          * @return      void
285          */
286         public final function removeCurrShip () {
287                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] removeCurrShip erreicht.<br />\n",
288                         $this->__toString()
289                 ));
290                 unset($this->currShip);
291         }
292
293         // Aktuelle Schiffsteil-Instanz entfernen
294         public final function removeCurrPart () {
295                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] removeCurrPart erreicht.<br />\n",
296                         $this->__toString()
297                 ));
298                 unset($this->currPart);
299         }
300
301         // Breite entfernen
302         public final function removeWidth () {
303                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Breite entfernt.<br />\n",
304                         $this->__toString()
305                 ));
306                 unset($this->width);
307         }
308
309         // Hoehe entfernen
310         public final function removeHeight () {
311                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] H&ouml;he entfernt.<br />\n",
312                         $this->__toString()
313                 ));
314                 unset($this->height);
315         }
316
317         // Laenge entfernen
318         public final function removeLength () {
319                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] L&auml;nge entfernt.<br />\n",
320                         $this->__toString()
321                 ));
322                 unset($this->length);
323         }
324
325         // Tiefgang entfernen
326         public final function removeDraught () {
327                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Tiefgang entfernt.<br />\n",
328                         $this->__toString()
329                 ));
330                 unset($this->draught);
331         }
332
333         // Getter-Methode fuer Element aus resizeFactor
334         public final function getResizeFactorElement ($el) {
335                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] getResizeFactorElement erreicht. (element=%s)<br />\n",
336                         $this->__toString(),
337                         $el
338                 ));
339                 if (isset($this->resizeFactorArray[$el])) {
340                         // Element gefunden
341                         return $this->resizeFactorArray[$el];
342                 } else {
343                         // Element nicht gefunden!
344                         return 0;
345                 }
346         }
347
348         // Setter-Methode fuer Element in resizeFactor
349         public final function setResizeFactorElement ($el, $value) {
350                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] Umberechnungsfaktor <strong>%s</strong>=<strong>%s</strong> gesetzt.<br />\n",
351                         $this->__toString(),
352                         $el,
353                         $value
354                 ));
355                 $this->resizeFactorArray[$el] = (float) $value;
356         }
357
358         // Kontrolliert, ob die Abmasse Schiffsteil->Schiff stimmen
359         public function isShipPartSizeValid () {
360                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] isShipPartSizeValid erreicht.<br />\n",
361                         $this->__toString()
362                 ));
363                 return (
364                         (
365                                 ( // Already defined ship messurings
366                                                  ($this->getCurrPart()->getWidth()  < $this->currShip->getWidth())
367                                         && ($this->getCurrPart()->getHeight() < $this->currShip->getDraught())
368                                         && ($this->getCurrPart()->getLength() < $this->currShip->getLength())
369                                 ) || ( // Ship messurings shall be calculated
370                                                  ($this->currShip->getWidth()  == 0)
371                                         && ($this->currShip->getHeight() == 0)
372                                         && ($this->currShip->getLength() == 0)
373                                 )
374                         // The inserted part must be messured!
375                         ) && ($this->getCurrPart()->getWidth()  > 0)
376                                 && ($this->getCurrPart()->getHeight() > 0)
377                                 && ($this->getCurrPart()->getLength() > 0)
378                 );
379         }
380
381         // Kontrolliert, ob die Abmasse Maschinenraum->Schiff stimmen
382         public function isNewSizeValid () {
383                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] isNewSizeValid erreicht.<br />\n",
384                         $this->__toString()
385                 ));
386                 return (
387                         ( // Already defined ship messurings
388                                          ($this->newWidth  < $this->currShip->getWidth())
389                                 && ($this->newHeight < $this->currShip->getDraught())
390                                 && ($this->newLength < $this->currShip->getLength())
391                         ) || ( // Ship messurings shall be calculated
392                                          ($this->currShip->getWidth()  == 0)
393                                 && ($this->currShip->getHeight() == 0)
394                                 && ($this->currShip->getLength() == 0)
395                         )
396                 );
397         }
398
399         // Masse extrahieren
400         public function extractDimensions ($dim) {
401                 if (defined('DEBUG_CORE')) $this->getDebugInstance()->output(sprintf("[%s:] extractDimensions erreicht f&uuml;r <strong>%s</strong>.<br />\n",
402                         $this->__toString(),
403                         $this->getPartDescr()
404                 ));
405
406                 // Abmasse setzen
407                 if ((isset($dim)) && (is_array($dim)) && (count($dim) == 3)) {
408                         // Abmasse aus Array holen
409                         $this->setWidth($dim[0]);
410                         $this->setHeight($dim[1]);
411                         $this->setLength($dim[2]);
412                 } else {
413                         // Nicht gefundene Abmasse!
414                         throw new DimNotFoundInArrayException($this, self::EXCEPTION_DIMENSION_ARRAY_INVALID);
415                 }
416         }
417
418         /**
419          * Getter for current part instance
420          *
421          * @return              $currPart       Instance of the current ship part object
422          */
423         public final function getCurrPart () {
424                 return $this->currPart;
425         }
426 }
427
428 // [EOF]
429 ?>