1use anyhow::Result;
4use serde::Serialize;
5use std::collections::{BTreeMap, BTreeSet};
6
7use abstutil::Counter;
8use geom::{Distance, Duration, PolyLine, Pt2D, Time};
9use map_model::{
10 BuildingID, IntersectionID, Lane, LaneID, Map, Path, Position, RoadID, TransitRouteID,
11 TransitStopID, Traversable, TurnID,
12};
13use synthpop::{OrigPersonID, Scenario, TripMode};
14
15use crate::analytics::SlidingWindow;
16use crate::{
17 AgentID, AgentType, Analytics, CarID, CommutersVehiclesCounts, DrawCarInput, DrawPedCrowdInput,
18 DrawPedestrianInput, PandemicModel, ParkedCar, ParkingSim, PedestrianID, Person, PersonID,
19 PersonState, Sim, TripEndpoint, TripID, TripInfo, TripResult, UnzoomedAgent, VehicleType,
20};
21
22impl Sim {
24 pub fn time(&self) -> Time {
25 self.time
26 }
27
28 pub fn is_done(&self) -> bool {
29 self.trips.is_done()
30 }
31
32 pub fn is_empty(&self) -> bool {
33 self.time == Time::START_OF_DAY && self.is_done()
34 }
35
36 pub fn num_trips(&self) -> (usize, usize) {
38 self.trips.num_trips()
39 }
40 pub fn num_agents(&self) -> Counter<AgentType> {
41 self.trips.num_agents(&self.transit)
42 }
43 pub fn num_commuters_vehicles(&self) -> CommutersVehiclesCounts {
44 self.trips
45 .num_commuters_vehicles(&self.transit, &self.walking)
46 }
47 pub fn num_ppl(&self) -> (usize, usize, usize) {
49 self.trips.num_ppl()
50 }
51
52 pub fn debug_ped(&self, id: PedestrianID) {
53 println!("{}", self.walking.debug_ped_json(id));
54 self.trips.debug_trip(AgentID::Pedestrian(id));
55 }
56
57 pub fn debug_car(&self, id: CarID) {
58 println!("{}", self.driving.debug_car_json(id));
59 self.trips.debug_trip(AgentID::Car(id));
60 }
61
62 pub fn debug_car_ui(&self, id: CarID) -> String {
64 self.driving.debug_car_ui(id)
65 }
66
67 pub fn debug_agent_json(&self, id: AgentID) -> String {
68 match id {
69 AgentID::Car(id) => self.driving.debug_car_json(id),
70 AgentID::Pedestrian(id) => self.walking.debug_ped_json(id),
71 AgentID::BusPassenger(_, id) => self.driving.debug_car_json(id),
72 }
73 }
74
75 pub fn debug_intersection_json(&self, id: IntersectionID, map: &Map) -> String {
76 self.intersections.debug_json(id, map)
77 }
78
79 pub fn debug_lane(&self, id: LaneID) {
80 self.driving.debug_lane(id);
81 }
82
83 pub fn agent_properties(&self, map: &Map, id: AgentID) -> AgentProperties {
85 match id {
86 AgentID::Pedestrian(id) => self.walking.agent_properties(map, id, self.time),
87 AgentID::Car(id) => self.driving.agent_properties(id, self.time),
88 AgentID::BusPassenger(_, _) => AgentProperties {
90 total_time: Duration::ZERO,
91 waiting_here: Duration::ZERO,
92 total_waiting: Duration::ZERO,
93 dist_crossed: Distance::ZERO,
94 total_dist: Distance::meters(0.1),
95 },
96 }
97 }
98
99 pub fn num_transit_passengers(&self, car: CarID) -> usize {
100 self.transit.get_passengers(car).len()
101 }
102
103 pub fn bus_route_id(&self, maybe_bus: CarID) -> Option<TransitRouteID> {
104 if maybe_bus.vehicle_type == VehicleType::Bus
105 || maybe_bus.vehicle_type == VehicleType::Train
106 {
107 Some(self.transit.bus_route(maybe_bus))
108 } else {
109 None
110 }
111 }
112
113 pub fn active_agents(&self) -> Vec<AgentID> {
114 self.trips.active_agents()
115 }
116 pub fn num_active_agents(&self) -> usize {
117 self.trips.num_active_agents()
118 }
119
120 pub fn agent_to_trip(&self, id: AgentID) -> Option<TripID> {
121 self.trips.agent_to_trip(id)
122 }
123
124 pub fn trip_to_agent(&self, id: TripID) -> TripResult<AgentID> {
125 self.trips.trip_to_agent(id)
126 }
127
128 pub fn trip_info(&self, id: TripID) -> TripInfo {
129 self.trips.trip_info(id)
130 }
131 pub fn all_trip_info(&self) -> Vec<(TripID, TripInfo)> {
132 self.trips.all_trip_info()
133 }
134 pub fn finished_trip_details(&self, id: TripID) -> Option<(Duration, Duration, Distance)> {
136 self.trips.finished_trip_details(id)
137 }
138 pub fn trip_blocked_time(&self, id: TripID) -> Duration {
140 self.trips.trip_blocked_time(id)
141 }
142
143 pub fn trip_to_person(&self, id: TripID) -> Option<PersonID> {
144 self.trips.trip_to_person(id)
145 }
146 pub fn agent_to_person(&self, id: AgentID) -> Option<PersonID> {
149 self.agent_to_trip(id)
150 .map(|t| self.trip_to_person(t).unwrap())
151 }
152 pub fn person_to_agent(&self, id: PersonID) -> Option<AgentID> {
153 if let PersonState::Trip(t) = self.trips.get_person(id)?.state {
154 self.trip_to_agent(t).ok()
155 } else {
156 None
157 }
158 }
159 pub fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
160 self.driving
161 .get_owner_of_car(id)
162 .or_else(|| self.parking.get_owner_of_car(id))
163 }
164 pub fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
165 self.parking.lookup_parked_car(id)
166 }
167 pub fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, Position)> {
169 self.parking
170 .all_parked_car_positions(map)
171 .into_iter()
172 .filter_map(|(car_pos, owner)| {
173 match self.trips.get_person(owner)?.state {
175 PersonState::Inside(b) => Some((car_pos, map.get_b(b).sidewalk_pos)),
176 PersonState::Trip(_) => None,
177 PersonState::OffMap => None,
178 }
179 })
180 .collect()
181 }
182
183 pub fn lookup_person(&self, id: PersonID) -> Option<&Person> {
184 self.trips.get_person(id)
185 }
186 pub fn get_person(&self, id: PersonID) -> &Person {
187 self.trips.get_person(id).unwrap()
188 }
189 pub fn find_person_by_orig_id(&self, id: OrigPersonID) -> Option<PersonID> {
190 for p in self.get_all_people() {
191 if p.orig_id == Some(id) {
192 return Some(p.id);
193 }
194 }
195 None
196 }
197 pub fn get_all_people(&self) -> &Vec<Person> {
198 self.trips.get_all_people()
199 }
200
201 pub fn lookup_car_id(&self, idx: usize) -> Option<CarID> {
202 for vehicle_type in [
203 VehicleType::Car,
204 VehicleType::Bike,
205 VehicleType::Bus,
206 VehicleType::Train,
207 ] {
208 let id = CarID {
209 id: idx,
210 vehicle_type,
211 };
212 if self.driving.does_car_exist(id) {
213 return Some(id);
214 }
215 }
216
217 let id = CarID {
218 id: idx,
219 vehicle_type: VehicleType::Car,
220 };
221 if self.parking.lookup_parked_car(id).is_some() {
223 return Some(id);
224 }
225
226 None
227 }
228
229 pub fn get_path(&self, id: AgentID) -> Option<&Path> {
230 match id {
231 AgentID::Car(car) => self.driving.get_path(car),
232 AgentID::Pedestrian(ped) => self.walking.get_path(ped),
233 AgentID::BusPassenger(_, _) => None,
234 }
235 }
236 pub fn get_all_driving_paths(&self) -> Vec<&Path> {
237 self.driving.get_all_driving_paths()
238 }
239
240 pub fn trace_route(&self, id: AgentID, map: &Map) -> Option<PolyLine> {
241 match id {
242 AgentID::Car(car) => self.driving.trace_route(self.time, car, map),
243 AgentID::Pedestrian(ped) => self.walking.trace_route(self.time, ped, map),
244 AgentID::BusPassenger(_, _) => None,
245 }
246 }
247
248 pub fn get_canonical_pt_per_trip(&self, trip: TripID, map: &Map) -> TripResult<Pt2D> {
249 let agent = match self.trips.trip_to_agent(trip) {
250 TripResult::Ok(a) => a,
251 x => {
252 return x.propagate_error();
253 }
254 };
255 if let Some(pt) = self.canonical_pt_for_agent(agent, map) {
256 return TripResult::Ok(pt);
257 }
258 TripResult::ModeChange
259 }
260 pub fn get_canonical_pt_per_person(&self, p: PersonID, map: &Map) -> Option<Pt2D> {
261 match self.trips.get_person(p)?.state {
262 PersonState::Inside(b) => Some(map.get_b(b).polygon.center()),
263 PersonState::Trip(t) => self.get_canonical_pt_per_trip(t, map).ok(),
264 PersonState::OffMap => None,
265 }
266 }
267
268 pub fn canonical_pt_for_agent(&self, id: AgentID, map: &Map) -> Option<Pt2D> {
269 match id {
270 AgentID::Car(id) => self
271 .parking
272 .canonical_pt(id, map)
273 .or_else(|| Some(self.get_draw_car(id, map)?.body.last_pt())),
274 AgentID::Pedestrian(id) => Some(self.get_draw_ped(id, map)?.pos),
275 AgentID::BusPassenger(_, bus) => Some(self.get_draw_car(bus, map)?.body.last_pt()),
276 }
277 }
278
279 pub fn get_accepted_agents(&self, id: IntersectionID) -> Vec<(AgentID, TurnID)> {
280 self.intersections.get_accepted_agents(id)
281 }
282 pub fn get_waiting_agents(&self, id: IntersectionID) -> Vec<(AgentID, TurnID, Time)> {
283 self.intersections.get_waiting_agents(id)
284 }
285
286 pub fn get_blocked_by_graph(&self, map: &Map) -> BTreeMap<AgentID, (Duration, DelayCause)> {
289 self.driving
291 .get_blocked_by_graph(self.time, map, &self.intersections)
292 }
293
294 pub fn status_of_buses(
296 &self,
297 route: TransitRouteID,
298 map: &Map,
299 ) -> Vec<(CarID, Option<usize>, f64, Pt2D)> {
300 let mut results = Vec::new();
301 for (bus, stop_idx) in self.transit.buses_for_route(route) {
302 results.push((
303 bus,
304 stop_idx,
305 self.driving.percent_along_route(bus),
306 self.canonical_pt_for_agent(AgentID::Car(bus), map).unwrap(),
307 ));
308 }
309 results
310 }
311
312 pub fn get_analytics(&self) -> &Analytics {
313 &self.analytics
314 }
315
316 pub fn delayed_intersections(&self, threshold: Duration) -> Vec<(IntersectionID, Time)> {
319 self.intersections
320 .delayed_intersections(self.time, threshold)
321 }
322
323 pub fn bldg_to_people(&self, b: BuildingID) -> Vec<PersonID> {
324 self.trips.bldg_to_people(b)
325 }
326
327 pub fn get_pandemic_model(&self) -> Option<&PandemicModel> {
328 self.pandemic.as_ref()
329 }
330
331 pub fn get_end_of_day(&self) -> Time {
332 self.scheduler
337 .get_last_time()
338 .max(Time::START_OF_DAY + Duration::hours(24))
339 }
340
341 pub fn current_stage_and_remaining_time(&self, i: IntersectionID) -> (usize, Duration) {
342 self.intersections
343 .current_stage_and_remaining_time(self.time, i)
344 }
345
346 pub fn all_arrivals_at_border(
349 &self,
350 i: IntersectionID,
351 ) -> Vec<(AgentType, Vec<(Time, usize)>)> {
352 let window_size = Duration::hours(1);
353 let mut pts_per_type: BTreeMap<AgentType, Vec<(Time, usize)>> = BTreeMap::new();
354 let mut windows_per_type: BTreeMap<AgentType, SlidingWindow> = BTreeMap::new();
355 for agent_type in AgentType::all() {
356 pts_per_type.insert(agent_type, vec![(Time::START_OF_DAY, 0)]);
357 windows_per_type.insert(agent_type, SlidingWindow::new(window_size));
358 }
359
360 for (t, agent_type) in self.trips.all_arrivals_at_border(i) {
361 let count = windows_per_type.get_mut(&agent_type).unwrap().add(t);
362 pts_per_type.get_mut(&agent_type).unwrap().push((t, count));
363 }
364
365 for (agent_type, pts) in pts_per_type.iter_mut() {
366 let mut window = windows_per_type.remove(agent_type).unwrap();
367 window.close_off_pts(pts, self.get_end_of_day());
368 }
369
370 pts_per_type.into_iter().collect()
371 }
372
373 pub fn target_lane_penalty(&self, lane: &Lane) -> (usize, usize) {
375 if lane.is_walkable() {
376 (0, 0)
377 } else {
378 self.driving.target_lane_penalty(lane.id)
379 }
380 }
381
382 pub fn get_people_waiting_at_stop(
383 &self,
384 at: TransitStopID,
385 ) -> &Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)> {
386 self.transit.get_people_waiting_at_stop(at)
387 }
388
389 pub fn generate_scenario(&self, map: &Map, name: String) -> Scenario {
390 self.trips.generate_scenario(map, name)
391 }
392
393 pub fn infinite_parking(&self) -> bool {
394 self.parking.is_infinite()
395 }
396
397 pub fn all_waiting_people(&self) -> BTreeMap<PersonID, Duration> {
398 let mut delays = BTreeMap::new();
399 self.walking.all_waiting_people(self.time, &mut delays);
400 self.driving.all_waiting_people(self.time, &mut delays);
401 delays
402 }
403
404 pub fn describe_internal_stats(&self) -> Vec<String> {
405 let mut stats = self.scheduler.describe_stats();
406 stats.push(String::new());
407 stats.extend(self.intersections.describe_stats());
408 stats
409 }
410
411 pub fn debug_queue_lengths(&self, l: LaneID) -> Option<(Distance, Distance)> {
412 self.driving.debug_queue_lengths(l)
413 }
414
415 pub fn get_trip_time_lower_bound(&self, map: &Map, id: TripID) -> Result<Duration> {
419 let info = self.trips.trip_info(id);
420 match TripEndpoint::path_req(info.start, info.end, info.mode, map) {
421 Some(req) => {
422 let path = map.pathfind(req)?;
423 let person = self
424 .trips
425 .get_person(self.trips.trip_to_person(id).unwrap())
426 .unwrap();
427 let max_speed = match info.mode {
428 TripMode::Walk | TripMode::Transit => Some(person.ped_speed),
429 TripMode::Drive => None,
431 TripMode::Bike => {
433 person
434 .vehicles
435 .iter()
436 .find(|v| v.vehicle_type == VehicleType::Bike)
437 .unwrap()
438 .max_speed
439 }
440 };
441 Ok(path.estimate_duration(map, max_speed))
442 }
443 None => bail!(
444 "can't figure out PathRequest from {:?} to {:?} via {}",
445 info.start,
446 info.end,
447 info.mode.ongoing_verb()
448 ),
449 }
450 }
451
452 pub fn get_highlighted_people(&self) -> &Option<BTreeSet<PersonID>> {
453 &self.highlighted_people
454 }
455
456 pub fn get_pedestrian_density(
459 &self,
460 map: &Map,
461 ) -> (BTreeMap<RoadID, f64>, BTreeMap<IntersectionID, f64>) {
462 self.walking.get_pedestrian_density(map)
463 }
464}
465
466impl Sim {
468 pub fn step_count(&self) -> usize {
469 self.step_count
470 }
471
472 pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
473 self.parking.get_draw_car(id, map).or_else(|| {
474 self.driving
475 .get_single_draw_car(id, self.time, map, &self.transit)
476 })
477 }
478
479 pub fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> {
480 self.walking.get_draw_ped(id, self.time, map)
481 }
482
483 pub fn get_draw_cars(&self, on: Traversable, map: &Map) -> Vec<DrawCarInput> {
484 let mut results = Vec::new();
485 if let Traversable::Lane(l) = on {
486 if map.get_l(l).is_parking() {
487 return self.parking.get_draw_cars(l, map);
488 }
489 results.extend(self.parking.get_draw_cars_in_lots(l, map));
490 }
491 results.extend(
492 self.driving
493 .get_draw_cars_on(self.time, on, map, &self.transit),
494 );
495 results
496 }
497
498 pub fn get_draw_peds(
499 &self,
500 on: Traversable,
501 map: &Map,
502 ) -> (Vec<DrawPedestrianInput>, Vec<DrawPedCrowdInput>) {
503 self.walking.get_draw_peds_on(self.time, on, map)
504 }
505
506 pub fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
507 let mut result = self
508 .driving
509 .get_all_draw_cars(self.time, map, &self.transit);
510 result.extend(self.parking.get_all_draw_cars(map));
511 result
512 }
513
514 pub fn get_all_draw_peds(&self, map: &Map) -> Vec<DrawPedestrianInput> {
515 self.walking.get_all_draw_peds(self.time, map)
516 }
517
518 pub fn get_unzoomed_agents(&self, map: &Map) -> Vec<UnzoomedAgent> {
521 let mut result = self.driving.get_unzoomed_agents(self.time, map);
522 result.extend(self.walking.get_unzoomed_agents(self.time, map));
523 result
524 }
525 pub fn get_unzoomed_transit_riders(&self, map: &Map) -> Vec<UnzoomedAgent> {
526 self.transit
527 .get_unzoomed_transit_riders(self.time, &self.driving, map)
528 }
529}
530
531pub struct AgentProperties {
532 pub total_time: Duration,
534 pub waiting_here: Duration,
535 pub total_waiting: Duration,
536
537 pub dist_crossed: Distance,
538 pub total_dist: Distance,
539}
540
541#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize)]
544pub enum DelayCause {
545 Agent(AgentID),
548 Intersection(IntersectionID),
550}