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 {
|
fn gridlock_panel(ui: &UI) -> Text {
|
||||||
let (now_all, now_per_mode) = ui
|
let (now_all, _, now_per_mode) = ui
|
||||||
.primary
|
.primary
|
||||||
.sim
|
.sim
|
||||||
.get_analytics()
|
.get_analytics()
|
||||||
.all_finished_trips(ui.primary.sim.time());
|
.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();
|
let mut txt = Text::new();
|
||||||
txt.add_appended(vec![
|
txt.add_appended(vec![
|
||||||
|
@ -76,7 +76,11 @@ fn faster_trips_panel(mode: TripMode, ui: &UI) -> Text {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for stat in Statistic::all() {
|
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(
|
txt.append_all(cmp_duration_shorter(
|
||||||
now.select(stat),
|
now.select(stat),
|
||||||
baseline.select(stat),
|
baseline.select(stat),
|
||||||
|
@ -229,7 +229,7 @@ fn manage_acs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shorter is better
|
// 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) {
|
if now.epsilon_eq(baseline) {
|
||||||
vec![Line(" (same as baseline)")]
|
vec![Line(" (same as baseline)")]
|
||||||
} else if now < baseline {
|
} else if now < baseline {
|
||||||
@ -250,7 +250,7 @@ fn cmp_duration_shorter(now: Duration, baseline: Duration) -> Vec<TextSpan> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fewer is better
|
// 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 {
|
if now < baseline {
|
||||||
Line(format!("{} fewer", prettyprint_usize(baseline - now))).fg(Color::GREEN)
|
Line(format!("{} fewer", prettyprint_usize(baseline - now))).fg(Color::GREEN)
|
||||||
} else if now > baseline {
|
} else if now > baseline {
|
||||||
@ -261,7 +261,7 @@ fn cmp_count_fewer(now: usize, baseline: usize) -> TextSpan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// More is better
|
// 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 {
|
if now < baseline {
|
||||||
Line(format!("{} fewer", prettyprint_usize(baseline - now))).fg(Color::RED)
|
Line(format!("{} fewer", prettyprint_usize(baseline - now))).fg(Color::RED)
|
||||||
} else if now > baseline {
|
} else if now > baseline {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use crate::game::{State, Transition, WizardState};
|
use crate::game::{State, Transition, WizardState};
|
||||||
|
use crate::sandbox::gameplay::{cmp_count_fewer, cmp_count_more, cmp_duration_shorter};
|
||||||
use crate::ui::UI;
|
use crate::ui::UI;
|
||||||
use abstutil::prettyprint_usize;
|
use abstutil::prettyprint_usize;
|
||||||
use ezgui::{
|
use ezgui::{
|
||||||
hotkey, Choice, Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, ModalMenu, Text,
|
hotkey, Choice, Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, ModalMenu, Text,
|
||||||
VerticalAlignment, Wizard,
|
VerticalAlignment, Wizard,
|
||||||
};
|
};
|
||||||
use geom::{Duration, DurationHistogram};
|
use geom::{Duration, Statistic};
|
||||||
use itertools::Itertools;
|
|
||||||
use sim::{TripID, TripMode};
|
use sim::{TripID, TripMode};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
@ -18,46 +18,80 @@ pub struct Scoreboard {
|
|||||||
impl Scoreboard {
|
impl Scoreboard {
|
||||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> Scoreboard {
|
pub fn new(ctx: &mut EventCtx, ui: &UI) -> Scoreboard {
|
||||||
let menu = ModalMenu::new(
|
let menu = ModalMenu::new(
|
||||||
"Scoreboard",
|
"Finished trips summary",
|
||||||
vec![
|
vec![
|
||||||
(hotkey(Key::Escape), "quit"),
|
(hotkey(Key::Escape), "quit"),
|
||||||
(hotkey(Key::B), "browse trips"),
|
(hotkey(Key::B), "browse trips"),
|
||||||
],
|
],
|
||||||
ctx,
|
ctx,
|
||||||
);
|
);
|
||||||
let t = ui.primary.sim.get_finished_trips();
|
|
||||||
|
|
||||||
let mut summary = Text::new();
|
let (now_all, now_aborted, now_per_mode) = ui
|
||||||
summary.add_appended(vec![
|
.primary
|
||||||
Line("Score at "),
|
.sim
|
||||||
Line(ui.primary.sim.time().to_string()).fg(Color::RED),
|
.get_analytics()
|
||||||
]);
|
.all_finished_trips(ui.primary.sim.time());
|
||||||
summary.add_appended(vec![
|
let (baseline_all, baseline_aborted, baseline_per_mode) =
|
||||||
Line(prettyprint_usize(t.unfinished_trips)).fg(Color::CYAN),
|
ui.prebaked.all_finished_trips(ui.primary.sim.time());
|
||||||
Line(" unfinished trips"),
|
|
||||||
]);
|
|
||||||
summary.add_appended(vec![
|
|
||||||
Line(prettyprint_usize(t.aborted_trips)).fg(Color::CYAN),
|
|
||||||
Line(" aborted trips"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
for (mode, trips) in &t
|
// TODO Include unfinished count
|
||||||
.finished_trips
|
let mut txt = Text::new();
|
||||||
.into_iter()
|
txt.add_appended(vec![
|
||||||
.sorted_by_key(|(_, m, _)| *m)
|
Line("Finished trips as of "),
|
||||||
.group_by(|(_, m, _)| *m)
|
Line(ui.primary.sim.time().ampm_tostring()).fg(Color::CYAN),
|
||||||
{
|
]);
|
||||||
let mut distrib: DurationHistogram = DurationHistogram::new();
|
txt.add_appended(vec![
|
||||||
for (_, _, dt) in trips {
|
Line(format!(
|
||||||
distrib.add(dt);
|
" {} 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!(
|
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),
|
abstutil::prettyprint_usize(self.count),
|
||||||
self.select(Statistic::P50).minimal_tostring(),
|
self.select(Statistic::P50).minimal_tostring(),
|
||||||
self.select(Statistic::P90).minimal_tostring(),
|
self.select(Statistic::P90).minimal_tostring(),
|
||||||
self.select(Statistic::P99).minimal_tostring(),
|
self.select(Statistic::P99).minimal_tostring(),
|
||||||
self.min.minimal_tostring(),
|
self.select(Statistic::Min).minimal_tostring(),
|
||||||
self.max.minimal_tostring(),
|
self.select(Statistic::Mean).minimal_tostring(),
|
||||||
|
self.select(Statistic::Max).minimal_tostring(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,6 +367,7 @@ impl DurationHistogram {
|
|||||||
Statistic::Min => {
|
Statistic::Min => {
|
||||||
return self.min;
|
return self.min;
|
||||||
}
|
}
|
||||||
|
Statistic::Mean => self.histogram.mean().unwrap(),
|
||||||
Statistic::Max => {
|
Statistic::Max => {
|
||||||
return self.max;
|
return self.max;
|
||||||
}
|
}
|
||||||
@ -381,6 +383,7 @@ impl DurationHistogram {
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum Statistic {
|
pub enum Statistic {
|
||||||
Min,
|
Min,
|
||||||
|
Mean,
|
||||||
P50,
|
P50,
|
||||||
P90,
|
P90,
|
||||||
P99,
|
P99,
|
||||||
@ -391,6 +394,7 @@ impl Statistic {
|
|||||||
pub fn all() -> Vec<Statistic> {
|
pub fn all() -> Vec<Statistic> {
|
||||||
vec![
|
vec![
|
||||||
Statistic::Min,
|
Statistic::Min,
|
||||||
|
Statistic::Mean,
|
||||||
Statistic::P50,
|
Statistic::P50,
|
||||||
Statistic::P90,
|
Statistic::P90,
|
||||||
Statistic::P99,
|
Statistic::P99,
|
||||||
@ -403,6 +407,7 @@ impl std::fmt::Display for Statistic {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Statistic::Min => write!(f, "minimum"),
|
Statistic::Min => write!(f, "minimum"),
|
||||||
|
Statistic::Mean => write!(f, "mean"),
|
||||||
Statistic::P50 => write!(f, "50%ile"),
|
Statistic::P50 => write!(f, "50%ile"),
|
||||||
Statistic::P90 => write!(f, "90%ile"),
|
Statistic::P90 => write!(f, "90%ile"),
|
||||||
Statistic::P99 => write!(f, "99%ile"),
|
Statistic::P99 => write!(f, "99%ile"),
|
||||||
|
@ -122,16 +122,21 @@ impl Analytics {
|
|||||||
distrib
|
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(
|
pub fn all_finished_trips(
|
||||||
&self,
|
&self,
|
||||||
now: Duration,
|
now: Duration,
|
||||||
) -> (DurationHistogram, BTreeMap<TripMode, DurationHistogram>) {
|
) -> (
|
||||||
|
DurationHistogram,
|
||||||
|
usize,
|
||||||
|
BTreeMap<TripMode, DurationHistogram>,
|
||||||
|
) {
|
||||||
let mut per_mode = TripMode::all()
|
let mut per_mode = TripMode::all()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|m| (m, DurationHistogram::new()))
|
.map(|m| (m, DurationHistogram::new()))
|
||||||
.collect::<BTreeMap<_, _>>();
|
.collect::<BTreeMap<_, _>>();
|
||||||
let mut all = DurationHistogram::new();
|
let mut all = DurationHistogram::new();
|
||||||
|
let mut num_aborted = 0;
|
||||||
for (t, m, dt) in &self.finished_trips {
|
for (t, m, dt) in &self.finished_trips {
|
||||||
if *t > now {
|
if *t > now {
|
||||||
break;
|
break;
|
||||||
@ -139,9 +144,11 @@ impl Analytics {
|
|||||||
if let Some(mode) = *m {
|
if let Some(mode) = *m {
|
||||||
all.add(*dt);
|
all.add(*dt);
|
||||||
per_mode.get_mut(&mode).unwrap().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(
|
pub fn bus_arrivals(
|
||||||
|
Loading…
Reference in New Issue
Block a user