create changelog entry
[debian/openrocket] / core / src / net / sf / openrocket / simulation / listeners / SimulationListenerHelper.java
1 package net.sf.openrocket.simulation.listeners;
2
3
4 import net.sf.openrocket.aerodynamics.AerodynamicForces;
5 import net.sf.openrocket.aerodynamics.FlightConditions;
6 import net.sf.openrocket.aerodynamics.Warning;
7 import net.sf.openrocket.logging.LogHelper;
8 import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
9 import net.sf.openrocket.motor.MotorId;
10 import net.sf.openrocket.motor.MotorInstance;
11 import net.sf.openrocket.rocketcomponent.MotorMount;
12 import net.sf.openrocket.rocketcomponent.RecoveryDevice;
13 import net.sf.openrocket.simulation.AccelerationData;
14 import net.sf.openrocket.simulation.FlightEvent;
15 import net.sf.openrocket.simulation.MassData;
16 import net.sf.openrocket.simulation.SimulationStatus;
17 import net.sf.openrocket.simulation.exception.SimulationException;
18 import net.sf.openrocket.startup.Application;
19 import net.sf.openrocket.util.Coordinate;
20 import net.sf.openrocket.util.MathUtil;
21
22 /**
23  * Helper methods for firing events to simulation listeners.
24  * 
25  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
26  */
27 public class SimulationListenerHelper {
28         
29         private static final LogHelper log = Application.getLogger();
30         
31         ////////  SimulationListener methods  ////////
32         
33
34         /**
35          * Fire startSimulation event.
36          */
37         public static void fireStartSimulation(SimulationStatus status)
38                         throws SimulationException {
39                 int modID = status.getModID();
40                 
41                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
42                         l.startSimulation(status);
43                         if (modID != status.getModID()) {
44                                 warn(status, l);
45                                 modID = status.getModID();
46                         }
47                 }
48         }
49         
50         
51         /**
52          * Fire endSimulation event.
53          */
54         public static void fireEndSimulation(SimulationStatus status, SimulationException exception) {
55                 int modID = status.getModID();
56                 
57                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
58                         l.endSimulation(status, exception);
59                         if (modID != status.getModID()) {
60                                 warn(status, l);
61                                 modID = status.getModID();
62                         }
63                 }
64         }
65         
66         
67
68
69         /**
70          * Fire preStep event.
71          * 
72          * @return      <code>true</code> to handle step normally, <code>false</code> to skip the step.
73          */
74         public static boolean firePreStep(SimulationStatus status)
75                         throws SimulationException {
76                 boolean b;
77                 int modID = status.getModID();
78                 
79                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
80                         b = l.preStep(status);
81                         if (modID != status.getModID()) {
82                                 warn(status, l);
83                                 modID = status.getModID();
84                         }
85                         if (b == false) {
86                                 warn(status, l);
87                                 return false;
88                         }
89                 }
90                 return true;
91         }
92         
93         
94         /**
95          * Fire postStep event.
96          */
97         public static void firePostStep(SimulationStatus status)
98                         throws SimulationException {
99                 int modID = status.getModID();
100                 
101                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
102                         l.postStep(status);
103                         if (modID != status.getModID()) {
104                                 warn(status, l);
105                                 modID = status.getModID();
106                         }
107                 }
108         }
109         
110         
111
112         ////////  SimulationEventListener methods  ////////
113         
114         /**
115          * Fire an add flight event event.
116          * 
117          * @return      <code>true</code> to add the event normally, <code>false</code> to skip adding the event.
118          */
119         public static boolean fireAddFlightEvent(SimulationStatus status, FlightEvent event) throws SimulationException {
120                 boolean b;
121                 int modID = status.getModID();
122                 
123                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
124                         if (l instanceof SimulationEventListener) {
125                                 b = ((SimulationEventListener) l).addFlightEvent(status, event);
126                                 if (modID != status.getModID()) {
127                                         warn(status, l);
128                                         modID = status.getModID();
129                                 }
130                                 if (b == false) {
131                                         warn(status, l);
132                                         return false;
133                                 }
134                         }
135                 }
136                 return true;
137         }
138         
139         /**
140          * Fire a handle flight event event.
141          * 
142          * @return      <code>true</code> to handle the event normally, <code>false</code> to skip event.
143          */
144         public static boolean fireHandleFlightEvent(SimulationStatus status, FlightEvent event) throws SimulationException {
145                 boolean b;
146                 int modID = status.getModID();
147                 
148                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
149                         if (l instanceof SimulationEventListener) {
150                                 b = ((SimulationEventListener) l).handleFlightEvent(status, event);
151                                 if (modID != status.getModID()) {
152                                         warn(status, l);
153                                         modID = status.getModID();
154                                 }
155                                 if (b == false) {
156                                         warn(status, l);
157                                         return false;
158                                 }
159                         }
160                 }
161                 return true;
162         }
163         
164         /**
165          * Fire motor ignition event.
166          * 
167          * @return      <code>true</code> to handle the event normally, <code>false</code> to skip event.
168          */
169         public static boolean fireMotorIgnition(SimulationStatus status, MotorId motorId, MotorMount mount,
170                         MotorInstance instance) throws SimulationException {
171                 boolean b;
172                 int modID = status.getModID(); // Contains also motor instance
173                 
174                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
175                         if (l instanceof SimulationEventListener) {
176                                 b = ((SimulationEventListener) l).motorIgnition(status, motorId, mount, instance);
177                                 if (modID != status.getModID()) {
178                                         warn(status, l);
179                                         modID = status.getModID();
180                                 }
181                                 if (b == false) {
182                                         warn(status, l);
183                                         return false;
184                                 }
185                         }
186                 }
187                 return true;
188         }
189         
190         
191         /**
192          * Fire recovery device deployment event.
193          * 
194          * @return      <code>true</code> to handle the event normally, <code>false</code> to skip event.
195          */
196         public static boolean fireRecoveryDeviceDeployment(SimulationStatus status, RecoveryDevice device)
197                         throws SimulationException {
198                 boolean b;
199                 int modID = status.getModID(); // Contains also motor instance
200                 
201                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
202                         if (l instanceof SimulationEventListener) {
203                                 b = ((SimulationEventListener) l).recoveryDeviceDeployment(status, device);
204                                 if (modID != status.getModID()) {
205                                         warn(status, l);
206                                         modID = status.getModID();
207                                 }
208                                 if (b == false) {
209                                         warn(status, l);
210                                         return false;
211                                 }
212                         }
213                 }
214                 return true;
215         }
216         
217         
218         ////////  SimulationComputationalListener methods  ////////
219         
220         /**
221          * Fire preAtmosphericModel event.
222          * 
223          * @return      <code>null</code> normally, or overriding atmospheric conditions.
224          */
225         public static AtmosphericConditions firePreAtmosphericModel(SimulationStatus status)
226                         throws SimulationException {
227                 AtmosphericConditions conditions;
228                 int modID = status.getModID();
229                 
230                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
231                         if (l instanceof SimulationComputationListener) {
232                                 conditions = ((SimulationComputationListener) l).preAtmosphericModel(status);
233                                 if (modID != status.getModID()) {
234                                         warn(status, l);
235                                         modID = status.getModID();
236                                 }
237                                 if (conditions != null) {
238                                         warn(status, l);
239                                         return conditions;
240                                 }
241                         }
242                 }
243                 return null;
244         }
245         
246         /**
247          * Fire postAtmosphericModel event.
248          * 
249          * @return      the atmospheric conditions to use.
250          */
251         public static AtmosphericConditions firePostAtmosphericModel(SimulationStatus status, AtmosphericConditions conditions)
252                         throws SimulationException {
253                 AtmosphericConditions c;
254                 AtmosphericConditions clone = conditions.clone();
255                 int modID = status.getModID();
256                 
257                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
258                         if (l instanceof SimulationComputationListener) {
259                                 c = ((SimulationComputationListener) l).postAtmosphericModel(status, clone);
260                                 if (modID != status.getModID()) {
261                                         warn(status, l);
262                                         modID = status.getModID();
263                                 }
264                                 if (c != null && !c.equals(conditions)) {
265                                         warn(status, l);
266                                         conditions = c;
267                                         clone = conditions.clone();
268                                 }
269                         }
270                 }
271                 return conditions;
272         }
273         
274         
275
276         /**
277          * Fire preWindModel event.
278          * 
279          * @return      <code>null</code> normally, or overriding wind.
280          */
281         public static Coordinate firePreWindModel(SimulationStatus status)
282                         throws SimulationException {
283                 Coordinate wind;
284                 int modID = status.getModID();
285                 
286                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
287                         if (l instanceof SimulationComputationListener) {
288                                 wind = ((SimulationComputationListener) l).preWindModel(status);
289                                 if (modID != status.getModID()) {
290                                         warn(status, l);
291                                         modID = status.getModID();
292                                 }
293                                 if (wind != null) {
294                                         warn(status, l);
295                                         return wind;
296                                 }
297                         }
298                 }
299                 return null;
300         }
301         
302         /**
303          * Fire postWindModel event.
304          * 
305          * @return      the wind to use.
306          */
307         public static Coordinate firePostWindModel(SimulationStatus status, Coordinate wind) throws SimulationException {
308                 Coordinate w;
309                 int modID = status.getModID();
310                 
311                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
312                         if (l instanceof SimulationComputationListener) {
313                                 w = ((SimulationComputationListener) l).postWindModel(status, wind);
314                                 if (modID != status.getModID()) {
315                                         warn(status, l);
316                                         modID = status.getModID();
317                                 }
318                                 if (w != null && !w.equals(wind)) {
319                                         warn(status, l);
320                                         wind = w;
321                                 }
322                         }
323                 }
324                 return wind;
325         }
326         
327         
328
329         /**
330          * Fire preGravityModel event.
331          * 
332          * @return      <code>NaN</code> normally, or overriding gravity.
333          */
334         public static double firePreGravityModel(SimulationStatus status)
335                         throws SimulationException {
336                 double gravity;
337                 int modID = status.getModID();
338                 
339                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
340                         if (l instanceof SimulationComputationListener) {
341                                 gravity = ((SimulationComputationListener) l).preGravityModel(status);
342                                 if (modID != status.getModID()) {
343                                         warn(status, l);
344                                         modID = status.getModID();
345                                 }
346                                 if (!Double.isNaN(gravity)) {
347                                         warn(status, l);
348                                         return gravity;
349                                 }
350                         }
351                 }
352                 return Double.NaN;
353         }
354         
355         /**
356          * Fire postGravityModel event.
357          * 
358          * @return      the gravity to use.
359          */
360         public static double firePostGravityModel(SimulationStatus status, double gravity) throws SimulationException {
361                 double g;
362                 int modID = status.getModID();
363                 
364                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
365                         if (l instanceof SimulationComputationListener) {
366                                 g = ((SimulationComputationListener) l).postGravityModel(status, gravity);
367                                 if (modID != status.getModID()) {
368                                         warn(status, l);
369                                         modID = status.getModID();
370                                 }
371                                 if (!Double.isNaN(g) && !MathUtil.equals(g, gravity)) {
372                                         warn(status, l);
373                                         gravity = g;
374                                 }
375                         }
376                 }
377                 return gravity;
378         }
379         
380         
381
382
383         /**
384          * Fire preFlightConditions event.
385          * 
386          * @return      <code>null</code> normally, or overriding flight conditions.
387          */
388         public static FlightConditions firePreFlightConditions(SimulationStatus status)
389                         throws SimulationException {
390                 FlightConditions conditions;
391                 int modID = status.getModID();
392                 
393                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
394                         if (l instanceof SimulationComputationListener) {
395                                 conditions = ((SimulationComputationListener) l).preFlightConditions(status);
396                                 if (modID != status.getModID()) {
397                                         warn(status, l);
398                                         modID = status.getModID();
399                                 }
400                                 if (conditions != null) {
401                                         warn(status, l);
402                                         return conditions;
403                                 }
404                         }
405                 }
406                 return null;
407         }
408         
409         /**
410          * Fire postFlightConditions event.
411          * 
412          * @return      the flight conditions to use: either <code>conditions</code> or a new object
413          *                      containing the modified conditions.
414          */
415         public static FlightConditions firePostFlightConditions(SimulationStatus status, FlightConditions conditions)
416                         throws SimulationException {
417                 FlightConditions c;
418                 FlightConditions clone = conditions.clone();
419                 int modID = status.getModID();
420                 
421                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
422                         if (l instanceof SimulationComputationListener) {
423                                 c = ((SimulationComputationListener) l).postFlightConditions(status, clone);
424                                 if (modID != status.getModID()) {
425                                         warn(status, l);
426                                         modID = status.getModID();
427                                 }
428                                 if (c != null && !c.equals(conditions)) {
429                                         warn(status, l);
430                                         conditions = c;
431                                         clone = conditions.clone();
432                                 }
433                         }
434                 }
435                 return conditions;
436         }
437         
438         
439
440
441         /**
442          * Fire preAerodynamicCalculation event.
443          * 
444          * @return      <code>null</code> normally, or overriding aerodynamic forces.
445          */
446         public static AerodynamicForces firePreAerodynamicCalculation(SimulationStatus status)
447                         throws SimulationException {
448                 AerodynamicForces forces;
449                 int modID = status.getModID();
450                 
451                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
452                         if (l instanceof SimulationComputationListener) {
453                                 forces = ((SimulationComputationListener) l).preAerodynamicCalculation(status);
454                                 if (modID != status.getModID()) {
455                                         warn(status, l);
456                                         modID = status.getModID();
457                                 }
458                                 if (forces != null) {
459                                         warn(status, l);
460                                         return forces;
461                                 }
462                         }
463                 }
464                 return null;
465         }
466         
467         /**
468          * Fire postAerodynamicCalculation event.
469          * 
470          * @return      the aerodynamic forces to use.
471          */
472         public static AerodynamicForces firePostAerodynamicCalculation(SimulationStatus status, AerodynamicForces forces)
473                         throws SimulationException {
474                 AerodynamicForces f;
475                 AerodynamicForces clone = forces.clone();
476                 int modID = status.getModID();
477                 
478                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
479                         if (l instanceof SimulationComputationListener) {
480                                 f = ((SimulationComputationListener) l).postAerodynamicCalculation(status, clone);
481                                 if (modID != status.getModID()) {
482                                         warn(status, l);
483                                         modID = status.getModID();
484                                 }
485                                 if (f != null && !f.equals(forces)) {
486                                         warn(status, l);
487                                         forces = f;
488                                         clone = forces.clone();
489                                 }
490                         }
491                 }
492                 return forces;
493         }
494         
495         
496
497
498
499         /**
500          * Fire preMassCalculation event.
501          * 
502          * @return      <code>null</code> normally, or overriding mass data.
503          */
504         public static MassData firePreMassCalculation(SimulationStatus status)
505                         throws SimulationException {
506                 MassData mass;
507                 int modID = status.getModID();
508                 
509                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
510                         if (l instanceof SimulationComputationListener) {
511                                 mass = ((SimulationComputationListener) l).preMassCalculation(status);
512                                 if (modID != status.getModID()) {
513                                         warn(status, l);
514                                         modID = status.getModID();
515                                 }
516                                 if (mass != null) {
517                                         warn(status, l);
518                                         return mass;
519                                 }
520                         }
521                 }
522                 return null;
523         }
524         
525         /**
526          * Fire postMassCalculation event.
527          * 
528          * @return      the aerodynamic forces to use.
529          */
530         public static MassData firePostMassCalculation(SimulationStatus status, MassData mass) throws SimulationException {
531                 MassData m;
532                 int modID = status.getModID();
533                 
534                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
535                         if (l instanceof SimulationComputationListener) {
536                                 m = ((SimulationComputationListener) l).postMassCalculation(status, mass);
537                                 if (modID != status.getModID()) {
538                                         warn(status, l);
539                                         modID = status.getModID();
540                                 }
541                                 if (m != null && !m.equals(mass)) {
542                                         warn(status, l);
543                                         mass = m;
544                                 }
545                         }
546                 }
547                 return mass;
548         }
549         
550         
551
552
553         /**
554          * Fire preThrustComputation event.
555          * 
556          * @return      <code>NaN</code> normally, or overriding thrust.
557          */
558         public static double firePreThrustCalculation(SimulationStatus status)
559                         throws SimulationException {
560                 double thrust;
561                 int modID = status.getModID();
562                 
563                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
564                         if (l instanceof SimulationComputationListener) {
565                                 thrust = ((SimulationComputationListener) l).preSimpleThrustCalculation(status);
566                                 if (modID != status.getModID()) {
567                                         warn(status, l);
568                                         modID = status.getModID();
569                                 }
570                                 if (!Double.isNaN(thrust)) {
571                                         warn(status, l);
572                                         return thrust;
573                                 }
574                         }
575                 }
576                 return Double.NaN;
577         }
578         
579         /**
580          * Fire postThrustComputation event.
581          * 
582          * @return      the thrust value to use.
583          */
584         public static double firePostThrustCalculation(SimulationStatus status, double thrust) throws SimulationException {
585                 double t;
586                 int modID = status.getModID();
587                 
588                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
589                         if (l instanceof SimulationComputationListener) {
590                                 t = ((SimulationComputationListener) l).postSimpleThrustCalculation(status, thrust);
591                                 if (modID != status.getModID()) {
592                                         warn(status, l);
593                                         modID = status.getModID();
594                                 }
595                                 if (!Double.isNaN(t) && !MathUtil.equals(t, thrust)) {
596                                         warn(status, l);
597                                         thrust = t;
598                                 }
599                         }
600                 }
601                 return thrust;
602         }
603         
604         
605
606
607
608         /**
609          * Fire preMassCalculation event.
610          * 
611          * @return      <code>null</code> normally, or overriding mass data.
612          */
613         public static AccelerationData firePreAccelerationCalculation(SimulationStatus status) throws SimulationException {
614                 AccelerationData acceleration;
615                 int modID = status.getModID();
616                 
617                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
618                         if (l instanceof SimulationComputationListener) {
619                                 acceleration = ((SimulationComputationListener) l).preAccelerationCalculation(status);
620                                 if (modID != status.getModID()) {
621                                         warn(status, l);
622                                         modID = status.getModID();
623                                 }
624                                 if (acceleration != null) {
625                                         warn(status, l);
626                                         return acceleration;
627                                 }
628                         }
629                 }
630                 return null;
631         }
632         
633         /**
634          * Fire postMassCalculation event.
635          * 
636          * @return      the aerodynamic forces to use.
637          */
638         public static AccelerationData firePostAccelerationCalculation(SimulationStatus status,
639                         AccelerationData acceleration) throws SimulationException {
640                 AccelerationData a;
641                 int modID = status.getModID();
642                 
643                 for (SimulationListener l : status.getSimulationConditions().getSimulationListenerList()) {
644                         if (l instanceof SimulationComputationListener) {
645                                 a = ((SimulationComputationListener) l).postAccelerationCalculation(status, acceleration);
646                                 if (modID != status.getModID()) {
647                                         warn(status, l);
648                                         modID = status.getModID();
649                                 }
650                                 if (a != null && !a.equals(acceleration)) {
651                                         warn(status, l);
652                                         acceleration = a;
653                                 }
654                         }
655                 }
656                 return acceleration;
657         }
658         
659         
660
661
662         private static void warn(SimulationStatus status, SimulationListener listener) {
663                 if (!listener.isSystemListener()) {
664                         log.info("Non-system listener " + listener + " affected the simulation");
665                         status.getWarnings().add(Warning.LISTENERS_AFFECTED);
666                 }
667         }
668 }