use scoreboard tool to show comparison for all trips

This commit is contained in:
Dustin Carlino 2019-11-15 13:19:57 -08:00
parent 2f31893c48
commit accc344054
6 changed files with 94 additions and 43 deletions

View File

@ -65,12 +65,13 @@ impl GameplayState for CreateGridlock {
}
fn gridlock_panel(ui: &UI) -> Text {
let (now_all, now_per_mode) = ui
let (now_all, _, now_per_mode) = ui
.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());
let (baseline_all, _, baseline_per_mode) =
ui.prebaked.all_finished_trips(ui.primary.sim.time());
let mut txt = Text::new();
txt.add_appended(vec![

View File

@ -76,7 +76,11 @@ fn faster_trips_panel(mode: TripMode, ui: &UI) -> Text {
}
for stat in Statistic::all() {
txt.add(Line(format!("{}: ", stat)));
txt.add(Line(format!(
"{}: {} ",
stat,
now.select(stat).minimal_tostring()
)));
txt.append_all(cmp_duration_shorter(
now.select(stat),
baseline.select(stat),

View File

@ -229,7 +229,7 @@ fn manage_acs(
}
// Shorter is better
fn cmp_duration_shorter(now: Duration, baseline: Duration) -> Vec<TextSpan> {
pub fn cmp_duration_shorter(now: Duration, baseline: Duration) -> Vec<TextSpan> {
if now.epsilon_eq(baseline) {
vec![Line(" (same as baseline)")]
} else if now < baseline {
@ -250,7 +250,7 @@ fn cmp_duration_shorter(now: Duration, baseline: Duration) -> Vec<TextSpan> {
}
// Fewer is better
fn cmp_count_fewer(now: usize, baseline: usize) -> TextSpan {
pub fn cmp_count_fewer(now: usize, baseline: usize) -> TextSpan {
if now < baseline {
Line(format!("{} fewer", prettyprint_usize(baseline - now))).fg(Color::GREEN)
} else if now > baseline {
@ -261,7 +261,7 @@ fn cmp_count_fewer(now: usize, baseline: usize) -> TextSpan {
}
// More is better
fn cmp_count_more(now: usize, baseline: usize) -> TextSpan {
pub fn cmp_count_more(now: usize, baseline: usize) -> TextSpan {
if now < baseline {
Line(format!("{} fewer", prettyprint_usize(baseline - now))).fg(Color::RED)
} else if now > baseline {

View File

@ -1,12 +1,12 @@
use crate::game::{State, Transition, WizardState};
use crate::sandbox::gameplay::{cmp_count_fewer, cmp_count_more, cmp_duration_shorter};
use crate::ui::UI;
use abstutil::prettyprint_usize;
use ezgui::{
hotkey, Choice, Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, ModalMenu, Text,
VerticalAlignment, Wizard,
};
use geom::{Duration, DurationHistogram};
use itertools::Itertools;
use geom::{Duration, Statistic};
use sim::{TripID, TripMode};
use std::collections::BTreeSet;
@ -18,46 +18,80 @@ pub struct Scoreboard {
impl Scoreboard {
pub fn new(ctx: &mut EventCtx, ui: &UI) -> Scoreboard {
let menu = ModalMenu::new(
"Scoreboard",
"Finished trips summary",
vec![
(hotkey(Key::Escape), "quit"),
(hotkey(Key::B), "browse trips"),
],
ctx,
);
let t = ui.primary.sim.get_finished_trips();
let mut summary = Text::new();
summary.add_appended(vec![
Line("Score at "),
Line(ui.primary.sim.time().to_string()).fg(Color::RED),
]);
summary.add_appended(vec![
Line(prettyprint_usize(t.unfinished_trips)).fg(Color::CYAN),
Line(" unfinished trips"),
]);
summary.add_appended(vec![
Line(prettyprint_usize(t.aborted_trips)).fg(Color::CYAN),
Line(" aborted trips"),
]);
let (now_all, now_aborted, now_per_mode) = ui
.primary
.sim
.get_analytics()
.all_finished_trips(ui.primary.sim.time());
let (baseline_all, baseline_aborted, baseline_per_mode) =
ui.prebaked.all_finished_trips(ui.primary.sim.time());
for (mode, trips) in &t
.finished_trips
.into_iter()
.sorted_by_key(|(_, m, _)| *m)
.group_by(|(_, m, _)| *m)
{
let mut distrib: DurationHistogram = DurationHistogram::new();
for (_, _, dt) in trips {
distrib.add(dt);
// 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),
]);
txt.add_appended(vec![
Line(format!(
" {} aborted trips (",
prettyprint_usize(now_aborted)
)),
cmp_count_fewer(now_aborted, baseline_aborted),
Line(")"),
]);
// TODO Refactor
txt.add_appended(vec![
Line(format!(
"{} total finished trips (",
prettyprint_usize(now_all.count())
)),
cmp_count_more(now_all.count(), baseline_all.count()),
Line(")"),
]);
if now_all.count() > 0 && baseline_all.count() > 0 {
for stat in Statistic::all() {
txt.add(Line(format!(
" {}: {} ",
stat,
now_all.select(stat).minimal_tostring()
)));
txt.append_all(cmp_duration_shorter(
now_all.select(stat),
baseline_all.select(stat),
));
}
summary.add_appended(vec![
Line(format!("{}", mode)).fg(Color::CYAN),
Line(format!(" trips: {}", distrib.describe())),
]);
}
Scoreboard { menu, summary }
for mode in TripMode::all() {
let a = &now_per_mode[&mode];
let b = &baseline_per_mode[&mode];
txt.add_appended(vec![
Line(format!("{} {} trips (", prettyprint_usize(a.count()), mode)),
cmp_count_more(a.count(), b.count()),
Line(")"),
]);
if a.count() > 0 && b.count() > 0 {
for stat in Statistic::all() {
txt.add(Line(format!(
" {}: {} ",
stat,
a.select(stat).minimal_tostring()
)));
txt.append_all(cmp_duration_shorter(a.select(stat), b.select(stat)));
}
}
}
Scoreboard { menu, summary: txt }
}
}

View File

@ -339,13 +339,14 @@ impl DurationHistogram {
}
format!(
"{} count, 50%ile {}, 90%ile {}, 99%ile {}, min {}, max {}",
"{} count, 50%ile {}, 90%ile {}, 99%ile {}, min {}, mean {}, max {}",
abstutil::prettyprint_usize(self.count),
self.select(Statistic::P50).minimal_tostring(),
self.select(Statistic::P90).minimal_tostring(),
self.select(Statistic::P99).minimal_tostring(),
self.min.minimal_tostring(),
self.max.minimal_tostring(),
self.select(Statistic::Min).minimal_tostring(),
self.select(Statistic::Mean).minimal_tostring(),
self.select(Statistic::Max).minimal_tostring(),
)
}
@ -366,6 +367,7 @@ impl DurationHistogram {
Statistic::Min => {
return self.min;
}
Statistic::Mean => self.histogram.mean().unwrap(),
Statistic::Max => {
return self.max;
}
@ -381,6 +383,7 @@ impl DurationHistogram {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Statistic {
Min,
Mean,
P50,
P90,
P99,
@ -391,6 +394,7 @@ impl Statistic {
pub fn all() -> Vec<Statistic> {
vec![
Statistic::Min,
Statistic::Mean,
Statistic::P50,
Statistic::P90,
Statistic::P99,
@ -403,6 +407,7 @@ impl std::fmt::Display for Statistic {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Statistic::Min => write!(f, "minimum"),
Statistic::Mean => write!(f, "mean"),
Statistic::P50 => write!(f, "50%ile"),
Statistic::P90 => write!(f, "90%ile"),
Statistic::P99 => write!(f, "99%ile"),

View File

@ -122,16 +122,21 @@ impl Analytics {
distrib
}
// Returns (all trips except aborted, trips by mode)
// Returns (all trips except aborted, number of aborted trips, trips by mode)
pub fn all_finished_trips(
&self,
now: Duration,
) -> (DurationHistogram, BTreeMap<TripMode, DurationHistogram>) {
) -> (
DurationHistogram,
usize,
BTreeMap<TripMode, DurationHistogram>,
) {
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 {
if *t > now {
break;
@ -139,9 +144,11 @@ impl Analytics {
if let Some(mode) = *m {
all.add(*dt);
per_mode.get_mut(&mode).unwrap().add(*dt);
} else {
num_aborted += 1;
}
}
(all, per_mode)
(all, num_aborted, per_mode)
}
pub fn bus_arrivals(