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 }