1 use crate::analytics::Window;
2 use crate::{
3     AgentID, AgentType, AlertLocation, Analytics, CapSimState, CarID, Command, CreateCar,
4     DrawCarInput, DrawPedCrowdInput, DrawPedestrianInput, DrivingSimState, Event, GetDrawAgents,
5     IntersectionSimState, OrigPersonID, PandemicModel, ParkedCar, ParkingSimState, ParkingSpot,
6     PedestrianID, Person, PersonID, PersonState, Router, Scenario, Scheduler, SidewalkPOI,
7     SidewalkSpot, TransitSimState, TripID, TripInfo, TripManager, TripPhaseType, TripResult,
8     TripSpawner, UnzoomedAgent, Vehicle, VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH,
9     LIGHT_RAIL_LENGTH, MIN_CAR_LENGTH, SPAWN_DIST,
10 };
11 use abstutil::{prettyprint_usize, serialized_size_bytes, Counter, Parallelism, Timer};
12 use geom::{Distance, Duration, PolyLine, Pt2D, Speed, Time};
13 use instant::Instant;
14 use map_model::{
15     BuildingID, BusRoute, BusRouteID, BusStopID, IntersectionID, Lane, LaneID, Map, ParkingLotID,
16     Path, PathConstraints, PathRequest, Position, RoadID, Traversable,
17 };
18 use rand_xorshift::XorShiftRng;
19 use serde::{Deserialize, Serialize};
20 use std::collections::{BTreeMap, HashSet};
21 use std::panic;
22 
23 // TODO Do something else.
24 const BLIND_RETRY_TO_SPAWN: Duration = Duration::const_seconds(5.0);
25 
26 #[derive(Serialize, Deserialize, Clone)]
27 pub struct Sim {
28     driving: DrivingSimState,
29     parking: ParkingSimState,
30     walking: WalkingSimState,
31     intersections: IntersectionSimState,
32     transit: TransitSimState,
33     cap: CapSimState,
34     trips: TripManager,
35     #[serde(skip_serializing, skip_deserializing)]
36     pandemic: Option<PandemicModel>,
37     scheduler: Scheduler,
38     time: Time,
39 
40     // TODO Reconsider these
41     pub(crate) map_name: String,
42     pub(crate) edits_name: String,
43     // Some tests deliberately set different scenario names for comparisons.
44     // TODO Maybe get rid of this, now that savestates aren't used
45     run_name: String,
46     step_count: usize,
47 
48     // Don't serialize, to reduce prebaked savestate size. Analytics are saved once covering the
49     // full day and can be trimmed to any time.
50     #[serde(skip_serializing, skip_deserializing)]
51     analytics: Analytics,
52 
53     #[serde(skip_serializing, skip_deserializing)]
54     alerts: AlertHandler,
55 }
56 
57 pub struct Ctx<'a> {
58     pub parking: &'a mut ParkingSimState,
59     pub intersections: &'a mut IntersectionSimState,
60     pub cap: &'a mut CapSimState,
61     pub scheduler: &'a mut Scheduler,
62     pub map: &'a Map,
63 }
64 
65 #[derive(Clone)]
66 pub struct SimOptions {
67     pub run_name: String,
68     pub use_freeform_policy_everywhere: bool,
69     pub dont_block_the_box: bool,
70     pub recalc_lanechanging: bool,
71     pub break_turn_conflict_cycles: bool,
72     pub handle_uber_turns: bool,
73     pub enable_pandemic_model: Option<XorShiftRng>,
74     pub alerts: AlertHandler,
75     pub pathfinding_upfront: bool,
76 }
77 
78 #[derive(Clone)]
79 pub enum AlertHandler {
80     // Just print the alert to STDOUT
81     Print,
82     // Print the alert to STDOUT and don't proceed until the UI calls clear_alerts()
83     Block,
84     // Don't do anything
85     Silence,
86 }
87 
88 impl std::default::Default for AlertHandler {
default() -> AlertHandler89     fn default() -> AlertHandler {
90         AlertHandler::Print
91     }
92 }
93 
94 impl SimOptions {
new(run_name: &str) -> SimOptions95     pub fn new(run_name: &str) -> SimOptions {
96         SimOptions {
97             run_name: run_name.to_string(),
98             use_freeform_policy_everywhere: false,
99             dont_block_the_box: true,
100             recalc_lanechanging: true,
101             break_turn_conflict_cycles: true,
102             handle_uber_turns: true,
103             enable_pandemic_model: None,
104             alerts: AlertHandler::Print,
105             pathfinding_upfront: false,
106         }
107     }
108 }
109 
110 // Setup
111 impl Sim {
new(map: &Map, opts: SimOptions, timer: &mut Timer) -> Sim112     pub fn new(map: &Map, opts: SimOptions, timer: &mut Timer) -> Sim {
113         let mut scheduler = Scheduler::new();
114         Sim {
115             driving: DrivingSimState::new(map, opts.recalc_lanechanging, opts.handle_uber_turns),
116             parking: ParkingSimState::new(map, timer),
117             walking: WalkingSimState::new(),
118             intersections: IntersectionSimState::new(
119                 map,
120                 &mut scheduler,
121                 opts.use_freeform_policy_everywhere,
122                 opts.dont_block_the_box,
123                 opts.break_turn_conflict_cycles,
124                 opts.handle_uber_turns,
125             ),
126             transit: TransitSimState::new(map),
127             cap: CapSimState::new(map),
128             trips: TripManager::new(opts.pathfinding_upfront),
129             pandemic: if let Some(rng) = opts.enable_pandemic_model {
130                 Some(PandemicModel::new(rng))
131             } else {
132                 None
133             },
134             scheduler,
135             time: Time::START_OF_DAY,
136 
137             map_name: map.get_name().to_string(),
138             // TODO
139             edits_name: "untitled edits".to_string(),
140             run_name: opts.run_name,
141             step_count: 0,
142             alerts: opts.alerts,
143 
144             analytics: Analytics::new(),
145         }
146     }
147 
make_spawner(&self) -> TripSpawner148     pub fn make_spawner(&self) -> TripSpawner {
149         TripSpawner::new()
150     }
flush_spawner(&mut self, spawner: TripSpawner, map: &Map, timer: &mut Timer)151     pub fn flush_spawner(&mut self, spawner: TripSpawner, map: &Map, timer: &mut Timer) {
152         spawner.finalize(map, &mut self.trips, &mut self.scheduler, timer);
153 
154         if let Some(ref mut m) = self.pandemic {
155             m.initialize(self.trips.get_all_people(), &mut self.scheduler);
156         }
157 
158         self.dispatch_events(Vec::new(), map);
159     }
160 
get_free_onstreet_spots(&self, l: LaneID) -> Vec<ParkingSpot>161     pub fn get_free_onstreet_spots(&self, l: LaneID) -> Vec<ParkingSpot> {
162         self.parking.get_free_onstreet_spots(l)
163     }
164 
get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot>165     pub fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot> {
166         self.parking.get_free_offstreet_spots(b)
167     }
168 
get_free_lot_spots(&self, pl: ParkingLotID) -> Vec<ParkingSpot>169     pub fn get_free_lot_spots(&self, pl: ParkingLotID) -> Vec<ParkingSpot> {
170         self.parking.get_free_lot_spots(pl)
171     }
172 
173     // (Filled, available)
get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>)174     pub fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
175         self.parking.get_all_parking_spots()
176     }
177 
178     // Also returns the start distance of the building. TODO Do that in the Path properly.
walking_path_to_nearest_parking_spot( &self, map: &Map, b: BuildingID, ) -> Option<(Path, Distance)>179     pub fn walking_path_to_nearest_parking_spot(
180         &self,
181         map: &Map,
182         b: BuildingID,
183     ) -> Option<(Path, Distance)> {
184         let vehicle = Vehicle {
185             id: CarID(0, VehicleType::Car),
186             owner: None,
187             vehicle_type: VehicleType::Car,
188             length: MIN_CAR_LENGTH,
189             max_speed: None,
190         };
191         let driving_lane = map.find_driving_lane_near_building(b);
192 
193         // Anything on the current lane? TODO Should find the closest one to the sidewalk, but
194         // need a new method in ParkingSimState to make that easy.
195         // TODO Refactor the logic in router
196         let spot = if let Some((spot, _)) = self
197             .parking
198             .get_all_free_spots(Position::start(driving_lane), &vehicle, b, map)
199             .get(0)
200         {
201             spot.clone()
202         } else {
203             let (_, spot, _) =
204                 self.parking
205                     .path_to_free_parking_spot(driving_lane, &vehicle, b, map)?;
206             spot
207         };
208 
209         let start = SidewalkSpot::building(b, map).sidewalk_pos;
210         let end = SidewalkSpot::parking_spot(spot, map, &self.parking).sidewalk_pos;
211         let path = map.pathfind(PathRequest {
212             start,
213             end,
214             constraints: PathConstraints::Pedestrian,
215         })?;
216         Some((path, start.dist_along()))
217     }
218 
219     // TODO Should these two be in TripSpawner?
new_person( &mut self, p: PersonID, orig_id: Option<OrigPersonID>, ped_speed: Speed, vehicle_specs: Vec<VehicleSpec>, )220     pub(crate) fn new_person(
221         &mut self,
222         p: PersonID,
223         orig_id: Option<OrigPersonID>,
224         ped_speed: Speed,
225         vehicle_specs: Vec<VehicleSpec>,
226     ) {
227         self.trips.new_person(p, orig_id, ped_speed, vehicle_specs);
228     }
random_person(&mut self, ped_speed: Speed, vehicle_specs: Vec<VehicleSpec>) -> &Person229     pub fn random_person(&mut self, ped_speed: Speed, vehicle_specs: Vec<VehicleSpec>) -> &Person {
230         self.trips.random_person(ped_speed, vehicle_specs)
231     }
seed_parked_car(&mut self, vehicle: Vehicle, spot: ParkingSpot)232     pub(crate) fn seed_parked_car(&mut self, vehicle: Vehicle, spot: ParkingSpot) {
233         self.parking.reserve_spot(spot);
234         self.parking.add_parked_car(ParkedCar { vehicle, spot });
235     }
236 
seed_bus_route(&mut self, route: &BusRoute)237     pub(crate) fn seed_bus_route(&mut self, route: &BusRoute) {
238         for t in &route.spawn_times {
239             self.scheduler.push(*t, Command::StartBus(route.id, *t));
240         }
241     }
242 
start_bus(&mut self, route: &BusRoute, map: &Map)243     fn start_bus(&mut self, route: &BusRoute, map: &Map) {
244         // Spawn one bus for the first leg.
245         let (req, path) = self.transit.create_empty_route(route, map);
246 
247         // For now, no desire for randomness. Caller can pass in list of specs if that ever
248         // changes.
249         let (vehicle_type, length) = match route.route_type {
250             PathConstraints::Bus => (VehicleType::Bus, BUS_LENGTH),
251             PathConstraints::Train => (VehicleType::Train, LIGHT_RAIL_LENGTH),
252             _ => unreachable!(),
253         };
254         let vehicle = VehicleSpec {
255             vehicle_type,
256             length,
257             max_speed: None,
258         }
259         .make(CarID(self.trips.new_car_id(), vehicle_type), None);
260         let start_lane = map.get_l(path.current_step().as_lane());
261         let start_dist = if map.get_i(start_lane.src_i).is_incoming_border() {
262             SPAWN_DIST
263         } else {
264             assert!(start_lane.length() > vehicle.length);
265             vehicle.length
266         };
267 
268         self.scheduler.push(
269             self.time,
270             Command::SpawnCar(
271                 CreateCar {
272                     start_dist,
273                     router: Router::follow_bus_route(
274                         vehicle.id,
275                         path.clone(),
276                         req.end.dist_along(),
277                     ),
278                     vehicle,
279                     req,
280                     maybe_parked_car: None,
281                     trip_and_person: None,
282                     maybe_route: Some(route.id),
283                 },
284                 true,
285             ),
286         );
287     }
288 
set_name(&mut self, name: String)289     pub fn set_name(&mut self, name: String) {
290         self.run_name = name;
291     }
292 }
293 
294 // Drawing
295 impl GetDrawAgents for Sim {
time(&self) -> Time296     fn time(&self) -> Time {
297         self.time
298     }
299 
step_count(&self) -> usize300     fn step_count(&self) -> usize {
301         self.step_count
302     }
303 
get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput>304     fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
305         self.parking.get_draw_car(id, map).or_else(|| {
306             self.driving
307                 .get_single_draw_car(id, self.time, map, &self.transit)
308         })
309     }
310 
get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput>311     fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> {
312         self.walking.get_draw_ped(id, self.time, map)
313     }
314 
get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput>315     fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput> {
316         let mut results = Vec::new();
317         if let Traversable::Lane(l) = on {
318             if map.get_l(l).is_parking() {
319                 return self.parking.get_draw_cars(l, map);
320             }
321             results.extend(self.parking.get_draw_cars_in_lots(l, map));
322         }
323         results.extend(
324             self.driving
325                 .get_draw_cars_on(self.time, on, map, &self.transit),
326         );
327         results
328     }
329 
get_draw_peds( &self, on: Traversable, map: &Map, ) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>)330     fn get_draw_peds(
331         &self,
332         on: Traversable,
333         map: &Map,
334     ) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>) {
335         self.walking.get_draw_peds_on(self.time, on, map)
336     }
337 
get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput>338     fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
339         let mut result = self
340             .driving
341             .get_all_draw_cars(self.time, map, &self.transit);
342         result.extend(self.parking.get_all_draw_cars(map));
343         result
344     }
345 
get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput>346     fn get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput> {
347         self.walking.get_all_draw_peds(self.time, map)
348     }
349 
get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent>350     fn get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent> {
351         let mut result = self.driving.get_unzoomed_agents(self.time, map);
352         result.extend(self.walking.get_unzoomed_agents(self.time, map));
353         result
354     }
355 }
356 
357 // Running
358 impl Sim {
359     // Advances time as minimally as possible, also limited by max_dt. Returns true if the callback
360     // said to halt the sim.
minimal_step( &mut self, map: &Map, max_dt: Duration, maybe_cb: &mut Option<Box<dyn SimCallback>>, ) -> bool361     fn minimal_step(
362         &mut self,
363         map: &Map,
364         max_dt: Duration,
365         maybe_cb: &mut Option<Box<dyn SimCallback>>,
366     ) -> bool {
367         self.step_count += 1;
368 
369         let max_time = if let Some(t) = self.scheduler.peek_next_time() {
370             if t > self.time + max_dt {
371                 // Next event is after when we want to stop.
372                 self.time += max_dt;
373                 return false;
374             }
375             t
376         } else {
377             // No events left at all
378             self.time += max_dt;
379             return false;
380         };
381 
382         let mut halt = false;
383         while let Some(time) = self.scheduler.peek_next_time() {
384             if time > max_time {
385                 return false;
386             }
387             if let Some(cmd) = self.scheduler.get_next() {
388                 if self.do_step(map, time, cmd, maybe_cb) {
389                     halt = true;
390                     break;
391                 }
392             }
393         }
394 
395         halt
396     }
397 
398     // If true, halt simulation because the callback said so.
do_step( &mut self, map: &Map, time: Time, cmd: Command, maybe_cb: &mut Option<Box<dyn SimCallback>>, ) -> bool399     fn do_step(
400         &mut self,
401         map: &Map,
402         time: Time,
403         cmd: Command,
404         maybe_cb: &mut Option<Box<dyn SimCallback>>,
405     ) -> bool {
406         self.time = time;
407         let mut events = Vec::new();
408         let mut halt = false;
409 
410         let mut ctx = Ctx {
411             parking: &mut self.parking,
412             intersections: &mut self.intersections,
413             cap: &mut self.cap,
414             scheduler: &mut self.scheduler,
415             map,
416         };
417 
418         match cmd {
419             Command::StartTrip(id, trip_spec, maybe_req, maybe_path) => {
420                 self.trips
421                     .start_trip(self.time, id, trip_spec, maybe_req, maybe_path, &mut ctx);
422             }
423             Command::SpawnCar(create_car, retry_if_no_room) => {
424                 if self.driving.start_car_on_lane(
425                     self.time,
426                     create_car.clone(),
427                     map,
428                     &self.intersections,
429                     &self.parking,
430                     &mut self.scheduler,
431                 ) {
432                     if let Some((trip, person)) = create_car.trip_and_person {
433                         self.trips
434                             .agent_starting_trip_leg(AgentID::Car(create_car.vehicle.id), trip);
435                         events.push(Event::TripPhaseStarting(
436                             trip,
437                             person,
438                             Some(create_car.req.clone()),
439                             if create_car.vehicle.id.1 == VehicleType::Car {
440                                 TripPhaseType::Driving
441                             } else {
442                                 TripPhaseType::Biking
443                             },
444                         ));
445                     }
446                     if let Some(parked_car) = create_car.maybe_parked_car {
447                         if let ParkingSpot::Offstreet(b, _) = parked_car.spot {
448                             // Buses don't start in parking garages, so trip must exist
449                             events.push(Event::PersonLeavesBuilding(
450                                 create_car.trip_and_person.unwrap().1,
451                                 b,
452                             ));
453                         }
454                         self.parking.remove_parked_car(parked_car);
455                     }
456                     if let Some(route) = create_car.maybe_route {
457                         self.transit.bus_created(create_car.vehicle.id, route);
458                     }
459                     self.analytics
460                         .record_demand(create_car.router.get_path(), map);
461                 } else if retry_if_no_room {
462                     // TODO Record this in the trip log
463                     self.scheduler.push(
464                         self.time + BLIND_RETRY_TO_SPAWN,
465                         Command::SpawnCar(create_car, retry_if_no_room),
466                     );
467                 } else {
468                     // Buses don't use Command::SpawnCar, so this must exist.
469                     let (trip, person) = create_car.trip_and_person.unwrap();
470                     println!(
471                         "No room to spawn car for {} by {}. Not retrying!",
472                         trip, person
473                     );
474                     // Have to redeclare for the borrow checker
475                     let mut ctx = Ctx {
476                         parking: &mut self.parking,
477                         intersections: &mut self.intersections,
478                         cap: &mut self.cap,
479                         scheduler: &mut self.scheduler,
480                         map,
481                     };
482                     self.trips
483                         .abort_trip(self.time, trip, Some(create_car.vehicle), &mut ctx);
484                 }
485             }
486             Command::SpawnPed(create_ped) => {
487                 // Do the order a bit backwards so we don't have to clone the
488                 // CreatePedestrian. spawn_ped can't fail.
489                 self.trips
490                     .agent_starting_trip_leg(AgentID::Pedestrian(create_ped.id), create_ped.trip);
491                 events.push(Event::TripPhaseStarting(
492                     create_ped.trip,
493                     create_ped.person,
494                     Some(create_ped.req.clone()),
495                     TripPhaseType::Walking,
496                 ));
497                 self.analytics.record_demand(&create_ped.path, map);
498 
499                 // Maybe there's actually no work to do!
500                 match (&create_ped.start.connection, &create_ped.goal.connection) {
501                     (
502                         SidewalkPOI::Building(b1),
503                         SidewalkPOI::ParkingSpot(ParkingSpot::Offstreet(b2, idx)),
504                     ) if b1 == b2 => {
505                         self.trips.ped_reached_parking_spot(
506                             self.time,
507                             create_ped.id,
508                             ParkingSpot::Offstreet(*b2, *idx),
509                             Duration::ZERO,
510                             &mut ctx,
511                         );
512                     }
513                     _ => {
514                         if let SidewalkPOI::Building(b) = &create_ped.start.connection {
515                             events.push(Event::PersonLeavesBuilding(create_ped.person, *b));
516                         }
517 
518                         self.walking
519                             .spawn_ped(self.time, create_ped, map, &mut self.scheduler);
520                     }
521                 }
522             }
523             Command::UpdateCar(car) => {
524                 self.driving.update_car(
525                     car,
526                     self.time,
527                     &mut ctx,
528                     &mut self.trips,
529                     &mut self.transit,
530                     &mut self.walking,
531                 );
532             }
533             Command::UpdateLaggyHead(car) => {
534                 self.driving.update_laggy_head(
535                     car,
536                     self.time,
537                     map,
538                     &mut self.intersections,
539                     &mut self.scheduler,
540                 );
541             }
542             Command::UpdatePed(ped) => {
543                 self.walking.update_ped(
544                     ped,
545                     self.time,
546                     &mut ctx,
547                     &mut self.trips,
548                     &mut self.transit,
549                 );
550             }
551             Command::UpdateIntersection(i) => {
552                 self.intersections
553                     .update_intersection(self.time, i, map, &mut self.scheduler);
554             }
555             Command::Callback(frequency) => {
556                 self.scheduler
557                     .push(self.time + frequency, Command::Callback(frequency));
558                 if maybe_cb.as_mut().unwrap().run(self, map) {
559                     halt = true;
560                 }
561             }
562             Command::Pandemic(cmd) => {
563                 self.pandemic
564                     .as_mut()
565                     .unwrap()
566                     .handle_cmd(self.time, cmd, &mut self.scheduler);
567             }
568             Command::FinishRemoteTrip(trip) => {
569                 self.trips.remote_trip_finished(self.time, trip, &mut ctx);
570             }
571             Command::StartBus(r, _) => {
572                 self.start_bus(map.get_br(r), map);
573             }
574         }
575 
576         // Record events at precisely the time they occur.
577         self.dispatch_events(events, map);
578 
579         halt
580     }
581 
dispatch_events(&mut self, mut events: Vec<Event>, map: &Map)582     fn dispatch_events(&mut self, mut events: Vec<Event>, map: &Map) {
583         events.extend(self.trips.collect_events());
584         events.extend(self.transit.collect_events());
585         events.extend(self.driving.collect_events());
586         events.extend(self.walking.collect_events());
587         events.extend(self.intersections.collect_events());
588         events.extend(self.parking.collect_events());
589         for ev in events {
590             if let Some(ref mut m) = self.pandemic {
591                 m.handle_event(self.time, &ev, &mut self.scheduler);
592             }
593 
594             self.analytics.event(ev, self.time, map);
595         }
596     }
597 
timed_step( &mut self, map: &Map, dt: Duration, maybe_cb: &mut Option<Box<dyn SimCallback>>, timer: &mut Timer, )598     pub fn timed_step(
599         &mut self,
600         map: &Map,
601         dt: Duration,
602         maybe_cb: &mut Option<Box<dyn SimCallback>>,
603         timer: &mut Timer,
604     ) {
605         let end_time = self.time + dt;
606         let start = Instant::now();
607         let mut last_update = Instant::now();
608 
609         timer.start(format!("Advance sim to {}", end_time));
610         while self.time < end_time {
611             if self.minimal_step(map, end_time - self.time, maybe_cb) {
612                 break;
613             }
614             if !self.analytics.alerts.is_empty() {
615                 match self.alerts {
616                     AlertHandler::Print => {
617                         for (t, loc, msg) in self.analytics.alerts.drain(..) {
618                             println!("Alert at {} ({:?}): {}", t, loc, msg);
619                         }
620                     }
621                     AlertHandler::Block => {
622                         for (t, loc, msg) in &self.analytics.alerts {
623                             println!("Alert at {} ({:?}): {}", t, loc, msg);
624                         }
625                         break;
626                     }
627                     AlertHandler::Silence => {
628                         self.analytics.alerts.clear();
629                     }
630                 }
631             }
632             if Duration::realtime_elapsed(last_update) >= Duration::seconds(1.0) {
633                 // TODO Not timer?
634                 println!(
635                     "- After {}, the sim is at {}. {} live agents",
636                     Duration::realtime_elapsed(start),
637                     self.time,
638                     prettyprint_usize(self.trips.num_active_agents()),
639                 );
640                 last_update = Instant::now();
641             }
642         }
643         timer.stop(format!("Advance sim to {}", end_time));
644     }
tiny_step(&mut self, map: &Map, maybe_cb: &mut Option<Box<dyn SimCallback>>)645     pub fn tiny_step(&mut self, map: &Map, maybe_cb: &mut Option<Box<dyn SimCallback>>) {
646         self.timed_step(
647             map,
648             Duration::seconds(0.1),
649             maybe_cb,
650             &mut Timer::throwaway(),
651         );
652     }
653 
time_limited_step( &mut self, map: &Map, dt: Duration, real_time_limit: Duration, maybe_cb: &mut Option<Box<dyn SimCallback>>, )654     pub fn time_limited_step(
655         &mut self,
656         map: &Map,
657         dt: Duration,
658         real_time_limit: Duration,
659         maybe_cb: &mut Option<Box<dyn SimCallback>>,
660     ) {
661         let started_at = Instant::now();
662         let end_time = self.time + dt;
663 
664         while self.time < end_time && Duration::realtime_elapsed(started_at) < real_time_limit {
665             if self.minimal_step(map, end_time - self.time, maybe_cb) {
666                 break;
667             }
668             if !self.analytics.alerts.is_empty() {
669                 match self.alerts {
670                     AlertHandler::Print => {
671                         for (t, loc, msg) in self.analytics.alerts.drain(..) {
672                             println!("Alert at {} ({:?}): {}", t, loc, msg);
673                         }
674                     }
675                     AlertHandler::Block => {
676                         for (t, loc, msg) in &self.analytics.alerts {
677                             println!("Alert at {} ({:?}): {}", t, loc, msg);
678                         }
679                         break;
680                     }
681                     AlertHandler::Silence => {
682                         self.analytics.alerts.clear();
683                     }
684                 }
685             }
686         }
687     }
688 
dump_before_abort(&self)689     pub fn dump_before_abort(&self) {
690         println!("At {}", self.time);
691         if let Some(path) = self.find_previous_savestate(self.time) {
692             println!("Debug from {}", path);
693         }
694     }
695 }
696 
697 // Helpers to run the sim
698 // TODO Old and gunky
699 impl Sim {
run_until_done<F: Fn(&mut Sim, &Map)>( &mut self, map: &Map, callback: F, time_limit: Option<Duration>, )700     pub fn run_until_done<F: Fn(&mut Sim, &Map)>(
701         &mut self,
702         map: &Map,
703         callback: F,
704         // Interpreted as a relative time
705         time_limit: Option<Duration>,
706     ) {
707         let mut last_print = Instant::now();
708         let mut last_sim_time = self.time();
709 
710         loop {
711             // TODO Regular printing doesn't happen if we use a time_limit :\
712             let dt = time_limit.unwrap_or_else(|| Duration::seconds(30.0));
713 
714             match panic::catch_unwind(panic::AssertUnwindSafe(|| {
715                 self.timed_step(map, dt, &mut None, &mut Timer::throwaway());
716             })) {
717                 Ok(()) => {}
718                 Err(err) => {
719                     println!(
720                         "*************************************************************************\
721                          *******"
722                     );
723                     println!("Sim broke:");
724                     self.dump_before_abort();
725                     panic::resume_unwind(err);
726                 }
727             }
728 
729             let dt_real = Duration::realtime_elapsed(last_print);
730             if dt_real >= Duration::seconds(1.0) {
731                 let (finished, unfinished) = self.num_trips();
732                 println!(
733                     "{}: {} trips finished, {} unfinished, speed = {:.2}x, {}",
734                     self.time(),
735                     prettyprint_usize(finished),
736                     prettyprint_usize(unfinished),
737                     (self.time() - last_sim_time) / dt_real,
738                     self.scheduler.describe_stats()
739                 );
740                 last_print = Instant::now();
741                 last_sim_time = self.time();
742             }
743             callback(self, map);
744             if self.is_done() {
745                 println!(
746                     "{}: speed = {:.2}x, {}",
747                     self.time(),
748                     (self.time() - last_sim_time) / dt_real,
749                     self.scheduler.describe_stats()
750                 );
751                 break;
752             }
753 
754             if let Some(lim) = time_limit {
755                 panic!("Time limit {} hit", lim);
756             }
757         }
758     }
759 }
760 
761 // Savestating
762 impl Sim {
save_dir(&self) -> String763     pub fn save_dir(&self) -> String {
764         abstutil::path_all_saves(&self.map_name, &self.edits_name, &self.run_name)
765     }
766 
save_path(&self, base_time: Time) -> String767     fn save_path(&self, base_time: Time) -> String {
768         // If we wanted to be even more reproducible, we'd encode RNG seed, version of code, etc,
769         // but that's overkill right now.
770         abstutil::path_save(
771             &self.map_name,
772             &self.edits_name,
773             &self.run_name,
774             base_time.as_filename(),
775         )
776     }
777 
save(&mut self) -> String778     pub fn save(&mut self) -> String {
779         let restore = self.scheduler.before_savestate();
780 
781         if true {
782             println!("sim savestate breakdown:");
783             println!(
784                 "- driving: {} bytes",
785                 prettyprint_usize(serialized_size_bytes(&self.driving))
786             );
787             println!(
788                 "- parking: {} bytes",
789                 prettyprint_usize(serialized_size_bytes(&self.parking))
790             );
791             println!(
792                 "- walking: {} bytes",
793                 prettyprint_usize(serialized_size_bytes(&self.walking))
794             );
795             println!(
796                 "- intersections: {} bytes",
797                 prettyprint_usize(serialized_size_bytes(&self.intersections))
798             );
799             println!(
800                 "- transit: {} bytes",
801                 prettyprint_usize(serialized_size_bytes(&self.transit))
802             );
803             println!(
804                 "- cap: {} bytes",
805                 prettyprint_usize(serialized_size_bytes(&self.cap))
806             );
807             println!(
808                 "- trips: {} bytes",
809                 prettyprint_usize(serialized_size_bytes(&self.trips))
810             );
811             println!(
812                 "- scheduler: {} bytes",
813                 prettyprint_usize(serialized_size_bytes(&self.scheduler))
814             );
815         }
816 
817         let path = self.save_path(self.time);
818         abstutil::write_binary(path.clone(), self);
819 
820         self.scheduler.after_savestate(restore);
821 
822         path
823     }
824 
find_previous_savestate(&self, base_time: Time) -> Option<String>825     pub fn find_previous_savestate(&self, base_time: Time) -> Option<String> {
826         abstutil::find_prev_file(self.save_path(base_time))
827     }
828 
find_next_savestate(&self, base_time: Time) -> Option<String>829     pub fn find_next_savestate(&self, base_time: Time) -> Option<String> {
830         abstutil::find_next_file(self.save_path(base_time))
831     }
832 
load_savestate( path: String, map: &Map, timer: &mut Timer, ) -> Result<Sim, std::io::Error>833     pub fn load_savestate(
834         path: String,
835         map: &Map,
836         timer: &mut Timer,
837     ) -> Result<Sim, std::io::Error> {
838         let mut sim: Sim = abstutil::maybe_read_binary(path, timer)?;
839         sim.restore_paths(map, timer);
840         Ok(sim)
841     }
842 
restore_paths(&mut self, map: &Map, timer: &mut Timer)843     pub fn restore_paths(&mut self, map: &Map, timer: &mut Timer) {
844         let paths = timer.parallelize(
845             "calculate paths",
846             Parallelism::Fastest,
847             self.scheduler.get_requests_for_savestate(),
848             |req| map.pathfind(req).unwrap(),
849         );
850         self.scheduler.after_savestate(paths);
851     }
852 
handle_live_edited_traffic_signals(&mut self, map: &Map)853     pub fn handle_live_edited_traffic_signals(&mut self, map: &Map) {
854         self.intersections.handle_live_edited_traffic_signals(map)
855     }
856 }
857 
858 // Queries of all sorts
859 // TODO Many of these just delegate to an inner piece. This is unorganized and hard to maintain.
860 impl Sim {
time(&self) -> Time861     pub fn time(&self) -> Time {
862         self.time
863     }
864 
is_done(&self) -> bool865     pub fn is_done(&self) -> bool {
866         self.trips.is_done()
867     }
868 
is_empty(&self) -> bool869     pub fn is_empty(&self) -> bool {
870         self.time == Time::START_OF_DAY && self.is_done()
871     }
872 
873     // (number of finished trips, number of unfinished trips)
num_trips(&self) -> (usize, usize)874     pub fn num_trips(&self) -> (usize, usize) {
875         self.trips.num_trips()
876     }
num_agents(&self) -> Counter<AgentType>877     pub fn num_agents(&self) -> Counter<AgentType> {
878         self.trips.num_agents(&self.transit)
879     }
880     // (total number of people, just in buildings, just off map)
num_ppl(&self) -> (usize, usize, usize)881     pub fn num_ppl(&self) -> (usize, usize, usize) {
882         self.trips.num_ppl()
883     }
884 
debug_ped(&self, id: PedestrianID)885     pub fn debug_ped(&self, id: PedestrianID) {
886         self.walking.debug_ped(id);
887         self.trips.debug_trip(AgentID::Pedestrian(id));
888     }
889 
debug_car(&self, id: CarID)890     pub fn debug_car(&self, id: CarID) {
891         self.driving.debug_car(id);
892         self.trips.debug_trip(AgentID::Car(id));
893     }
894 
debug_intersection(&self, id: IntersectionID, map: &Map)895     pub fn debug_intersection(&self, id: IntersectionID, map: &Map) {
896         self.intersections.debug(id, map);
897     }
898 
debug_lane(&self, id: LaneID)899     pub fn debug_lane(&self, id: LaneID) {
900         self.driving.debug_lane(id);
901     }
902 
903     // Only call for active agents, will panic otherwise
agent_properties(&self, id: AgentID) -> AgentProperties904     pub fn agent_properties(&self, id: AgentID) -> AgentProperties {
905         match id {
906             AgentID::Pedestrian(id) => self.walking.agent_properties(id, self.time),
907             AgentID::Car(id) => self.driving.agent_properties(id, self.time),
908             // TODO Harder to measure some of this stuff
909             AgentID::BusPassenger(_, _) => AgentProperties {
910                 total_time: Duration::ZERO,
911                 waiting_here: Duration::ZERO,
912                 total_waiting: Duration::ZERO,
913                 dist_crossed: Distance::ZERO,
914                 total_dist: Distance::meters(0.1),
915                 lanes_crossed: 0,
916                 total_lanes: 0,
917             },
918         }
919     }
920 
num_transit_passengers(&self, car: CarID) -> usize921     pub fn num_transit_passengers(&self, car: CarID) -> usize {
922         self.transit.get_passengers(car).len()
923     }
924 
bus_route_id(&self, maybe_bus: CarID) -> Option<BusRouteID>925     pub fn bus_route_id(&self, maybe_bus: CarID) -> Option<BusRouteID> {
926         if maybe_bus.1 == VehicleType::Bus || maybe_bus.1 == VehicleType::Train {
927             Some(self.transit.bus_route(maybe_bus))
928         } else {
929             None
930         }
931     }
932 
active_agents(&self) -> Vec<AgentID>933     pub fn active_agents(&self) -> Vec<AgentID> {
934         self.trips.active_agents()
935     }
936 
agent_to_trip(&self, id: AgentID) -> Option<TripID>937     pub fn agent_to_trip(&self, id: AgentID) -> Option<TripID> {
938         self.trips.agent_to_trip(id)
939     }
940 
trip_to_agent(&self, id: TripID) -> TripResult<AgentID>941     pub fn trip_to_agent(&self, id: TripID) -> TripResult<AgentID> {
942         self.trips.trip_to_agent(id)
943     }
944 
trip_info(&self, id: TripID) -> TripInfo945     pub fn trip_info(&self, id: TripID) -> TripInfo {
946         self.trips.trip_info(id)
947     }
all_trip_info(&self) -> Vec<(TripID, TripInfo)>948     pub fn all_trip_info(&self) -> Vec<(TripID, TripInfo)> {
949         self.trips.all_trip_info()
950     }
951     // If trip is finished, returns (total time, total waiting time)
finished_trip_time(&self, id: TripID) -> Option<(Duration, Duration)>952     pub fn finished_trip_time(&self, id: TripID) -> Option<(Duration, Duration)> {
953         self.trips.finished_trip_time(id)
954     }
955 
trip_to_person(&self, id: TripID) -> PersonID956     pub fn trip_to_person(&self, id: TripID) -> PersonID {
957         self.trips.trip_to_person(id)
958     }
959     // TODO This returns None for parked cars owned by people! That's confusing. Dedupe with
960     // get_owner_of_car.
agent_to_person(&self, id: AgentID) -> Option<PersonID>961     pub fn agent_to_person(&self, id: AgentID) -> Option<PersonID> {
962         self.agent_to_trip(id).map(|t| self.trip_to_person(t))
963     }
get_owner_of_car(&self, id: CarID) -> Option<PersonID>964     pub fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
965         self.driving
966             .get_owner_of_car(id)
967             .or_else(|| self.parking.get_owner_of_car(id))
968     }
lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar>969     pub fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
970         self.parking.lookup_parked_car(id)
971     }
972 
lookup_person(&self, id: PersonID) -> Option<&Person>973     pub fn lookup_person(&self, id: PersonID) -> Option<&Person> {
974         self.trips.get_person(id)
975     }
get_person(&self, id: PersonID) -> &Person976     pub fn get_person(&self, id: PersonID) -> &Person {
977         self.trips.get_person(id).unwrap()
978     }
find_person_by_orig_id(&self, id: OrigPersonID) -> Option<PersonID>979     pub fn find_person_by_orig_id(&self, id: OrigPersonID) -> Option<PersonID> {
980         for p in self.get_all_people() {
981             if p.orig_id == Some(id) {
982                 return Some(p.id);
983             }
984         }
985         None
986     }
get_all_people(&self) -> &Vec<Person>987     pub fn get_all_people(&self) -> &Vec<Person> {
988         self.trips.get_all_people()
989     }
990 
lookup_car_id(&self, idx: usize) -> Option<CarID>991     pub fn lookup_car_id(&self, idx: usize) -> Option<CarID> {
992         for vt in &[
993             VehicleType::Car,
994             VehicleType::Bike,
995             VehicleType::Bus,
996             VehicleType::Train,
997         ] {
998             let id = CarID(idx, *vt);
999             if self.driving.does_car_exist(id) {
1000                 return Some(id);
1001             }
1002         }
1003 
1004         let id = CarID(idx, VehicleType::Car);
1005         // Only cars can be parked.
1006         if self.parking.lookup_parked_car(id).is_some() {
1007             return Some(id);
1008         }
1009 
1010         None
1011     }
1012 
get_path(&self, id: AgentID) -> Option<&Path>1013     pub fn get_path(&self, id: AgentID) -> Option<&Path> {
1014         match id {
1015             AgentID::Car(car) => self.driving.get_path(car),
1016             AgentID::Pedestrian(ped) => self.walking.get_path(ped),
1017             AgentID::BusPassenger(_, _) => None,
1018         }
1019     }
get_all_driving_paths(&self) -> Vec<&Path>1020     pub fn get_all_driving_paths(&self) -> Vec<&Path> {
1021         self.driving.get_all_driving_paths()
1022     }
1023 
trace_route( &self, id: AgentID, map: &Map, dist_ahead: Option<Distance>, ) -> Option<PolyLine>1024     pub fn trace_route(
1025         &self,
1026         id: AgentID,
1027         map: &Map,
1028         dist_ahead: Option<Distance>,
1029     ) -> Option<PolyLine> {
1030         match id {
1031             AgentID::Car(car) => self.driving.trace_route(self.time, car, map, dist_ahead),
1032             AgentID::Pedestrian(ped) => self.walking.trace_route(self.time, ped, map, dist_ahead),
1033             AgentID::BusPassenger(_, _) => None,
1034         }
1035     }
1036 
get_canonical_pt_per_trip(&self, trip: TripID, map: &Map) -> TripResult<Pt2D>1037     pub fn get_canonical_pt_per_trip(&self, trip: TripID, map: &Map) -> TripResult<Pt2D> {
1038         let agent = match self.trips.trip_to_agent(trip) {
1039             TripResult::Ok(a) => a,
1040             x => {
1041                 return x.propagate_error();
1042             }
1043         };
1044         if let Some(pt) = self.canonical_pt_for_agent(agent, map) {
1045             return TripResult::Ok(pt);
1046         }
1047         TripResult::ModeChange
1048     }
get_canonical_pt_per_person(&self, p: PersonID, map: &Map) -> Option<Pt2D>1049     pub fn get_canonical_pt_per_person(&self, p: PersonID, map: &Map) -> Option<Pt2D> {
1050         match self.trips.get_person(p)?.state {
1051             PersonState::Inside(b) => Some(map.get_b(b).polygon.center()),
1052             PersonState::Trip(t) => self.get_canonical_pt_per_trip(t, map).ok(),
1053             PersonState::OffMap => None,
1054         }
1055     }
1056 
canonical_pt_for_agent(&self, id: AgentID, map: &Map) -> Option<Pt2D>1057     pub fn canonical_pt_for_agent(&self, id: AgentID, map: &Map) -> Option<Pt2D> {
1058         match id {
1059             AgentID::Car(id) => self
1060                 .parking
1061                 .canonical_pt(id, map)
1062                 .or_else(|| Some(self.get_draw_car(id, map)?.body.last_pt())),
1063             AgentID::Pedestrian(id) => Some(self.get_draw_ped(id, map)?.pos),
1064             AgentID::BusPassenger(_, bus) => Some(self.get_draw_car(bus, map)?.body.last_pt()),
1065         }
1066     }
1067 
get_accepted_agents(&self, id: IntersectionID) -> HashSet<AgentID>1068     pub fn get_accepted_agents(&self, id: IntersectionID) -> HashSet<AgentID> {
1069         self.intersections.get_accepted_agents(id)
1070     }
get_blocked_by(&self, a: AgentID) -> HashSet<AgentID>1071     pub fn get_blocked_by(&self, a: AgentID) -> HashSet<AgentID> {
1072         self.intersections.get_blocked_by(a)
1073     }
1074 
1075     // (bus, stop index it's coming from, percent to next stop, location)
status_of_buses( &self, route: BusRouteID, map: &Map, ) -> Vec<(CarID, Option<usize>, f64, Pt2D)>1076     pub fn status_of_buses(
1077         &self,
1078         route: BusRouteID,
1079         map: &Map,
1080     ) -> Vec<(CarID, Option<usize>, f64, Pt2D)> {
1081         let mut results = Vec::new();
1082         for (bus, stop_idx) in self.transit.buses_for_route(route) {
1083             results.push((
1084                 bus,
1085                 stop_idx,
1086                 self.driving.percent_along_route(bus),
1087                 self.canonical_pt_for_agent(AgentID::Car(bus), map).unwrap(),
1088             ));
1089         }
1090         results
1091     }
1092 
get_analytics(&self) -> &Analytics1093     pub fn get_analytics(&self) -> &Analytics {
1094         &self.analytics
1095     }
1096 
find_blockage_front(&self, car: CarID, map: &Map) -> String1097     pub fn find_blockage_front(&self, car: CarID, map: &Map) -> String {
1098         self.driving
1099             .find_blockage_front(car, map, &self.intersections)
1100     }
1101 
1102     // For intersections with an agent waiting beyond some threshold, return when they started
1103     // waiting. Sorted by earliest waiting (likely the root cause of gridlock).
delayed_intersections(&self, threshold: Duration) -> Vec<(IntersectionID, Time)>1104     pub fn delayed_intersections(&self, threshold: Duration) -> Vec<(IntersectionID, Time)> {
1105         self.intersections
1106             .delayed_intersections(self.time, threshold)
1107     }
1108 
bldg_to_people(&self, b: BuildingID) -> Vec<PersonID>1109     pub fn bldg_to_people(&self, b: BuildingID) -> Vec<PersonID> {
1110         self.trips.bldg_to_people(b)
1111     }
1112 
worst_delay( &self, map: &Map, ) -> ( BTreeMap<RoadID, Duration>, BTreeMap<IntersectionID, Duration>, )1113     pub fn worst_delay(
1114         &self,
1115         map: &Map,
1116     ) -> (
1117         BTreeMap<RoadID, Duration>,
1118         BTreeMap<IntersectionID, Duration>,
1119     ) {
1120         self.intersections.worst_delay(self.time, map)
1121     }
1122 
get_pandemic_model(&self) -> Option<&PandemicModel>1123     pub fn get_pandemic_model(&self) -> Option<&PandemicModel> {
1124         self.pandemic.as_ref()
1125     }
1126 
get_end_of_day(&self) -> Time1127     pub fn get_end_of_day(&self) -> Time {
1128         // Always count at least 24 hours
1129         self.scheduler
1130             .get_last_time()
1131             .max(Time::START_OF_DAY + Duration::hours(24))
1132     }
1133 
current_stage_and_remaining_time(&self, i: IntersectionID) -> (usize, Duration)1134     pub fn current_stage_and_remaining_time(&self, i: IntersectionID) -> (usize, Duration) {
1135         self.intersections
1136             .current_stage_and_remaining_time(self.time, i)
1137     }
1138 
1139     // TODO This is an awkward copy of raw_throughput
1140     // TODO And it does NOT count buses/trains spawning
all_arrivals_at_border( &self, i: IntersectionID, ) -> Vec<(AgentType, Vec<(Time, usize)>)>1141     pub fn all_arrivals_at_border(
1142         &self,
1143         i: IntersectionID,
1144     ) -> Vec<(AgentType, Vec<(Time, usize)>)> {
1145         let window_size = Duration::hours(1);
1146         let mut pts_per_type: BTreeMap<AgentType, Vec<(Time, usize)>> = BTreeMap::new();
1147         let mut windows_per_type: BTreeMap<AgentType, Window> = BTreeMap::new();
1148         for agent_type in AgentType::all() {
1149             pts_per_type.insert(agent_type, vec![(Time::START_OF_DAY, 0)]);
1150             windows_per_type.insert(agent_type, Window::new(window_size));
1151         }
1152 
1153         for (t, agent_type) in self.trips.all_arrivals_at_border(i) {
1154             let count = windows_per_type.get_mut(&agent_type).unwrap().add(t);
1155             pts_per_type.get_mut(&agent_type).unwrap().push((t, count));
1156         }
1157 
1158         for (agent_type, pts) in pts_per_type.iter_mut() {
1159             let mut window = windows_per_type.remove(agent_type).unwrap();
1160 
1161             // Add a drop-off after window_size (+ a little epsilon!)
1162             let end = self.get_end_of_day();
1163             let t = (pts.last().unwrap().0 + window_size + Duration::seconds(0.1)).min(end);
1164             if pts.last().unwrap().0 != t {
1165                 pts.push((t, window.count(t)));
1166             }
1167 
1168             if pts.last().unwrap().0 != end {
1169                 pts.push((end, window.count(end)));
1170             }
1171         }
1172 
1173         pts_per_type.into_iter().collect()
1174     }
1175 
1176     // (number of vehicles in the lane, penalty if a bike or other slow vehicle is present)
target_lane_penalty(&self, lane: &Lane) -> (usize, usize)1177     pub fn target_lane_penalty(&self, lane: &Lane) -> (usize, usize) {
1178         if lane.is_walkable() {
1179             (0, 0)
1180         } else {
1181             self.driving.target_lane_penalty(lane.id)
1182         }
1183     }
1184 
get_people_waiting_at_stop( &self, at: BusStopID, ) -> &Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)>1185     pub fn get_people_waiting_at_stop(
1186         &self,
1187         at: BusStopID,
1188     ) -> &Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)> {
1189         self.transit.get_people_waiting_at_stop(at)
1190     }
1191 
generate_scenario(&self, map: &Map, name: String) -> Scenario1192     pub fn generate_scenario(&self, map: &Map, name: String) -> Scenario {
1193         self.trips.generate_scenario(map, name)
1194     }
1195 
get_cap_counter(&self, l: LaneID) -> usize1196     pub fn get_cap_counter(&self, l: LaneID) -> usize {
1197         self.cap.get_cap_counter(l)
1198     }
1199 }
1200 
1201 // Invasive debugging
1202 impl Sim {
kill_stuck_car(&mut self, id: CarID, map: &Map)1203     pub fn kill_stuck_car(&mut self, id: CarID, map: &Map) {
1204         if let Some(trip) = self.agent_to_trip(AgentID::Car(id)) {
1205             let vehicle = self.driving.kill_stuck_car(
1206                 id,
1207                 self.time,
1208                 map,
1209                 &mut self.scheduler,
1210                 &mut self.intersections,
1211             );
1212             let mut ctx = Ctx {
1213                 parking: &mut self.parking,
1214                 intersections: &mut self.intersections,
1215                 cap: &mut self.cap,
1216                 scheduler: &mut self.scheduler,
1217                 map,
1218             };
1219             self.trips
1220                 .abort_trip(self.time, trip, Some(vehicle), &mut ctx);
1221             println!("Forcibly killed {}", id);
1222         } else {
1223             println!("{} has no trip?!", id);
1224         }
1225     }
1226 
clear_alerts(&mut self) -> Vec<(Time, AlertLocation, String)>1227     pub fn clear_alerts(&mut self) -> Vec<(Time, AlertLocation, String)> {
1228         std::mem::replace(&mut self.analytics.alerts, Vec::new())
1229     }
1230 }
1231 
1232 // Callbacks
1233 pub trait SimCallback: downcast_rs::Downcast {
1234     // Run at some scheduled time. If this returns true, halt simulation.
run(&mut self, sim: &Sim, map: &Map) -> bool1235     fn run(&mut self, sim: &Sim, map: &Map) -> bool;
1236 }
1237 downcast_rs::impl_downcast!(SimCallback);
1238 
1239 impl Sim {
1240     // Only one at a time supported.
set_periodic_callback(&mut self, frequency: Duration)1241     pub fn set_periodic_callback(&mut self, frequency: Duration) {
1242         // TODO Round up time nicely?
1243         self.scheduler
1244             .push(self.time + frequency, Command::Callback(frequency));
1245     }
unset_periodic_callback(&mut self)1246     pub fn unset_periodic_callback(&mut self) {
1247         // Frequency doesn't matter
1248         self.scheduler
1249             .cancel(Command::Callback(Duration::seconds(1.0)));
1250     }
1251 }
1252 
1253 pub struct AgentProperties {
1254     // TODO Of this leg of the trip only!
1255     pub total_time: Duration,
1256     pub waiting_here: Duration,
1257     pub total_waiting: Duration,
1258 
1259     // TODO More continuous on a single lane
1260     pub dist_crossed: Distance,
1261     pub total_dist: Distance,
1262 
1263     pub lanes_crossed: usize,
1264     pub total_lanes: usize,
1265 }
1266