clean up some fallout from the grand data refreshening. mostly

robustifying tutorials/challenges by using IDs stable across map updates
This commit is contained in:
Dustin Carlino 2020-05-01 10:54:43 -07:00
parent dbc47aee7d
commit 01bd4aec6f
16 changed files with 169 additions and 174 deletions

View File

@ -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,

View File

@ -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

View File

@ -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(),

View File

@ -211,6 +211,7 @@ pub fn bio(
is_paused: bool,
) -> Vec<Widget> {
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 {

View File

@ -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<dyn GameplayState> {
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,
);

View File

@ -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),

View File

@ -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<ScenarioGenerator> {
vec![make_bike_lane_scenario(), make_bus_lane_scenario()]
pub fn scenarios_to_prebake(map: &Map) -> Vec<ScenarioGenerator> {
vec![make_bike_lane_scenario(map)]
}
}

View File

@ -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<OrigPersonID> = 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),

View File

@ -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<Option<IndividTrip>> = 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<OrigPersonID, ((usize, bool, usize), usize)> =
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<Option<IndividTrip>> = 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<OrigPersonID, ((usize, bool, usize), usize)> =
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() {

View File

@ -640,26 +640,36 @@ impl Map {
None
}
pub(crate) fn find_r(&self, id: OriginalRoad) -> Option<RoadID> {
// TODO Speed up with a mapping?
pub fn find_r_by_osm_id(&self, osm_way_id: i64, osm_node_ids: (i64, i64)) -> Option<RoadID> {
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<IntersectionID> {
// TODO Speed up with a mapping?
pub fn find_i_by_osm_id(&self, osm_node_id: i64) -> Option<IntersectionID> {
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<BuildingID> {
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<PolyLine> {
self.driving_side.right_shift(pl, width)
}

View File

@ -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<Tur
Some(TurnGroupID {
from: find_r(id.from, map)?,
to: find_r(id.to, map)?,
parent: map.find_i(OriginalIntersection {
osm_node_id: id.intersection_osm_node_id,
})?,
parent: map.find_i_by_osm_id(id.intersection_osm_node_id)?,
crosswalk: id.is_crosswalk,
})
}
fn find_r(id: seattle_traffic_signals::DirectedRoad, map: &Map) -> Option<DirectedRoadID> {
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,
})
}

View File

@ -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,

View File

@ -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 {

View File

@ -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<OrigPersonID>,
pub trips: Vec<IndividTrip>,
}
@ -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));

View File

@ -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<VehicleSpec>) {
self.trips.new_person(p, ped_speed, vehicle_specs);
pub(crate) fn new_person(
&mut self,
p: PersonID,
orig_id: Option<OrigPersonID>,
ped_speed: Speed,
vehicle_specs: Vec<VehicleSpec>,
) {
self.trips.new_person(p, orig_id, ped_speed, vehicle_specs);
}
pub fn random_person(&mut self, ped_speed: Speed, vehicle_specs: Vec<VehicleSpec>) -> &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<PersonID> {
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<Person> {
self.trips.get_all_people()
}

View File

@ -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<VehicleSpec>) {
pub fn new_person(
&mut self,
id: PersonID,
orig_id: Option<OrigPersonID>,
ped_speed: Speed,
vehicle_specs: Vec<VehicleSpec>,
) {
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<VehicleSpec>) -> &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<T> TripResult<T> {
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
pub struct Person {
pub id: PersonID,
pub orig_id: Option<OrigPersonID>,
pub trips: Vec<TripID>,
// TODO home
pub state: PersonState,