1 use crate::sim::Ctx;
2 use crate::{
3     CarID, Event, PedestrianID, PersonID, Router, TripID, TripManager, TripPhaseType, VehicleType,
4     WalkingSimState,
5 };
6 use abstutil::{deserialize_btreemap, serialize_btreemap};
7 use geom::Time;
8 use map_model::{BusRoute, BusRouteID, BusStopID, Map, Path, PathRequest, Position};
9 use serde::{Deserialize, Serialize};
10 use std::collections::{BTreeMap, BTreeSet};
11 
12 // These index stops along a route, not stops along a single sidewalk.
13 type StopIdx = usize;
14 
15 #[derive(Serialize, Deserialize, Clone)]
16 struct Stop {
17     id: BusStopID,
18     driving_pos: Position,
19     next_stop: Option<(PathRequest, Path)>,
20 }
21 
22 #[derive(Serialize, Deserialize, Clone)]
23 struct Route {
24     stops: Vec<Stop>,
25     start: (PathRequest, Path),
26     end_at_border: Option<(PathRequest, Path)>,
27     active_vehicles: BTreeSet<CarID>,
28 }
29 
30 #[derive(Serialize, Deserialize, Clone)]
31 struct Bus {
32     car: CarID,
33     route: BusRouteID,
34     // Where does each passenger want to deboard?
35     passengers: Vec<(PersonID, Option<BusStopID>)>,
36     state: BusState,
37 }
38 
39 #[derive(Serialize, Deserialize, Clone)]
40 enum BusState {
41     DrivingToStop(StopIdx),
42     AtStop(StopIdx),
43     DrivingOffMap,
44     Done,
45 }
46 
47 // This kind of acts like TripManager, managing transitions... but a bit more statefully.
48 #[derive(Serialize, Deserialize, Clone)]
49 pub struct TransitSimState {
50     #[serde(
51         serialize_with = "serialize_btreemap",
52         deserialize_with = "deserialize_btreemap"
53     )]
54     buses: BTreeMap<CarID, Bus>,
55     #[serde(
56         serialize_with = "serialize_btreemap",
57         deserialize_with = "deserialize_btreemap"
58     )]
59     routes: BTreeMap<BusRouteID, Route>,
60     // waiting at => (ped, route, bound for, started waiting)
61     #[serde(
62         serialize_with = "serialize_btreemap",
63         deserialize_with = "deserialize_btreemap"
64     )]
65     peds_waiting: BTreeMap<BusStopID, Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)>>,
66 
67     events: Vec<Event>,
68 }
69 
70 impl TransitSimState {
new(map: &Map) -> TransitSimState71     pub fn new(map: &Map) -> TransitSimState {
72         // Keep this filled out always so get_passengers can return &Vec without a hassle
73         let mut peds_waiting = BTreeMap::new();
74         for bs in map.all_bus_stops().keys() {
75             peds_waiting.insert(*bs, Vec::new());
76         }
77 
78         TransitSimState {
79             buses: BTreeMap::new(),
80             routes: BTreeMap::new(),
81             peds_waiting,
82             events: Vec::new(),
83         }
84     }
85 
86     // Returns the path for the first leg.
create_empty_route(&mut self, bus_route: &BusRoute, map: &Map) -> (PathRequest, Path)87     pub fn create_empty_route(&mut self, bus_route: &BusRoute, map: &Map) -> (PathRequest, Path) {
88         if !self.routes.contains_key(&bus_route.id) {
89             assert!(bus_route.stops.len() > 1);
90             let mut stops = Vec::new();
91             for (idx, stop1_id) in bus_route.stops.iter().enumerate() {
92                 let stop1 = map.get_bs(*stop1_id);
93                 if idx == bus_route.stops.len() - 1 {
94                     stops.push(Stop {
95                         id: stop1.id,
96                         driving_pos: stop1.driving_pos,
97                         next_stop: None,
98                     });
99                     continue;
100                 }
101                 let req = PathRequest {
102                     start: stop1.driving_pos,
103                     end: map.get_bs(bus_route.stops[idx + 1]).driving_pos,
104                     constraints: bus_route.route_type,
105                 };
106                 if let Some(path) = map.pathfind(req.clone()) {
107                     if path.is_empty() {
108                         panic!("Empty path between stops?! {}", req);
109                     }
110                     stops.push(Stop {
111                         id: stop1.id,
112                         driving_pos: stop1.driving_pos,
113                         next_stop: Some((req, path)),
114                     });
115                 } else {
116                     panic!("No route between stops: {}", req);
117                 }
118             }
119             let start_req = PathRequest {
120                 start: Position::start(bus_route.start),
121                 end: map.get_bs(bus_route.stops[0]).driving_pos,
122                 constraints: bus_route.route_type,
123             };
124             let start = (
125                 start_req.clone(),
126                 map.pathfind(start_req).expect("no route to first stop"),
127             );
128             let end_at_border = if let Some(l) = bus_route.end_border {
129                 let req = PathRequest {
130                     start: map.get_bs(*bus_route.stops.last().unwrap()).driving_pos,
131                     end: Position::end(l, map),
132                     constraints: bus_route.route_type,
133                 };
134                 let path = map
135                     .pathfind(req.clone())
136                     .expect("no route from last stop to border");
137                 Some((req, path))
138             } else {
139                 None
140             };
141             self.routes.insert(
142                 bus_route.id,
143                 Route {
144                     active_vehicles: BTreeSet::new(),
145                     stops,
146                     start,
147                     end_at_border,
148                 },
149             );
150         }
151 
152         self.routes[&bus_route.id].start.clone()
153     }
154 
bus_created(&mut self, bus: CarID, r: BusRouteID)155     pub fn bus_created(&mut self, bus: CarID, r: BusRouteID) {
156         let route = self.routes.get_mut(&r).unwrap();
157         route.active_vehicles.insert(bus);
158         self.buses.insert(
159             bus,
160             Bus {
161                 car: bus,
162                 route: r,
163                 passengers: Vec::new(),
164                 state: BusState::DrivingToStop(0),
165             },
166         );
167     }
168 
169     // If true, the bus is idling. If false, the bus actually arrived at a border and should now
170     // vanish.
bus_arrived_at_stop( &mut self, now: Time, id: CarID, trips: &mut TripManager, walking: &mut WalkingSimState, ctx: &mut Ctx, ) -> bool171     pub fn bus_arrived_at_stop(
172         &mut self,
173         now: Time,
174         id: CarID,
175         trips: &mut TripManager,
176         walking: &mut WalkingSimState,
177         ctx: &mut Ctx,
178     ) -> bool {
179         let mut bus = self.buses.get_mut(&id).unwrap();
180         match bus.state {
181             BusState::DrivingToStop(stop_idx) => {
182                 bus.state = BusState::AtStop(stop_idx);
183                 let stop1 = self.routes[&bus.route].stops[stop_idx].id;
184                 self.events
185                     .push(Event::BusArrivedAtStop(id, bus.route, stop1));
186 
187                 // Deboard existing passengers.
188                 let mut still_riding = Vec::new();
189                 for (person, maybe_stop2) in bus.passengers.drain(..) {
190                     if Some(stop1) == maybe_stop2 {
191                         trips.person_left_bus(now, person, bus.car, ctx);
192                         self.events.push(Event::PassengerAlightsTransit(
193                             person, bus.car, bus.route, stop1,
194                         ));
195                     } else {
196                         still_riding.push((person, maybe_stop2));
197                     }
198                 }
199                 bus.passengers = still_riding;
200 
201                 // Board new passengers.
202                 let mut still_waiting = Vec::new();
203                 for (ped, route, maybe_stop2, started_waiting) in
204                     self.peds_waiting.remove(&stop1).unwrap()
205                 {
206                     if bus.route == route {
207                         let (trip, person) = trips.ped_boarded_bus(
208                             now,
209                             ped,
210                             bus.car,
211                             now - started_waiting,
212                             walking,
213                         );
214                         self.events.push(Event::PassengerBoardsTransit(
215                             person,
216                             bus.car,
217                             bus.route,
218                             stop1,
219                             now - started_waiting,
220                         ));
221                         self.events.push(Event::TripPhaseStarting(
222                             trip,
223                             person,
224                             Some(PathRequest {
225                                 start: ctx.map.get_bs(stop1).driving_pos,
226                                 end: if let Some(stop2) = maybe_stop2 {
227                                     ctx.map.get_bs(stop2).driving_pos
228                                 } else {
229                                     self.routes[&route].end_at_border.as_ref().unwrap().0.end
230                                 },
231                                 constraints: bus.car.1.to_constraints(),
232                             }),
233                             TripPhaseType::RidingBus(route, stop1, bus.car),
234                         ));
235                         bus.passengers.push((person, maybe_stop2));
236                     } else {
237                         still_waiting.push((ped, route, maybe_stop2, started_waiting));
238                     }
239                 }
240                 self.peds_waiting.insert(stop1, still_waiting);
241                 true
242             }
243             BusState::DrivingOffMap => {
244                 self.routes
245                     .get_mut(&bus.route)
246                     .unwrap()
247                     .active_vehicles
248                     .remove(&id);
249                 bus.state = BusState::Done;
250                 for (person, maybe_stop2) in bus.passengers.drain(..) {
251                     if let Some(stop2) = maybe_stop2 {
252                         panic!(
253                             "{} fell asleep on {} and just rode off-map, but they were supposed \
254                              to hop off at {}",
255                             person, bus.car, stop2
256                         );
257                     }
258                     trips.transit_rider_reached_border(now, person, id, ctx);
259                 }
260                 false
261             }
262             BusState::AtStop(_) | BusState::Done => unreachable!(),
263         }
264     }
265 
bus_departed_from_stop(&mut self, id: CarID, map: &Map) -> Router266     pub fn bus_departed_from_stop(&mut self, id: CarID, map: &Map) -> Router {
267         let mut bus = self.buses.get_mut(&id).unwrap();
268         let route = self.routes.get_mut(&bus.route).unwrap();
269         match bus.state {
270             BusState::DrivingToStop(_) | BusState::DrivingOffMap | BusState::Done => unreachable!(),
271             BusState::AtStop(stop_idx) => {
272                 let stop = &route.stops[stop_idx];
273                 self.events
274                     .push(Event::BusDepartedFromStop(id, bus.route, stop.id));
275                 if let Some((req, path)) = stop.next_stop.clone() {
276                     bus.state = BusState::DrivingToStop(stop_idx + 1);
277                     Router::follow_bus_route(id, path, req.end.dist_along())
278                 } else {
279                     if let Some((req, path)) = route.end_at_border.clone() {
280                         bus.state = BusState::DrivingOffMap;
281                         Router::follow_bus_route(id, path, req.end.dist_along())
282                     } else {
283                         let on = stop.driving_pos.lane();
284                         route.active_vehicles.remove(&id);
285                         for (person, stop2) in &bus.passengers {
286                             panic!(
287                                 "{} of {} is vanishing at its last stop, but {} is still riding \
288                                  until {:?}",
289                                 bus.car, bus.route, person, stop2
290                             );
291                         }
292                         bus.state = BusState::Done;
293                         Router::vanish_bus(id, on, map)
294                     }
295                 }
296             }
297         }
298     }
299 
300     // Returns the bus if the pedestrian boarded immediately.
ped_waiting_for_bus( &mut self, now: Time, ped: PedestrianID, trip: TripID, person: PersonID, stop1: BusStopID, route_id: BusRouteID, maybe_stop2: Option<BusStopID>, map: &Map, ) -> Option<CarID>301     pub fn ped_waiting_for_bus(
302         &mut self,
303         now: Time,
304         ped: PedestrianID,
305         trip: TripID,
306         person: PersonID,
307         stop1: BusStopID,
308         route_id: BusRouteID,
309         maybe_stop2: Option<BusStopID>,
310         map: &Map,
311     ) -> Option<CarID> {
312         assert!(Some(stop1) != maybe_stop2);
313         if let Some(route) = self.routes.get(&route_id) {
314             for bus in &route.active_vehicles {
315                 if let BusState::AtStop(idx) = self.buses[bus].state {
316                     if route.stops[idx].id == stop1 {
317                         self.buses
318                             .get_mut(bus)
319                             .unwrap()
320                             .passengers
321                             .push((person, maybe_stop2));
322                         self.events.push(Event::TripPhaseStarting(
323                             trip,
324                             person,
325                             Some(PathRequest {
326                                 start: map.get_bs(stop1).driving_pos,
327                                 end: if let Some(stop2) = maybe_stop2 {
328                                     map.get_bs(stop2).driving_pos
329                                 } else {
330                                     route.end_at_border.as_ref().unwrap().0.end
331                                 },
332                                 constraints: bus.1.to_constraints(),
333                             }),
334                             TripPhaseType::RidingBus(route_id, stop1, *bus),
335                         ));
336                         return Some(*bus);
337                     }
338                 }
339             }
340         } else {
341             println!(
342                 "WARNING: {} waiting for {}, but that route hasn't been instantiated",
343                 ped, route_id
344             );
345         }
346 
347         self.peds_waiting
348             .get_mut(&stop1)
349             .unwrap()
350             .push((ped, route_id, maybe_stop2, now));
351         None
352     }
353 
collect_events(&mut self) -> Vec<Event>354     pub fn collect_events(&mut self) -> Vec<Event> {
355         self.events.drain(..).collect()
356     }
357 
get_passengers(&self, bus: CarID) -> &Vec<(PersonID, Option<BusStopID>)>358     pub fn get_passengers(&self, bus: CarID) -> &Vec<(PersonID, Option<BusStopID>)> {
359         &self.buses[&bus].passengers
360     }
361 
bus_route(&self, bus: CarID) -> BusRouteID362     pub fn bus_route(&self, bus: CarID) -> BusRouteID {
363         self.buses[&bus].route
364     }
365 
366     // also stop idx that the bus is coming from
buses_for_route(&self, route: BusRouteID) -> Vec<(CarID, Option<usize>)>367     pub fn buses_for_route(&self, route: BusRouteID) -> Vec<(CarID, Option<usize>)> {
368         if let Some(ref r) = self.routes.get(&route) {
369             r.active_vehicles
370                 .iter()
371                 .map(|bus| {
372                     let stop = match self.buses[bus].state {
373                         BusState::DrivingToStop(idx) => {
374                             if idx == 0 {
375                                 None
376                             } else {
377                                 Some(idx - 1)
378                             }
379                         }
380                         BusState::AtStop(idx) => Some(idx),
381                         BusState::DrivingOffMap => Some(r.stops.len() - 1),
382                         BusState::Done => unreachable!(),
383                     };
384                     (*bus, stop)
385                 })
386                 .collect()
387         } else {
388             Vec::new()
389         }
390     }
391 
392     // (buses, trains)
active_vehicles(&self) -> (usize, usize)393     pub fn active_vehicles(&self) -> (usize, usize) {
394         let mut buses = 0;
395         let mut trains = 0;
396         for r in self.routes.values() {
397             let len = r.active_vehicles.len();
398             if len > 0 {
399                 if r.active_vehicles.iter().next().unwrap().1 == VehicleType::Bus {
400                     buses += len;
401                 } else {
402                     trains += len;
403                 }
404             }
405         }
406         (buses, trains)
407     }
408 
get_people_waiting_at_stop( &self, at: BusStopID, ) -> &Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)>409     pub fn get_people_waiting_at_stop(
410         &self,
411         at: BusStopID,
412     ) -> &Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)> {
413         &self.peds_waiting[&at]
414     }
415 }
416