diff --git a/sim/src/helpers.rs b/sim/src/helpers.rs index 3fb514ff40..3d50b79c1b 100644 --- a/sim/src/helpers.rs +++ b/sim/src/helpers.rs @@ -158,7 +158,7 @@ impl Sim { pub fn seed_driving_trips(&mut self, map: &Map, num_cars: usize) { let mut cars: Vec = self .parking_state - .get_all_parked_cars() + .get_all_parked_cars(None) .into_iter() .filter_map(|parked_car| { let lane = parked_car.spot.lane; diff --git a/sim/src/parking.rs b/sim/src/parking.rs index ff08382c02..db56fee527 100644 --- a/sim/src/parking.rs +++ b/sim/src/parking.rs @@ -110,12 +110,18 @@ impl ParkingSimState { None } - pub fn get_all_parked_cars(&self) -> Vec { + pub fn get_all_parked_cars(&self, in_poly: Option<&Polygon>) -> Vec { let mut result = Vec::new(); for l in &self.lanes { for (idx, maybe_car) in l.occupants.iter().enumerate() { if let Some(car) = maybe_car { - result.push(ParkedCar::new(*car, ParkingSpot::new(l.id, idx))); + // Just match based on the front of the spot + if in_poly + .map(|p| p.contains_pt(l.spots[idx].pos)) + .unwrap_or(true) + { + result.push(ParkedCar::new(*car, ParkingSpot::new(l.id, idx))); + } } } } diff --git a/sim/src/scenario.rs b/sim/src/scenario.rs index 77e2695cbc..258db35ee3 100644 --- a/sim/src/scenario.rs +++ b/sim/src/scenario.rs @@ -3,7 +3,7 @@ use geom::{Polygon, Pt2D}; use map_model::{BuildingID, Map}; use rand::Rng; use std::collections::HashMap; -use {Sim, Tick}; +use {ParkedCar, Sim, Tick}; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct Scenario { @@ -83,27 +83,63 @@ impl Scenario { ); } + let mut parked_cars_per_neighborhood: HashMap> = HashMap::new(); + for (name, neighborhood) in &neighborhoods { + parked_cars_per_neighborhood.insert( + name.to_string(), + sim.parking_state + .get_all_parked_cars(Some(&Polygon::new(&neighborhood.points))), + ); + } + for s in &self.spawn_over_time { for _ in 0..s.num_agents { // TODO normal distribution, not uniform let spawn_time = Tick(sim.rng.gen_range(s.start_tick.0, s.stop_tick.0)); - if sim.rng.gen_bool(s.percent_drive) { - // TODO - } else { - let from = *sim - .rng - .choose(&bldgs_per_neighborhood[&s.start_from_neighborhood]) - .unwrap(); - let to = *sim - .rng - .choose(&bldgs_per_neighborhood[&s.go_to_neighborhood]) - .unwrap(); + // Note that it's fine for agents to start/end at the same building. Later we might + // want a better assignment of people per household, or workers per office building. + let from_bldg = *sim + .rng + .choose(&bldgs_per_neighborhood[&s.start_from_neighborhood]) + .unwrap(); + let to_bldg = *sim + .rng + .choose(&bldgs_per_neighborhood[&s.go_to_neighborhood]) + .unwrap(); + if sim.rng.gen_bool(s.percent_drive) { + if parked_cars_per_neighborhood[&s.start_from_neighborhood].is_empty() { + panic!( + "{} has no parked cars; can't instantiate {}", + s.start_from_neighborhood, self.scenario_name + ); + } + // TODO Probably prefer parked cars close to from_bldg, unless the particular + // area is tight on parking. :) + let idx = sim.rng.gen_range( + 0, + parked_cars_per_neighborhood[&s.start_from_neighborhood].len(), + ); + let parked_car = parked_cars_per_neighborhood + .get_mut(&s.start_from_neighborhood) + .unwrap() + .remove(idx); + + sim.spawner.start_trip_using_parked_car( + spawn_time, + map, + parked_car, + &sim.parking_state, + from_bldg, + to_bldg, + &mut sim.trips_state, + ); + } else { sim.spawner.start_trip_just_walking( spawn_time, map, - from, - to, + from_bldg, + to_bldg, &mut sim.trips_state, ); }