mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-03 03:47:23 +03:00
include ongoing trips in measured trip times. adjust wording of
"finished trips" things.
This commit is contained in:
parent
0a7b8adbe1
commit
d56803a12a
@ -208,9 +208,9 @@ f9f0a109966db097617a13122ecaa6f3 data/system/scenarios/downtown/weekday.bin
|
||||
dd54763cfda7fce4c401ae122c6daf57 data/system/scenarios/huge_seattle/weekday.bin
|
||||
47dea892a1c4331da02494d15ce02a02 data/system/scenarios/caphill/weekday.bin
|
||||
7d6a8e8f5d716ce8674ed63d27f2da51 data/system/scenarios/montlake/weekday.bin
|
||||
80be03bcfdbb24d809d53b1ad9105b84 data/system/prebaked_results/23rd/weekday.bin
|
||||
d68c8f3beb5915c359228e38112c970b data/system/prebaked_results/signal_single/tutorial lvl1.bin
|
||||
a6437680221c61b92964c3f376b76809 data/system/prebaked_results/signal_single/tutorial lvl2.bin
|
||||
ffc3199512974f67299bfa2a262df6c6 data/system/prebaked_results/montlake/car vs bike contention.bin
|
||||
b21a3366793c9295a8c6b6050eac778f data/system/prebaked_results/montlake/weekday.bin
|
||||
0c0bade4ea0fe2fd1d31278a0f8fb3eb data/system/prebaked_results/montlake/car vs bus contention.bin
|
||||
7dfe19826f9c24e47b64ea973dbabf9c data/system/prebaked_results/23rd/weekday.bin
|
||||
e5b494a5e969951ea63a19ab932801f8 data/system/prebaked_results/signal_single/tutorial lvl1.bin
|
||||
08c2771c555f7e52ed0c89c511248f99 data/system/prebaked_results/signal_single/tutorial lvl2.bin
|
||||
460bd68fcc0c4686db7d654de372f46d data/system/prebaked_results/montlake/car vs bike contention.bin
|
||||
f3d268e6c1a4b868e4006453b293236b data/system/prebaked_results/montlake/weekday.bin
|
||||
2a3e97b847acfc9d6e381354e7dc46f7 data/system/prebaked_results/montlake/car vs bus contention.bin
|
||||
|
@ -24,7 +24,7 @@ pub enum Overlays {
|
||||
BikeNetwork(Colorer),
|
||||
BusNetwork(Colorer),
|
||||
Edits(Colorer),
|
||||
FinishedTripsHistogram(Time, Composite),
|
||||
TripsHistogram(Time, Composite),
|
||||
|
||||
// These aren't selectable from the main picker
|
||||
IntersectionDemand(Time, IntersectionID, Drawable, Composite),
|
||||
@ -58,9 +58,9 @@ impl Overlays {
|
||||
ui.overlay = Overlays::intersection_demand(i, ctx, ui);
|
||||
}
|
||||
}
|
||||
Overlays::FinishedTripsHistogram(t, _) => {
|
||||
Overlays::TripsHistogram(t, _) => {
|
||||
if now != t {
|
||||
ui.overlay = Overlays::finished_trips_histogram(ctx, ui);
|
||||
ui.overlay = Overlays::trips_histogram(ctx, ui);
|
||||
}
|
||||
}
|
||||
Overlays::BusRoute(t, id, _) => {
|
||||
@ -154,7 +154,7 @@ impl Overlays {
|
||||
}
|
||||
}
|
||||
}
|
||||
Overlays::FinishedTripsHistogram(_, ref mut c)
|
||||
Overlays::TripsHistogram(_, ref mut c)
|
||||
| Overlays::BusDelaysOverTime(_, _, ref mut c) => {
|
||||
c.align_above(ctx, minimap);
|
||||
match c.event(ctx) {
|
||||
@ -186,7 +186,7 @@ impl Overlays {
|
||||
| Overlays::Edits(ref heatmap) => {
|
||||
heatmap.draw(g);
|
||||
}
|
||||
Overlays::FinishedTripsHistogram(_, ref composite)
|
||||
Overlays::TripsHistogram(_, ref composite)
|
||||
| Overlays::BusDelaysOverTime(_, _, ref composite) => {
|
||||
composite.draw(g);
|
||||
}
|
||||
@ -219,7 +219,7 @@ impl Overlays {
|
||||
pub fn change_overlays(ctx: &mut EventCtx, ui: &UI) -> Option<Transition> {
|
||||
let mut choices = vec![
|
||||
WrappedComposite::text_button(ctx, "None", hotkey(Key::N)),
|
||||
WrappedComposite::text_button(ctx, "finished trips histogram", hotkey(Key::F)),
|
||||
WrappedComposite::text_button(ctx, "trip times histogram", hotkey(Key::F)),
|
||||
WrappedComposite::text_button(ctx, "map edits", hotkey(Key::E)),
|
||||
ManagedWidget::btn(Button::rectangle_svg(
|
||||
"../data/system/assets/layers/parking_avail.svg",
|
||||
@ -258,7 +258,7 @@ impl Overlays {
|
||||
)),
|
||||
];
|
||||
if ui.has_prebaked().is_none() {
|
||||
choices.retain(|w| !w.has_name("finished trips histogram"));
|
||||
choices.retain(|w| !w.has_name("trip times histogram"));
|
||||
}
|
||||
// TODO Grey out the inactive SVGs, and add the green checkmark
|
||||
if let Some((find, replace)) = match ui.overlay {
|
||||
@ -284,9 +284,9 @@ impl Overlays {
|
||||
ManagedWidget::draw_svg(ctx, "../data/system/assets/layers/bus_network.svg"),
|
||||
)),
|
||||
Overlays::Edits(_) => Some(("map edits", Button::inactive_button(ctx, "map edits"))),
|
||||
Overlays::FinishedTripsHistogram(_, _) => Some((
|
||||
"finished trips histogram",
|
||||
Button::inactive_button(ctx, "finished trips histogram"),
|
||||
Overlays::TripsHistogram(_, _) => Some((
|
||||
"trip times histogram",
|
||||
Button::inactive_button(ctx, "trip times histogram"),
|
||||
)),
|
||||
_ => None,
|
||||
} {
|
||||
@ -358,9 +358,9 @@ impl Overlays {
|
||||
}),
|
||||
)
|
||||
.maybe_cb(
|
||||
"finished trips histogram",
|
||||
"trip times histogram",
|
||||
Box::new(|ctx, ui| {
|
||||
ui.overlay = Overlays::finished_trips_histogram(ctx, ui);
|
||||
ui.overlay = Overlays::trips_histogram(ctx, ui);
|
||||
Some(Transition::Pop)
|
||||
}),
|
||||
)
|
||||
@ -567,19 +567,19 @@ impl Overlays {
|
||||
Overlays::BusNetwork(colorer.build(ctx, ui))
|
||||
}
|
||||
|
||||
pub fn finished_trips_histogram(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
pub fn trips_histogram(ctx: &mut EventCtx, ui: &UI) -> Overlays {
|
||||
if ui.has_prebaked().is_none() {
|
||||
return Overlays::Inactive;
|
||||
}
|
||||
|
||||
let now = ui.primary.sim.time();
|
||||
Overlays::FinishedTripsHistogram(
|
||||
Overlays::TripsHistogram(
|
||||
now,
|
||||
Composite::new(
|
||||
ManagedWidget::col(vec![
|
||||
ManagedWidget::row(vec![
|
||||
ManagedWidget::draw_text(ctx, {
|
||||
let mut txt = Text::from(Line("Are finished trips "));
|
||||
let mut txt = Text::from(Line("Are trips "));
|
||||
txt.append(Line("faster").fg(Color::GREEN));
|
||||
txt.append(Line(", "));
|
||||
txt.append(Line("slower").fg(Color::RED));
|
||||
@ -595,7 +595,7 @@ impl Overlays {
|
||||
ui.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.finished_trip_deltas(now, ui.prebaked()),
|
||||
.trip_time_deltas(now, ui.prebaked()),
|
||||
ctx,
|
||||
),
|
||||
])
|
||||
|
@ -19,7 +19,7 @@ use std::collections::BTreeMap;
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum Tab {
|
||||
FinishedTripsSummary,
|
||||
TripsSummary,
|
||||
IndividualFinishedTrips(Option<TripMode>),
|
||||
ParkingOverhead,
|
||||
ExploreBusRoute,
|
||||
@ -28,7 +28,7 @@ pub enum Tab {
|
||||
// Oh the dashboards melted, but we still had the radio
|
||||
pub fn make(ctx: &mut EventCtx, ui: &UI, tab: Tab) -> Box<dyn State> {
|
||||
let tab_data = vec![
|
||||
(Tab::FinishedTripsSummary, "Finished trips summary"),
|
||||
(Tab::TripsSummary, "Trips summary"),
|
||||
(
|
||||
Tab::IndividualFinishedTrips(None),
|
||||
"Individual finished trips",
|
||||
@ -50,7 +50,7 @@ pub fn make(ctx: &mut EventCtx, ui: &UI, tab: Tab) -> Box<dyn State> {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let (content, cbs) = match tab {
|
||||
Tab::FinishedTripsSummary => (finished_trips_summary_prebaked(ctx, ui), Vec::new()),
|
||||
Tab::TripsSummary => (trips_summary_prebaked(ctx, ui), Vec::new()),
|
||||
Tab::IndividualFinishedTrips(None) => pick_finished_trips_mode(ctx),
|
||||
Tab::IndividualFinishedTrips(Some(m)) => pick_finished_trips(m, ctx, ui),
|
||||
Tab::ParkingOverhead => (parking_overhead(ctx, ui), Vec::new()),
|
||||
@ -91,25 +91,26 @@ pub fn make(ctx: &mut EventCtx, ui: &UI, tab: Tab) -> Box<dyn State> {
|
||||
ManagedGUIState::fullscreen(c)
|
||||
}
|
||||
|
||||
fn finished_trips_summary_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
fn trips_summary_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
if ui.has_prebaked().is_none() {
|
||||
return finished_trips_summary_not_prebaked(ctx, ui);
|
||||
return trips_summary_not_prebaked(ctx, ui);
|
||||
}
|
||||
|
||||
let (now_all, now_aborted, now_per_mode) = ui
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.all_finished_trips(ui.primary.sim.time());
|
||||
.trip_times(ui.primary.sim.time());
|
||||
let (baseline_all, baseline_aborted, baseline_per_mode) =
|
||||
ui.prebaked().all_finished_trips(ui.primary.sim.time());
|
||||
ui.prebaked().trip_times(ui.primary.sim.time());
|
||||
|
||||
// TODO Include unfinished count
|
||||
let mut txt = Text::new();
|
||||
txt.add_appended(vec![
|
||||
Line("Finished trips as of "),
|
||||
Line(ui.primary.sim.time().ampm_tostring()).fg(Color::CYAN),
|
||||
Line("Trips as of "),
|
||||
Line(ui.primary.sim.time().ampm_tostring()).roboto_bold(),
|
||||
]);
|
||||
txt.highlight_last_line(Color::BLUE);
|
||||
txt.add_appended(vec![
|
||||
Line(format!(
|
||||
"{} aborted trips (",
|
||||
@ -121,7 +122,7 @@ fn finished_trips_summary_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
// TODO Refactor
|
||||
txt.add_appended(vec![
|
||||
Line(format!(
|
||||
"{} total finished trips (",
|
||||
"{} total trips (",
|
||||
prettyprint_usize(now_all.count())
|
||||
)),
|
||||
cmp_count_more(now_all.count(), baseline_all.count()),
|
||||
@ -129,7 +130,8 @@ fn finished_trips_summary_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
]);
|
||||
if now_all.count() > 0 && baseline_all.count() > 0 {
|
||||
for stat in Statistic::all() {
|
||||
txt.add(Line(format!(" {}: {} (", stat, now_all.select(stat))));
|
||||
// TODO Ideally we could indent
|
||||
txt.add(Line(format!("{}: {} (", stat, now_all.select(stat))));
|
||||
txt.append_all(cmp_duration_shorter(
|
||||
now_all.select(stat),
|
||||
baseline_all.select(stat),
|
||||
@ -146,9 +148,10 @@ fn finished_trips_summary_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
cmp_count_more(a.count(), b.count()),
|
||||
Line(")"),
|
||||
]);
|
||||
txt.highlight_last_line(Color::BLUE);
|
||||
if a.count() > 0 && b.count() > 0 {
|
||||
for stat in Statistic::all() {
|
||||
txt.add(Line(format!(" {}: {} (", stat, a.select(stat))));
|
||||
txt.add(Line(format!("{}: {} (", stat, a.select(stat))));
|
||||
txt.append_all(cmp_duration_shorter(a.select(stat), b.select(stat)));
|
||||
txt.append(Line(")"));
|
||||
}
|
||||
@ -160,45 +163,44 @@ fn finished_trips_summary_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
finished_trips_plot(ctx, ui).bg(colors::SECTION_BG),
|
||||
ManagedWidget::draw_text(
|
||||
ctx,
|
||||
Text::from(Line(
|
||||
"Are finished trips faster or slower than the baseline?",
|
||||
)),
|
||||
Text::from(Line("Are trips faster or slower than the baseline?")),
|
||||
),
|
||||
Histogram::new(
|
||||
ui.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.finished_trip_deltas(ui.primary.sim.time(), ui.prebaked()),
|
||||
.trip_time_deltas(ui.primary.sim.time(), ui.prebaked()),
|
||||
ctx,
|
||||
)
|
||||
.bg(colors::SECTION_BG),
|
||||
])
|
||||
}
|
||||
|
||||
fn finished_trips_summary_not_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
fn trips_summary_not_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
|
||||
let (all, aborted, per_mode) = ui
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.all_finished_trips(ui.primary.sim.time());
|
||||
.trip_times(ui.primary.sim.time());
|
||||
|
||||
// TODO Include unfinished count
|
||||
let mut txt = Text::new();
|
||||
txt.add_appended(vec![
|
||||
Line("Finished trips as of "),
|
||||
Line(ui.primary.sim.time().ampm_tostring()).fg(Color::CYAN),
|
||||
Line("Trips as of "),
|
||||
Line(ui.primary.sim.time().ampm_tostring()).roboto_bold(),
|
||||
]);
|
||||
txt.highlight_last_line(Color::BLUE);
|
||||
txt.add(Line(format!(
|
||||
" {} aborted trips",
|
||||
"{} aborted trips",
|
||||
prettyprint_usize(aborted)
|
||||
)));
|
||||
txt.add(Line(format!(
|
||||
"{} total finished trips",
|
||||
"{} total trips",
|
||||
prettyprint_usize(all.count())
|
||||
)));
|
||||
if all.count() > 0 {
|
||||
for stat in Statistic::all() {
|
||||
txt.add(Line(format!(" {}: {}", stat, all.select(stat))));
|
||||
txt.add(Line(format!("{}: {}", stat, all.select(stat))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,9 +211,10 @@ fn finished_trips_summary_not_prebaked(ctx: &EventCtx, ui: &UI) -> ManagedWidget
|
||||
prettyprint_usize(a.count()),
|
||||
mode
|
||||
)));
|
||||
txt.highlight_last_line(Color::BLUE);
|
||||
if a.count() > 0 {
|
||||
for stat in Statistic::all() {
|
||||
txt.add(Line(format!(" {}: {}", stat, a.select(stat))));
|
||||
txt.add(Line(format!("{}: {}", stat, a.select(stat))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,14 +76,13 @@ fn gridlock_panel(ui: &UI) -> Text {
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.all_finished_trips(ui.primary.sim.time());
|
||||
let (baseline_all, _, baseline_per_mode) =
|
||||
ui.prebaked().all_finished_trips(ui.primary.sim.time());
|
||||
.trip_times(ui.primary.sim.time());
|
||||
let (baseline_all, _, baseline_per_mode) = ui.prebaked().trip_times(ui.primary.sim.time());
|
||||
|
||||
let mut txt = Text::new();
|
||||
txt.add_appended(vec![
|
||||
Line(format!(
|
||||
"{} total finished trips (",
|
||||
"{} total trips (",
|
||||
prettyprint_usize(now_all.count())
|
||||
)),
|
||||
cmp_count_fewer(now_all.count(), baseline_all.count()),
|
||||
|
@ -65,8 +65,15 @@ impl GameplayState for FasterTrips {
|
||||
|
||||
pub fn faster_trips_panel(mode: TripMode, ui: &UI) -> Text {
|
||||
let time = ui.primary.sim.time();
|
||||
let now = ui.primary.sim.get_analytics().finished_trips(time, mode);
|
||||
let baseline = ui.prebaked().finished_trips(time, mode);
|
||||
let now = ui
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.trip_times(time)
|
||||
.2
|
||||
.remove(&mode)
|
||||
.unwrap();
|
||||
let baseline = ui.prebaked().trip_times(time).2.remove(&mode).unwrap();
|
||||
|
||||
// Enable to debug why sim results don't match prebaked.
|
||||
if false && !now.seems_eq(&baseline) {
|
||||
@ -88,7 +95,7 @@ pub fn faster_trips_panel(mode: TripMode, ui: &UI) -> Text {
|
||||
let mut txt = Text::new();
|
||||
txt.add_appended(vec![
|
||||
Line(format!(
|
||||
"{} finished {} trips (",
|
||||
"{} {} trips (",
|
||||
prettyprint_usize(now.count()),
|
||||
mode
|
||||
)),
|
||||
|
@ -42,7 +42,7 @@ impl GameplayState for FixTrafficSignals {
|
||||
) -> (Option<Transition>, bool) {
|
||||
// Once is never...
|
||||
if self.once {
|
||||
ui.overlay = Overlays::finished_trips_histogram(ctx, ui);
|
||||
ui.overlay = Overlays::trips_histogram(ctx, ui);
|
||||
self.once = false;
|
||||
}
|
||||
|
||||
@ -86,14 +86,10 @@ fn final_score(ui: &UI) -> String {
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.all_finished_trips(time)
|
||||
.0
|
||||
.select(Statistic::Mean);
|
||||
let baseline = ui
|
||||
.prebaked()
|
||||
.all_finished_trips(time)
|
||||
.trip_times(time)
|
||||
.0
|
||||
.select(Statistic::Mean);
|
||||
let baseline = ui.prebaked().trip_times(time).0.select(Statistic::Mean);
|
||||
|
||||
if now < baseline - GOAL {
|
||||
format!(
|
||||
|
@ -387,7 +387,7 @@ impl GameplayState for Tutorial {
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.all_finished_trips(ui.primary.sim.time());
|
||||
.trip_times(ui.primary.sim.time());
|
||||
let max = all.select(Statistic::Max);
|
||||
|
||||
if !tut.score_delivered {
|
||||
|
@ -395,7 +395,7 @@ impl AgentMeter {
|
||||
ManagedWidget::draw_text(ctx, txt)
|
||||
},
|
||||
// TODO The SVG button uses clip and doesn't seem to work
|
||||
WrappedComposite::text_button(ctx, "finished trip data", hotkey(Key::Q)),
|
||||
WrappedComposite::text_button(ctx, "finished trips data", hotkey(Key::Q)),
|
||||
];
|
||||
// TODO Slight hack. If we're jumping right into a tutorial and don't have the prebaked
|
||||
// stuff loaded yet, just skip a tick.
|
||||
@ -405,8 +405,8 @@ impl AgentMeter {
|
||||
.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.all_finished_trips(ui.primary.sim.time());
|
||||
let (baseline, _, _) = ui.prebaked().all_finished_trips(ui.primary.sim.time());
|
||||
.trip_times(ui.primary.sim.time());
|
||||
let (baseline, _, _) = ui.prebaked().trip_times(ui.primary.sim.time());
|
||||
let mut txt = Text::from(Line(format!("{} trip time: ", stat)).size(20));
|
||||
if now.count() > 0 && baseline.count() > 0 {
|
||||
txt.append_all(cmp_duration_shorter(
|
||||
@ -439,11 +439,11 @@ impl AgentMeter {
|
||||
}
|
||||
match self.composite.event(ctx) {
|
||||
Some(Outcome::Clicked(x)) => match x.as_ref() {
|
||||
"finished trip data" => {
|
||||
"finished trips data" => {
|
||||
return Some(Transition::Push(dashboards::make(
|
||||
ctx,
|
||||
ui,
|
||||
dashboards::Tab::FinishedTripsSummary,
|
||||
dashboards::Tab::TripsSummary,
|
||||
)));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -15,6 +15,8 @@ pub struct Analytics {
|
||||
pub(crate) test_expectations: VecDeque<Event>,
|
||||
pub bus_arrivals: Vec<(Time, CarID, BusRouteID, BusStopID)>,
|
||||
pub bus_passengers_waiting: Vec<(Time, BusStopID, BusRouteID)>,
|
||||
// TODO Scraping TripMode from TripPhaseStarting is frustrating.
|
||||
pub started_trips: BTreeMap<TripID, (Time, TripMode)>,
|
||||
// TODO Hack: No TripMode means aborted
|
||||
// Finish time, ID, mode (or None as aborted), trip duration
|
||||
pub finished_trips: Vec<(Time, TripID, Option<TripMode>, Duration)>,
|
||||
@ -55,6 +57,7 @@ impl Analytics {
|
||||
test_expectations: VecDeque::new(),
|
||||
bus_arrivals: Vec::new(),
|
||||
bus_passengers_waiting: Vec::new(),
|
||||
started_trips: BTreeMap::new(),
|
||||
finished_trips: Vec::new(),
|
||||
trip_log: Vec::new(),
|
||||
intersection_delays: BTreeMap::new(),
|
||||
@ -112,6 +115,19 @@ impl Analytics {
|
||||
self.bus_passengers_waiting.push((time, stop, route));
|
||||
}
|
||||
|
||||
// Started trips
|
||||
if let Event::TripPhaseStarting(id, mode, _, _) = ev {
|
||||
// TODO More efficiently
|
||||
if !self.started_trips.contains_key(&id)
|
||||
&& !self
|
||||
.finished_trips
|
||||
.iter()
|
||||
.any(|(_, trip, _, _)| *trip == id)
|
||||
{
|
||||
self.started_trips.insert(id, (time, mode));
|
||||
}
|
||||
}
|
||||
|
||||
// Finished trips
|
||||
if let Event::TripFinished(id, mode, dt) = ev {
|
||||
self.finished_trips.push((time, id, Some(mode), dt));
|
||||
@ -129,7 +145,7 @@ impl Analytics {
|
||||
|
||||
// TODO Kinda hacky, but these all consume the event, so kinda bundle em.
|
||||
match ev {
|
||||
Event::TripPhaseStarting(id, maybe_req, metadata) => {
|
||||
Event::TripPhaseStarting(id, _, maybe_req, metadata) => {
|
||||
self.trip_log.push((time, id, maybe_req, metadata));
|
||||
}
|
||||
Event::TripAborted(id) => {
|
||||
@ -160,21 +176,9 @@ impl Analytics {
|
||||
// TODO If these ever need to be speeded up, just cache the histogram and index in the events
|
||||
// list.
|
||||
|
||||
pub fn finished_trips(&self, now: Time, mode: TripMode) -> DurationHistogram {
|
||||
let mut distrib = DurationHistogram::new();
|
||||
for (t, _, m, dt) in &self.finished_trips {
|
||||
if *t > now {
|
||||
break;
|
||||
}
|
||||
if *m == Some(mode) {
|
||||
distrib.add(*dt);
|
||||
}
|
||||
}
|
||||
distrib
|
||||
}
|
||||
|
||||
// Returns (all trips except aborted, number of aborted trips, trips by mode)
|
||||
pub fn all_finished_trips(
|
||||
// Returns (all trips except aborted, number of aborted trips, trips by mode). For completed
|
||||
// and ongoing trips as of now.
|
||||
pub fn trip_times(
|
||||
&self,
|
||||
now: Time,
|
||||
) -> (
|
||||
@ -182,16 +186,18 @@ impl Analytics {
|
||||
usize,
|
||||
BTreeMap<TripMode, DurationHistogram>,
|
||||
) {
|
||||
let mut ongoing = self.started_trips.clone();
|
||||
let mut per_mode = TripMode::all()
|
||||
.into_iter()
|
||||
.map(|m| (m, DurationHistogram::new()))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
let mut all = DurationHistogram::new();
|
||||
let mut num_aborted = 0;
|
||||
for (t, _, m, dt) in &self.finished_trips {
|
||||
for (t, id, m, dt) in &self.finished_trips {
|
||||
if *t > now {
|
||||
break;
|
||||
}
|
||||
ongoing.remove(id);
|
||||
if let Some(mode) = *m {
|
||||
all.add(*dt);
|
||||
per_mode.get_mut(&mode).unwrap().add(*dt);
|
||||
@ -199,35 +205,42 @@ impl Analytics {
|
||||
num_aborted += 1;
|
||||
}
|
||||
}
|
||||
for (_, (start, m)) in ongoing {
|
||||
if start < now {
|
||||
all.add(now - start);
|
||||
per_mode.get_mut(&m).unwrap().add(now - start);
|
||||
}
|
||||
}
|
||||
(all, num_aborted, per_mode)
|
||||
}
|
||||
|
||||
// Returns unsorted list of deltas, one for each trip finished in both worlds. Positive dt
|
||||
// means faster.
|
||||
pub fn finished_trip_deltas(&self, now: Time, baseline: &Analytics) -> Vec<Duration> {
|
||||
let a: BTreeMap<TripID, Duration> = self
|
||||
.finished_trips
|
||||
.iter()
|
||||
.filter_map(|(t, id, mode, dt)| {
|
||||
if *t <= now && mode.is_some() {
|
||||
Some((*id, *dt))
|
||||
} else {
|
||||
None
|
||||
// Returns unsorted list of deltas, one for each trip finished or ongoing in both worlds.
|
||||
// Positive dt means faster.
|
||||
pub fn trip_time_deltas(&self, now: Time, baseline: &Analytics) -> Vec<Duration> {
|
||||
fn trip_times(a: &Analytics, now: Time) -> BTreeMap<TripID, Duration> {
|
||||
let mut ongoing = a.started_trips.clone();
|
||||
let mut trips = BTreeMap::new();
|
||||
for (t, id, m, dt) in &a.finished_trips {
|
||||
if *t > now {
|
||||
break;
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let b: BTreeMap<TripID, Duration> = baseline
|
||||
.finished_trips
|
||||
.iter()
|
||||
.filter_map(|(t, id, mode, dt)| {
|
||||
if *t <= now && mode.is_some() {
|
||||
Some((*id, *dt))
|
||||
} else {
|
||||
None
|
||||
ongoing.remove(id);
|
||||
if m.is_some() {
|
||||
trips.insert(*id, *dt);
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
for (trip, (start, _)) in ongoing {
|
||||
if start < now {
|
||||
trips.insert(trip, now - start);
|
||||
}
|
||||
}
|
||||
trips
|
||||
}
|
||||
|
||||
let a = trip_times(&self, now);
|
||||
let b = trip_times(baseline, now);
|
||||
|
||||
// TODO Think through what missing (aborted) in one but not the other means
|
||||
a.into_iter()
|
||||
.filter_map(|(id, dt1)| b.get(&id).map(|dt2| *dt2 - dt1))
|
||||
.collect()
|
||||
|
@ -27,7 +27,7 @@ pub enum Event {
|
||||
|
||||
TripFinished(TripID, TripMode, Duration),
|
||||
TripAborted(TripID),
|
||||
TripPhaseStarting(TripID, Option<PathRequest>, String),
|
||||
TripPhaseStarting(TripID, TripMode, Option<PathRequest>, String),
|
||||
|
||||
// Just use for parking replanning. Not happy about copying the full path in here, but the way
|
||||
// to plumb info into Analytics is Event.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::mechanics::Queue;
|
||||
use crate::{Event, ParkingSimState, ParkingSpot, SidewalkSpot, TripID, Vehicle};
|
||||
use crate::{Event, ParkingSimState, ParkingSpot, SidewalkSpot, TripID, TripMode, Vehicle};
|
||||
use geom::Distance;
|
||||
use map_model::{
|
||||
BuildingID, IntersectionID, LaneID, Map, Path, PathConstraints, PathRequest, PathStep,
|
||||
@ -194,6 +194,7 @@ impl Router {
|
||||
) {
|
||||
events.push(Event::TripPhaseStarting(
|
||||
trip,
|
||||
TripMode::Drive,
|
||||
Some(PathRequest {
|
||||
start: Position::new(current_lane, front),
|
||||
end: new_pos,
|
||||
@ -214,6 +215,7 @@ impl Router {
|
||||
// TODO This path might not be the same as the one found here...
|
||||
events.push(Event::TripPhaseStarting(
|
||||
trip,
|
||||
TripMode::Drive,
|
||||
Some(PathRequest {
|
||||
start: Position::new(current_lane, front),
|
||||
end: new_pos,
|
||||
|
@ -398,6 +398,12 @@ impl Sim {
|
||||
}
|
||||
events.push(Event::TripPhaseStarting(
|
||||
create_car.trip,
|
||||
// TODO sketchy...
|
||||
if create_car.vehicle.id.1 == VehicleType::Car {
|
||||
TripMode::Drive
|
||||
} else {
|
||||
TripMode::Bike
|
||||
},
|
||||
Some(create_car.req.clone()),
|
||||
if create_car.vehicle.id.1 == VehicleType::Car {
|
||||
"driving".to_string()
|
||||
@ -485,6 +491,7 @@ impl Sim {
|
||||
);
|
||||
events.push(Event::TripPhaseStarting(
|
||||
create_ped.trip,
|
||||
TripMode::Walk,
|
||||
Some(create_ped.req.clone()),
|
||||
"walking".to_string(),
|
||||
));
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::{CarID, Event, PedestrianID, Router, Scheduler, TripManager, WalkingSimState};
|
||||
use crate::{
|
||||
CarID, Event, PedestrianID, Router, Scheduler, TripManager, TripMode, WalkingSimState,
|
||||
};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap};
|
||||
use geom::{Distance, Time};
|
||||
use map_model::{
|
||||
@ -184,6 +186,7 @@ impl TransitSimState {
|
||||
let trip = trips.ped_boarded_bus(ped, walking);
|
||||
self.events.push(Event::TripPhaseStarting(
|
||||
trip,
|
||||
TripMode::Transit,
|
||||
Some(PathRequest {
|
||||
start: map.get_bs(stop1).driving_pos,
|
||||
end: map.get_bs(stop2).driving_pos,
|
||||
|
@ -351,6 +351,7 @@ impl TripManager {
|
||||
self.events.push(Event::PedReachedBusStop(ped, stop, route));
|
||||
self.events.push(Event::TripPhaseStarting(
|
||||
trip.id,
|
||||
trip.mode,
|
||||
None,
|
||||
format!("waiting for bus {}", map.get_br(route).name),
|
||||
));
|
||||
|
Loading…
Reference in New Issue
Block a user