reverse earlier decision and put prebaked analytics back in UI, so existing plumbing works. but it's optional and carefully set/reset

This commit is contained in:
Dustin Carlino 2019-12-22 10:14:19 -08:00
parent 7c37c786fd
commit c130e49cb4
11 changed files with 55 additions and 72 deletions

View File

@ -10,7 +10,7 @@ use ezgui::{
hotkey, Choice, Color, EventCtx, Key, Line, ManagedWidget, Plot, Series, Text, Wizard,
};
use geom::{Duration, Statistic, Time};
use sim::{Analytics, TripID, TripMode};
use sim::{TripID, TripMode};
use std::collections::{BTreeMap, BTreeSet};
#[derive(PartialEq, Clone, Copy)]
@ -22,7 +22,7 @@ pub enum Tab {
}
// Oh the dashboards melted, but we still had the radio
pub fn make(ctx: &EventCtx, ui: &UI, prebaked: &Analytics, tab: Tab) -> Box<dyn State> {
pub fn make(ctx: &EventCtx, ui: &UI, tab: Tab) -> Box<dyn State> {
let tab_data = vec![
(Tab::FinishedTripsSummary, "Finished trips summary"),
(
@ -46,7 +46,7 @@ pub fn make(ctx: &EventCtx, ui: &UI, prebaked: &Analytics, tab: Tab) -> Box<dyn
tabs.push(Composite::text_button(ctx, "BACK", hotkey(Key::Escape)));
let content = match tab {
Tab::FinishedTripsSummary => finished_trips_summary(ctx, ui, prebaked),
Tab::FinishedTripsSummary => finished_trips_summary(ctx, ui),
Tab::IndividualFinishedTrips => {
return WizardState::new(Box::new(browse_trips));
}
@ -65,15 +65,7 @@ pub fn make(ctx: &EventCtx, ui: &UI, prebaked: &Analytics, tab: Tab) -> Box<dyn
if t != tab {
c = c.cb(
label,
Box::new(move |ctx, ui| {
Some(Transition::Replace(make(
ctx,
ui,
// TODO prebaked?
&Analytics::new(),
t,
)))
}),
Box::new(move |ctx, ui| Some(Transition::Replace(make(ctx, ui, t)))),
);
}
}
@ -81,14 +73,14 @@ pub fn make(ctx: &EventCtx, ui: &UI, prebaked: &Analytics, tab: Tab) -> Box<dyn
ManagedGUIState::new(c)
}
fn finished_trips_summary(ctx: &EventCtx, ui: &UI, prebaked: &Analytics) -> ManagedWidget {
fn finished_trips_summary(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
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) =
prebaked.all_finished_trips(ui.primary.sim.time());
ui.prebaked().all_finished_trips(ui.primary.sim.time());
// TODO Include unfinished count
let mut txt = Text::new();

View File

@ -8,7 +8,7 @@ use crate::ui::UI;
use abstutil::prettyprint_usize;
use ezgui::{hotkey, EventCtx, Key, Line, ModalMenu, Text};
use geom::Time;
use sim::{Analytics, TripMode};
use sim::TripMode;
pub struct CreateGridlock {
time: Time,
@ -39,7 +39,6 @@ impl GameplayState for CreateGridlock {
ctx: &mut EventCtx,
ui: &mut UI,
_: &mut Overlays,
prebaked: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition> {
menu.event(ctx);
@ -54,7 +53,7 @@ impl GameplayState for CreateGridlock {
if self.time != ui.primary.sim.time() {
self.time = ui.primary.sim.time();
menu.set_info(ctx, gridlock_panel(ui, prebaked));
menu.set_info(ctx, gridlock_panel(ui));
}
if menu.action("help") {
@ -68,13 +67,14 @@ impl GameplayState for CreateGridlock {
}
}
fn gridlock_panel(ui: &UI, prebaked: &Analytics) -> Text {
fn gridlock_panel(ui: &UI) -> Text {
let (now_all, _, now_per_mode) = ui
.primary
.sim
.get_analytics()
.all_finished_trips(ui.primary.sim.time());
let (baseline_all, _, baseline_per_mode) = 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

@ -7,7 +7,7 @@ use crate::ui::UI;
use abstutil::prettyprint_usize;
use ezgui::{hotkey, EventCtx, Key, Line, ModalMenu, Text};
use geom::{Statistic, Time};
use sim::{Analytics, TripMode};
use sim::TripMode;
pub struct FasterTrips {
mode: TripMode,
@ -41,14 +41,13 @@ impl GameplayState for FasterTrips {
ctx: &mut EventCtx,
ui: &mut UI,
_: &mut Overlays,
prebaked: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition> {
menu.event(ctx);
if self.time != ui.primary.sim.time() {
self.time = ui.primary.sim.time();
menu.set_info(ctx, faster_trips_panel(self.mode, ui, prebaked));
menu.set_info(ctx, faster_trips_panel(self.mode, ui));
}
if menu.action("help") {
@ -61,10 +60,10 @@ impl GameplayState for FasterTrips {
}
}
pub fn faster_trips_panel(mode: TripMode, ui: &UI, prebaked: &Analytics) -> Text {
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 = prebaked.finished_trips(time, mode);
let baseline = ui.prebaked().finished_trips(time, mode);
// Enable to debug why sim results don't match prebaked.
if false && !now.seems_eq(&baseline) {
@ -72,7 +71,8 @@ pub fn faster_trips_panel(mode: TripMode, ui: &UI, prebaked: &Analytics) -> Text
"../current_sim.json".to_string(),
&ui.primary.sim.get_analytics().finished_trips,
);
let filtered = prebaked
let filtered = ui
.prebaked()
.finished_trips
.iter()
.filter(|(t, _, _, _)| *t <= time)
@ -106,10 +106,10 @@ pub fn faster_trips_panel(mode: TripMode, ui: &UI, prebaked: &Analytics) -> Text
txt
}
pub fn small_faster_trips_panel(mode: TripMode, ui: &UI, prebaked: &Analytics) -> Text {
pub fn small_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 = prebaked.finished_trips(time, mode);
let baseline = ui.prebaked().finished_trips(time, mode);
let mut txt = Text::new();
txt.add_appended(vec![

View File

@ -8,7 +8,7 @@ use crate::ui::UI;
use ezgui::{hotkey, EventCtx, Key, ModalMenu};
use geom::{Duration, Statistic, Time};
use map_model::{IntersectionID, Map};
use sim::{Analytics, BorderSpawnOverTime, OriginDestination, Scenario, TripMode};
use sim::{BorderSpawnOverTime, OriginDestination, Scenario, TripMode};
pub struct FixTrafficSignals {
time: Time,
@ -47,12 +47,11 @@ impl GameplayState for FixTrafficSignals {
ctx: &mut EventCtx,
ui: &mut UI,
overlays: &mut Overlays,
prebaked: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition> {
// Once is never...
if self.once {
*overlays = Overlays::finished_trips_histogram(ctx, ui, prebaked);
*overlays = Overlays::finished_trips_histogram(ctx, ui);
self.once = false;
}
@ -85,12 +84,12 @@ impl GameplayState for FixTrafficSignals {
},
self.time != ui.primary.sim.time(),
) {
*overlays = Overlays::finished_trips_histogram(ctx, ui, prebaked);
*overlays = Overlays::finished_trips_histogram(ctx, ui);
}
if self.time != ui.primary.sim.time() {
self.time = ui.primary.sim.time();
menu.set_info(ctx, small_faster_trips_panel(TripMode::Drive, ui, prebaked));
menu.set_info(ctx, small_faster_trips_panel(TripMode::Drive, ui));
}
if menu.action("help") {
@ -103,32 +102,26 @@ impl GameplayState for FixTrafficSignals {
}
if menu.action("final score") {
return Some(Transition::Push(msg(
"Final score",
final_score(ui, prebaked),
)));
return Some(Transition::Push(msg("Final score", final_score(ui))));
}
if ui.primary.sim.time() >= Time::END_OF_DAY {
// TODO Stop the challenge somehow
return Some(Transition::Push(msg(
"Final score",
final_score(ui, prebaked),
)));
return Some(Transition::Push(msg("Final score", final_score(ui))));
}
None
}
}
fn final_score(ui: &UI, prebaked: &Analytics) -> Vec<String> {
fn final_score(ui: &UI) -> Vec<String> {
let time = ui.primary.sim.time();
let now = ui
.primary
.sim
.get_analytics()
.finished_trips(time, TripMode::Drive);
let baseline = prebaked.finished_trips(time, TripMode::Drive);
let baseline = ui.prebaked().finished_trips(time, TripMode::Drive);
// TODO Annoying to repeat this everywhere; any refactor possible?
if now.count() == 0 || baseline.count() == 0 {
return vec!["No data yet, run the simulation for longer".to_string()];

View File

@ -10,7 +10,6 @@ use ezgui::{
ModalMenu, Text, VerticalAlignment,
};
use map_model::IntersectionID;
use sim::Analytics;
use std::collections::BTreeSet;
// TODO Maybe remember what things were spawned, offer to replay this later
@ -37,7 +36,6 @@ impl GameplayState for Freeform {
ctx: &mut EventCtx,
ui: &mut UI,
_: &mut Overlays,
_: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition> {
menu.event(ctx);

View File

@ -23,7 +23,6 @@ pub struct GameplayRunner {
pub menu: ModalMenu,
controller: Composite,
state: Box<dyn GameplayState>,
pub prebaked: Analytics,
}
#[derive(Clone)]
@ -47,7 +46,6 @@ pub trait GameplayState: downcast_rs::Downcast {
ctx: &mut EventCtx,
ui: &mut UI,
overlays: &mut Overlays,
prebaked: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition>;
fn draw(&self, _: &mut GfxCtx, _: &UI) {}
@ -158,6 +156,7 @@ impl GameplayRunner {
fix_traffic_signals::FixTrafficSignals::new(ctx, ui, mode.clone())
}
};
// TODO Maybe don't load this for Freeform mode
let prebaked = ctx.loading_screen("instantiate scenario", |_, timer| {
if let Some(scenario) =
mode.scenario(&ui.primary.map, ui.primary.current_flags.num_agents, timer)
@ -184,9 +183,9 @@ impl GameplayRunner {
Analytics::new()
}
});
ui.set_prebaked(Some(prebaked));
GameplayRunner {
mode,
prebaked,
menu: menu
.set_standalone_layout(layout::ContainerOrientation::TopRightButDownABit(150.0)),
controller,
@ -207,8 +206,7 @@ impl GameplayRunner {
Some(Outcome::Clicked(_)) => unreachable!(),
None => {}
}
self.state
.event(ctx, ui, overlays, &self.prebaked, &mut self.menu)
self.state.event(ctx, ui, overlays, &mut self.menu)
}
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {

View File

@ -13,7 +13,6 @@ use ezgui::{
};
use geom::{Statistic, Time};
use map_model::BusRouteID;
use sim::Analytics;
pub struct OptimizeBus {
route: BusRouteID,
@ -55,7 +54,6 @@ impl GameplayState for OptimizeBus {
ctx: &mut EventCtx,
ui: &mut UI,
overlays: &mut Overlays,
prebaked: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition> {
menu.event(ctx);
@ -95,7 +93,7 @@ impl GameplayState for OptimizeBus {
// TODO Expensive
if self.time != ui.primary.sim.time() {
self.time = ui.primary.sim.time();
menu.set_info(ctx, bus_route_panel(self.route, self.stat, ui, prebaked));
menu.set_info(ctx, bus_route_panel(self.route, self.stat, ui));
}
if menu.action("change statistic") {
@ -140,13 +138,13 @@ impl GameplayState for OptimizeBus {
}
}
fn bus_route_panel(id: BusRouteID, stat: Statistic, ui: &UI, prebaked: &Analytics) -> Text {
fn bus_route_panel(id: BusRouteID, stat: Statistic, ui: &UI) -> Text {
let now = ui
.primary
.sim
.get_analytics()
.bus_arrivals(ui.primary.sim.time(), id);
let baseline = prebaked.bus_arrivals(ui.primary.sim.time(), id);
let baseline = ui.prebaked().bus_arrivals(ui.primary.sim.time(), id);
let route = ui.primary.map.get_br(id);
let mut txt = Text::new();

View File

@ -5,7 +5,6 @@ use crate::sandbox::gameplay::{GameplayMode, GameplayState};
use crate::sandbox::overlays::Overlays;
use crate::ui::UI;
use ezgui::{hotkey, EventCtx, Key, ModalMenu};
use sim::Analytics;
pub struct PlayScenario;
@ -33,7 +32,6 @@ impl GameplayState for PlayScenario {
ctx: &mut EventCtx,
_: &mut UI,
_: &mut Overlays,
_: &Analytics,
menu: &mut ModalMenu,
) -> Option<Transition> {
menu.event(ctx);

View File

@ -141,7 +141,7 @@ impl State for SandboxMode {
if let Some(t) = self.common.event(ctx, ui) {
return t;
}
if let Some(t) = self.overlay.event(ctx, ui, &self.gameplay.prebaked) {
if let Some(t) = self.overlay.event(ctx, ui) {
return t;
}
match self.tool_panel.event(ctx, ui) {
@ -150,7 +150,6 @@ impl State for SandboxMode {
}
Some(Outcome::Clicked(x)) => match x.as_ref() {
"back" => {
// TODO Clear edits?
return Transition::Push(WizardState::new(Box::new(move |wiz, ctx, ui| {
let mut wizard = wiz.wrap(ctx);
let dirty = ui.primary.map.get_edits().dirty;
@ -183,6 +182,7 @@ impl State for SandboxMode {
&mut Timer::new("reset edits"),
);
ui.primary.clear_sim();
ui.set_prebaked(None);
ctx.canvas.save_camera_state(ui.primary.map.get_name());
Some(Transition::Clear(main_menu(ctx, ui)))
}
@ -200,6 +200,7 @@ impl State for SandboxMode {
);
}
ui.primary.clear_sim();
ui.set_prebaked(None);
ctx.canvas.save_camera_state(ui.primary.map.get_name());
Some(Transition::Clear(main_menu(ctx, ui)))
}
@ -212,7 +213,6 @@ impl State for SandboxMode {
return Transition::Push(dashboards::make(
ctx,
ui,
&self.gameplay.prebaked,
dashboards::Tab::FinishedTripsSummary,
));
}

View File

@ -11,7 +11,7 @@ use abstutil::{prettyprint_usize, Counter};
use ezgui::{Choice, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx, Key, Line, Text};
use geom::{Distance, Duration, PolyLine, Time};
use map_model::IntersectionID;
use sim::{Analytics, ParkingSpot};
use sim::ParkingSpot;
use std::collections::HashSet;
pub enum Overlays {
@ -29,12 +29,7 @@ pub enum Overlays {
}
impl Overlays {
pub fn event(
&mut self,
ctx: &mut EventCtx,
ui: &UI,
baseline: &Analytics,
) -> Option<Transition> {
pub fn event(&mut self, ctx: &mut EventCtx, ui: &UI) -> Option<Transition> {
let now = ui.primary.sim.time();
match self {
// Don't bother with Inactive, BusRoute, BusDelaysOverTime, BikeNetwork, BusNetwork --
@ -52,7 +47,7 @@ impl Overlays {
*self = Overlays::intersection_demand(*i, ctx, ui);
}
Overlays::FinishedTripsHistogram(t, _) if now != *t => {
*self = Overlays::finished_trips_histogram(ctx, ui, baseline);
*self = Overlays::finished_trips_histogram(ctx, ui);
}
_ => {}
};
@ -121,8 +116,7 @@ impl Overlays {
Choice::new("parking availability", ()).key(Key::P),
Choice::new("intersection delay", ()).key(Key::I),
Choice::new("cumulative throughput", ()).key(Key::T),
// TODO baseline borrow doesn't live long enough
//Choice::new("finished trips histogram", ()).key(Key::H),
Choice::new("finished trips histogram", ()).key(Key::H),
Choice::new("bike network", ()).key(Key::B),
Choice::new("bus network", ()).key(Key::U),
]
@ -134,6 +128,7 @@ impl Overlays {
"parking availability" => Overlays::parking_availability(ctx, ui),
"intersection delay" => Overlays::intersection_delay(ctx, ui),
"cumulative throughput" => Overlays::cumulative_throughput(ctx, ui),
"finished trips histogram" => Overlays::finished_trips_histogram(ctx, ui),
"bike network" => Overlays::bike_network(ctx, ui),
"bus network" => Overlays::bus_network(ctx, ui),
_ => unreachable!(),
@ -329,7 +324,7 @@ impl Overlays {
Overlays::BusNetwork(colorer.build(ctx, &ui.primary.map))
}
pub fn finished_trips_histogram(ctx: &EventCtx, ui: &UI, baseline: &Analytics) -> Overlays {
pub fn finished_trips_histogram(ctx: &EventCtx, ui: &UI) -> Overlays {
let now = ui.primary.sim.time();
Overlays::FinishedTripsHistogram(
now,
@ -337,7 +332,7 @@ impl Overlays {
ui.primary
.sim
.get_analytics()
.finished_trip_deltas(now, baseline),
.finished_trip_deltas(now, ui.prebaked()),
ctx,
),
)

View File

@ -10,12 +10,14 @@ use ezgui::{Color, EventCtx, GfxCtx, Prerender, TextureType};
use geom::{Bounds, Circle, Distance, Pt2D};
use map_model::{Map, Traversable};
use rand::seq::SliceRandom;
use sim::{GetDrawAgents, Sim, SimFlags};
use sim::{Analytics, GetDrawAgents, Sim, SimFlags};
pub struct UI {
pub primary: PerMapUI,
// Invariant: This is Some(...) iff we're in A/B test mode or a sub-state.
pub secondary: Option<PerMapUI>,
// Only exists in some gameplay modes. Must be carefully reset otherwise.
prebaked: Option<Analytics>,
pub cs: ColorScheme,
// TODO This is a bit weird to keep here; it's controlled almost entirely by the minimap panel.
// It has no meaning in edit mode.
@ -67,6 +69,7 @@ impl UI {
UI {
primary,
secondary: None,
prebaked: None,
agent_cs: AgentColorScheme::default(&cs),
cs,
opts,
@ -74,6 +77,14 @@ impl UI {
}
}
pub fn prebaked(&self) -> &Analytics {
self.prebaked.as_ref().unwrap()
}
pub fn set_prebaked(&mut self, prebaked: Option<Analytics>) {
self.prebaked = prebaked;
}
pub fn switch_map(&mut self, ctx: &mut EventCtx, load: String) {
ctx.canvas.save_camera_state(self.primary.map.get_name());
let mut flags = self.primary.current_flags.clone();