mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
spawn a specific number of parked cars per bldg for a scenario. dont use
them yet.
This commit is contained in:
parent
c267b27fa0
commit
048976a256
@ -295,6 +295,7 @@ impl<'a> Timer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// The order of the result is deterministic / matches the input.
|
||||
pub fn parallelize<I, O, F: Fn(I) -> O>(
|
||||
&mut self,
|
||||
timer_name: &str,
|
||||
|
@ -12,6 +12,7 @@ use ezgui::{hotkey, EventCtx, GfxCtx, Key, ModalMenu, Wizard, WrappedWizard};
|
||||
use geom::Duration;
|
||||
use popdat::trips_to_scenario;
|
||||
use sim::Scenario;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct MissionEditMode {
|
||||
menu: ModalMenu,
|
||||
@ -137,6 +138,7 @@ fn create_new_scenario(wiz: &mut Wizard, ctx: &mut EventCtx, ui: &mut UI) -> Opt
|
||||
spawn_over_time: Vec::new(),
|
||||
border_spawn_over_time: Vec::new(),
|
||||
individ_trips: Vec::new(),
|
||||
individ_parked_cars: BTreeMap::new(),
|
||||
},
|
||||
ctx,
|
||||
ui,
|
||||
|
@ -107,8 +107,8 @@ impl ScenarioManager {
|
||||
}
|
||||
}
|
||||
|
||||
let (filled_spots, total_parking_spots) = ui.primary.sim.get_total_parking_spots();
|
||||
assert_eq!(filled_spots, 0);
|
||||
let (filled_spots, free_parking_spots) = ui.primary.sim.get_all_parking_spots();
|
||||
assert!(filled_spots.is_empty());
|
||||
|
||||
ScenarioManager {
|
||||
menu: ModalMenu::new(
|
||||
@ -135,7 +135,7 @@ impl ScenarioManager {
|
||||
trips_to_bldg,
|
||||
cars_needed_per_bldg,
|
||||
total_cars_needed,
|
||||
total_parking_spots,
|
||||
total_parking_spots: free_parking_spots.len(),
|
||||
override_colors,
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ pub struct Parcel {
|
||||
pub offstreet_parking_spaces: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Mode {
|
||||
Walk,
|
||||
Bike,
|
||||
|
@ -4,9 +4,9 @@ use abstutil::Timer;
|
||||
use geom::{Distance, Duration, LonLat, PolyLine, Polygon, Pt2D};
|
||||
use map_model::{BuildingID, IntersectionID, LaneType, Map, PathRequest, Position};
|
||||
use sim::{DrivingGoal, Scenario, SidewalkSpot, SpawnTrip, TripSpec};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Trip {
|
||||
pub from: TripEndpt,
|
||||
pub to: TripEndpt,
|
||||
@ -20,7 +20,7 @@ pub struct Trip {
|
||||
pub route: Option<PolyLine>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TripEndpt {
|
||||
Building(BuildingID),
|
||||
// The Pt2D is the original point. It'll be outside the map and likely out-of-bounds entirely,
|
||||
@ -259,8 +259,9 @@ pub fn clip_trips(map: &Map, timer: &mut Timer) -> (Vec<Trip>, HashMap<BuildingI
|
||||
|
||||
pub fn trips_to_scenario(map: &Map, t1: Duration, t2: Duration, timer: &mut Timer) -> Scenario {
|
||||
let (trips, _) = clip_trips(map, timer);
|
||||
// TODO Don't clone trips for parallelize
|
||||
let individ_trips = timer
|
||||
.parallelize("turn PSRC trips into SpawnTrips", trips, |trip| {
|
||||
.parallelize("turn PSRC trips into SpawnTrips", trips.clone(), |trip| {
|
||||
if trip.depart_at < t1 || trip.depart_at > t2 {
|
||||
return None;
|
||||
}
|
||||
@ -343,6 +344,29 @@ pub fn trips_to_scenario(map: &Map, t1: Duration, t2: Duration, timer: &mut Time
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
// This is another variation of the 'recycle' algorithm in editor's ScenarioManager.
|
||||
let mut individ_parked_cars = BTreeMap::new();
|
||||
let mut avail_per_bldg = BTreeMap::new();
|
||||
for b in map.all_buildings() {
|
||||
individ_parked_cars.insert(b.id, 0);
|
||||
avail_per_bldg.insert(b.id, 0);
|
||||
}
|
||||
for trip in trips {
|
||||
if trip.depart_at < t1 || trip.depart_at > t2 || trip.mode != Mode::Drive {
|
||||
continue;
|
||||
}
|
||||
if let TripEndpt::Building(b) = trip.from {
|
||||
if avail_per_bldg[&b] > 0 {
|
||||
*avail_per_bldg.get_mut(&b).unwrap() -= 1;
|
||||
} else {
|
||||
*individ_parked_cars.get_mut(&b).unwrap() += 1;
|
||||
}
|
||||
}
|
||||
if let TripEndpt::Building(b) = trip.to {
|
||||
*avail_per_bldg.get_mut(&b).unwrap() += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Scenario {
|
||||
scenario_name: format!("psrc {} to {}", t1, t2),
|
||||
map_name: map.get_name().to_string(),
|
||||
@ -350,5 +374,6 @@ pub fn trips_to_scenario(map: &Map, t1: Duration, t2: Duration, timer: &mut Time
|
||||
spawn_over_time: Vec::new(),
|
||||
border_spawn_over_time: Vec::new(),
|
||||
individ_trips,
|
||||
individ_parked_cars,
|
||||
}
|
||||
}
|
||||
|
@ -13,17 +13,21 @@ use rand::seq::SliceRandom;
|
||||
use rand::Rng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeSet, HashMap, HashSet, VecDeque};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct Scenario {
|
||||
pub scenario_name: String,
|
||||
pub map_name: String,
|
||||
|
||||
// Higher-level ways of specifying stuff
|
||||
pub seed_parked_cars: Vec<SeedParkedCars>,
|
||||
pub spawn_over_time: Vec<SpawnOverTime>,
|
||||
pub border_spawn_over_time: Vec<BorderSpawnOverTime>,
|
||||
|
||||
// Much more detailed
|
||||
pub individ_trips: Vec<SpawnTrip>,
|
||||
pub individ_parked_cars: BTreeMap<BuildingID, usize>,
|
||||
}
|
||||
|
||||
// SpawnOverTime and BorderSpawnOverTime should be kept separate. Agents in SpawnOverTime pick
|
||||
@ -78,6 +82,10 @@ impl Scenario {
|
||||
prettyprint_usize(self.border_spawn_over_time.len())
|
||||
),
|
||||
format!("{} SpawnTrip", prettyprint_usize(self.individ_trips.len())),
|
||||
format!(
|
||||
"{} specific parked cars at buildings",
|
||||
prettyprint_usize(self.individ_parked_cars.len())
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
@ -134,6 +142,15 @@ impl Scenario {
|
||||
s.spawn_bikes(rng, sim, &neighborhoods, map, timer);
|
||||
}
|
||||
|
||||
let mut individ_parked_cars: Vec<(BuildingID, usize)> = Vec::new();
|
||||
for (b, cnt) in &self.individ_parked_cars {
|
||||
if *cnt != 0 {
|
||||
individ_parked_cars.push((*b, *cnt));
|
||||
}
|
||||
}
|
||||
individ_parked_cars.shuffle(rng);
|
||||
seed_individ_parked_cars(individ_parked_cars, sim, map, rng, timer);
|
||||
|
||||
timer.start_iter("SpawnTrip", self.individ_trips.len());
|
||||
for t in &self.individ_trips {
|
||||
match t.clone() {
|
||||
@ -249,6 +266,7 @@ impl Scenario {
|
||||
})
|
||||
.collect(),
|
||||
individ_trips: Vec::new(),
|
||||
individ_parked_cars: BTreeMap::new(),
|
||||
};
|
||||
for i in map.all_outgoing_borders() {
|
||||
s.spawn_over_time.push(SpawnOverTime {
|
||||
@ -273,6 +291,7 @@ impl Scenario {
|
||||
spawn_over_time: Vec::new(),
|
||||
border_spawn_over_time: Vec::new(),
|
||||
individ_trips: Vec::new(),
|
||||
individ_parked_cars: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,6 +317,7 @@ impl Scenario {
|
||||
}],
|
||||
border_spawn_over_time: Vec::new(),
|
||||
individ_trips: Vec::new(),
|
||||
individ_parked_cars: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -773,6 +793,47 @@ fn seed_parked_cars(
|
||||
));
|
||||
}
|
||||
|
||||
fn seed_individ_parked_cars(
|
||||
individ_parked_cars: Vec<(BuildingID, usize)>,
|
||||
sim: &mut Sim,
|
||||
map: &Map,
|
||||
base_rng: &mut XorShiftRng,
|
||||
timer: &mut Timer,
|
||||
) {
|
||||
let mut open_spots_per_road: HashMap<RoadID, Vec<ParkingSpot>> = HashMap::new();
|
||||
for spot in sim.get_all_parking_spots().1 {
|
||||
let r = match spot {
|
||||
ParkingSpot::Onstreet(l, _) => map.get_l(l).parent,
|
||||
ParkingSpot::Offstreet(b, _) => map.get_l(map.get_b(b).sidewalk()).parent,
|
||||
};
|
||||
open_spots_per_road
|
||||
.entry(r)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(spot);
|
||||
}
|
||||
let all_roads = map
|
||||
.all_roads()
|
||||
.iter()
|
||||
.map(|r| r.id)
|
||||
.collect::<BTreeSet<_>>();
|
||||
|
||||
timer.start_iter("seed individual parked cars", individ_parked_cars.len());
|
||||
for (b, cnt) in individ_parked_cars {
|
||||
timer.next();
|
||||
for _ in 0..cnt {
|
||||
// TODO Fork?
|
||||
if let Some(spot) =
|
||||
find_spot_near_building(b, &mut open_spots_per_road, &all_roads, map, timer)
|
||||
{
|
||||
sim.seed_parked_car(Scenario::rand_car(base_rng), spot, Some(b));
|
||||
} else {
|
||||
// TODO Guard against this outright just by total counts.
|
||||
panic!("No room to seed individual parked cars.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick a parking spot for this building. If the building's road has a free spot, use it. If not,
|
||||
// start BFSing out from the road in a deterministic way until finding a nearby road with an open
|
||||
// spot.
|
||||
|
@ -292,24 +292,25 @@ impl ParkingSimState {
|
||||
}
|
||||
|
||||
// (Filled, available)
|
||||
pub fn get_total_parking_spots(&self) -> (usize, usize) {
|
||||
let mut filled = 0;
|
||||
let mut available = 0;
|
||||
pub fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
|
||||
let mut filled = Vec::new();
|
||||
let mut available = Vec::new();
|
||||
|
||||
for lane in self.onstreet_lanes.values() {
|
||||
for spot in lane.spots() {
|
||||
if self.is_free(spot) {
|
||||
available += 1;
|
||||
available.push(spot);
|
||||
} else {
|
||||
filled += 1;
|
||||
filled.push(spot);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (b, idx) in &self.num_spots_per_offstreet {
|
||||
if self.is_free(ParkingSpot::Offstreet(*b, *idx)) {
|
||||
available += 1;
|
||||
let spot = ParkingSpot::Offstreet(*b, *idx);
|
||||
if self.is_free(spot) {
|
||||
available.push(spot);
|
||||
} else {
|
||||
filled += 1;
|
||||
filled.push(spot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,8 +171,8 @@ impl Sim {
|
||||
}
|
||||
|
||||
// (Filled, available)
|
||||
pub fn get_total_parking_spots(&self) -> (usize, usize) {
|
||||
self.parking.get_total_parking_spots()
|
||||
pub fn get_all_parking_spots(&self) -> (Vec<ParkingSpot>, Vec<ParkingSpot>) {
|
||||
self.parking.get_all_parking_spots()
|
||||
}
|
||||
|
||||
pub fn seed_parked_car(
|
||||
|
Loading…
Reference in New Issue
Block a user