multimodalsim-viewer 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- multimodalsim_viewer/common/__init__.py +0 -0
- multimodalsim_viewer/common/environments/.env +4 -0
- multimodalsim_viewer/common/utils.py +223 -0
- multimodalsim_viewer/server/http_routes.py +135 -125
- multimodalsim_viewer/server/log_manager.py +10 -15
- multimodalsim_viewer/server/scripts.py +106 -32
- multimodalsim_viewer/server/server.py +196 -210
- multimodalsim_viewer/server/simulation.py +167 -154
- multimodalsim_viewer/server/simulation_manager.py +570 -607
- multimodalsim_viewer/server/simulation_visualization_data_collector.py +729 -756
- multimodalsim_viewer/server/simulation_visualization_data_model.py +1552 -1693
- multimodalsim_viewer/ui/angular_app.py +40 -0
- multimodalsim_viewer/ui/static/chunk-6VAXIXEZ.js +7 -0
- multimodalsim_viewer/ui/static/{chunk-MTC2LSCT.js → chunk-IGIP6IOU.js} +1 -1
- multimodalsim_viewer/ui/static/environment.json +7 -0
- multimodalsim_viewer/ui/static/index.html +16 -15
- multimodalsim_viewer/ui/static/{main-X7OVCS3N.js → main-FGMGJ32M.js} +3648 -3648
- multimodalsim_viewer/ui/static/polyfills-FFHMD2TL.js +2 -2
- multimodalsim_viewer/ui/static/scripts/load-environment.script.js +20 -0
- multimodalsim_viewer/ui/static/styles-KU7LTPET.css +1 -1
- multimodalsim_viewer-0.0.2.dist-info/METADATA +70 -0
- multimodalsim_viewer-0.0.2.dist-info/RECORD +41 -0
- {multimodalsim_viewer-0.0.1.dist-info → multimodalsim_viewer-0.0.2.dist-info}/WHEEL +1 -1
- multimodalsim_viewer-0.0.2.dist-info/entry_points.txt +2 -0
- multimodalsim_viewer/server/server_utils.py +0 -129
- multimodalsim_viewer/ui/cli.py +0 -45
- multimodalsim_viewer/ui/server.py +0 -44
- multimodalsim_viewer/ui/static/chunk-U5CGW4P4.js +0 -7
- multimodalsim_viewer-0.0.1.dist-info/METADATA +0 -21
- multimodalsim_viewer-0.0.1.dist-info/RECORD +0 -38
- multimodalsim_viewer-0.0.1.dist-info/entry_points.txt +0 -8
- {multimodalsim_viewer-0.0.1.dist-info → multimodalsim_viewer-0.0.2.dist-info}/top_level.txt +0 -0
@@ -1,756 +1,729 @@
|
|
1
|
-
import threading
|
2
|
-
from typing import Optional
|
3
|
-
|
4
|
-
from multimodalsim.observer.data_collector import DataCollector
|
5
|
-
from multimodalsim.simulator.environment import Environment
|
6
|
-
from multimodalsim.simulator.event import Event, RecurrentTimeSyncEvent
|
7
|
-
from multimodalsim.simulator.optimization_event import (
|
8
|
-
EnvironmentIdle,
|
9
|
-
EnvironmentUpdate,
|
10
|
-
Hold,
|
11
|
-
Optimize,
|
12
|
-
)
|
13
|
-
from multimodalsim.simulator.passenger_event import (
|
14
|
-
PassengerAlighting,
|
15
|
-
PassengerAssignment,
|
16
|
-
PassengerReady,
|
17
|
-
PassengerRelease,
|
18
|
-
PassengerToBoard,
|
19
|
-
)
|
20
|
-
from multimodalsim.simulator.simulation import Simulation
|
21
|
-
from multimodalsim.simulator.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
from
|
35
|
-
|
36
|
-
from multimodalsim_viewer.
|
37
|
-
HOST,
|
38
|
-
|
39
|
-
STATE_SAVE_STEP,
|
40
|
-
SimulationStatus,
|
41
|
-
build_simulation_id,
|
42
|
-
)
|
43
|
-
from multimodalsim_viewer.server.
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
# MARK: Data Collector
|
62
|
-
class SimulationVisualizationDataCollector(DataCollector):
|
63
|
-
simulation_id: str
|
64
|
-
update_counter: int
|
65
|
-
visualized_environment: VisualizedEnvironment
|
66
|
-
simulation_information: SimulationInformation
|
67
|
-
current_save_file_path: str
|
68
|
-
|
69
|
-
max_duration: float | None
|
70
|
-
"
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
self.
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
self.
|
127
|
-
self.
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
self.
|
178
|
-
self.
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
self.
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
self.
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
print("
|
223
|
-
|
224
|
-
print(
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
self.
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
self
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
#
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
elif update.
|
355
|
-
vehicle = self.visualized_environment.get_vehicle(update.data.vehicle_id)
|
356
|
-
|
357
|
-
|
358
|
-
vehicle =
|
359
|
-
|
360
|
-
vehicle.
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
self.add_update(
|
434
|
-
Update(
|
435
|
-
UpdateType.
|
436
|
-
|
437
|
-
event.state_machine.owner,
|
438
|
-
),
|
439
|
-
event.time,
|
440
|
-
),
|
441
|
-
environment,
|
442
|
-
)
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
)
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
#
|
486
|
-
if
|
487
|
-
self.flush(environment)
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
)
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
else:
|
731
|
-
raise NotImplementedError(f"Event {event} not implemented")
|
732
|
-
|
733
|
-
# MARK: +- Clean Up
|
734
|
-
def clean_up(self, env):
|
735
|
-
self.simulation_information.simulation_end_time = (
|
736
|
-
self.visualized_environment.timestamp
|
737
|
-
)
|
738
|
-
self.simulation_information.last_update_order = (
|
739
|
-
self.visualized_environment.order
|
740
|
-
)
|
741
|
-
|
742
|
-
SimulationVisualizationDataManager.set_simulation_information(
|
743
|
-
self.simulation_id, self.simulation_information
|
744
|
-
)
|
745
|
-
|
746
|
-
if self.stop_event is not None:
|
747
|
-
self.stop_event.set()
|
748
|
-
|
749
|
-
if self.connection_thread is not None:
|
750
|
-
self.connection_thread.join()
|
751
|
-
|
752
|
-
if self.isConnected:
|
753
|
-
self.sio.disconnect()
|
754
|
-
|
755
|
-
if self.sio is not None:
|
756
|
-
self.sio.wait()
|
1
|
+
import threading
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from multimodalsim.observer.data_collector import DataCollector
|
5
|
+
from multimodalsim.simulator.environment import Environment
|
6
|
+
from multimodalsim.simulator.event import Event, RecurrentTimeSyncEvent
|
7
|
+
from multimodalsim.simulator.optimization_event import (
|
8
|
+
EnvironmentIdle,
|
9
|
+
EnvironmentUpdate,
|
10
|
+
Hold,
|
11
|
+
Optimize,
|
12
|
+
)
|
13
|
+
from multimodalsim.simulator.passenger_event import (
|
14
|
+
PassengerAlighting,
|
15
|
+
PassengerAssignment,
|
16
|
+
PassengerReady,
|
17
|
+
PassengerRelease,
|
18
|
+
PassengerToBoard,
|
19
|
+
)
|
20
|
+
from multimodalsim.simulator.simulation import Simulation
|
21
|
+
from multimodalsim.simulator.vehicle_event import (
|
22
|
+
VehicleAlighted,
|
23
|
+
VehicleArrival,
|
24
|
+
VehicleBoarded,
|
25
|
+
VehicleBoarding,
|
26
|
+
VehicleComplete,
|
27
|
+
VehicleDeparture,
|
28
|
+
VehicleNotification,
|
29
|
+
VehicleReady,
|
30
|
+
VehicleUpdatePositionEvent,
|
31
|
+
VehicleWaiting,
|
32
|
+
)
|
33
|
+
from multimodalsim.statistics.data_analyzer import DataAnalyzer
|
34
|
+
from socketio import Client
|
35
|
+
|
36
|
+
from multimodalsim_viewer.common.utils import (
|
37
|
+
HOST,
|
38
|
+
SERVER_PORT,
|
39
|
+
STATE_SAVE_STEP,
|
40
|
+
SimulationStatus,
|
41
|
+
build_simulation_id,
|
42
|
+
)
|
43
|
+
from multimodalsim_viewer.server.log_manager import register_log
|
44
|
+
from multimodalsim_viewer.server.simulation_visualization_data_model import (
|
45
|
+
PassengerLegsUpdate,
|
46
|
+
PassengerStatusUpdate,
|
47
|
+
SimulationInformation,
|
48
|
+
SimulationVisualizationDataManager,
|
49
|
+
StatisticUpdate,
|
50
|
+
Update,
|
51
|
+
UpdateType,
|
52
|
+
VehicleStatusUpdate,
|
53
|
+
VehicleStopsUpdate,
|
54
|
+
VisualizedEnvironment,
|
55
|
+
VisualizedPassenger,
|
56
|
+
VisualizedStop,
|
57
|
+
VisualizedVehicle,
|
58
|
+
)
|
59
|
+
|
60
|
+
|
61
|
+
# MARK: Data Collector
|
62
|
+
class SimulationVisualizationDataCollector(DataCollector): # pylint: disable=too-many-instance-attributes
|
63
|
+
simulation_id: str
|
64
|
+
update_counter: int
|
65
|
+
visualized_environment: VisualizedEnvironment
|
66
|
+
simulation_information: SimulationInformation
|
67
|
+
current_save_file_path: str
|
68
|
+
|
69
|
+
max_duration: float | None
|
70
|
+
"""
|
71
|
+
Maximum duration of the simulation in in-simulation time (seconds).
|
72
|
+
The simulation will stop if it exceeds this duration.
|
73
|
+
"""
|
74
|
+
|
75
|
+
# Special events
|
76
|
+
last_queued_event_time: float
|
77
|
+
passenger_assignment_event_queue: list[PassengerAssignment]
|
78
|
+
vehicle_notification_event_queue: list[VehicleNotification]
|
79
|
+
|
80
|
+
# Statistics
|
81
|
+
data_analyzer: DataAnalyzer
|
82
|
+
statistics_delta_time: int
|
83
|
+
last_statistics_update_time: int
|
84
|
+
|
85
|
+
# Communication
|
86
|
+
sio: Client | None = None
|
87
|
+
stop_event: threading.Event | None = None
|
88
|
+
connection_thread: threading.Thread | None = None
|
89
|
+
_simulation: Simulation | None = None
|
90
|
+
status: SimulationStatus | None = None
|
91
|
+
|
92
|
+
# Polylines
|
93
|
+
saved_polylines_coordinates_pairs: set[str] = set()
|
94
|
+
|
95
|
+
# Estimated end time
|
96
|
+
last_estimated_end_time: float | None = None
|
97
|
+
|
98
|
+
def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments
|
99
|
+
self,
|
100
|
+
data_analyzer: DataAnalyzer,
|
101
|
+
statistics_delta_time: int = 10,
|
102
|
+
name: str = "simulation",
|
103
|
+
input_data_description: str = "unknown",
|
104
|
+
simulation_id: str | None = None,
|
105
|
+
max_duration: float | None = None,
|
106
|
+
offline: bool = False,
|
107
|
+
stop_event: threading.Event | None = None,
|
108
|
+
) -> None:
|
109
|
+
super().__init__()
|
110
|
+
|
111
|
+
if simulation_id is None:
|
112
|
+
simulation_id, _ = build_simulation_id(name)
|
113
|
+
|
114
|
+
self.simulation_id = simulation_id
|
115
|
+
self.update_counter = 0
|
116
|
+
self.visualized_environment = VisualizedEnvironment()
|
117
|
+
|
118
|
+
self.simulation_information = SimulationInformation(
|
119
|
+
simulation_id, input_data_description, None, None, None, None
|
120
|
+
)
|
121
|
+
|
122
|
+
self.current_save_file_path = None
|
123
|
+
|
124
|
+
self.max_duration = max_duration
|
125
|
+
|
126
|
+
self.passenger_assignment_event_queue = []
|
127
|
+
self.vehicle_notification_event_queue = []
|
128
|
+
self.last_queued_event_time = 0
|
129
|
+
|
130
|
+
self.data_analyzer = data_analyzer
|
131
|
+
self.statistics_delta_time = statistics_delta_time
|
132
|
+
self.last_statistics_update_time = None
|
133
|
+
|
134
|
+
self.stop_event = stop_event
|
135
|
+
|
136
|
+
if not offline:
|
137
|
+
self.initialize_communication()
|
138
|
+
|
139
|
+
@property
|
140
|
+
def is_connected(self) -> bool:
|
141
|
+
return self.sio is not None and self.sio.connected
|
142
|
+
|
143
|
+
# MARK: +- Communication
|
144
|
+
def initialize_communication(self) -> None:
|
145
|
+
sio = Client(reconnection_attempts=1)
|
146
|
+
|
147
|
+
self.sio = sio
|
148
|
+
self.status = SimulationStatus.RUNNING
|
149
|
+
|
150
|
+
@sio.on("pause-simulation")
|
151
|
+
def pause_simulator():
|
152
|
+
if self._simulation is not None:
|
153
|
+
self._simulation.pause()
|
154
|
+
self.status = SimulationStatus.PAUSED
|
155
|
+
if self.is_connected:
|
156
|
+
self.sio.emit("simulation-pause", self.simulation_id)
|
157
|
+
|
158
|
+
@sio.on("resume-simulation")
|
159
|
+
def resume_simulator():
|
160
|
+
if self._simulation is not None:
|
161
|
+
self._simulation.resume()
|
162
|
+
self.status = SimulationStatus.RUNNING
|
163
|
+
if self.is_connected:
|
164
|
+
self.sio.emit("simulation-resume", self.simulation_id)
|
165
|
+
|
166
|
+
@sio.on("stop-simulation")
|
167
|
+
def stop_simulator():
|
168
|
+
if self._simulation is not None:
|
169
|
+
self._simulation.stop()
|
170
|
+
self.status = SimulationStatus.STOPPING
|
171
|
+
|
172
|
+
@sio.on("connect")
|
173
|
+
def on_connect():
|
174
|
+
sio.emit(
|
175
|
+
"simulation-identification",
|
176
|
+
(
|
177
|
+
self.simulation_id,
|
178
|
+
self.simulation_information.data,
|
179
|
+
self.simulation_information.simulation_start_time,
|
180
|
+
self.visualized_environment.timestamp,
|
181
|
+
self.visualized_environment.estimated_end_time,
|
182
|
+
self.max_duration,
|
183
|
+
self.status.value,
|
184
|
+
),
|
185
|
+
)
|
186
|
+
|
187
|
+
@sio.on("edit-simulation-configuration")
|
188
|
+
def on_edit_simulation_configuration(max_duration: float | None):
|
189
|
+
self.max_duration = max_duration
|
190
|
+
|
191
|
+
if self.last_estimated_end_time is None:
|
192
|
+
return
|
193
|
+
|
194
|
+
# Notify the server if the estimated end time has changed
|
195
|
+
new_estimated_end_time = min(
|
196
|
+
self.last_estimated_end_time,
|
197
|
+
(
|
198
|
+
self.simulation_information.simulation_start_time + self.max_duration
|
199
|
+
if self.max_duration is not None
|
200
|
+
else self.last_estimated_end_time
|
201
|
+
),
|
202
|
+
)
|
203
|
+
|
204
|
+
if new_estimated_end_time != self.visualized_environment.estimated_end_time:
|
205
|
+
self.sio.emit(
|
206
|
+
"simulation-update-estimated-end-time",
|
207
|
+
(self.simulation_id, new_estimated_end_time),
|
208
|
+
)
|
209
|
+
self.visualized_environment.estimated_end_time = new_estimated_end_time
|
210
|
+
|
211
|
+
if self.stop_event is None:
|
212
|
+
self.stop_event = threading.Event()
|
213
|
+
|
214
|
+
self.connection_thread = threading.Thread(target=self.handle_connection)
|
215
|
+
self.connection_thread.start()
|
216
|
+
|
217
|
+
def handle_connection(self) -> None:
|
218
|
+
while not self.stop_event.is_set():
|
219
|
+
|
220
|
+
if not self.sio.connected:
|
221
|
+
try:
|
222
|
+
print("Trying to reconnect")
|
223
|
+
self.sio.connect(f"http://{HOST}:{SERVER_PORT}", auth={"type": "simulation"})
|
224
|
+
print("Connected")
|
225
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
226
|
+
print(f"Failed to connect to server: {e}")
|
227
|
+
print("Continuing in offline mode")
|
228
|
+
|
229
|
+
self.sio.sleep(5) # Check every 5 seconds
|
230
|
+
|
231
|
+
self.sio.disconnect()
|
232
|
+
self.sio.wait()
|
233
|
+
|
234
|
+
# MARK: +- Collect
|
235
|
+
def collect(
|
236
|
+
self,
|
237
|
+
env: Environment,
|
238
|
+
current_event: Optional[Event] = None,
|
239
|
+
event_index: Optional[int] = None,
|
240
|
+
event_priority: Optional[int] = None,
|
241
|
+
) -> None:
|
242
|
+
env.simulation_config.max_time = (
|
243
|
+
(
|
244
|
+
(
|
245
|
+
self.simulation_information.simulation_start_time
|
246
|
+
if self.simulation_information.simulation_start_time is not None
|
247
|
+
else env.current_time
|
248
|
+
)
|
249
|
+
+ self.max_duration
|
250
|
+
)
|
251
|
+
if self.max_duration is not None
|
252
|
+
else env.simulation_config.max_time
|
253
|
+
)
|
254
|
+
|
255
|
+
if current_event is None:
|
256
|
+
return
|
257
|
+
|
258
|
+
message = self.process_event(current_event, env)
|
259
|
+
register_log(self.simulation_id, message)
|
260
|
+
|
261
|
+
if self.is_connected:
|
262
|
+
self.sio.emit("log", (self.simulation_id, message))
|
263
|
+
|
264
|
+
if (
|
265
|
+
self.last_statistics_update_time is None
|
266
|
+
or current_event.time >= self.last_statistics_update_time + self.statistics_delta_time
|
267
|
+
):
|
268
|
+
self.last_statistics_update_time = current_event.time
|
269
|
+
self.add_update(
|
270
|
+
Update(
|
271
|
+
UpdateType.UPDATE_STATISTIC,
|
272
|
+
StatisticUpdate(self.data_analyzer.get_statistics()),
|
273
|
+
current_event.time,
|
274
|
+
),
|
275
|
+
env,
|
276
|
+
)
|
277
|
+
|
278
|
+
# MARK: +- Add Update
|
279
|
+
def add_update( # pylint: disable=too-many-branches, too-many-statements
|
280
|
+
self, update: Update, environment: Environment
|
281
|
+
) -> None:
|
282
|
+
update.order = self.update_counter
|
283
|
+
self.visualized_environment.order = self.update_counter
|
284
|
+
|
285
|
+
if self.update_counter == 0:
|
286
|
+
# Add the simulation start time to the simulation information
|
287
|
+
self.simulation_information.simulation_start_time = update.timestamp
|
288
|
+
|
289
|
+
# Save the simulation information
|
290
|
+
SimulationVisualizationDataManager.set_simulation_information(
|
291
|
+
self.simulation_id, self.simulation_information
|
292
|
+
)
|
293
|
+
|
294
|
+
# Notify the server that the simulation has started and send the simulation start time
|
295
|
+
if self.is_connected:
|
296
|
+
self.sio.emit("simulation-start", (self.simulation_id, update.timestamp))
|
297
|
+
|
298
|
+
if self.visualized_environment.timestamp != update.timestamp:
|
299
|
+
# Notify the server that the simulation time has been updated
|
300
|
+
if self.is_connected:
|
301
|
+
self.sio.emit(
|
302
|
+
"simulation-update-time",
|
303
|
+
(
|
304
|
+
self.simulation_id,
|
305
|
+
update.timestamp,
|
306
|
+
),
|
307
|
+
)
|
308
|
+
self.visualized_environment.timestamp = update.timestamp
|
309
|
+
|
310
|
+
# Remember the last estimated end time in case of max_duration updates
|
311
|
+
self.last_estimated_end_time = environment.estimated_end_time
|
312
|
+
estimated_end_time = min(
|
313
|
+
environment.estimated_end_time,
|
314
|
+
(
|
315
|
+
self.simulation_information.simulation_start_time + self.max_duration
|
316
|
+
if self.max_duration is not None
|
317
|
+
else environment.estimated_end_time
|
318
|
+
),
|
319
|
+
)
|
320
|
+
if estimated_end_time != self.visualized_environment.estimated_end_time:
|
321
|
+
# Notify the server that the simulation estimated end time has been updated
|
322
|
+
if self.is_connected:
|
323
|
+
self.sio.emit(
|
324
|
+
"simulation-update-estimated-end-time",
|
325
|
+
(self.simulation_id, estimated_end_time),
|
326
|
+
)
|
327
|
+
self.visualized_environment.estimated_end_time = estimated_end_time
|
328
|
+
|
329
|
+
# Save the state of the simulation every SAVE_STATE_STEP events before applying the update
|
330
|
+
if self.update_counter % STATE_SAVE_STEP == 0:
|
331
|
+
self.current_save_file_path = SimulationVisualizationDataManager.save_state(
|
332
|
+
self.simulation_id, self.visualized_environment
|
333
|
+
)
|
334
|
+
|
335
|
+
if update.update_type == UpdateType.CREATE_PASSENGER:
|
336
|
+
self.visualized_environment.add_passenger(update.data)
|
337
|
+
elif update.update_type == UpdateType.CREATE_VEHICLE:
|
338
|
+
self.visualized_environment.add_vehicle(update.data)
|
339
|
+
data: VisualizedVehicle = update.data
|
340
|
+
if data.polylines is not None:
|
341
|
+
self.update_polylines_if_needed(data)
|
342
|
+
elif update.update_type == UpdateType.UPDATE_PASSENGER_STATUS:
|
343
|
+
passenger = self.visualized_environment.get_passenger(update.data.passenger_id)
|
344
|
+
passenger.status = update.data.status
|
345
|
+
elif update.update_type == UpdateType.UPDATE_PASSENGER_LEGS:
|
346
|
+
passenger = self.visualized_environment.get_passenger(update.data.passenger_id)
|
347
|
+
legs_update: PassengerLegsUpdate = update.data
|
348
|
+
passenger.previous_legs = legs_update.previous_legs
|
349
|
+
passenger.next_legs = legs_update.next_legs
|
350
|
+
passenger.current_leg = legs_update.current_leg
|
351
|
+
elif update.update_type == UpdateType.UPDATE_VEHICLE_STATUS:
|
352
|
+
vehicle = self.visualized_environment.get_vehicle(update.data.vehicle_id)
|
353
|
+
vehicle.status = update.data.status
|
354
|
+
elif update.update_type == UpdateType.UPDATE_VEHICLE_STOPS:
|
355
|
+
vehicle = self.visualized_environment.get_vehicle(update.data.vehicle_id)
|
356
|
+
stops_update: VehicleStopsUpdate = update.data
|
357
|
+
vehicle.previous_stops = stops_update.previous_stops
|
358
|
+
vehicle.next_stops = stops_update.next_stops
|
359
|
+
vehicle.current_stop = stops_update.current_stop
|
360
|
+
if vehicle.polylines is not None:
|
361
|
+
self.update_polylines_if_needed(vehicle)
|
362
|
+
elif update.update_type == UpdateType.UPDATE_STATISTIC:
|
363
|
+
statistic_update: StatisticUpdate = update.data
|
364
|
+
self.visualized_environment.statistic = statistic_update.statistic
|
365
|
+
|
366
|
+
SimulationVisualizationDataManager.save_update(self.current_save_file_path, update)
|
367
|
+
|
368
|
+
self.update_counter += 1
|
369
|
+
|
370
|
+
# MARK: +- Polylines
|
371
|
+
def update_polylines_if_needed(self, vehicle: VisualizedVehicle) -> None:
|
372
|
+
polylines = vehicle.polylines
|
373
|
+
stops = vehicle.all_stops
|
374
|
+
|
375
|
+
# A polyline needs to have at least 2 points
|
376
|
+
if len(stops) < 2:
|
377
|
+
return
|
378
|
+
|
379
|
+
# Notify if their are not enough polylines
|
380
|
+
if len(polylines) < len(stops) - 1:
|
381
|
+
raise ValueError(f"Vehicle {vehicle.vehicle_id} has not enough polylines for its stops")
|
382
|
+
|
383
|
+
stops_pairs: list[tuple[tuple[VisualizedStop, VisualizedStop], tuple[str, list[float]]]] = zip(
|
384
|
+
[(stops[i], stops[i + 1]) for i in range(len(stops) - 1)],
|
385
|
+
polylines.values(),
|
386
|
+
strict=False, # There may be more polylines than stops
|
387
|
+
)
|
388
|
+
|
389
|
+
polylines_to_save: dict[str, tuple[str, list[float]]] = {}
|
390
|
+
|
391
|
+
for stop_pair, polyline in stops_pairs:
|
392
|
+
first_stop, second_stop = stop_pair
|
393
|
+
|
394
|
+
if (
|
395
|
+
first_stop.latitude is None
|
396
|
+
or first_stop.longitude is None
|
397
|
+
or second_stop.latitude is None
|
398
|
+
or second_stop.longitude is None
|
399
|
+
):
|
400
|
+
raise ValueError(f"Vehicle {vehicle.vehicle_id} has stops without coordinates")
|
401
|
+
|
402
|
+
coordinates_pair = (
|
403
|
+
f"{first_stop.latitude},{first_stop.longitude},{second_stop.latitude},{second_stop.longitude}"
|
404
|
+
)
|
405
|
+
|
406
|
+
if coordinates_pair not in self.saved_polylines_coordinates_pairs:
|
407
|
+
polylines_to_save[coordinates_pair] = polyline
|
408
|
+
self.saved_polylines_coordinates_pairs.add(coordinates_pair)
|
409
|
+
|
410
|
+
if len(polylines_to_save) > 0:
|
411
|
+
SimulationVisualizationDataManager.set_polylines(self.simulation_id, polylines_to_save)
|
412
|
+
|
413
|
+
if self.is_connected:
|
414
|
+
self.sio.emit(
|
415
|
+
"simulation-update-polylines-version",
|
416
|
+
self.simulation_id,
|
417
|
+
)
|
418
|
+
|
419
|
+
# MARK: +- Flush
|
420
|
+
def flush(self, environment) -> None:
|
421
|
+
for event in self.passenger_assignment_event_queue:
|
422
|
+
self.add_update(
|
423
|
+
Update(
|
424
|
+
UpdateType.UPDATE_PASSENGER_STATUS,
|
425
|
+
PassengerStatusUpdate.from_trip(
|
426
|
+
event.state_machine.owner,
|
427
|
+
),
|
428
|
+
event.time,
|
429
|
+
),
|
430
|
+
environment,
|
431
|
+
)
|
432
|
+
previous_passenger = self.visualized_environment.get_passenger(event.state_machine.owner.id)
|
433
|
+
self.add_update(
|
434
|
+
Update(
|
435
|
+
UpdateType.UPDATE_PASSENGER_LEGS,
|
436
|
+
PassengerLegsUpdate.from_trip_environment_and_previous_passenger(
|
437
|
+
event.state_machine.owner, environment, previous_passenger
|
438
|
+
),
|
439
|
+
event.time,
|
440
|
+
),
|
441
|
+
environment,
|
442
|
+
)
|
443
|
+
|
444
|
+
for event in self.vehicle_notification_event_queue:
|
445
|
+
vehicle = event._VehicleNotification__vehicle # pylint: disable=protected-access
|
446
|
+
route = event._VehicleNotification__route # pylint: disable=protected-access
|
447
|
+
existing_vehicle = self.visualized_environment.get_vehicle(vehicle.id)
|
448
|
+
if vehicle.polylines != existing_vehicle.polylines:
|
449
|
+
existing_vehicle.polylines = vehicle.polylines
|
450
|
+
|
451
|
+
self.add_update(
|
452
|
+
Update(
|
453
|
+
UpdateType.UPDATE_VEHICLE_STOPS,
|
454
|
+
VehicleStopsUpdate.from_vehicle_and_route(vehicle, route),
|
455
|
+
event.time,
|
456
|
+
),
|
457
|
+
environment,
|
458
|
+
)
|
459
|
+
|
460
|
+
self.passenger_assignment_event_queue = []
|
461
|
+
self.vehicle_notification_event_queue = []
|
462
|
+
|
463
|
+
@property
|
464
|
+
def has_to_flush(self) -> bool:
|
465
|
+
return len(self.passenger_assignment_event_queue) > 0 or len(self.vehicle_notification_event_queue) > 0
|
466
|
+
|
467
|
+
# MARK: +- Process Event
|
468
|
+
def process_event( # pylint: disable=too-many-branches, too-many-statements, too-many-return-statements
|
469
|
+
self, event: Event, environment: Environment
|
470
|
+
) -> str:
|
471
|
+
# In case that a queued event is not linked to EnvironmentIdle
|
472
|
+
if self.has_to_flush and event.time > self.last_queued_event_time:
|
473
|
+
self.flush(environment)
|
474
|
+
|
475
|
+
# Optimize
|
476
|
+
if isinstance(event, Optimize):
|
477
|
+
# Do nothing ?
|
478
|
+
return f"{event.time} TODO Optimize"
|
479
|
+
|
480
|
+
# EnvironmentUpdate
|
481
|
+
if isinstance(event, EnvironmentUpdate):
|
482
|
+
# Do nothing ?
|
483
|
+
return f"{event.time} TODO EnvironmentUpdate"
|
484
|
+
|
485
|
+
# EnvironmentIdle
|
486
|
+
if isinstance(event, EnvironmentIdle):
|
487
|
+
self.flush(environment)
|
488
|
+
return f"{event.time} TODO EnvironmentIdle"
|
489
|
+
|
490
|
+
# PassengerRelease
|
491
|
+
if isinstance(event, PassengerRelease):
|
492
|
+
passenger = VisualizedPassenger.from_trip_and_environment(event.trip, environment)
|
493
|
+
self.add_update(
|
494
|
+
Update(
|
495
|
+
UpdateType.CREATE_PASSENGER,
|
496
|
+
passenger,
|
497
|
+
event.time,
|
498
|
+
),
|
499
|
+
environment,
|
500
|
+
)
|
501
|
+
return f"{event.time} TODO PassengerRelease"
|
502
|
+
|
503
|
+
# PassengerAssignment
|
504
|
+
if isinstance(event, PassengerAssignment):
|
505
|
+
self.passenger_assignment_event_queue.append(event)
|
506
|
+
self.last_queued_event_time = event.time
|
507
|
+
return f"{event.time} TODO PassengerAssignment"
|
508
|
+
|
509
|
+
# PassengerReady
|
510
|
+
if isinstance(event, PassengerReady):
|
511
|
+
self.add_update(
|
512
|
+
Update(
|
513
|
+
UpdateType.UPDATE_PASSENGER_STATUS,
|
514
|
+
PassengerStatusUpdate.from_trip(
|
515
|
+
event.state_machine.owner,
|
516
|
+
),
|
517
|
+
event.time,
|
518
|
+
),
|
519
|
+
environment,
|
520
|
+
)
|
521
|
+
return f"{event.time} TODO PassengerReady"
|
522
|
+
|
523
|
+
# PassengerToBoard
|
524
|
+
if isinstance(event, PassengerToBoard):
|
525
|
+
self.add_update(
|
526
|
+
Update(
|
527
|
+
UpdateType.UPDATE_PASSENGER_STATUS,
|
528
|
+
PassengerStatusUpdate.from_trip(
|
529
|
+
event.state_machine.owner,
|
530
|
+
),
|
531
|
+
event.time,
|
532
|
+
),
|
533
|
+
environment,
|
534
|
+
)
|
535
|
+
previous_passenger = self.visualized_environment.get_passenger(event.state_machine.owner.id)
|
536
|
+
self.add_update(
|
537
|
+
Update(
|
538
|
+
UpdateType.UPDATE_PASSENGER_LEGS,
|
539
|
+
PassengerLegsUpdate.from_trip_environment_and_previous_passenger(
|
540
|
+
event.state_machine.owner, environment, previous_passenger
|
541
|
+
),
|
542
|
+
event.time,
|
543
|
+
),
|
544
|
+
environment,
|
545
|
+
)
|
546
|
+
return f"{event.time} TODO PassengerToBoard"
|
547
|
+
|
548
|
+
# PassengerAlighting
|
549
|
+
if isinstance(event, PassengerAlighting):
|
550
|
+
self.add_update(
|
551
|
+
Update(
|
552
|
+
UpdateType.UPDATE_PASSENGER_STATUS,
|
553
|
+
PassengerStatusUpdate.from_trip(
|
554
|
+
event.state_machine.owner,
|
555
|
+
),
|
556
|
+
event.time,
|
557
|
+
),
|
558
|
+
environment,
|
559
|
+
)
|
560
|
+
previous_passenger = self.visualized_environment.get_passenger(event.state_machine.owner.id)
|
561
|
+
self.add_update(
|
562
|
+
Update(
|
563
|
+
UpdateType.UPDATE_PASSENGER_LEGS,
|
564
|
+
PassengerLegsUpdate.from_trip_environment_and_previous_passenger(
|
565
|
+
event.state_machine.owner, environment, previous_passenger
|
566
|
+
),
|
567
|
+
event.time,
|
568
|
+
),
|
569
|
+
environment,
|
570
|
+
)
|
571
|
+
return f"{event.time} TODO PassengerAlighting"
|
572
|
+
|
573
|
+
# VehicleWaiting
|
574
|
+
if isinstance(event, VehicleWaiting):
|
575
|
+
self.add_update(
|
576
|
+
Update(
|
577
|
+
UpdateType.UPDATE_VEHICLE_STATUS,
|
578
|
+
VehicleStatusUpdate.from_vehicle(event.state_machine.owner),
|
579
|
+
event.time,
|
580
|
+
),
|
581
|
+
environment,
|
582
|
+
)
|
583
|
+
return f"{event.time} TODO VehicleWaiting"
|
584
|
+
|
585
|
+
# VehicleBoarding
|
586
|
+
if isinstance(event, VehicleBoarding):
|
587
|
+
self.add_update(
|
588
|
+
Update(
|
589
|
+
UpdateType.UPDATE_VEHICLE_STATUS,
|
590
|
+
VehicleStatusUpdate.from_vehicle(
|
591
|
+
event.state_machine.owner,
|
592
|
+
),
|
593
|
+
event.time,
|
594
|
+
),
|
595
|
+
environment,
|
596
|
+
)
|
597
|
+
return f"{event.time} TODO VehicleBoarding"
|
598
|
+
|
599
|
+
# VehicleDeparture
|
600
|
+
if isinstance(event, VehicleDeparture):
|
601
|
+
route = event._VehicleDeparture__route # pylint: disable=protected-access
|
602
|
+
vehicle = event.state_machine.owner
|
603
|
+
|
604
|
+
self.add_update(
|
605
|
+
Update(
|
606
|
+
UpdateType.UPDATE_VEHICLE_STATUS,
|
607
|
+
VehicleStatusUpdate.from_vehicle(
|
608
|
+
event.state_machine.owner,
|
609
|
+
),
|
610
|
+
event.time,
|
611
|
+
),
|
612
|
+
environment,
|
613
|
+
)
|
614
|
+
|
615
|
+
self.add_update(
|
616
|
+
Update(
|
617
|
+
UpdateType.UPDATE_VEHICLE_STOPS,
|
618
|
+
VehicleStopsUpdate.from_vehicle_and_route(vehicle, route),
|
619
|
+
event.time,
|
620
|
+
),
|
621
|
+
environment,
|
622
|
+
)
|
623
|
+
return f"{event.time} TODO VehicleDeparture"
|
624
|
+
|
625
|
+
# VehicleArrival
|
626
|
+
if isinstance(event, VehicleArrival):
|
627
|
+
route = event._VehicleArrival__route # pylint: disable=protected-access
|
628
|
+
vehicle = event.state_machine.owner
|
629
|
+
|
630
|
+
self.add_update(
|
631
|
+
Update(
|
632
|
+
UpdateType.UPDATE_VEHICLE_STATUS,
|
633
|
+
VehicleStatusUpdate.from_vehicle(
|
634
|
+
event.state_machine.owner,
|
635
|
+
),
|
636
|
+
event.time,
|
637
|
+
),
|
638
|
+
environment,
|
639
|
+
)
|
640
|
+
|
641
|
+
self.add_update(
|
642
|
+
Update(
|
643
|
+
UpdateType.UPDATE_VEHICLE_STOPS,
|
644
|
+
VehicleStopsUpdate.from_vehicle_and_route(vehicle, route),
|
645
|
+
event.time,
|
646
|
+
),
|
647
|
+
environment,
|
648
|
+
)
|
649
|
+
|
650
|
+
return f"{event.time} TODO VehicleArrival"
|
651
|
+
|
652
|
+
# VehicleComplete
|
653
|
+
if isinstance(event, VehicleComplete):
|
654
|
+
self.add_update(
|
655
|
+
Update(
|
656
|
+
UpdateType.UPDATE_VEHICLE_STATUS,
|
657
|
+
VehicleStatusUpdate.from_vehicle(
|
658
|
+
event.state_machine.owner,
|
659
|
+
),
|
660
|
+
event.time,
|
661
|
+
),
|
662
|
+
environment,
|
663
|
+
)
|
664
|
+
return f"{event.time} TODO VehicleComplete"
|
665
|
+
|
666
|
+
# VehicleReady
|
667
|
+
if isinstance(event, VehicleReady):
|
668
|
+
vehicle = VisualizedVehicle.from_vehicle_and_route(
|
669
|
+
event.vehicle, event._VehicleReady__route # pylint: disable=protected-access
|
670
|
+
)
|
671
|
+
self.add_update(
|
672
|
+
Update(
|
673
|
+
UpdateType.CREATE_VEHICLE,
|
674
|
+
vehicle,
|
675
|
+
event.time,
|
676
|
+
),
|
677
|
+
environment,
|
678
|
+
)
|
679
|
+
return f"{event.time} TODO VehicleReady"
|
680
|
+
|
681
|
+
# VehicleNotification
|
682
|
+
if isinstance(event, VehicleNotification):
|
683
|
+
self.vehicle_notification_event_queue.append(event)
|
684
|
+
self.last_queued_event_time = event.time
|
685
|
+
return f"{event.time} TODO VehicleNotification"
|
686
|
+
|
687
|
+
# VehicleBoarded
|
688
|
+
if isinstance(event, VehicleBoarded):
|
689
|
+
return f"{event.time} TODO VehicleBoarded"
|
690
|
+
|
691
|
+
# VehicleAlighted
|
692
|
+
if isinstance(event, VehicleAlighted):
|
693
|
+
return f"{event.time} TODO VehicleAlighted"
|
694
|
+
|
695
|
+
# VehicleUpdatePositionEvent
|
696
|
+
if isinstance(event, VehicleUpdatePositionEvent):
|
697
|
+
# Do nothing ?
|
698
|
+
return f"{event.time} TODO VehicleUpdatePositionEvent"
|
699
|
+
|
700
|
+
# RecurrentTimeSyncEvent
|
701
|
+
if isinstance(event, RecurrentTimeSyncEvent):
|
702
|
+
# Do nothing ?
|
703
|
+
return f"{event.time} TODO RecurrentTimeSyncEvent"
|
704
|
+
|
705
|
+
# Hold
|
706
|
+
if isinstance(event, Hold):
|
707
|
+
# Do nothing ?
|
708
|
+
return f"{event.time} TODO Hold"
|
709
|
+
|
710
|
+
raise NotImplementedError(f"Event {event} not implemented")
|
711
|
+
|
712
|
+
# MARK: +- Clean Up
|
713
|
+
def clean_up(self, env):
|
714
|
+
self.simulation_information.simulation_end_time = self.visualized_environment.timestamp
|
715
|
+
self.simulation_information.last_update_order = self.visualized_environment.order
|
716
|
+
|
717
|
+
SimulationVisualizationDataManager.set_simulation_information(self.simulation_id, self.simulation_information)
|
718
|
+
|
719
|
+
if self.stop_event is not None:
|
720
|
+
self.stop_event.set()
|
721
|
+
|
722
|
+
if self.connection_thread is not None:
|
723
|
+
self.connection_thread.join()
|
724
|
+
|
725
|
+
if self.is_connected:
|
726
|
+
self.sio.disconnect()
|
727
|
+
|
728
|
+
if self.sio is not None:
|
729
|
+
self.sio.wait()
|