From 01bd4aec6fdff7bfb0481ac16d3d846aa4311bf7 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Fri, 1 May 2020 10:54:43 -0700 Subject: [PATCH] clean up some fallout from the grand data refreshening. mostly robustifying tutorials/challenges by using IDs stable across map updates --- convert_osm/src/osm_reader.rs | 3 - data/MANIFEST.txt | 41 +++++---- game/src/challenges.rs | 12 ++- game/src/info/person.rs | 3 +- game/src/sandbox/gameplay/commute.rs | 25 +++--- game/src/sandbox/gameplay/mod.rs | 4 +- game/src/sandbox/gameplay/tutorial.rs | 115 ++++++++------------------ importer/src/soundcast/popdat.rs | 8 +- importer/src/soundcast/trips.rs | 20 +++-- map_model/src/map.rs | 22 +++-- map_model/src/traffic_signals.rs | 20 ++--- sim/src/lib.rs | 3 + sim/src/make/generator.rs | 14 ++-- sim/src/make/scenario.rs | 15 ++-- sim/src/sim.rs | 20 ++++- sim/src/trips.rs | 18 ++-- 16 files changed, 169 insertions(+), 174 deletions(-) diff --git a/convert_osm/src/osm_reader.rs b/convert_osm/src/osm_reader.rs index 7b410000e9..a9b088e0a0 100644 --- a/convert_osm/src/osm_reader.rs +++ b/convert_osm/src/osm_reader.rs @@ -268,9 +268,6 @@ pub fn extract_osm( }); } - // TODO This is upstreamed, but we can't grab fresh OSM until fixing the sidewalk disconnection - turn_restrictions.push((RestrictionType::BanTurns, 92170540, 53211693, 243334881)); - ( map, roads, diff --git a/data/MANIFEST.txt b/data/MANIFEST.txt index a3a174ffeb..3517269006 100644 --- a/data/MANIFEST.txt +++ b/data/MANIFEST.txt @@ -89,7 +89,7 @@ d729d8ef4f797d51dbb53096a4aac233 data/input/seattle/neighborhoods/huge_seattle/ 19e8073a9f6c807b4492681b2c7570de data/input/seattle/blockface.bin db63d7d606e8702d12f9399e87e6a00f data/input/seattle/parcels_urbansim.txt 2bc84e4d194d7cea6007ae3b93f3b11b data/input/seattle/neighborhoods.geojson -c32993ec1be884c04985740e9e345f5c data/input/seattle/popdat.bin +7cbf604cb6d080292a5e69fdf0caf3b3 data/input/seattle/popdat.bin 428bc2e92ea02089cedbb614ce1d8f25 data/input/seattle/polygons/caphill.poly 4f291bbe84ac32a98d7d100be79ddc4b data/input/seattle/polygons/huge_seattle.poly 6b221b5e68a38f16f34e46a208c7ca15 data/input/seattle/polygons/lakeslice.poly @@ -113,17 +113,17 @@ b66cb4c0a24b2d038427aa6e1aa1954a data/input/seattle/google_transit/block.txt ca5a7569e1af41e0046fe5e8865cf733 data/input/seattle/google_transit/fare_attributes.txt 8610cdc491d036eee88c9b7ae24d692d data/input/seattle/google_transit/stops.txt 75f564fcc06b1950b7b33acf9d61f696 data/input/seattle/google_transit/agency.txt -bd3448b36bf07603e78a3a4a65707dd9 data/input/raw_maps/huge_seattle.bin +55a13d6252de8273153fce7f3d43864b data/input/raw_maps/huge_seattle.bin 9ff05ead40b54f842ea99c97c274f2f9 data/input/raw_maps/ballard.bin 34aea57a80555addd96406917e472357 data/input/raw_maps/downtown.bin -9c8ddb01846b4d8c304246cf798efb89 data/input/raw_maps/caphill.bin -49ff57346957ac5008d72e02ce007baa data/input/raw_maps/lakeslice.bin +e6972c81efaa95e891660a3e565a4760 data/input/raw_maps/caphill.bin +8926263ac28d92fe264f977fb851a99e data/input/raw_maps/lakeslice.bin b50223a417508afb924252ae3ecd24ad data/input/raw_maps/huge_austin.bin d4f6ece8ef35c594c794928d651c5916 data/input/raw_maps/downtown_atx.bin 530521311e09da554127fd08bb43c34b data/input/raw_maps/montlake.bin 984e24fd958aedf7f9dcf030ecbd0b42 data/input/raw_maps/intl_district.bin f7ea2e3cfcd688e0effae80ec9440af0 data/input/raw_maps/downtown_la.bin -9516b66d8965a7e9ef1ab110eb36e261 data/input/raw_maps/23rd.bin +9bfd89ddbc346a4e74fd8e64d6c6a0c0 data/input/raw_maps/23rd.bin 9b2c4729d3031553a477bb2e1134a6bf data/input/los_angeles/osm/downtown_la.osm 1dd1b7d3a6d38829a8266b0b6ea60b85 data/input/los_angeles/osm/socal.osm.pbf 97672583e0e9bc2e3d076645a1ccb8f5 data/input/los_angeles/polygons/downtown_la.poly @@ -224,31 +224,28 @@ d02d0d103f7b00672a5f1145c5169d8c data/system/fonts/Overpass-Bold.ttf 2a13391023ce8787887331530cac35a7 data/system/fonts/BungeeInline-Regular.ttf 17a1468e62195d0688a6f3bd12da2e92 data/system/fonts/Overpass-SemiBold.ttf 259d4afad7edca07e727ef80f5bbce07 data/system/fonts/Bungee-Regular.ttf -e1585fa67c5ccf56d69df0cd7252f70c data/system/maps/huge_seattle.bin +81c2d11a033555efb78d8ec07ccecf80 data/system/maps/huge_seattle.bin 32585d4a4d10b56e5d03b7bfd997e270 data/system/maps/ballard.bin 32204ce12eecd28829f4951c1b77ae16 data/system/maps/downtown.bin -db73a6ac20c03401d1c83b6a6160d17e data/system/maps/caphill.bin -14de88f522280473353f06a246cfe921 data/system/maps/lakeslice.bin +987b161dc0dbf9f791f4c602d285d369 data/system/maps/caphill.bin +eca90c51326fedc60cbd4f4e9481ddc0 data/system/maps/lakeslice.bin 4961886805fc8a5576a37cffc6adc9be data/system/maps/huge_austin.bin 94d44bfd4c5e2431c7f8555943e70709 data/system/maps/downtown_atx.bin 930d7b8add199635e19a8b701a3d3d8a data/system/maps/montlake.bin a5252a956553ea999b1969a89b2d5cf7 data/system/maps/intl_district.bin 2857ce1b2e3b233323a04d459d533024 data/system/maps/downtown_la.bin -0f59c67185e49cc28e27f3fb1eaab9c7 data/system/maps/23rd.bin +a9aaaaea906cc620f1710be5dc316a80 data/system/maps/23rd.bin cc45f42cb24cad1cfdbf5ed7a0cb86d4 data/system/synthetic_maps/signal_double.json 8b949cc34d9a27ace0bd8ecde55a9520 data/system/synthetic_maps/signal_single.json 1cd7be125e1d992613ed3a41e8b25b6a data/system/synthetic_maps/signal_fan_in.json -f57d3277ff6902034920d91d570584f2 data/system/scenarios/ballard/weekday.bin -55ef7fecaf48daa1ecc95891efd9f943 data/system/scenarios/intl_district/weekday.bin -57c8d6aaf2b9d7ca834cc73a0868a05b data/system/scenarios/23rd/weekday.bin -acc1339ee4625f16b8316f4e440f51b3 data/system/scenarios/lakeslice/weekday.bin -b395c98920656f24bf7bec600410caf4 data/system/scenarios/downtown/weekday.bin -eedbca7c08fdeb028d37dc2e385ccfa7 data/system/scenarios/huge_seattle/weekday.bin -503244891a7e60c696e8312a302abd22 data/system/scenarios/caphill/weekday.bin -9e96140d4b49a6abbbdcdda0b3eddd7c data/system/scenarios/montlake/everyone_weekday.bin -53e7061fd3ba0f03c8a00e2c09feb060 data/system/scenarios/montlake/weekday.bin -f9c2c0d6b2beb8260ee35e0e3ec23a3e data/system/prebaked_results/signal_single/tutorial lvl1.bin -ff80c3565b243cdbf7a0f0c3fa0f559a data/system/prebaked_results/signal_single/tutorial lvl2.bin -859ec1f6cbe4db9e321e00435e4298d5 data/system/prebaked_results/montlake/car vs bike contention.bin +624326d36bb63f5ffe57acd8c03eda4f data/system/scenarios/ballard/weekday.bin +737dfc33af6400225405f02c4ae576bb data/system/scenarios/intl_district/weekday.bin +d23f322d55424bdc3da93452d71a1683 data/system/scenarios/23rd/weekday.bin +a8240a7c953291ed4e0e479f3b29fab5 data/system/scenarios/lakeslice/weekday.bin +f1b22bc7c5cbcf78b91476a33fc469f8 data/system/scenarios/downtown/weekday.bin +fc2f434254ed22862a163bb9d05383bb data/system/scenarios/huge_seattle/weekday.bin +101b5d430d55fdc81748298b7f44e16d data/system/scenarios/caphill/weekday.bin +8eab93be03f8807d154cb27948da5b20 data/system/scenarios/montlake/everyone_weekday.bin +b6c27dd92bc9c978d1dfe49048ccfc19 data/system/scenarios/montlake/weekday.bin +84bf817c20e62c03465be72bea25b320 data/system/prebaked_results/montlake/car vs bike contention.bin 18272ae5ec70de3a61826a7497174bf0 data/system/prebaked_results/montlake/weekday.bin -cde373b434090989d2fcf64ced328ff7 data/system/prebaked_results/montlake/car vs bus contention.bin diff --git a/game/src/challenges.rs b/game/src/challenges.rs index 236a11c586..c741c86166 100644 --- a/game/src/challenges.rs +++ b/game/src/challenges.rs @@ -6,7 +6,7 @@ use abstutil::Timer; use ezgui::{hotkey, Btn, Color, Composite, EventCtx, Key, Line, Text, TextExt, Widget}; use geom::{Duration, Time}; use map_model::Map; -use sim::{AlertHandler, PersonID, Scenario, Sim, SimFlags, SimOptions}; +use sim::{AlertHandler, OrigPersonID, Scenario, Sim, SimFlags, SimOptions}; use std::collections::{BTreeMap, HashSet}; // TODO Also have some kind of screenshot to display for each challenge @@ -30,12 +30,16 @@ impl Challenge { let mut tree = BTreeMap::new(); tree.insert( "Optimize one commute".to_string(), + // TODO Need to tune both people and goals again. vec![ Challenge { title: "Part 1".to_string(), description: vec!["Speed up one VIP's daily commute, at any cost!".to_string()], alias: "commute/pt1".to_string(), - gameplay: GameplayMode::OptimizeCommute(PersonID(8819), Duration::minutes(2)), + gameplay: GameplayMode::OptimizeCommute( + OrigPersonID(140030, 1), + Duration::minutes(2), + ), cutscene: Some( crate::sandbox::gameplay::commute::OptimizeCommute::cutscene_pt1, ), @@ -45,7 +49,7 @@ impl Challenge { description: vec!["Speed up another VIP's commute".to_string()], alias: "commute/pt2".to_string(), gameplay: GameplayMode::OptimizeCommute( - PersonID(13121), + OrigPersonID(140288, 3), Duration::seconds(90.0), ), cutscene: Some( @@ -324,7 +328,7 @@ pub fn prebake_all() { } // TODO A weird hack to glue up tutorial scenarios. if map.get_name() == "montlake" { - for generator in TutorialState::scenarios_to_prebake() { + for generator in TutorialState::scenarios_to_prebake(&map) { let scenario = generator.generate( &map, &mut SimFlags::for_test("prebaked").make_rng(), diff --git a/game/src/info/person.rs b/game/src/info/person.rs index 74d1ce0854..9cb39b6003 100644 --- a/game/src/info/person.rs +++ b/game/src/info/person.rs @@ -211,6 +211,7 @@ pub fn bio( is_paused: bool, ) -> Vec { let mut rows = header(ctx, app, details, id, Tab::PersonBio(id), is_paused); + let person = app.primary.sim.get_person(id); // TODO A little picture rows.extend(make_table( @@ -219,6 +220,7 @@ pub fn bio( ("Name", "Somebody".to_string()), ("Age", "42".to_string()), ("Occupation", "classified".to_string()), + ("Debug ID", format!("{:?}", person.orig_id)), ], )); // TODO Mad libs! @@ -255,7 +257,6 @@ pub fn bio( ); } - let person = app.primary.sim.get_person(id); let mut has_bike = false; for v in &person.vehicles { if v.vehicle_type == VehicleType::Bike { diff --git a/game/src/sandbox/gameplay/commute.rs b/game/src/sandbox/gameplay/commute.rs index 95f020681c..6633e85d6a 100644 --- a/game/src/sandbox/gameplay/commute.rs +++ b/game/src/sandbox/gameplay/commute.rs @@ -14,7 +14,7 @@ use ezgui::{ TextExt, VerticalAlignment, Widget, }; use geom::{Duration, Time}; -use sim::{PersonID, TripID}; +use sim::{OrigPersonID, PersonID, TripID}; use std::collections::BTreeMap; // TODO A nice level to unlock: specifying your own commute, getting to work on it @@ -22,6 +22,7 @@ use std::collections::BTreeMap; pub struct OptimizeCommute { top_center: Composite, person: PersonID, + mode: GameplayMode, goal: Duration, time: Time, @@ -35,9 +36,10 @@ impl OptimizeCommute { pub fn new( ctx: &mut EventCtx, app: &App, - person: PersonID, + orig_person: OrigPersonID, goal: Duration, ) -> Box { + let person = app.primary.sim.find_person_by_orig_id(orig_person).unwrap(); let trips = app.primary.sim.get_person(person).trips.clone(); Box::new(OptimizeCommute { top_center: make_top_center( @@ -50,6 +52,7 @@ impl OptimizeCommute { goal, ), person, + mode: GameplayMode::OptimizeCommute(orig_person, goal), goal, time: Time::START_OF_DAY, trips, @@ -159,7 +162,7 @@ impl GameplayState for OptimizeCommute { Some(final_score( ctx, app, - GameplayMode::OptimizeCommute(self.person, self.goal), + self.mode.clone(), before, after, self.goal, @@ -176,22 +179,18 @@ impl GameplayState for OptimizeCommute { Some(Transition::Push(Box::new(EditMode::new( ctx, app, - GameplayMode::OptimizeCommute(self.person, self.goal), + self.mode.clone(), )))), false, ); } "instructions" => { return ( - Some(Transition::Push((Challenge::find( - &GameplayMode::OptimizeCommute(self.person, self.goal), - ) - .0 - .cutscene - .unwrap())( - ctx, - app, - &GameplayMode::OptimizeCommute(self.person, self.goal), + Some(Transition::Push((Challenge::find(&self.mode) + .0 + .cutscene + .unwrap())( + ctx, app, &self.mode ))), false, ); diff --git a/game/src/sandbox/gameplay/mod.rs b/game/src/sandbox/gameplay/mod.rs index 9c088a4dbe..9c2c8b2495 100644 --- a/game/src/sandbox/gameplay/mod.rs +++ b/game/src/sandbox/gameplay/mod.rs @@ -24,7 +24,7 @@ use ezgui::{ use geom::{Duration, Polygon}; use map_model::{EditCmd, EditIntersection, Map, MapEdits}; use rand_xorshift::XorShiftRng; -use sim::{Analytics, PersonID, Scenario, ScenarioGenerator}; +use sim::{Analytics, OrigPersonID, Scenario, ScenarioGenerator}; #[derive(PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum GameplayMode { @@ -39,7 +39,7 @@ pub enum GameplayMode { // TODO Kinda gross. What stage in the tutorial? #[allow(unused)] FixTrafficSignalsTutorial(usize), - OptimizeCommute(PersonID, Duration), + OptimizeCommute(OrigPersonID, Duration), // current Tutorial(TutorialPointer), diff --git a/game/src/sandbox/gameplay/tutorial.rs b/game/src/sandbox/gameplay/tutorial.rs index 2d50d56a73..042b6f941e 100644 --- a/game/src/sandbox/gameplay/tutorial.rs +++ b/game/src/sandbox/gameplay/tutorial.rs @@ -15,13 +15,13 @@ use ezgui::{ VerticalAlignment, Widget, }; use geom::{Distance, Duration, PolyLine, Polygon, Pt2D, Time}; -use map_model::{BuildingID, IntersectionID, IntersectionType, LaneType, RoadID}; -use maplit::btreeset; +use map_model::{BuildingID, IntersectionID, IntersectionType, LaneType, Map}; use sim::{ AgentID, Analytics, BorderSpawnOverTime, CarID, OriginDestination, ScenarioGenerator, VehicleType, }; +// TODO Unfortunately this has to be tuned when major map / simulation changes happen. const ESCORT: CarID = CarID(34, VehicleType::Car); const CAR_BIKE_CONTENTION_GOAL: Duration = Duration::const_seconds(60.0); @@ -151,7 +151,7 @@ impl Tutorial { // Interaction things if tut.interaction() == Task::Camera { - if app.primary.current_selection == Some(ID::Building(BuildingID(9))) + if app.primary.current_selection == Some(ID::Building(tut.montlake_market)) && app.per_obj.left_click(ctx, "put out the... fire?") { tut.next(); @@ -299,11 +299,6 @@ impl Tutorial { } return (Some(transition(ctx, app, tut)), false); } - } else if tut.interaction() == Task::WatchBuses { - if app.primary.sim.time() >= Time::START_OF_DAY + Duration::minutes(5) { - tut.next(); - return (Some(transition(ctx, app, tut)), false); - } } else if tut.interaction() == Task::Done { // If the player chooses to stay here, at least go back to the message panel. tut.prev(); @@ -365,7 +360,7 @@ impl GameplayState for Tutorial { if tut.interaction() == Task::Camera { g.draw_polygon( Color::hex("#e25822"), - &app.primary.map.get_b(BuildingID(9)).polygon, + &app.primary.map.get_b(tut.montlake_market).polygon, ); } } @@ -407,8 +402,6 @@ enum Task { LowParking, WatchBikes, FixBikes, - WatchBuses, - FixBuses, Done, } @@ -475,8 +468,6 @@ impl Task { CAR_BIKE_CONTENTION_GOAL ))); } - Task::WatchBuses => "Simulate 5 minutes and watch the buses", - Task::FixBuses => "Speed up bus 43 and 48", Task::Done => "Tutorial complete!", }; @@ -496,8 +487,6 @@ impl Task { Task::LowParking => "Using extra data layers", Task::WatchBikes => "Observing a problem", Task::FixBikes => "Editing lanes", - Task::WatchBuses => "Observing buses", - Task::FixBuses => "Speeding up buses", Task::Done => "Tutorial complete!", } } @@ -616,9 +605,11 @@ pub struct TutorialState { parking_found: bool, score_delivered: bool, + + montlake_market: BuildingID, } -fn make_bike_lane_scenario() -> ScenarioGenerator { +fn make_bike_lane_scenario(map: &Map) -> ScenarioGenerator { let mut s = ScenarioGenerator::empty("car vs bike contention"); s.border_spawn_over_time.push(BorderSpawnOverTime { num_peds: 0, @@ -627,34 +618,15 @@ fn make_bike_lane_scenario() -> ScenarioGenerator { percent_use_transit: 0.0, start_time: Time::START_OF_DAY, stop_time: Time::START_OF_DAY + Duration::seconds(10.0), - start_from_border: RoadID(303).backwards(), - goal: OriginDestination::GotoBldg(BuildingID(3)), + start_from_border: map + .find_r_by_osm_id(263665925, (2499826475, 53096959)) + .unwrap() + .backwards(), + goal: OriginDestination::GotoBldg(map.find_b_by_osm_id(40833037).unwrap()), }); s } -fn make_bus_lane_scenario() -> ScenarioGenerator { - let mut s = ScenarioGenerator::empty("car vs bus contention"); - s.only_seed_buses = Some(btreeset! {"43".to_string(), "48".to_string()}); - for src in vec![ - RoadID(61).backwards(), - RoadID(240).forwards(), - RoadID(56).forwards(), - ] { - s.border_spawn_over_time.push(BorderSpawnOverTime { - num_peds: 100, - num_cars: 100, - num_bikes: 0, - percent_use_transit: 1.0, - start_time: Time::START_OF_DAY, - stop_time: Time::START_OF_DAY + Duration::seconds(10.0), - start_from_border: src, - goal: OriginDestination::EndOfRoad(RoadID(0).forwards()), - }); - } - s -} - fn transition(ctx: &mut EventCtx, app: &mut App, tut: &mut TutorialState) -> Transition { tut.reset_state(); let mode = GameplayMode::Tutorial(tut.current); @@ -899,6 +871,8 @@ impl TutorialState { prank_done: false, parking_found: false, score_delivered: false, + + montlake_market: app.primary.map.find_b_by_osm_id(97430815).unwrap(), }; let tool_panel = tool_panel(ctx, app); @@ -916,10 +890,15 @@ impl TutorialState { 0.97 * ctx.canvas.window_height, ); + let map = &app.primary.map; + state.stages.push( Stage::new(Task::Camera) // TODO Call these by orig_id to be robust to changes - .warp_to(ID::Intersection(IntersectionID(141)), None) + .warp_to( + ID::Intersection(map.find_i_by_osm_id(53149407).unwrap()), + None, + ) .msg( vec![ "Welcome to your first day as a contract traffic engineer --", @@ -998,7 +977,10 @@ impl TutorialState { state.stages.push( Stage::new(Task::TimeControls) - .warp_to(ID::Intersection(IntersectionID(64)), None) + .warp_to( + ID::Intersection(map.find_i_by_osm_id(53096945).unwrap()), + None, + ) .msg( vec![ "Inspection complete!", @@ -1059,8 +1041,11 @@ impl TutorialState { state.stages.push( Stage::new(Task::Escort) // Don't center on where the agents are, be a little offset - .warp_to(ID::Building(BuildingID(813)), Some(10.0)) - .spawn_around(IntersectionID(247)) + .warp_to( + ID::Building(map.find_b_by_osm_id(217699780).unwrap()), + Some(10.0), + ) + .spawn_around(map.find_i_by_osm_id(1709145066).unwrap()) .msg( vec!["Alright alright, no need to wear out your spacebar."], None, @@ -1142,11 +1127,12 @@ impl TutorialState { ), ); - let bike_lane_scenario = make_bike_lane_scenario(); + let bike_lane_scenario = make_bike_lane_scenario(map); + let bike_lane_focus_pt = map.find_b_by_osm_id(217699496).unwrap(); state.stages.push( Stage::new(Task::WatchBikes) - .warp_to(ID::Building(BuildingID(543)), None) + .warp_to(ID::Building(bike_lane_focus_pt), None) .spawn_scenario(bike_lane_scenario.clone()) .msg( vec![ @@ -1163,7 +1149,7 @@ impl TutorialState { state.stages.push( Stage::new(Task::FixBikes) .spawn_scenario(bike_lane_scenario) - .warp_to(ID::Building(BuildingID(543)), None) + .warp_to(ID::Building(bike_lane_focus_pt), None) .msg( vec![ "Looks like lots of cars and bikes trying to go to the playfield.", @@ -1211,36 +1197,6 @@ impl TutorialState { ), ); - if false { - let bus_lane_scenario = make_bus_lane_scenario(); - // TODO There's no clear measurement for how well the buses are doing. - // TODO Probably want a steady stream of the cars appearing - - state.stages.push( - Stage::new(Task::WatchBuses) - .warp_to(ID::Building(BuildingID(1979)), Some(0.5)) - .spawn_scenario(bus_lane_scenario.clone()) - .msg( - vec![ - "Alright, now it's a game day at the University of Washington.", - "Everyone's heading north across the bridge.", - "Watch what happens to the bus 43 and 48.", - ], - None, - ), - ); - - state.stages.push( - Stage::new(Task::FixBuses) - .warp_to(ID::Building(BuildingID(1979)), Some(0.5)) - .spawn_scenario(bus_lane_scenario.clone()) - .msg( - vec!["Let's speed up the poor bus! Why not dedicate some bus lanes to it?"], - None, - ), - ); - } - state.stages.push(Stage::new(Task::Done).msg( vec![ "Training complete!", @@ -1270,9 +1226,8 @@ impl TutorialState { // work. } - // TODO Weird hack to prebake. - pub fn scenarios_to_prebake() -> Vec { - vec![make_bike_lane_scenario(), make_bus_lane_scenario()] + pub fn scenarios_to_prebake(map: &Map) -> Vec { + vec![make_bike_lane_scenario(map)] } } diff --git a/importer/src/soundcast/popdat.rs b/importer/src/soundcast/popdat.rs index ac4bb68f25..079e3c6f5a 100644 --- a/importer/src/soundcast/popdat.rs +++ b/importer/src/soundcast/popdat.rs @@ -2,7 +2,7 @@ use abstutil::{prettyprint_usize, FileWithProgress, Timer}; use geom::{Distance, Duration, FindClosest, LonLat, Pt2D, Time}; use map_model::Map; use serde_derive::{Deserialize, Serialize}; -use sim::TripMode; +use sim::{OrigPersonID, TripMode}; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fs::File; use std::io::Write; @@ -46,7 +46,7 @@ fn import_trips( let mut trips = Vec::new(); let (reader, done) = FileWithProgress::new(trips_path)?; let mut total_records = 0; - let mut people: HashSet<(usize, usize)> = HashSet::new(); + let mut people: HashSet = HashSet::new(); for rec in csv::Reader::from_reader(reader).deserialize() { total_records += 1; @@ -75,7 +75,7 @@ fn import_trips( let trip_time = Duration::f64_minutes(rec.travtime); let trip_dist = Distance::miles(rec.travdist); - let person = (rec.hhno as usize, rec.pno as usize); + let person = OrigPersonID(rec.hhno as usize, rec.pno as usize); people.insert(person); let seq = (rec.tour as usize, rec.half == 2.0, rec.tseg as usize); @@ -277,7 +277,7 @@ pub struct OrigTrip { pub mode: TripMode, // (household, person within household) - pub person: (usize, usize), + pub person: OrigPersonID, // (tour, false is to destination and true is back from dst, trip within half-tour) pub seq: (usize, bool, usize), pub purpose: (Purpose, Purpose), diff --git a/importer/src/soundcast/trips.rs b/importer/src/soundcast/trips.rs index 3bba638769..3d8d87c336 100644 --- a/importer/src/soundcast/trips.rs +++ b/importer/src/soundcast/trips.rs @@ -3,8 +3,8 @@ use abstutil::{prettyprint_usize, MultiMap, Timer}; use geom::LonLat; use map_model::{BuildingID, IntersectionID, Map, PathConstraints}; use sim::{ - DrivingGoal, IndividTrip, OffMapLocation, PersonID, PersonSpec, Scenario, SidewalkSpot, - SpawnTrip, TripMode, + DrivingGoal, IndividTrip, OffMapLocation, OrigPersonID, PersonID, PersonSpec, Scenario, + SidewalkSpot, SpawnTrip, TripMode, }; use std::collections::HashMap; @@ -230,7 +230,7 @@ pub fn make_weekday_scenario(map: &Map, timer: &mut Timer) -> Scenario { let mut individ_trips: Vec> = Vec::new(); // person -> (trip seq, index into individ_trips) - let mut trips_per_person: MultiMap<(usize, usize), ((usize, bool, usize), usize)> = + let mut trips_per_person: MultiMap = MultiMap::new(); for (trip, depart, person, seq) in timer.parallelize("turn Soundcast trips into SpawnTrips", trips, |trip| { @@ -264,7 +264,11 @@ pub fn make_weekday_scenario(map: &Map, timer: &mut Timer) -> Scenario { // departure time starting with midnight. trips.sort_by_key(|t| t.depart); - people.push(PersonSpec { id, orig_id, trips }); + people.push(PersonSpec { + id, + orig_id: Some(orig_id), + trips, + }); } for maybe_t in individ_trips { if maybe_t.is_some() { @@ -286,7 +290,7 @@ pub fn make_weekday_scenario_with_everyone(map: &Map, timer: &mut Timer) -> Scen let mut individ_trips: Vec> = Vec::new(); // person -> (trip seq, index into individ_trips) - let mut trips_per_person: MultiMap<(usize, usize), ((usize, bool, usize), usize)> = + let mut trips_per_person: MultiMap = MultiMap::new(); timer.start_iter("turn Soundcast trips into SpawnTrips", popdat.trips.len()); for orig_trip in popdat.trips { @@ -328,7 +332,11 @@ pub fn make_weekday_scenario_with_everyone(map: &Map, timer: &mut Timer) -> Scen // departure time starting with midnight. trips.sort_by_key(|t| t.depart); - people.push(PersonSpec { id, orig_id, trips }); + people.push(PersonSpec { + id, + orig_id: Some(orig_id), + trips, + }); } for maybe_t in individ_trips { if maybe_t.is_some() { diff --git a/map_model/src/map.rs b/map_model/src/map.rs index d1b7f61835..032319dd0c 100644 --- a/map_model/src/map.rs +++ b/map_model/src/map.rs @@ -640,26 +640,36 @@ impl Map { None } - pub(crate) fn find_r(&self, id: OriginalRoad) -> Option { - // TODO Speed up with a mapping? + pub fn find_r_by_osm_id(&self, osm_way_id: i64, osm_node_ids: (i64, i64)) -> Option { for r in self.all_roads() { - if r.orig_id == id { + if r.orig_id.osm_way_id == osm_way_id + && r.orig_id.i1.osm_node_id == osm_node_ids.0 + && r.orig_id.i2.osm_node_id == osm_node_ids.1 + { return Some(r.id); } } None } - pub(crate) fn find_i(&self, id: OriginalIntersection) -> Option { - // TODO Speed up with a mapping? + pub fn find_i_by_osm_id(&self, osm_node_id: i64) -> Option { for i in self.all_intersections() { - if i.orig_id == id { + if i.orig_id.osm_node_id == osm_node_id { return Some(i.id); } } None } + pub fn find_b_by_osm_id(&self, osm_way_id: i64) -> Option { + for b in self.all_buildings() { + if b.osm_way_id == osm_way_id { + return Some(b.id); + } + } + None + } + pub fn right_shift(&self, pl: PolyLine, width: Distance) -> Warn { self.driving_side.right_shift(pl, width) } diff --git a/map_model/src/traffic_signals.rs b/map_model/src/traffic_signals.rs index 60834f4af2..2cca7698f2 100644 --- a/map_model/src/traffic_signals.rs +++ b/map_model/src/traffic_signals.rs @@ -1,4 +1,3 @@ -use crate::raw::{OriginalIntersection, OriginalRoad}; use crate::{ DirectedRoadID, IntersectionID, Map, RoadID, TurnGroup, TurnGroupID, TurnID, TurnPriority, TurnType, @@ -51,6 +50,11 @@ impl ControlTrafficSignal { { if let Some(ts) = ControlTrafficSignal::import(raw, id, map) { results.push(("hand-mapped current real settings".to_string(), ts)); + } else { + panic!( + "seattle_traffic_signals data for {} out of date, go update it", + map.get_i(id).orig_id.osm_node_id + ); } } @@ -728,24 +732,14 @@ fn import_turn_group(id: seattle_traffic_signals::Turn, map: &Map) -> Option Option { Some(DirectedRoadID { - id: map.find_r(OriginalRoad { - osm_way_id: id.osm_way_id, - i1: OriginalIntersection { - osm_node_id: id.osm_node1, - }, - i2: OriginalIntersection { - osm_node_id: id.osm_node2, - }, - })?, + id: map.find_r_by_osm_id(id.osm_way_id, (id.osm_node1, id.osm_node2))?, forwards: id.is_forwards, }) } diff --git a/sim/src/lib.rs b/sim/src/lib.rs index fd7e3f3822..ba467555d0 100644 --- a/sim/src/lib.rs +++ b/sim/src/lib.rs @@ -121,6 +121,9 @@ impl fmt::Display for PersonID { } } +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct OrigPersonID(pub usize, pub usize); + #[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)] pub enum VehicleType { Car, diff --git a/sim/src/make/generator.rs b/sim/src/make/generator.rs index bf1b4864ef..aed2a0c0a6 100644 --- a/sim/src/make/generator.rs +++ b/sim/src/make/generator.rs @@ -199,7 +199,7 @@ impl SpawnOverTime { { scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::UsingParkedCar(from_bldg, goal), @@ -218,7 +218,7 @@ impl SpawnOverTime { { scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::UsingBike(start_spot, goal), @@ -242,7 +242,7 @@ impl SpawnOverTime { { scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::UsingTransit(start_spot, goal, route, stop1, stop2), @@ -254,7 +254,7 @@ impl SpawnOverTime { scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::JustWalking(start_spot, goal), @@ -304,7 +304,7 @@ impl BorderSpawnOverTime { { scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::UsingTransit( @@ -322,7 +322,7 @@ impl BorderSpawnOverTime { scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::JustWalking(start.clone(), goal), @@ -351,7 +351,7 @@ impl BorderSpawnOverTime { let id = PersonID(scenario.people.len()); scenario.people.push(PersonSpec { id, - orig_id: (0, 0), + orig_id: None, trips: vec![IndividTrip { depart, trip: SpawnTrip::FromBorder { diff --git a/sim/src/make/scenario.rs b/sim/src/make/scenario.rs index 079198759f..8c4264a2e1 100644 --- a/sim/src/make/scenario.rs +++ b/sim/src/make/scenario.rs @@ -1,7 +1,7 @@ use crate::{ - CarID, DrivingGoal, ParkingSpot, PersonID, SidewalkPOI, SidewalkSpot, Sim, TripEndpoint, - TripMode, TripSpec, Vehicle, VehicleSpec, VehicleType, BIKE_LENGTH, MAX_CAR_LENGTH, - MIN_CAR_LENGTH, + CarID, DrivingGoal, OrigPersonID, ParkingSpot, PersonID, SidewalkPOI, SidewalkSpot, Sim, + TripEndpoint, TripMode, TripSpec, Vehicle, VehicleSpec, VehicleType, BIKE_LENGTH, + MAX_CAR_LENGTH, MIN_CAR_LENGTH, }; use abstutil::{prettyprint_usize, Counter, Timer}; use geom::{Distance, Duration, LonLat, Speed, Time}; @@ -29,7 +29,7 @@ pub struct Scenario { pub struct PersonSpec { pub id: PersonID, // Just used for debugging - pub orig_id: (usize, usize), + pub orig_id: Option, pub trips: Vec, } @@ -105,7 +105,12 @@ impl Scenario { let (vehicle_specs, cars_initially_parked_at, vehicle_foreach_trip) = p.get_vehicles(rng); - sim.new_person(p.id, Scenario::rand_ped_speed(rng), vehicle_specs); + sim.new_person( + p.id, + p.orig_id, + Scenario::rand_ped_speed(rng), + vehicle_specs, + ); let person = sim.get_person(p.id); for (idx, b) in cars_initially_parked_at { parked_cars.push((person.vehicles[idx].clone(), b)); diff --git a/sim/src/sim.rs b/sim/src/sim.rs index 3b134c39a0..40264686f8 100644 --- a/sim/src/sim.rs +++ b/sim/src/sim.rs @@ -1,6 +1,6 @@ use crate::{ AgentID, AlertLocation, Analytics, CarID, Command, CreateCar, DrawCarInput, DrawPedCrowdInput, - DrawPedestrianInput, DrivingSimState, Event, GetDrawAgents, IntersectionSimState, + DrawPedestrianInput, DrivingSimState, Event, GetDrawAgents, IntersectionSimState, OrigPersonID, PandemicModel, ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, Person, PersonID, PersonState, Router, Scheduler, SidewalkPOI, SidewalkSpot, TransitSimState, TripEndpoint, TripID, TripManager, TripMode, TripPhaseType, TripPositions, TripResult, TripSpawner, @@ -218,8 +218,14 @@ impl Sim { } // TODO Should these two be in TripSpawner? - pub fn new_person(&mut self, p: PersonID, ped_speed: Speed, vehicle_specs: Vec) { - self.trips.new_person(p, ped_speed, vehicle_specs); + pub(crate) fn new_person( + &mut self, + p: PersonID, + orig_id: Option, + ped_speed: Speed, + vehicle_specs: Vec, + ) { + self.trips.new_person(p, orig_id, ped_speed, vehicle_specs); } pub fn random_person(&mut self, ped_speed: Speed, vehicle_specs: Vec) -> &Person { self.trips.random_person(ped_speed, vehicle_specs) @@ -1000,6 +1006,14 @@ impl Sim { pub fn get_person(&self, id: PersonID) -> &Person { self.trips.get_person(id).unwrap() } + pub fn find_person_by_orig_id(&self, id: OrigPersonID) -> Option { + for p in self.get_all_people() { + if p.orig_id == Some(id) { + return Some(p.id); + } + } + None + } pub fn get_all_people(&self) -> &Vec { self.trips.get_all_people() } diff --git a/sim/src/trips.rs b/sim/src/trips.rs index 8a233286e9..94f8c98dcb 100644 --- a/sim/src/trips.rs +++ b/sim/src/trips.rs @@ -1,8 +1,8 @@ use crate::{ AgentID, AlertLocation, CarID, Command, CreateCar, CreatePedestrian, DrivingGoal, Event, - OffMapLocation, ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, PersonID, Scheduler, - SidewalkPOI, SidewalkSpot, TransitSimState, TripID, TripPhaseType, TripSpec, Vehicle, - VehicleSpec, VehicleType, WalkingSimState, + OffMapLocation, OrigPersonID, ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, PersonID, + Scheduler, SidewalkPOI, SidewalkSpot, TransitSimState, TripID, TripPhaseType, TripSpec, + Vehicle, VehicleSpec, VehicleType, WalkingSimState, }; use abstutil::{deserialize_btreemap, serialize_btreemap, Counter}; use geom::{Distance, Duration, Speed, Time}; @@ -43,7 +43,13 @@ impl TripManager { } // TODO assert the specs are correct yo - pub fn new_person(&mut self, id: PersonID, ped_speed: Speed, vehicle_specs: Vec) { + pub fn new_person( + &mut self, + id: PersonID, + orig_id: Option, + ped_speed: Speed, + vehicle_specs: Vec, + ) { assert_eq!(id.0, self.people.len()); let vehicles = vehicle_specs .into_iter() @@ -54,6 +60,7 @@ impl TripManager { .collect(); self.people.push(Person { id, + orig_id, trips: Vec::new(), // The first new_trip will set this properly. state: PersonState::OffMap, @@ -65,7 +72,7 @@ impl TripManager { } pub fn random_person(&mut self, ped_speed: Speed, vehicle_specs: Vec) -> &Person { let id = PersonID(self.people.len()); - self.new_person(id, ped_speed, vehicle_specs); + self.new_person(id, None, ped_speed, vehicle_specs); self.get_person(id).unwrap() } @@ -1359,6 +1366,7 @@ impl TripResult { #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] pub struct Person { pub id: PersonID, + pub orig_id: Option, pub trips: Vec, // TODO home pub state: PersonState,