mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
displaying different bus arrival info, and experimenting with storing the data differently. no prebaking yet.
This commit is contained in:
parent
8d32671834
commit
7eeebb72ec
@ -182,7 +182,7 @@ impl FasterTrips {
|
||||
TripMode::Transit,
|
||||
TripMode::Drive,
|
||||
] {
|
||||
distribs.insert(m, Default::default());
|
||||
distribs.insert(m, DurationHistogram::new());
|
||||
}
|
||||
for (t, mode, dt) in &self.0 {
|
||||
if *t > now {
|
||||
|
@ -3,7 +3,8 @@ use crate::game::{State, Transition};
|
||||
use crate::helpers::ID;
|
||||
use crate::ui::UI;
|
||||
use ezgui::{hotkey, Color, EventCtx, GfxCtx, Key, Line, ModalMenu, Text};
|
||||
use geom::DurationHistogram;
|
||||
use geom::Duration;
|
||||
use sim::CarID;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub struct InfoPanel {
|
||||
@ -205,20 +206,21 @@ fn info_for(id: ID, ui: &UI, ctx: &EventCtx) -> Text {
|
||||
styled_kv(&mut txt, &draw_map.get_es(id).attributes);
|
||||
}
|
||||
ID::BusStop(id) => {
|
||||
let arrivals = &sim.get_analytics().bus_arrivals;
|
||||
let all_arrivals = &sim.get_analytics().bus_arrivals;
|
||||
let passengers = &sim.get_analytics().total_bus_passengers;
|
||||
for r in map.get_routes_serving_stop(id) {
|
||||
txt.add_appended(vec![Line("- Route "), Line(&r.name).fg(name_color)]);
|
||||
if let Some(ref times) = arrivals.get(&(id, r.id)) {
|
||||
let arrivals: Vec<(Duration, CarID)> = all_arrivals
|
||||
.iter()
|
||||
.filter(|(_, _, route, stop)| r.id == *route && id == *stop)
|
||||
.map(|(t, car, _, _)| (*t, *car))
|
||||
.collect();
|
||||
if let Some((t, car)) = arrivals.last() {
|
||||
txt.add(Line(format!(
|
||||
" Last bus arrived {} ago",
|
||||
(sim.time() - *times.last().unwrap()).minimal_tostring()
|
||||
" Last bus arrived {} ago ({})",
|
||||
(sim.time() - *t).minimal_tostring(),
|
||||
car
|
||||
)));
|
||||
let mut distrib: DurationHistogram = Default::default();
|
||||
for pair in times.windows(2) {
|
||||
distrib.add(pair[1] - pair[0]);
|
||||
}
|
||||
txt.add(Line(format!(" All arrivals: {}", distrib.describe())));
|
||||
} else {
|
||||
txt.add(Line(" No arrivals yet"));
|
||||
}
|
||||
|
@ -6,8 +6,9 @@ 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;
|
||||
use sim::{Scenario, TripMode};
|
||||
use map_model::{BusRouteID, BusStopID};
|
||||
use sim::{CarID, Scenario, TripMode};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum GameplayMode {
|
||||
@ -356,22 +357,37 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
let route = ui.primary.map.get_br(id);
|
||||
let arrivals = &ui.primary.sim.get_analytics().bus_arrivals;
|
||||
let mut txt = Text::new();
|
||||
txt.add(Line(format!("{} frequency stop is visited", stat)));
|
||||
for (idx, stop) in route.stops.iter().enumerate() {
|
||||
txt.add(Line(format!("Stop {}: ", idx + 1)));
|
||||
if let Some(ref times) = arrivals.get(&(*stop, route.id)) {
|
||||
if times.len() < 2 {
|
||||
txt.append(Line("only one arrival so far"));
|
||||
} else {
|
||||
let mut distrib: DurationHistogram = Default::default();
|
||||
for pair in times.windows(2) {
|
||||
distrib.add(pair[1] - pair[0]);
|
||||
}
|
||||
txt.append(Line(distrib.select(stat).minimal_tostring()));
|
||||
}
|
||||
txt.add(Line(format!("{} delay between stops", stat)));
|
||||
for idx1 in 0..route.stops.len() {
|
||||
let idx2 = if idx1 == route.stops.len() - 1 {
|
||||
0
|
||||
} else {
|
||||
idx1 + 1
|
||||
};
|
||||
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()));
|
||||
} else {
|
||||
txt.append(Line("no arrivals yet"));
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ impl Scoreboard {
|
||||
.sorted_by_key(|(_, m, _)| *m)
|
||||
.group_by(|(_, m, _)| *m)
|
||||
{
|
||||
let mut distrib: DurationHistogram = std::default::Default::default();
|
||||
let mut distrib: DurationHistogram = DurationHistogram::new();
|
||||
for (_, _, dt) in trips {
|
||||
distrib.add(dt);
|
||||
}
|
||||
|
@ -282,6 +282,10 @@ impl Default for DurationHistogram {
|
||||
}
|
||||
|
||||
impl DurationHistogram {
|
||||
pub fn new() -> DurationHistogram {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn add(&mut self, t: Duration) {
|
||||
if self.count == 0 {
|
||||
self.min = t;
|
||||
|
@ -1,15 +1,15 @@
|
||||
use crate::{Event, TripMode};
|
||||
use crate::{CarID, Event, TripMode};
|
||||
use abstutil::Counter;
|
||||
use geom::Duration;
|
||||
use map_model::{BusRouteID, BusStopID, IntersectionID, Map, RoadID, Traversable};
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
// Embed a deeper structure with its own impl when that makes sense, or feel free to just inline
|
||||
// things.
|
||||
pub struct Analytics {
|
||||
pub thruput_stats: ThruputStats,
|
||||
pub(crate) test_expectations: VecDeque<Event>,
|
||||
pub bus_arrivals: HashMap<(BusStopID, BusRouteID), Vec<Duration>>,
|
||||
pub bus_arrivals: Vec<(Duration, CarID, BusRouteID, BusStopID)>,
|
||||
pub total_bus_passengers: Counter<BusRouteID>,
|
||||
// TODO Hack: No TripMode means aborted
|
||||
// Finish time, mode (or None as aborted), trip duration
|
||||
@ -29,7 +29,7 @@ impl Default for Analytics {
|
||||
count_per_intersection: Counter::new(),
|
||||
},
|
||||
test_expectations: VecDeque::new(),
|
||||
bus_arrivals: HashMap::new(),
|
||||
bus_arrivals: Vec::new(),
|
||||
total_bus_passengers: Counter::new(),
|
||||
finished_trips: Vec::new(),
|
||||
}
|
||||
@ -53,11 +53,8 @@ impl Analytics {
|
||||
}
|
||||
|
||||
// Bus arrivals
|
||||
if let Event::BusArrivedAtStop(_, route, stop) = ev {
|
||||
self.bus_arrivals
|
||||
.entry((stop, route))
|
||||
.or_insert(Vec::new())
|
||||
.push(time);
|
||||
if let Event::BusArrivedAtStop(bus, route, stop) = ev {
|
||||
self.bus_arrivals.push((time, bus, route, stop));
|
||||
}
|
||||
|
||||
// Bus passengers
|
||||
|
@ -31,6 +31,7 @@ struct State {
|
||||
deserialize_with = "deserialize_btreemap"
|
||||
)]
|
||||
waiting: BTreeMap<Request, Duration>,
|
||||
// TODO Can we move this to analytics?
|
||||
#[derivative(PartialEq = "ignore")]
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
delays: DurationHistogram,
|
||||
@ -55,7 +56,7 @@ impl IntersectionSimState {
|
||||
id: i.id,
|
||||
accepted: BTreeSet::new(),
|
||||
waiting: BTreeMap::new(),
|
||||
delays: std::default::Default::default(),
|
||||
delays: DurationHistogram::new(),
|
||||
},
|
||||
);
|
||||
if i.is_traffic_signal() && !use_freeform_policy_everywhere {
|
||||
|
@ -94,7 +94,7 @@ impl Scheduler {
|
||||
items: BinaryHeap::new(),
|
||||
queued_commands: BTreeMap::new(),
|
||||
latest_time: Duration::ZERO,
|
||||
delta_times: std::default::Default::default(),
|
||||
delta_times: DurationHistogram::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user