start representing bus spawn rates explicitly

This commit is contained in:
Dustin Carlino 2020-08-03 13:12:02 -07:00
parent 22afb60421
commit f73516d183
7 changed files with 105 additions and 32 deletions

View File

@ -39,19 +39,19 @@ data/input/seattle/parcels_urbansim.txt,db63d7d606e8702d12f9399e87e6a00f,https:/
data/input/seattle/popdat.bin,0fd10698d2c6bf41da3d57804c617d15,https://www.dropbox.com/s/iboctakleznvslq/popdat.bin.zip?dl=0
data/input/seattle/trips_2014.csv,d4a8e733045b28c0385fb81359d6df03,https://www.dropbox.com/s/5ppravwmk6bf20d/trips_2014.csv.zip?dl=0
data/system/cities/seattle.bin,4ddc0f99d53ae3171f0c4ad2e4c646bd,https://www.dropbox.com/s/m7q6y6w9gw3ubjs/seattle.bin.zip?dl=0
data/system/maps/ballard.bin,82ced46cda865fb65bc11e7ff68ff877,https://www.dropbox.com/s/ilwsscuwtdhv2wu/ballard.bin.zip?dl=0
data/system/maps/berlin_center.bin,bfb07f2bb165fabcdaf7779c6fc5a71d,https://www.dropbox.com/s/f9m84s5ilcys3ah/berlin_center.bin.zip?dl=0
data/system/maps/downtown.bin,8f51a3079520982d61418e3ef8c3ffb3,https://www.dropbox.com/s/rh3netnh4p7qv5w/downtown.bin.zip?dl=0
data/system/maps/huge_seattle.bin,2a758381fd5f94417bb5646025842e50,https://www.dropbox.com/s/n5cstox0s8czqhx/huge_seattle.bin.zip?dl=0
data/system/maps/krakow_center.bin,ee128d15bd8c65b70b0a4ad090a7e736,https://www.dropbox.com/s/bkri62r9se3s46y/krakow_center.bin.zip?dl=0
data/system/maps/lakeslice.bin,10269590012e297df17acf6195770b96,https://www.dropbox.com/s/xcp4s1dvdy414nz/lakeslice.bin.zip?dl=0
data/system/maps/montlake.bin,34a67457c7411291ff03772fd785c98d,https://www.dropbox.com/s/sjl8j4or361e7bc/montlake.bin.zip?dl=0
data/system/maps/south_seattle.bin,97ec71f95acb4db29abe58cee88d2a21,https://www.dropbox.com/s/wa1azyqelse3t1e/south_seattle.bin.zip?dl=0
data/system/maps/udistrict.bin,475e177d37876ac1b49f03646e147371,https://www.dropbox.com/s/qcxcqy3xe0m9dv2/udistrict.bin.zip?dl=0
data/system/maps/west_seattle.bin,32cd4866c222a56c543ae9a31256f08e,https://www.dropbox.com/s/gw8hjjrl4cahm0j/west_seattle.bin.zip?dl=0
data/system/prebaked_results/lakeslice/weekday.bin,872d2c49b63659b2dbe3d9424f5448b5,https://www.dropbox.com/s/dg5lalw3caec0ra/weekday.bin.zip?dl=0
data/system/prebaked_results/montlake/car vs bike contention.bin,b0ae18d18936d1ae32e20bfc1afbe726,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0
data/system/prebaked_results/montlake/weekday.bin,f32fd37202433a4b6a4515db68e70012,https://www.dropbox.com/s/mus8cpyc1q58tq4/weekday.bin.zip?dl=0
data/system/maps/ballard.bin,907a708c024c000028088d43602f9647,https://www.dropbox.com/s/racyl5o04700rth/ballard.bin.zip?dl=0
data/system/maps/berlin_center.bin,496e1f7384de1a10421d413992b524ce,https://www.dropbox.com/s/vmtmypye5w2bovt/berlin_center.bin.zip?dl=0
data/system/maps/downtown.bin,5ff683efaea52e2e132cee573aa6ac41,https://www.dropbox.com/s/v5hwild4luavcie/downtown.bin.zip?dl=0
data/system/maps/huge_seattle.bin,3c91184af8f24323e2c2d9cd858748f8,https://www.dropbox.com/s/kckex9w5c6099xv/huge_seattle.bin.zip?dl=0
data/system/maps/krakow_center.bin,41940148947fa64aff85694afee49e8e,https://www.dropbox.com/s/2zctje85ht9yxxo/krakow_center.bin.zip?dl=0
data/system/maps/lakeslice.bin,ce2f18ddb9d078d99ec79af1876dd654,https://www.dropbox.com/s/aqwpe0uiiktmbfj/lakeslice.bin.zip?dl=0
data/system/maps/montlake.bin,ea576940ceeca71fbf67661dec3d08ee,https://www.dropbox.com/s/593up23e6k67c00/montlake.bin.zip?dl=0
data/system/maps/south_seattle.bin,9017d61af15518419fd0d883e407a988,https://www.dropbox.com/s/u9w8wdwun0x6wy1/south_seattle.bin.zip?dl=0
data/system/maps/udistrict.bin,d077fef667a6a7ff9b14f94d24bd843b,https://www.dropbox.com/s/cwcxxggn1hzzrdr/udistrict.bin.zip?dl=0
data/system/maps/west_seattle.bin,00c05db8bb2b0ef88a89addfe9edd751,https://www.dropbox.com/s/urcz6x43ejfrzqz/west_seattle.bin.zip?dl=0
data/system/prebaked_results/lakeslice/weekday.bin,e0bc89230f2f26659b8c5ff469130e7d,https://www.dropbox.com/s/jc66uhy4p037b2c/weekday.bin.zip?dl=0
data/system/prebaked_results/montlake/car vs bike contention.bin,e3d09d3f71fb6c3f39ce9b73291fba5a,https://www.dropbox.com/s/jefg0ikjy9dsrdd/car%20vs%20bike%20contention.bin.zip?dl=0
data/system/prebaked_results/montlake/weekday.bin,d5058f6aedfe7a6320e60b192de0f962,https://www.dropbox.com/s/zkny87kygnxd30b/weekday.bin.zip?dl=0
data/system/scenarios/ballard/weekday.bin,b5252821a3e5e7b1f5bdb83191e9890b,https://www.dropbox.com/s/wam0a5q0mhzxm6x/weekday.bin.zip?dl=0
data/system/scenarios/downtown/weekday.bin,bc31ac91a67eaa6d865b507432330f5e,https://www.dropbox.com/s/vrhsp920swdgdgk/weekday.bin.zip?dl=0
data/system/scenarios/huge_seattle/weekday.bin,cce3d979adb1126ffc159884858fc900,https://www.dropbox.com/s/3jldfrhmhcbofmw/weekday.bin.zip?dl=0

View File

@ -5,7 +5,7 @@ use crate::info::{header_btns, make_tabs, Details, Tab};
use abstutil::{prettyprint_usize, Counter};
use ezgui::{Btn, Color, EventCtx, Line, RewriteColor, Text, TextExt, Widget};
use geom::{Circle, Distance, Time};
use map_model::{BusRouteID, BusStopID, PathConstraints, PathStep};
use map_model::{BusRoute, BusRouteID, BusStopID, PathStep};
use sim::{AgentID, CarID};
pub fn stop(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID) -> Vec<Widget> {
@ -175,11 +175,7 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
let buses = app.primary.sim.status_of_buses(id, map);
let mut bus_locations = Vec::new();
if buses.is_empty() {
if route.route_type == PathConstraints::Bus {
rows.push("No buses running".draw_text(ctx));
} else {
rows.push("No trains running".draw_text(ctx));
}
rows.push(format!("No {} running", route.plural_noun()).draw_text(ctx));
} else {
for (bus, _, _, pt) in buses {
rows.push(Btn::text_fg(bus.to_string()).build_def(ctx, None));
@ -281,6 +277,11 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
details.warpers.insert(name, ID::Intersection(i.id));
}
// TODO Soon it'll be time to split into tabs
{
rows.push(describe_schedule(route).draw(ctx));
}
// Draw the route, label stops, and show location of buses
{
let mut colorer = ColorNetwork::new(app);
@ -325,3 +326,47 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
rows
}
// TODO Unit test
fn describe_schedule(route: &BusRoute) -> Text {
let mut txt = Text::new();
txt.add(Line(format!(
"{} {}s run this route daily",
route.spawn_times.len(),
route.plural_noun()
)));
// Compress the times
let mut start = route.spawn_times[0];
let mut last = None;
let mut dt = None;
for t in route.spawn_times.iter().skip(1) {
if let Some(l) = last {
let new_dt = *t - l;
if Some(new_dt) == dt {
last = Some(*t);
} else {
txt.add(Line(format!(
"Every {} from {} to {}",
dt.unwrap(),
start.ampm_tostring(),
l.ampm_tostring()
)));
start = l;
last = Some(*t);
dt = Some(new_dt);
}
} else {
last = Some(*t);
dt = Some(*t - start);
}
}
// Handle end
txt.add(Line(format!(
"Every {} from {} to {}",
dt.unwrap(),
start.ampm_tostring(),
last.unwrap().ampm_tostring()
)));
txt
}

View File

@ -4,7 +4,7 @@ use crate::{
BusRoute, BusRouteID, BusStop, BusStopID, LaneID, LaneType, Map, PathConstraints, Position,
};
use abstutil::Timer;
use geom::{Distance, HashablePt2D};
use geom::{Distance, Duration, HashablePt2D, Time};
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::error::Error;
@ -136,6 +136,7 @@ fn make_route(
route_type,
start,
end_border,
spawn_times: default_spawn_times(),
};
// Make sure the route is connected
@ -323,3 +324,16 @@ fn pick_start_lane(
first_stop.lane()
))
}
fn default_spawn_times() -> Vec<Time> {
// Hourly spawning from midnight to 7, then every 30 minutes till 7, then hourly again
let mut times = Vec::new();
for i in 0..24 {
let hour = Time::START_OF_DAY + Duration::hours(i);
times.push(hour);
if i >= 7 && i <= 19 {
times.push(hour + Duration::minutes(30));
}
}
times
}

View File

@ -1,5 +1,6 @@
use crate::{LaneID, Map, PathConstraints, PathRequest, Position};
use abstutil::{deserialize_usize, serialize_usize};
use geom::Time;
use serde::{Deserialize, Serialize};
use std::fmt;
@ -53,6 +54,8 @@ pub struct BusRoute {
pub start: LaneID,
pub end_border: Option<LaneID>,
pub route_type: PathConstraints,
// Non-empty, times in order for one day when a vehicle should begin at start.
pub spawn_times: Vec<Time>,
}
impl BusRoute {
@ -79,4 +82,12 @@ impl BusRoute {
}
steps
}
pub fn plural_noun(&self) -> &'static str {
if self.route_type == PathConstraints::Bus {
"buses"
} else {
"trains"
}
}
}

View File

@ -104,13 +104,13 @@ impl Scenario {
if let Some(ref routes) = self.only_seed_buses {
for route in map.all_bus_routes() {
if routes.contains(&route.full_name) {
sim.seed_bus_route(route, map);
sim.seed_bus_route(route);
}
}
} else {
// All of them
for route in map.all_bus_routes() {
sim.seed_bus_route(route, map);
sim.seed_bus_route(route);
}
}

View File

@ -23,7 +23,8 @@ pub enum Command {
Callback(Duration),
Pandemic(pandemic::Cmd),
FinishRemoteTrip(TripID),
SeedBus(BusRouteID),
// The Time is redundant, just used to dedupe commands
StartBus(BusRouteID, Time),
}
impl Command {
@ -47,7 +48,7 @@ impl Command {
Command::Callback(_) => CommandType::Callback,
Command::Pandemic(ref p) => CommandType::Pandemic(p.clone()),
Command::FinishRemoteTrip(t) => CommandType::FinishRemoteTrip(*t),
Command::SeedBus(r) => CommandType::SeedBus(*r),
Command::StartBus(r, t) => CommandType::StartBus(*r, *t),
}
}
}
@ -64,7 +65,7 @@ pub enum CommandType {
Callback,
Pandemic(pandemic::Cmd),
FinishRemoteTrip(TripID),
SeedBus(BusRouteID),
StartBus(BusRouteID, Time),
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]

View File

@ -228,7 +228,13 @@ impl Sim {
self.parking.add_parked_car(ParkedCar { vehicle, spot });
}
pub(crate) fn seed_bus_route(&mut self, route: &BusRoute, map: &Map) {
pub(crate) fn seed_bus_route(&mut self, route: &BusRoute) {
for t in &route.spawn_times {
self.scheduler.push(*t, Command::StartBus(route.id, *t));
}
}
fn start_bus(&mut self, route: &BusRoute, map: &Map) {
// Spawn one bus for the first leg.
let (req, path) = self.transit.create_empty_route(route, map);
@ -272,10 +278,6 @@ impl Sim {
true,
),
);
// TODO Change the rate of spawning based on a schedule from GTFS or player's choice
self.scheduler
.push(self.time + Duration::hours(1), Command::SeedBus(route.id));
}
pub fn set_name(&mut self, name: String) {
@ -571,8 +573,8 @@ impl Sim {
&mut self.scheduler,
);
}
Command::SeedBus(r) => {
self.seed_bus_route(map.get_br(r), map);
Command::StartBus(r, _) => {
self.start_bus(map.get_br(r), map);
}
}