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