1   package org.opentrafficsim.swing.script;
2   
3   import java.awt.Dimension;
4   import java.rmi.RemoteException;
5   import java.util.HashMap;
6   import java.util.List;
7   import java.util.Map;
8   
9   import org.djunits.value.vdouble.scalar.Duration;
10  import org.djunits.value.vdouble.scalar.Time;
11  import org.djutils.exceptions.Throw;
12  import org.djutils.exceptions.Try;
13  import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
14  import org.opentrafficsim.core.dsol.OTSAnimator;
15  import org.opentrafficsim.core.dsol.OTSModelInterface;
16  import org.opentrafficsim.core.dsol.OTSSimulator;
17  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
18  import org.opentrafficsim.core.network.OTSLink;
19  import org.opentrafficsim.core.network.OTSNetwork;
20  import org.opentrafficsim.core.network.OTSNode;
21  import org.opentrafficsim.draw.core.OTSDrawingException;
22  import org.opentrafficsim.draw.factory.DefaultAnimationFactory;
23  import org.opentrafficsim.road.gtu.generator.GTUGenerator;
24  import org.opentrafficsim.road.network.lane.object.SpeedSign;
25  import org.opentrafficsim.swing.gui.AnimationToggles;
26  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
27  import org.opentrafficsim.swing.gui.OTSSwingApplication;
28  
29  import nl.tudelft.simulation.dsol.SimRuntimeException;
30  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
31  import nl.tudelft.simulation.dsol.model.outputstatistics.OutputStatistic;
32  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
33  import nl.tudelft.simulation.event.EventInterface;
34  import nl.tudelft.simulation.event.EventListenerInterface;
35  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
36  import nl.tudelft.simulation.jstats.streams.StreamInterface;
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  public abstract class AbstractSimulationScript implements EventListenerInterface
50  {
51      
52      final String name;
53  
54      
55      final String description;
56  
57      
58      OTSSimulatorInterface simulator;
59  
60      
61      private OTSNetwork network;
62  
63      
64      private final Map<String, String> props = new HashMap<>();
65  
66      
67      private GTUColorer gtuColorer = OTSSwingApplication.DEFAULT_COLORER;
68  
69      
70      protected OTSAnimationPanel animationPanel = null;
71  
72      
73  
74  
75  
76  
77  
78      protected AbstractSimulationScript(final String name, final String description, final String[] properties)
79      {
80          this.name = name;
81          this.description = description;
82          this.props.put("seed", "1");
83          this.props.put("startTime", "0");
84          this.props.put("warmupTime", "0");
85          this.props.put("simulationTime", "3600");
86          this.props.put("autorun", "false");
87          setDefaultProperties();
88          for (int i = 0; i < properties.length; i += 2)
89          {
90              System.out.println("Adding argument " + properties[i] + " with argument " + properties[i + 1]);
91              this.props.put(properties[i], properties[i + 1]);
92          }
93      }
94  
95      
96  
97  
98  
99  
100     public final void setProperty(final String propertyName, final Object propertyValue)
101     {
102         this.props.put(propertyName, propertyValue.toString());
103     }
104 
105     
106 
107 
108 
109 
110     public final String getProperty(final String propertyName)
111     {
112         String p = this.props.get(propertyName);
113         Throw.when(p == null, IllegalStateException.class, "Property %s is not given.", propertyName);
114         return p;
115     }
116 
117     
118 
119 
120 
121 
122     public final double getDoubleProperty(final String propertyName)
123     {
124         return Double.parseDouble(getProperty(propertyName));
125     }
126 
127     
128 
129 
130 
131 
132     public final boolean getBooleanProperty(final String propertyName)
133     {
134         return Boolean.parseBoolean(getProperty(propertyName));
135     }
136 
137     
138 
139 
140 
141 
142     public final int getIntegerProperty(final String propertyName)
143     {
144         return Integer.parseInt(getProperty(propertyName));
145     }
146 
147     
148 
149 
150 
151 
152     public final long getLongProperty(final String propertyName)
153     {
154         return Long.parseLong(getProperty(propertyName));
155     }
156 
157     
158 
159 
160 
161 
162     public final Duration getDurationProperty(final String propertyName)
163     {
164         return Duration.createSI(getDoubleProperty(propertyName));
165     }
166 
167     
168 
169 
170 
171 
172     public final Time getTimeProperty(final String propertyName)
173     {
174         return Time.createSI(getDoubleProperty(propertyName));
175     }
176 
177     
178 
179 
180 
181     public final void setGtuColorer(final GTUColorer colorer)
182     {
183         this.gtuColorer = colorer;
184     }
185 
186     
187 
188 
189 
190     public final GTUColorer getGtuColorer()
191     {
192         return this.gtuColorer;
193     }
194 
195     
196 
197 
198     public final void start()
199     {
200         Time startTime = getTimeProperty("startTime");
201         Duration warmupTime = getDurationProperty("warmupTime");
202         Duration simulationTime = getDurationProperty("simulationTime");
203         if (getBooleanProperty("autorun"))
204         {
205             try
206             {
207                 this.simulator = new OTSSimulator();
208                 final ScriptModel scriptModel = new ScriptModel(this.simulator);
209                 this.simulator.initialize(startTime, warmupTime, simulationTime, scriptModel);
210                 this.simulator.addListener(this, SimulatorInterface.END_REPLICATION_EVENT);
211                 double tReport = 60.0;
212                 Time t = this.simulator.getSimulatorTime();
213                 while (t.si < simulationTime.si)
214                 {
215                     this.simulator.step();
216                     t = this.simulator.getSimulatorTime();
217                     if (t.si >= tReport)
218                     {
219                         System.out.println("Simulation time is " + t);
220                         tReport += 60.0;
221                     }
222                 }
223                 
224                 onSimulationEnd(); 
225             }
226             catch (Exception exception)
227             {
228                 exception.printStackTrace();
229             }
230         }
231         else
232         {
233             try
234             {
235                 this.simulator = new OTSAnimator();
236                 final ScriptModel scriptModel = new ScriptModel(this.simulator);
237                 this.simulator.initialize(startTime, warmupTime, simulationTime, scriptModel);
238                 this.animationPanel = new OTSAnimationPanel(scriptModel.getNetwork().getExtent(), new Dimension(800, 600),
239                         (OTSAnimator) this.simulator, scriptModel, getGtuColorer(), scriptModel.getNetwork());
240                 addAnimationToggles(this.animationPanel);
241                 setupDemo(this.animationPanel, scriptModel.getNetwork());
242                 OTSSwingApplication app = new OTSSwingApplication(scriptModel, this.animationPanel);
243                 addTabs(this.simulator, app);
244                 app.setExitOnClose(true);
245             }
246             catch (Exception exception)
247             {
248                 exception.printStackTrace();
249             }
250         }
251     }
252 
253     
254     @Override
255     public final void notify(final EventInterface event) throws RemoteException
256     {
257         if (event.getType().equals(SimulatorInterface.END_REPLICATION_EVENT))
258         {
259             onSimulationEnd();
260             
261             AbstractSimulationScript.this.simulator.removeListener(AbstractSimulationScript.this,
262                     SimulatorInterface.END_REPLICATION_EVENT);
263         }
264     }
265 
266     
267 
268 
269 
270     public final OTSSimulatorInterface getSimulator()
271     {
272         return AbstractSimulationScript.this.simulator;
273     }
274 
275     
276 
277 
278 
279     public final OTSNetwork getNetwork()
280     {
281         return AbstractSimulationScript.this.network;
282     }
283 
284     
285 
286     
287 
288 
289 
290 
291     protected void animateNetwork(final OTSNetwork net, final boolean xmlNetwork)
292     {
293         try
294         {
295             if (xmlNetwork)
296             {
297                 DefaultAnimationFactory.animateXmlNetwork(net, getSimulator(), getGtuColorer());
298             }
299             else
300             {
301                 DefaultAnimationFactory.animateNetwork(net, getSimulator(), getGtuColorer());
302             }
303         }
304         catch (OTSDrawingException exception)
305         {
306             throw new RuntimeException("Exception while creating network animation.", exception);
307         }
308     }
309 
310     
311 
312 
313 
314 
315     protected void addTabs(final OTSSimulatorInterface sim, final OTSSwingApplication animation)
316     {
317         
318     }
319 
320     
321 
322 
323     protected void setDefaultProperties()
324     {
325         
326     }
327 
328     
329 
330 
331     protected void onSimulationEnd()
332     {
333         
334     }
335 
336     
337 
338 
339 
340 
341     protected void setupDemo(final OTSAnimationPanel animationPanel, final OTSNetwork net)
342     {
343         
344     }
345 
346     
347 
348 
349 
350     protected void addAnimationToggles(final OTSAnimationPanel animation)
351     {
352         AnimationToggles.setIconAnimationTogglesFull(animation);
353         animation.getAnimationPanel().toggleClass(OTSLink.class);
354         animation.getAnimationPanel().toggleClass(OTSNode.class);
355         animation.getAnimationPanel().toggleClass(GTUGenerator.class);
356         animation.getAnimationPanel().showClass(SpeedSign.class);
357     }
358 
359     
360 
361     
362 
363 
364 
365 
366 
367 
368     protected abstract OTSNetwork setupSimulation(OTSSimulatorInterface sim) throws Exception;
369 
370     
371 
372     
373 
374 
375 
376 
377 
378 
379 
380 
381 
382 
383 
384     private class ScriptModel implements OTSModelInterface
385     {
386         
387         private static final long serialVersionUID = 20180409L;
388 
389         
390 
391 
392         ScriptModel(final OTSSimulatorInterface simulator)
393         {
394             AbstractSimulationScript.this.simulator = simulator;
395         }
396 
397         
398         @SuppressWarnings("synthetic-access")
399         @Override
400         public void constructModel() throws SimRuntimeException
401         {
402             Map<String, StreamInterface> streams = new HashMap<>();
403             long seed = getLongProperty("seed");
404             StreamInterface stream = new MersenneTwister(seed);
405             streams.put("generation", stream);
406             stream = new MersenneTwister(seed + 1);
407             streams.put("default", stream);
408             AbstractSimulationScript.this.simulator.getReplication().setStreams(streams);
409             AbstractSimulationScript.this.network =
410                     Try.assign(() -> AbstractSimulationScript.this.setupSimulation(AbstractSimulationScript.this.simulator),
411                             RuntimeException.class, "Exception while setting up simulation.");
412             try
413             {
414                 AbstractSimulationScript.this.simulator.addListener(AbstractSimulationScript.this,
415                         SimulatorInterface.END_REPLICATION_EVENT);
416             }
417             catch (RemoteException exception)
418             {
419                 throw new SimRuntimeException(exception);
420             }
421         }
422 
423         
424         @Override
425         public OTSSimulatorInterface getSimulator()
426         {
427             return AbstractSimulationScript.this.simulator;
428         }
429 
430         
431         @SuppressWarnings("synthetic-access")
432         @Override
433         public OTSNetwork getNetwork()
434         {
435             return AbstractSimulationScript.this.network;
436         }
437 
438         
439         @Override
440         public InputParameterMap getInputParameterMap()
441         {
442             return null;
443         }
444 
445         
446         @Override
447         public List<OutputStatistic<?>> getOutputStatistics()
448         {
449             return null;
450         }
451 
452         
453         @Override
454         public String getShortName()
455         {
456             return AbstractSimulationScript.this.name;
457         }
458 
459         
460         @Override
461         public String getDescription()
462         {
463             return AbstractSimulationScript.this.description;
464         }
465     }
466 
467 }