1use std::collections::{BTreeMap, BTreeSet};
2
3use serde::{Deserialize, Serialize};
4
5use abstutil::{deserialize_btreemap, serialize_btreemap};
6use geom::Time;
7use map_model::{Map, Path, TransitRoute, TransitRouteID, TransitStopID};
8
9use crate::sim::Ctx;
10use crate::{
11 AgentID, CarID, DrivingSimState, Event, PedestrianID, PersonID, Router, TripID, TripManager,
12 TripPhaseType, UnzoomedAgent, VehicleType, WalkingSimState,
13};
14
15type StopIdx = usize;
17
18#[derive(Serialize, Deserialize, Clone)]
19struct Route {
20 paths: Vec<Path>,
23 stops: Vec<TransitStopID>,
24 active_vehicles: BTreeSet<CarID>,
25}
26
27#[derive(Serialize, Deserialize, Clone)]
28struct Bus {
29 car: CarID,
30 route: TransitRouteID,
31 passengers: Vec<(PersonID, Option<TransitStopID>)>,
33 state: BusState,
34}
35
36#[derive(Serialize, Deserialize, Clone)]
37enum BusState {
38 DrivingToStop(StopIdx),
39 AtStop(StopIdx),
40 DrivingOffMap,
42 Finished,
43}
44
45#[derive(Serialize, Deserialize, Clone)]
48pub(crate) struct TransitSimState {
49 #[serde(
50 serialize_with = "serialize_btreemap",
51 deserialize_with = "deserialize_btreemap"
52 )]
53 buses: BTreeMap<CarID, Bus>,
54 #[serde(
55 serialize_with = "serialize_btreemap",
56 deserialize_with = "deserialize_btreemap"
57 )]
58 routes: BTreeMap<TransitRouteID, Route>,
59 #[serde(
61 serialize_with = "serialize_btreemap",
62 deserialize_with = "deserialize_btreemap"
63 )]
64 peds_waiting:
65 BTreeMap<TransitStopID, Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)>>,
66
67 events: Vec<Event>,
68}
69
70impl TransitSimState {
71 pub fn new(map: &Map) -> TransitSimState {
72 let mut peds_waiting = BTreeMap::new();
74 for ts in map.all_transit_stops().keys() {
75 peds_waiting.insert(*ts, 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 pub fn create_empty_route(&mut self, bus_route: &TransitRoute, map: &Map) -> Path {
88 self.routes
89 .entry(bus_route.id)
90 .or_insert_with(|| match bus_route.all_paths(map) {
91 Ok(paths) => {
92 let stops = bus_route.stops.clone();
93 assert_eq!(paths.len(), stops.len() + 1);
94 Route {
95 stops,
96 paths,
97 active_vehicles: BTreeSet::new(),
98 }
99 }
100 Err(err) => {
101 panic!("{} wound up with bad paths: {}", bus_route.short_name, err);
102 }
103 });
104
105 self.routes[&bus_route.id].paths[0].clone()
106 }
107
108 pub fn bus_created(&mut self, bus: CarID, r: TransitRouteID) {
109 let route = self.routes.get_mut(&r).unwrap();
110 route.active_vehicles.insert(bus);
111 self.buses.insert(
112 bus,
113 Bus {
114 car: bus,
115 route: r,
116 passengers: Vec::new(),
117 state: BusState::DrivingToStop(0),
118 },
119 );
120 }
121
122 pub fn bus_arrived_at_stop(
127 &mut self,
128 now: Time,
129 id: CarID,
130 trips: &mut TripManager,
131 walking: &mut WalkingSimState,
132 ctx: &mut Ctx,
133 ) -> bool {
134 let bus = self.buses.get_mut(&id).unwrap();
135 match bus.state {
136 BusState::DrivingToStop(stop_idx) => {
137 bus.state = BusState::AtStop(stop_idx);
138 let stop1 = self.routes[&bus.route].stops[stop_idx];
139 self.events
140 .push(Event::BusArrivedAtStop(id, bus.route, stop1));
141
142 let mut still_riding = Vec::new();
144 for (person, maybe_stop2) in bus.passengers.drain(..) {
145 if Some(stop1) == maybe_stop2 {
146 trips.person_left_bus(now, person, bus.car, ctx);
147 self.events.push(Event::PassengerAlightsTransit(
148 person, bus.car, bus.route, stop1,
149 ));
150 } else {
151 still_riding.push((person, maybe_stop2));
152 }
153 }
154 bus.passengers = still_riding;
155
156 let mut still_waiting = Vec::new();
158 for (ped, route, maybe_stop2, started_waiting) in
159 self.peds_waiting.remove(&stop1).unwrap()
160 {
161 if bus.route == route {
162 let (trip, person) = trips.ped_boarded_bus(
163 now,
164 ped,
165 bus.car,
166 now - started_waiting,
167 walking,
168 );
169 self.events.push(Event::PassengerBoardsTransit(
170 person,
171 bus.car,
172 bus.route,
173 stop1,
174 now - started_waiting,
175 ));
176 self.events.push(Event::TripPhaseStarting(
181 trip,
182 person,
183 None,
184 TripPhaseType::RidingBus(route, stop1, bus.car),
185 ));
186 bus.passengers.push((person, maybe_stop2));
187 } else {
188 still_waiting.push((ped, route, maybe_stop2, started_waiting));
189 }
190 }
191 self.peds_waiting.insert(stop1, still_waiting);
192 true
193 }
194 BusState::DrivingOffMap => {
195 self.routes
196 .get_mut(&bus.route)
197 .unwrap()
198 .active_vehicles
199 .remove(&id);
200 for (person, maybe_stop2) in bus.passengers.drain(..) {
201 if let Some(stop2) = maybe_stop2 {
202 panic!(
203 "{} fell asleep on {} and just rode off-map, but they were supposed \
204 to hop off at {}",
205 person, bus.car, stop2
206 );
207 }
208 trips.transit_rider_reached_border(now, person, id, ctx);
209 }
210 bus.state = BusState::Finished;
211 false
212 }
213 BusState::AtStop(_) | BusState::Finished => unreachable!(),
214 }
215 }
216
217 pub fn bus_departed_from_stop(&mut self, id: CarID, _: &Map) -> Router {
218 let bus = self.buses.get_mut(&id).unwrap();
219 let route = self.routes.get_mut(&bus.route).unwrap();
220 match bus.state {
221 BusState::AtStop(stop_idx) => {
222 self.events.push(Event::BusDepartedFromStop(
223 id,
224 bus.route,
225 route.stops[stop_idx],
226 ));
227
228 if stop_idx == route.stops.len() - 1 {
229 bus.state = BusState::DrivingOffMap;
230 } else {
231 bus.state = BusState::DrivingToStop(stop_idx + 1);
232 }
233 Router::follow_bus_route(id, route.paths[stop_idx + 1].clone())
234 }
235 BusState::DrivingToStop(_) | BusState::DrivingOffMap | BusState::Finished => {
236 unreachable!()
237 }
238 }
239 }
240
241 pub fn ped_waiting_for_bus(
243 &mut self,
244 now: Time,
245 ped: PedestrianID,
246 trip: TripID,
247 person: PersonID,
248 stop1: TransitStopID,
249 route_id: TransitRouteID,
250 maybe_stop2: Option<TransitStopID>,
251 _: &Map,
252 ) -> Option<CarID> {
253 assert!(Some(stop1) != maybe_stop2);
254 if let Some(route) = self.routes.get(&route_id) {
255 for bus in &route.active_vehicles {
256 if let BusState::AtStop(idx) = self.buses[bus].state {
257 if route.stops[idx] == stop1 {
258 self.buses
259 .get_mut(bus)
260 .unwrap()
261 .passengers
262 .push((person, maybe_stop2));
263 self.events.push(Event::TripPhaseStarting(
265 trip,
266 person,
267 None,
268 TripPhaseType::RidingBus(route_id, stop1, *bus),
269 ));
270 return Some(*bus);
271 }
272 }
273 }
274 } else {
275 println!(
276 "WARNING: {} waiting for {}, but that route hasn't been instantiated",
277 ped, route_id
278 );
279 }
280
281 self.peds_waiting
282 .get_mut(&stop1)
283 .unwrap()
284 .push((ped, route_id, maybe_stop2, now));
285 None
286 }
287
288 pub fn collect_events(&mut self) -> Vec<Event> {
289 self.events.drain(..).collect()
290 }
291
292 pub fn get_passengers(&self, bus: CarID) -> &Vec<(PersonID, Option<TransitStopID>)> {
293 &self.buses[&bus].passengers
294 }
295
296 pub fn bus_route(&self, bus: CarID) -> TransitRouteID {
297 self.buses[&bus].route
298 }
299
300 pub fn buses_for_route(&self, route: TransitRouteID) -> Vec<(CarID, Option<usize>)> {
302 if let Some(r) = self.routes.get(&route) {
303 r.active_vehicles
304 .iter()
305 .map(|bus| {
306 let stop = match self.buses[bus].state {
307 BusState::DrivingToStop(idx) => {
308 if idx == 0 {
309 None
310 } else {
311 Some(idx - 1)
312 }
313 }
314 BusState::AtStop(idx) => Some(idx),
315 BusState::DrivingOffMap => Some(r.stops.len() - 1),
316 BusState::Finished => unreachable!(),
317 };
318 (*bus, stop)
319 })
320 .collect()
321 } else {
322 Vec::new()
323 }
324 }
325
326 pub fn active_vehicles(&self) -> (usize, usize) {
328 let mut buses = 0;
329 let mut trains = 0;
330 for r in self.routes.values() {
331 let len = r.active_vehicles.len();
332 if len > 0 {
333 if r.active_vehicles.iter().next().unwrap().vehicle_type == VehicleType::Bus {
334 buses += len;
335 } else {
336 trains += len;
337 }
338 }
339 }
340 (buses, trains)
341 }
342
343 pub fn get_people_waiting_at_stop(
344 &self,
345 at: TransitStopID,
346 ) -> &Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)> {
347 &self.peds_waiting[&at]
348 }
349
350 pub fn get_unzoomed_transit_riders(
351 &self,
352 now: Time,
353 driving: &DrivingSimState,
354 map: &Map,
355 ) -> Vec<UnzoomedAgent> {
356 let mut results = Vec::new();
357 for (bus_id, bus) in &self.buses {
358 if bus.passengers.is_empty() {
359 continue;
360 }
361 let pos = if let Some(input) = driving.get_single_draw_car(*bus_id, now, map, self) {
362 input.body.last_pt()
363 } else {
364 panic!(
365 "At {}, bus {} can't be drawn, yet it has passengers {:?}",
366 now, bus_id, bus.passengers
367 );
368 };
369 for (person, _) in &bus.passengers {
370 let agent = AgentID::BusPassenger(*person, *bus_id);
371 results.push(UnzoomedAgent {
372 id: agent,
373 pos,
374 person: Some(*person),
375 parking: false,
376 });
377 }
378 }
379 results
380 }
381}