mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-30 18:24:04 +03:00
use scoreboard tool to show comparison for all trips
This commit is contained in:
parent
2f31893c48
commit
accc344054
@ -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![
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user