mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
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:
parent
dbc47aee7d
commit
01bd4aec6f
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
);
|
||||
|
@ -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),
|
||||
|
@ -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)]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user