1use std::collections::{hash_map::Entry, BTreeMap, BTreeSet, BinaryHeap, HashMap};
2
3use enum_dispatch::enum_dispatch;
4use rand::{Rng, SeedableRng};
5use rand_xorshift::XorShiftRng;
6use serde::{Deserialize, Serialize};
7
8use abstutil::{
9 deserialize_btreemap, deserialize_multimap, serialize_btreemap, serialize_multimap, MultiMap,
10 Timer,
11};
12use geom::{Distance, PolyLine, Pt2D};
13use map_model::{
14 BuildingID, Lane, LaneID, LaneType, Map, OffstreetParking, ParkingLotID, PathConstraints,
15 PathStep, Position, Traversable, TurnID,
16};
17
18use crate::{CarID, CarStatus, DrawCarInput, Event, ParkedCar, ParkingSpot, PersonID, Vehicle};
19
20#[enum_dispatch(ParkingSimState)]
25pub trait ParkingSim {
26 fn handle_live_edits(&mut self, map: &Map, timer: &mut Timer) -> (Vec<ParkedCar>, Vec<CarID>);
29 fn get_free_onstreet_spots(&self, l: LaneID) -> Vec<ParkingSpot>;
30 fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot>;
31 fn get_free_lot_spots(&self, pl: ParkingLotID) -> Vec<ParkingSpot>;
32 fn reserve_spot(&mut self, spot: ParkingSpot, car: CarID);
33 fn unreserve_spot(&mut self, car: CarID);
35 fn remove_parked_car(&mut self, p: ParkedCar);
36 fn add_parked_car(&mut self, p: ParkedCar);
37 fn get_draw_cars(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput>;
38 fn get_draw_cars_in_lots(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput>;
39 fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput>;
40 fn canonical_pt(&self, id: CarID, map: &Map) -> Option<Pt2D>;
42 fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput>;
43 fn is_free(&self, spot: ParkingSpot) -> bool;
44 fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<&ParkedCar>;
45 fn get_all_free_spots(
48 &self,
49 driving_pos: Position,
50 vehicle: &Vehicle,
51 target: BuildingID,
54 map: &Map,
55 ) -> Vec<(ParkingSpot, Position)>;
56 fn spot_to_driving_pos(&self, spot: ParkingSpot, vehicle: &Vehicle, map: &Map) -> Position;
57 fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position;
58 fn get_owner_of_car(&self, id: CarID) -> Option<PersonID>;
59 fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar>;
60 fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>);
62 fn path_to_free_parking_spot(
69 &self,
70 start: LaneID,
71 vehicle: &Vehicle,
72 target: BuildingID,
73 map: &Map,
74 ) -> Option<(Vec<PathStep>, ParkingSpot, Position)>;
75 fn collect_events(&mut self) -> Vec<Event>;
76 fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, PersonID)>;
77 fn bldg_to_parked_cars(&self, b: BuildingID) -> Vec<CarID>;
78}
79
80#[enum_dispatch]
81#[derive(Serialize, Deserialize, Clone)]
82pub enum ParkingSimState {
83 Normal(NormalParkingSimState),
84 Infinite(InfiniteParkingSimState),
85}
86
87impl ParkingSimState {
88 pub fn new(map: &Map, infinite: bool, timer: &mut Timer) -> ParkingSimState {
91 if infinite {
92 ParkingSimState::Infinite(InfiniteParkingSimState::new(map))
93 } else {
94 ParkingSimState::Normal(NormalParkingSimState::new(map, timer))
95 }
96 }
97
98 pub fn is_infinite(&self) -> bool {
99 match self {
100 ParkingSimState::Normal(_) => false,
101 ParkingSimState::Infinite(_) => true,
102 }
103 }
104}
105
106#[derive(Serialize, Deserialize, Clone)]
107pub struct NormalParkingSimState {
108 #[serde(
109 serialize_with = "serialize_btreemap",
110 deserialize_with = "deserialize_btreemap"
111 )]
112 parked_cars: BTreeMap<CarID, ParkedCar>,
113 #[serde(
114 serialize_with = "serialize_btreemap",
115 deserialize_with = "deserialize_btreemap"
116 )]
117 occupants: BTreeMap<ParkingSpot, CarID>,
118 #[serde(
119 serialize_with = "serialize_btreemap",
120 deserialize_with = "deserialize_btreemap"
121 )]
122 reserved_spots: BTreeMap<ParkingSpot, CarID>,
123
124 onstreet_lanes: BTreeMap<LaneID, ParkingLane>,
126 #[serde(
128 serialize_with = "serialize_multimap",
129 deserialize_with = "deserialize_multimap"
130 )]
131 driving_to_parking_lanes: MultiMap<LaneID, LaneID>,
132
133 num_spots_per_offstreet: BTreeMap<BuildingID, usize>,
135 #[serde(
137 serialize_with = "serialize_multimap",
138 deserialize_with = "deserialize_multimap"
139 )]
140 driving_to_offstreet: MultiMap<LaneID, (BuildingID, Distance)>,
141
142 num_spots_per_lot: BTreeMap<ParkingLotID, usize>,
144 #[serde(
145 serialize_with = "serialize_multimap",
146 deserialize_with = "deserialize_multimap"
147 )]
148 driving_to_lots: MultiMap<LaneID, ParkingLotID>,
149
150 events: Vec<Event>,
151}
152
153impl NormalParkingSimState {
154 fn new(map: &Map, timer: &mut Timer) -> NormalParkingSimState {
155 let mut sim = NormalParkingSimState {
156 parked_cars: BTreeMap::new(),
157 occupants: BTreeMap::new(),
158 reserved_spots: BTreeMap::new(),
159
160 onstreet_lanes: BTreeMap::new(),
161 driving_to_parking_lanes: MultiMap::new(),
162 num_spots_per_offstreet: BTreeMap::new(),
163 driving_to_offstreet: MultiMap::new(),
164 num_spots_per_lot: BTreeMap::new(),
165 driving_to_lots: MultiMap::new(),
166
167 events: Vec::new(),
168 };
169 for l in map.all_lanes() {
170 if let Some(lane) = ParkingLane::new(l, map) {
171 sim.driving_to_parking_lanes.insert(lane.driving_lane, l.id);
172 sim.onstreet_lanes.insert(lane.parking_lane, lane);
173 }
174 }
175 for (b, pos, num_spots) in timer
177 .parallelize(
178 "setup offstreet parking",
179 map.all_buildings().iter().collect(),
180 |b| {
181 if let Some((pos, _)) = b.driving_connection(map) {
182 if !map.get_l(pos.lane()).driving_blackhole {
183 let num_spots = b.num_parking_spots();
184 if num_spots > 0 {
185 Some((b.id, pos, num_spots))
186 } else {
187 None
188 }
189 } else {
190 None
191 }
192 } else {
193 None
194 }
195 },
196 )
197 .into_iter()
198 .flatten()
199 {
200 sim.num_spots_per_offstreet.insert(b, num_spots);
201 sim.driving_to_offstreet
202 .insert(pos.lane(), (b, pos.dist_along()));
203 }
204
205 for pl in map.all_parking_lots() {
206 if !map.get_l(pl.driving_pos.lane()).driving_blackhole {
207 sim.num_spots_per_lot.insert(pl.id, pl.capacity());
208 sim.driving_to_lots.insert(pl.driving_pos.lane(), pl.id);
209 }
210 }
211
212 sim
213 }
214}
215
216impl ParkingSim for NormalParkingSimState {
217 fn handle_live_edits(&mut self, map: &Map, timer: &mut Timer) -> (Vec<ParkedCar>, Vec<CarID>) {
218 let (filled_before, _) = self.get_all_parking_spots();
219 let new = NormalParkingSimState::new(map, timer);
220 let (_, avail_after) = new.get_all_parking_spots();
221 let avail_after: BTreeSet<ParkingSpot> = avail_after.into_iter().collect();
222
223 self.onstreet_lanes = new.onstreet_lanes;
225 self.driving_to_parking_lanes = new.driving_to_parking_lanes;
226 self.num_spots_per_offstreet = new.num_spots_per_offstreet;
227 self.driving_to_offstreet = new.driving_to_offstreet;
228 self.num_spots_per_lot = new.num_spots_per_lot;
229 self.driving_to_lots = new.driving_to_lots;
230
231 let mut evicted = Vec::new();
234 for spot in filled_before {
235 if !avail_after.contains(&spot) {
236 if let Some(car) = self.occupants.remove(&spot) {
239 evicted.push(self.parked_cars.remove(&car).unwrap());
240 }
241 }
242 }
243
244 let mut moving_into_deleted_spot = Vec::new();
245 self.reserved_spots.retain(|spot, car| {
246 if avail_after.contains(spot) {
247 true
248 } else {
249 moving_into_deleted_spot.push(*car);
250 false
251 }
252 });
253
254 (evicted, moving_into_deleted_spot)
255 }
256
257 fn get_free_onstreet_spots(&self, l: LaneID) -> Vec<ParkingSpot> {
258 let mut spots: Vec<ParkingSpot> = Vec::new();
259 if let Some(lane) = self.onstreet_lanes.get(&l) {
260 for spot in lane.spots() {
261 if self.is_free(spot) {
262 spots.push(spot);
263 }
264 }
265 }
266 spots
267 }
268
269 fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot> {
270 let mut spots: Vec<ParkingSpot> = Vec::new();
271 for idx in 0..self.num_spots_per_offstreet.get(&b).cloned().unwrap_or(0) {
272 let spot = ParkingSpot::Offstreet(b, idx);
273 if self.is_free(spot) {
274 spots.push(spot);
275 }
276 }
277 spots
278 }
279
280 fn get_free_lot_spots(&self, pl: ParkingLotID) -> Vec<ParkingSpot> {
281 let mut spots: Vec<ParkingSpot> = Vec::new();
282 for idx in 0..self.num_spots_per_lot.get(&pl).cloned().unwrap_or(0) {
283 let spot = ParkingSpot::Lot(pl, idx);
284 if self.is_free(spot) {
285 spots.push(spot);
286 }
287 }
288 spots
289 }
290
291 fn reserve_spot(&mut self, spot: ParkingSpot, car: CarID) {
292 assert!(self.is_free(spot));
293 self.reserved_spots.insert(spot, car);
294
295 match spot {
297 ParkingSpot::Onstreet(l, idx) => {
298 assert!(idx < self.onstreet_lanes[&l].spot_dist_along.len());
299 }
300 ParkingSpot::Offstreet(b, idx) => {
301 assert!(idx < self.num_spots_per_offstreet[&b]);
302 }
303 ParkingSpot::Lot(pl, idx) => {
304 assert!(idx < self.num_spots_per_lot[&pl]);
305 }
306 }
307 }
308
309 fn unreserve_spot(&mut self, car: CarID) {
310 self.reserved_spots.retain(|_, c| car != *c);
311 }
312
313 fn remove_parked_car(&mut self, p: ParkedCar) {
314 if self.parked_cars.remove(&p.vehicle.id).is_none() {
315 panic!("remove_parked_car {:?} missing from parked_cars", p);
316 }
317 if self.occupants.remove(&p.spot).is_none() {
318 panic!("remove_parked_car {:?} missing from occupants", p);
319 }
320 self.events
321 .push(Event::CarLeftParkingSpot(p.vehicle.id, p.spot));
322 }
323
324 fn add_parked_car(&mut self, p: ParkedCar) {
325 self.events
326 .push(Event::CarReachedParkingSpot(p.vehicle.id, p.spot));
327
328 assert_eq!(self.reserved_spots.remove(&p.spot), Some(p.vehicle.id));
329
330 assert!(!self.occupants.contains_key(&p.spot));
331 self.occupants.insert(p.spot, p.vehicle.id);
332
333 assert!(!self.parked_cars.contains_key(&p.vehicle.id));
334 self.parked_cars.insert(p.vehicle.id, p);
335 }
336
337 fn get_draw_cars(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput> {
338 let mut cars = Vec::new();
339 if let Some(lane) = self.onstreet_lanes.get(&id) {
340 for spot in lane.spots() {
341 if let Some(car) = self.occupants.get(&spot) {
342 cars.push(self.get_draw_car(*car, map).unwrap());
343 }
344 }
345 }
346 cars
347 }
348
349 fn get_draw_cars_in_lots(&self, id: LaneID, map: &Map) -> Vec<DrawCarInput> {
350 let mut cars = Vec::new();
351 for pl in self.driving_to_lots.get(id) {
352 for idx in 0..self.num_spots_per_lot[pl] {
353 if let Some(car) = self.occupants.get(&ParkingSpot::Lot(*pl, idx)) {
354 if let Some(d) = self.get_draw_car(*car, map) {
355 cars.push(d);
356 }
357 }
358 }
359 }
360 cars
361 }
362
363 fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
364 let p = self.parked_cars.get(&id)?;
365 match p.spot {
366 ParkingSpot::Onstreet(lane, idx) => {
367 let front_dist =
368 self.onstreet_lanes[&lane].dist_along_for_car(idx, &p.vehicle, map);
369 Some(DrawCarInput {
370 id: p.vehicle.id,
371 waiting_for_turn: None,
372 status: CarStatus::Parked,
373 intent: None,
374 on: Traversable::Lane(lane),
375 partly_on: Vec::new(),
376 label: None,
377 person: None,
378
379 body: map
380 .get_l(lane)
381 .lane_center_pts
382 .exact_slice(front_dist - p.vehicle.length, front_dist),
383 })
384 }
385 ParkingSpot::Offstreet(_, _) => None,
386 ParkingSpot::Lot(pl, idx) => {
387 let pl = map.get_pl(pl);
388 let (pt, angle) = pl.spots.get(idx)?;
390 let buffer = Distance::meters(0.5);
391 Some(DrawCarInput {
392 id: p.vehicle.id,
393 waiting_for_turn: None,
394 status: CarStatus::Parked,
395 intent: None,
396 on: Traversable::Lane(pl.driving_pos.lane()),
398 partly_on: Vec::new(),
399 label: None,
400 person: None,
401
402 body: PolyLine::must_new(vec![
403 pt.project_away(buffer, *angle),
404 pt.project_away(map_model::PARKING_LOT_SPOT_LENGTH - buffer, *angle),
405 ]),
406 })
407 }
408 }
409 }
410
411 fn canonical_pt(&self, id: CarID, map: &Map) -> Option<Pt2D> {
412 let p = self.parked_cars.get(&id)?;
413 match p.spot {
414 ParkingSpot::Onstreet(_, _) => Some(self.get_draw_car(id, map).unwrap().body.last_pt()),
415 ParkingSpot::Lot(pl, _) => {
416 if let Some(car) = self.get_draw_car(id, map) {
417 Some(car.body.last_pt())
418 } else {
419 Some(map.get_pl(pl).polygon.center())
420 }
421 }
422 ParkingSpot::Offstreet(b, _) => Some(map.get_b(b).label_center),
423 }
424 }
425
426 fn get_all_draw_cars(&self, map: &Map) -> Vec<DrawCarInput> {
427 self.parked_cars
428 .keys()
429 .filter_map(|id| self.get_draw_car(*id, map))
430 .collect()
431 }
432
433 fn is_free(&self, spot: ParkingSpot) -> bool {
434 !self.occupants.contains_key(&spot) && !self.reserved_spots.contains_key(&spot)
435 }
436
437 fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<&ParkedCar> {
438 let car = self.occupants.get(&spot)?;
439 Some(&self.parked_cars[car])
440 }
441
442 fn get_all_free_spots(
443 &self,
444 driving_pos: Position,
445 vehicle: &Vehicle,
446 target: BuildingID,
449 map: &Map,
450 ) -> Vec<(ParkingSpot, Position)> {
451 let mut candidates = Vec::new();
452
453 for l in self.driving_to_parking_lanes.get(driving_pos.lane()) {
454 for spot in self.onstreet_lanes[l].spots() {
455 if self.is_free(spot)
456 && driving_pos.dist_along()
457 <= self.spot_to_driving_pos(spot, vehicle, map).dist_along()
458 {
459 candidates.push(spot);
460 }
461 }
462 }
463
464 for (b, bldg_dist) in self.driving_to_offstreet.get(driving_pos.lane()) {
465 if let OffstreetParking::Private(_, _) = map.get_b(*b).parking {
466 if target != *b {
467 continue;
468 }
469 }
470 if driving_pos.dist_along() < *bldg_dist {
471 for idx in 0..self.num_spots_per_offstreet[b] {
472 let spot = ParkingSpot::Offstreet(*b, idx);
473 if self.is_free(spot) {
474 candidates.push(spot);
475 }
476 }
477 }
478 }
479
480 for pl in self.driving_to_lots.get(driving_pos.lane()) {
481 let lot_dist = map.get_pl(*pl).driving_pos.dist_along();
482 if driving_pos.dist_along() < lot_dist {
483 for idx in 0..self.num_spots_per_lot[pl] {
484 let spot = ParkingSpot::Lot(*pl, idx);
485 if self.is_free(spot) {
486 candidates.push(spot);
487 }
488 }
489 }
490 }
491
492 candidates
493 .into_iter()
494 .map(|spot| (spot, self.spot_to_driving_pos(spot, vehicle, map)))
495 .collect()
496 }
497
498 fn spot_to_driving_pos(&self, spot: ParkingSpot, vehicle: &Vehicle, map: &Map) -> Position {
499 match spot {
500 ParkingSpot::Onstreet(l, idx) => {
501 let lane = &self.onstreet_lanes[&l];
502 Position::new(l, lane.dist_along_for_car(idx, vehicle, map))
503 .equiv_pos_for_long_object(lane.driving_lane, vehicle.length, map)
504 }
505 ParkingSpot::Offstreet(b, _) => map.get_b(b).driving_connection(map).unwrap().0,
506 ParkingSpot::Lot(pl, _) => map.get_pl(pl).driving_pos,
507 }
508 }
509
510 fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position {
511 match spot {
512 ParkingSpot::Onstreet(l, idx) => {
513 let lane = &self.onstreet_lanes[&l];
514 Position::new(
516 l,
517 lane.spot_dist_along[idx] - (map.get_config().street_parking_spot_length / 2.0),
518 )
519 .equiv_pos(lane.sidewalk, map)
520 }
521 ParkingSpot::Offstreet(b, _) => map.get_b(b).sidewalk_pos,
522 ParkingSpot::Lot(pl, _) => map.get_pl(pl).sidewalk_pos,
523 }
524 }
525
526 fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
527 self.parked_cars.get(&id).and_then(|p| p.vehicle.owner)
528 }
529 fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
530 self.parked_cars.get(&id)
531 }
532
533 fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
534 let mut spots = Vec::new();
535 for lane in self.onstreet_lanes.values() {
536 spots.extend(lane.spots());
537 }
538 for (b, num_spots) in &self.num_spots_per_offstreet {
539 for idx in 0..*num_spots {
540 spots.push(ParkingSpot::Offstreet(*b, idx));
541 }
542 }
543 for (pl, num_spots) in &self.num_spots_per_lot {
544 for idx in 0..*num_spots {
545 spots.push(ParkingSpot::Lot(*pl, idx));
546 }
547 }
548
549 let mut filled = Vec::new();
550 let mut available = Vec::new();
551 for spot in spots {
552 if self.is_free(spot) {
553 available.push(spot);
554 } else {
555 filled.push(spot);
556 }
557 }
558 (filled, available)
559 }
560
561 fn path_to_free_parking_spot(
562 &self,
563 start: LaneID,
564 vehicle: &Vehicle,
565 target: BuildingID,
566 map: &Map,
567 ) -> Option<(Vec<PathStep>, ParkingSpot, Position)> {
568 let mut backrefs: HashMap<LaneID, TurnID> = HashMap::new();
569 let mut queue: BinaryHeap<(Distance, LaneID)> = BinaryHeap::new();
573 queue.push((Distance::ZERO, start));
574
575 let mut rng =
580 XorShiftRng::seed_from_u64((vehicle.id.id + start.encode_u32() as usize) as u64);
581
582 while !queue.is_empty() {
583 let (dist_so_far, current) = queue.pop().unwrap();
584 if current != start {
587 if let Some((spot, pos)) = self
590 .get_all_free_spots(Position::start(current), vehicle, target, map)
591 .into_iter()
592 .min_by_key(|(_, pos)| pos.dist_along())
593 {
594 let mut steps = vec![PathStep::Lane(current)];
595 let mut current = current;
596 loop {
597 if current == start {
598 steps.pop();
600 steps.reverse();
601 return Some((steps, spot, pos));
602 }
603 let turn = backrefs[¤t];
604 steps.push(PathStep::Turn(turn));
605 steps.push(PathStep::Lane(turn.src));
606 current = turn.src;
607 }
608 }
609 }
610 for turn in map.get_turns_for(current, PathConstraints::Car) {
611 if let Entry::Vacant(e) = backrefs.entry(turn.id.dst) {
612 let dist_this_step = turn.geom.length() + map.get_l(current).length();
613 let jitter = rng.gen_range(0.1..0.9);
621 e.insert(turn.id);
622 queue.push((dist_so_far - jitter * dist_this_step, turn.id.dst));
624 }
625 }
626 }
627
628 None
629 }
630
631 fn collect_events(&mut self) -> Vec<Event> {
632 std::mem::take(&mut self.events)
633 }
634
635 fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, PersonID)> {
636 self.parked_cars
637 .values()
638 .map(|p| {
639 (
640 self.spot_to_sidewalk_pos(p.spot, map),
641 p.vehicle.owner.unwrap(),
642 )
643 })
644 .collect()
645 }
646
647 fn bldg_to_parked_cars(&self, b: BuildingID) -> Vec<CarID> {
648 let mut cars = Vec::new();
649 for idx in 0..self.num_spots_per_offstreet.get(&b).cloned().unwrap_or(0) {
650 let spot = ParkingSpot::Offstreet(b, idx);
651 if let Some(car) = self.occupants.get(&spot) {
652 cars.push(*car);
653 }
654 }
655 cars
656 }
657}
658
659#[derive(Serialize, Deserialize, Clone)]
660struct ParkingLane {
661 parking_lane: LaneID,
662 driving_lane: LaneID,
663 sidewalk: LaneID,
664 spot_dist_along: Vec<Distance>,
666}
667
668impl ParkingLane {
669 fn new(lane: &Lane, map: &Map) -> Option<ParkingLane> {
670 if lane.lane_type != LaneType::Parking {
671 return None;
672 }
673
674 let driving_lane = if let Some(l) = map.get_parent(lane.id).parking_to_driving(lane.id) {
675 l
676 } else {
677 error!("Parking lane {} has no driving lane!", lane.id);
678 return None;
679 };
680 if map.get_l(driving_lane).driving_blackhole {
681 return None;
682 }
683 let sidewalk = if let Some(l) = map
684 .get_parent(lane.id)
685 .find_closest_lane(lane.id, |l| l.is_walkable())
686 {
687 l
688 } else {
689 warn!("Parking lane {} has no sidewalk!", lane.id);
690 return None;
691 };
692
693 Some(ParkingLane {
694 parking_lane: lane.id,
695 driving_lane,
696 sidewalk,
697 spot_dist_along: (0..lane.number_parking_spots(map.get_config()))
698 .map(|idx| map.get_config().street_parking_spot_length * (2.0 + idx as f64))
699 .collect(),
700 })
701 }
702
703 fn dist_along_for_car(&self, spot_idx: usize, vehicle: &Vehicle, map: &Map) -> Distance {
704 self.spot_dist_along[spot_idx]
706 - (map.get_config().street_parking_spot_length - vehicle.length) / 2.0
707 }
708
709 fn spots(&self) -> Vec<ParkingSpot> {
710 let mut spots = Vec::new();
711 for idx in 0..self.spot_dist_along.len() {
712 spots.push(ParkingSpot::Onstreet(self.parking_lane, idx));
713 }
714 spots
715 }
716}
717
718#[derive(Serialize, Deserialize, Clone)]
726pub struct InfiniteParkingSimState {
727 #[serde(
728 serialize_with = "serialize_btreemap",
729 deserialize_with = "deserialize_btreemap"
730 )]
731 parked_cars: BTreeMap<CarID, ParkedCar>,
732 #[serde(
733 serialize_with = "serialize_btreemap",
734 deserialize_with = "deserialize_btreemap"
735 )]
736 occupants: BTreeMap<ParkingSpot, CarID>,
737 #[serde(
738 serialize_with = "serialize_btreemap",
739 deserialize_with = "deserialize_btreemap"
740 )]
741 reserved_spots: BTreeMap<ParkingSpot, CarID>,
742
743 #[serde(
745 serialize_with = "serialize_multimap",
746 deserialize_with = "deserialize_multimap"
747 )]
748 driving_to_offstreet: MultiMap<LaneID, (BuildingID, Distance)>,
749 blackholed_building_redirects: BTreeMap<BuildingID, BuildingID>,
752
753 num_occupants_per_offstreet: BTreeMap<BuildingID, usize>,
755
756 events: Vec<Event>,
757}
758
759impl InfiniteParkingSimState {
760 fn new(map: &Map) -> InfiniteParkingSimState {
761 let mut sim = InfiniteParkingSimState {
762 parked_cars: BTreeMap::new(),
763 occupants: BTreeMap::new(),
764 reserved_spots: BTreeMap::new(),
765
766 driving_to_offstreet: MultiMap::new(),
767 blackholed_building_redirects: BTreeMap::new(),
768
769 num_occupants_per_offstreet: BTreeMap::new(),
770
771 events: Vec::new(),
772 };
773 let mut blackholes = Vec::new();
774 for b in map.all_buildings() {
775 if let Some((pos, _)) = b.driving_connection(map) {
776 if !map.get_l(pos.lane()).driving_blackhole {
777 sim.driving_to_offstreet
778 .insert(pos.lane(), (b.id, pos.dist_along()));
779 continue;
780 }
781 }
782 blackholes.push(b.id);
783 }
784
785 for b in blackholes {
787 let mut queue = vec![map.find_driving_lane_near_building(b)];
789 let mut seen = BTreeSet::new();
790 loop {
791 let current = queue.pop().unwrap();
792 if seen.contains(¤t) {
793 continue;
794 }
795 seen.insert(current);
796 if let Some((redirect, _)) = sim.driving_to_offstreet.get(current).iter().next() {
797 sim.blackholed_building_redirects.insert(b, *redirect);
798 break;
799 }
800 for turn in map.get_turns_for(current, PathConstraints::Car) {
801 queue.push(turn.id.dst);
802 }
803 }
804 }
805
806 sim
807 }
808
809 fn get_free_bldg_spot(&self, b: BuildingID) -> ParkingSpot {
810 if let Some(redirect) = self.blackholed_building_redirects.get(&b) {
811 return self.get_free_bldg_spot(*redirect);
814 }
815
816 let mut i = self
821 .num_occupants_per_offstreet
822 .get(&b)
823 .cloned()
824 .unwrap_or(0);
825 loop {
826 let spot = ParkingSpot::Offstreet(b, i);
827 if self.is_free(spot) {
828 return spot;
829 }
830 i += 1;
831 }
832 }
833}
834
835impl ParkingSim for InfiniteParkingSimState {
836 fn handle_live_edits(&mut self, map: &Map, _: &mut Timer) -> (Vec<ParkedCar>, Vec<CarID>) {
837 let new = InfiniteParkingSimState::new(map);
839 self.driving_to_offstreet = new.driving_to_offstreet;
840 self.blackholed_building_redirects = new.blackholed_building_redirects;
841
842 (Vec::new(), Vec::new())
843 }
844
845 fn get_free_onstreet_spots(&self, _: LaneID) -> Vec<ParkingSpot> {
846 Vec::new()
847 }
848
849 fn get_free_offstreet_spots(&self, b: BuildingID) -> Vec<ParkingSpot> {
850 vec![self.get_free_bldg_spot(b)]
852 }
853
854 fn get_free_lot_spots(&self, _: ParkingLotID) -> Vec<ParkingSpot> {
855 Vec::new()
856 }
857
858 fn reserve_spot(&mut self, spot: ParkingSpot, car: CarID) {
859 assert!(self.is_free(spot));
860 self.reserved_spots.insert(spot, car);
861 }
862
863 fn unreserve_spot(&mut self, car: CarID) {
864 self.reserved_spots.retain(|_, c| car != *c);
865 }
866
867 fn remove_parked_car(&mut self, p: ParkedCar) {
868 self.parked_cars
869 .remove(&p.vehicle.id)
870 .expect("remove_parked_car missing from parked_cars");
871 self.occupants
872 .remove(&p.spot)
873 .expect("remove_parked_car missing from occupants");
874 self.events
875 .push(Event::CarLeftParkingSpot(p.vehicle.id, p.spot));
876
877 if let ParkingSpot::Offstreet(b, _) = p.spot {
878 *self.num_occupants_per_offstreet.get_mut(&b).unwrap() -= 1;
879 }
880 }
881
882 fn add_parked_car(&mut self, p: ParkedCar) {
883 self.events
884 .push(Event::CarReachedParkingSpot(p.vehicle.id, p.spot));
885
886 assert_eq!(self.reserved_spots.remove(&p.spot), Some(p.vehicle.id));
887
888 assert!(!self.occupants.contains_key(&p.spot));
889 self.occupants.insert(p.spot, p.vehicle.id);
890
891 if let ParkingSpot::Offstreet(b, _) = p.spot {
892 *self.num_occupants_per_offstreet.entry(b).or_insert(0) += 1;
893 }
894
895 assert!(!self.parked_cars.contains_key(&p.vehicle.id));
896 self.parked_cars.insert(p.vehicle.id, p);
897 }
898
899 fn get_draw_cars(&self, _: LaneID, _: &Map) -> Vec<DrawCarInput> {
900 Vec::new()
901 }
902
903 fn get_draw_cars_in_lots(&self, _: LaneID, _: &Map) -> Vec<DrawCarInput> {
904 Vec::new()
905 }
906
907 fn get_draw_car(&self, _: CarID, _: &Map) -> Option<DrawCarInput> {
908 None
909 }
910
911 fn canonical_pt(&self, id: CarID, map: &Map) -> Option<Pt2D> {
912 let p = self.parked_cars.get(&id)?;
913 match p.spot {
914 ParkingSpot::Offstreet(b, _) => Some(map.get_b(b).label_center),
915 _ => unreachable!(),
916 }
917 }
918
919 fn get_all_draw_cars(&self, _: &Map) -> Vec<DrawCarInput> {
920 Vec::new()
921 }
922
923 fn is_free(&self, spot: ParkingSpot) -> bool {
924 !self.occupants.contains_key(&spot) && !self.reserved_spots.contains_key(&spot)
925 }
926
927 fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<&ParkedCar> {
928 let car = self.occupants.get(&spot)?;
929 Some(&self.parked_cars[car])
930 }
931
932 fn get_all_free_spots(
933 &self,
934 driving_pos: Position,
935 vehicle: &Vehicle,
936 target: BuildingID,
937 map: &Map,
938 ) -> Vec<(ParkingSpot, Position)> {
939 let mut bldg: Option<BuildingID> = None;
942 for (b, bldg_dist) in self.driving_to_offstreet.get(driving_pos.lane()) {
943 if driving_pos.dist_along() > *bldg_dist {
944 continue;
945 }
946 if target == *b {
947 bldg = Some(target);
948 break;
949 } else if bldg.is_none() {
950 bldg = Some(*b);
952 }
953 }
954 if let Some(b) = bldg {
955 let spot = self.get_free_bldg_spot(b);
956 vec![(spot, self.spot_to_driving_pos(spot, vehicle, map))]
957 } else {
958 Vec::new()
959 }
960 }
961
962 fn spot_to_driving_pos(&self, spot: ParkingSpot, _: &Vehicle, map: &Map) -> Position {
963 match spot {
964 ParkingSpot::Offstreet(b, _) => map.get_b(b).driving_connection(map).unwrap().0,
965 _ => unreachable!(),
966 }
967 }
968
969 fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position {
970 match spot {
971 ParkingSpot::Offstreet(b, _) => map.get_b(b).sidewalk_pos,
972 _ => unreachable!(),
973 }
974 }
975
976 fn get_owner_of_car(&self, id: CarID) -> Option<PersonID> {
977 self.parked_cars.get(&id).and_then(|p| p.vehicle.owner)
978 }
979 fn lookup_parked_car(&self, id: CarID) -> Option<&ParkedCar> {
980 self.parked_cars.get(&id)
981 }
982
983 fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
984 unreachable!()
985 }
986
987 fn path_to_free_parking_spot(
988 &self,
989 start: LaneID,
990 vehicle: &Vehicle,
991 target: BuildingID,
992 map: &Map,
993 ) -> Option<(Vec<PathStep>, ParkingSpot, Position)> {
994 let mut backrefs: HashMap<LaneID, TurnID> = HashMap::new();
997 let mut queue: BinaryHeap<(Distance, LaneID)> = BinaryHeap::new();
1001 queue.push((Distance::ZERO, start));
1002
1003 while !queue.is_empty() {
1004 let (dist_so_far, current) = queue.pop().unwrap();
1005 if current != start {
1008 if let Some((spot, pos)) = self
1011 .get_all_free_spots(Position::start(current), vehicle, target, map)
1012 .into_iter()
1013 .min_by_key(|(_, pos)| pos.dist_along())
1014 {
1015 let mut steps = vec![PathStep::Lane(current)];
1016 let mut current = current;
1017 loop {
1018 if current == start {
1019 steps.pop();
1021 steps.reverse();
1022 return Some((steps, spot, pos));
1023 }
1024 let turn = backrefs[¤t];
1025 steps.push(PathStep::Turn(turn));
1026 steps.push(PathStep::Lane(turn.src));
1027 current = turn.src;
1028 }
1029 }
1030 }
1031 for turn in map.get_turns_for(current, PathConstraints::Car) {
1032 if let Entry::Vacant(e) = backrefs.entry(turn.id.dst) {
1033 let dist_this_step = turn.geom.length() + map.get_l(current).length();
1034 e.insert(turn.id);
1035 queue.push((dist_so_far - dist_this_step, turn.id.dst));
1037 }
1038 }
1039 }
1040
1041 None
1042 }
1043
1044 fn collect_events(&mut self) -> Vec<Event> {
1045 std::mem::take(&mut self.events)
1046 }
1047
1048 fn all_parked_car_positions(&self, map: &Map) -> Vec<(Position, PersonID)> {
1049 self.parked_cars
1050 .values()
1051 .map(|p| {
1052 (
1053 self.spot_to_sidewalk_pos(p.spot, map),
1054 p.vehicle.owner.unwrap(),
1055 )
1056 })
1057 .collect()
1058 }
1059
1060 fn bldg_to_parked_cars(&self, b: BuildingID) -> Vec<CarID> {
1061 let mut cars = Vec::new();
1063 for (spot, car) in &self.occupants {
1064 if let ParkingSpot::Offstreet(bldg, _) = spot {
1065 if b == *bldg {
1066 cars.push(*car);
1067 }
1068 }
1069 }
1070 cars
1071 }
1072}