mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-25 11:44:25 +03:00
prebaking bus arrivals, and adding a comparison
This commit is contained in:
parent
7eeebb72ec
commit
33e2c3a2fe
@ -7,8 +7,9 @@ use ezgui::{
|
||||
VerticalAlignment,
|
||||
};
|
||||
use geom::{Duration, DurationHistogram, DurationStats};
|
||||
use map_model::{BusRouteID, BusStopID};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use sim::{Sim, SimFlags, SimOptions, TripMode};
|
||||
use sim::{CarID, Sim, SimFlags, SimOptions, TripMode};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
// TODO Also have some kind of screenshot to display for each challenge
|
||||
@ -153,6 +154,7 @@ pub fn prebake() {
|
||||
let results = PrebakedResults {
|
||||
faster_trips: FasterTrips::from(&sim),
|
||||
gridlock_delays: GridlockDelays::from(&sim),
|
||||
bus_arrivals: BusArrivals::from(&sim),
|
||||
};
|
||||
abstutil::write_json("../data/prebaked_results.json", &results).unwrap();
|
||||
}
|
||||
@ -160,15 +162,16 @@ pub fn prebake() {
|
||||
// TODO Something more general?
|
||||
// - key by GameplayMode (which needs map name too maybe)
|
||||
// - different baselines/benchmarks
|
||||
// TODO Actually, can we just store sim Analytics, and move all of this derived stuff there?
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PrebakedResults {
|
||||
pub faster_trips: FasterTrips,
|
||||
pub gridlock_delays: GridlockDelays,
|
||||
pub bus_arrivals: BusArrivals,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FasterTrips(pub Vec<(Duration, Option<TripMode>, Duration)>);
|
||||
|
||||
impl FasterTrips {
|
||||
pub fn from(sim: &Sim) -> FasterTrips {
|
||||
FasterTrips(sim.get_analytics().finished_trips.clone())
|
||||
@ -201,13 +204,48 @@ impl FasterTrips {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct BusArrivals(pub Vec<(Duration, CarID, BusRouteID, BusStopID)>);
|
||||
impl BusArrivals {
|
||||
pub fn from(sim: &Sim) -> BusArrivals {
|
||||
BusArrivals(sim.get_analytics().bus_arrivals.clone())
|
||||
}
|
||||
|
||||
pub fn to_stats(&self, r: BusRouteID, now: Duration) -> BTreeMap<BusStopID, DurationStats> {
|
||||
let mut per_bus: BTreeMap<CarID, Vec<(Duration, BusStopID)>> = BTreeMap::new();
|
||||
for (t, car, route, stop) in &self.0 {
|
||||
if *t > now {
|
||||
break;
|
||||
}
|
||||
if *route == r {
|
||||
per_bus
|
||||
.entry(*car)
|
||||
.or_insert_with(Vec::new)
|
||||
.push((*t, *stop));
|
||||
}
|
||||
}
|
||||
let mut delay_to_stop: BTreeMap<BusStopID, DurationHistogram> = BTreeMap::new();
|
||||
for events in per_bus.values() {
|
||||
for pair in events.windows(2) {
|
||||
delay_to_stop
|
||||
.entry(pair[1].1)
|
||||
.or_insert_with(DurationHistogram::new)
|
||||
.add(pair[1].0 - pair[0].0);
|
||||
}
|
||||
}
|
||||
delay_to_stop
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.to_stats()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct GridlockDelays {
|
||||
pub lt_1m: usize,
|
||||
pub lt_5m: usize,
|
||||
pub stuck: usize,
|
||||
}
|
||||
|
||||
impl GridlockDelays {
|
||||
pub fn from(sim: &Sim) -> GridlockDelays {
|
||||
let mut delays = GridlockDelays {
|
||||
|
@ -1,14 +1,13 @@
|
||||
use crate::challenges::{FasterTrips, GridlockDelays, PrebakedResults};
|
||||
use crate::challenges::{BusArrivals, FasterTrips, GridlockDelays, PrebakedResults};
|
||||
use crate::game::{msg, Transition, WizardState};
|
||||
use crate::render::AgentColorScheme;
|
||||
use crate::sandbox::{analytics, bus_explorer, spawner, SandboxMode};
|
||||
use crate::ui::UI;
|
||||
use abstutil::{prettyprint_usize, Timer};
|
||||
use ezgui::{hotkey, Choice, Color, EventCtx, GfxCtx, Key, Line, ModalMenu, Text, Wizard};
|
||||
use geom::{Duration, DurationHistogram, Statistic};
|
||||
use map_model::{BusRouteID, BusStopID};
|
||||
use sim::{CarID, Scenario, TripMode};
|
||||
use std::collections::BTreeMap;
|
||||
use geom::{Duration, Statistic};
|
||||
use map_model::BusRouteID;
|
||||
use sim::{Scenario, TripMode};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum GameplayMode {
|
||||
@ -261,7 +260,8 @@ impl GameplayState {
|
||||
// TODO Expensive
|
||||
if *time != ui.primary.sim.time() {
|
||||
*time = ui.primary.sim.time();
|
||||
self.menu.set_info(ctx, bus_route_panel(route, ui, *stat));
|
||||
self.menu
|
||||
.set_info(ctx, bus_route_panel(route, ui, *stat, &self.prebaked));
|
||||
}
|
||||
|
||||
if self.menu.action("change statistic") {
|
||||
@ -356,25 +356,9 @@ impl GameplayState {
|
||||
}
|
||||
}
|
||||
|
||||
fn bus_route_panel(id: BusRouteID, ui: &UI, stat: Statistic) -> Text {
|
||||
let mut per_bus: BTreeMap<CarID, Vec<(Duration, BusStopID)>> = BTreeMap::new();
|
||||
for (t, car, route, stop) in &ui.primary.sim.get_analytics().bus_arrivals {
|
||||
if *route == id {
|
||||
per_bus
|
||||
.entry(*car)
|
||||
.or_insert_with(Vec::new)
|
||||
.push((*t, *stop));
|
||||
}
|
||||
}
|
||||
let mut delay_to_stop: BTreeMap<BusStopID, DurationHistogram> = BTreeMap::new();
|
||||
for events in per_bus.values() {
|
||||
for pair in events.windows(2) {
|
||||
delay_to_stop
|
||||
.entry(pair[1].1)
|
||||
.or_insert_with(DurationHistogram::new)
|
||||
.add(pair[1].0 - pair[0].0);
|
||||
}
|
||||
}
|
||||
fn bus_route_panel(id: BusRouteID, ui: &UI, stat: Statistic, prebaked: &PrebakedResults) -> Text {
|
||||
let now = BusArrivals::from(&ui.primary.sim).to_stats(id, ui.primary.sim.time());
|
||||
let baseline = prebaked.bus_arrivals.to_stats(id, ui.primary.sim.time());
|
||||
|
||||
let route = ui.primary.map.get_br(id);
|
||||
let mut txt = Text::new();
|
||||
@ -385,9 +369,24 @@ fn bus_route_panel(id: BusRouteID, ui: &UI, stat: Statistic) -> Text {
|
||||
} else {
|
||||
idx1 + 1
|
||||
};
|
||||
// TODO Also display number of arrivals...
|
||||
txt.add(Line(format!("Stop {}->{}: ", idx1 + 1, idx2 + 1)));
|
||||
if let Some(ref distrib) = delay_to_stop.get(&route.stops[idx2]) {
|
||||
txt.append(Line(distrib.select(stat).minimal_tostring()));
|
||||
if let Some(ref stats1) = now.get(&route.stops[idx2]) {
|
||||
let us = stats1.stats[&stat];
|
||||
txt.append(Line(us.minimal_tostring()));
|
||||
|
||||
if let Some(ref stats2) = baseline.get(&route.stops[idx2]) {
|
||||
let vs = stats2.stats[&stat];
|
||||
if us <= vs {
|
||||
txt.append(Line(" ("));
|
||||
txt.append(Line((vs - us).minimal_tostring()).fg(Color::GREEN));
|
||||
txt.append(Line(" faster)"));
|
||||
} else {
|
||||
txt.append(Line(" ("));
|
||||
txt.append(Line((us - vs).minimal_tostring()).fg(Color::RED));
|
||||
txt.append(Line(" slower)"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
txt.append(Line("no arrivals yet"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user