From c130e49cb4b1e4f2ce16bb7f9b00defd47de120d Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Sun, 22 Dec 2019 10:14:19 -0800 Subject: [PATCH] reverse earlier decision and put prebaked analytics back in UI, so existing plumbing works. but it's optional and carefully set/reset --- game/src/sandbox/dashboards.rs | 20 +++++----------- game/src/sandbox/gameplay/create_gridlock.rs | 10 ++++---- game/src/sandbox/gameplay/faster_trips.rs | 16 ++++++------- .../sandbox/gameplay/fix_traffic_signals.rs | 23 +++++++------------ game/src/sandbox/gameplay/freeform.rs | 2 -- game/src/sandbox/gameplay/mod.rs | 8 +++---- game/src/sandbox/gameplay/optimize_bus.rs | 8 +++---- game/src/sandbox/gameplay/play_scenario.rs | 2 -- game/src/sandbox/mod.rs | 6 ++--- game/src/sandbox/overlays.rs | 19 ++++++--------- game/src/ui.rs | 13 ++++++++++- 11 files changed, 55 insertions(+), 72 deletions(-) diff --git a/game/src/sandbox/dashboards.rs b/game/src/sandbox/dashboards.rs index 1118c09870..f1cbb6a8ba 100644 --- a/game/src/sandbox/dashboards.rs +++ b/game/src/sandbox/dashboards.rs @@ -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 { +pub fn make(ctx: &EventCtx, ui: &UI, tab: Tab) -> Box { 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 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 Box 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(); diff --git a/game/src/sandbox/gameplay/create_gridlock.rs b/game/src/sandbox/gameplay/create_gridlock.rs index c247e37fa5..fffbb76c37 100644 --- a/game/src/sandbox/gameplay/create_gridlock.rs +++ b/game/src/sandbox/gameplay/create_gridlock.rs @@ -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 { 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![ diff --git a/game/src/sandbox/gameplay/faster_trips.rs b/game/src/sandbox/gameplay/faster_trips.rs index 1ac9f98460..e23c4dc620 100644 --- a/game/src/sandbox/gameplay/faster_trips.rs +++ b/game/src/sandbox/gameplay/faster_trips.rs @@ -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 { 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![ diff --git a/game/src/sandbox/gameplay/fix_traffic_signals.rs b/game/src/sandbox/gameplay/fix_traffic_signals.rs index e8f7b1e317..fd41b2b945 100644 --- a/game/src/sandbox/gameplay/fix_traffic_signals.rs +++ b/game/src/sandbox/gameplay/fix_traffic_signals.rs @@ -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 { // 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 { +fn final_score(ui: &UI) -> Vec { 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()]; diff --git a/game/src/sandbox/gameplay/freeform.rs b/game/src/sandbox/gameplay/freeform.rs index e328a1d40d..b8334774df 100644 --- a/game/src/sandbox/gameplay/freeform.rs +++ b/game/src/sandbox/gameplay/freeform.rs @@ -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 { menu.event(ctx); diff --git a/game/src/sandbox/gameplay/mod.rs b/game/src/sandbox/gameplay/mod.rs index bf92d3d746..4cfded4186 100644 --- a/game/src/sandbox/gameplay/mod.rs +++ b/game/src/sandbox/gameplay/mod.rs @@ -23,7 +23,6 @@ pub struct GameplayRunner { pub menu: ModalMenu, controller: Composite, state: Box, - 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; 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) { diff --git a/game/src/sandbox/gameplay/optimize_bus.rs b/game/src/sandbox/gameplay/optimize_bus.rs index 2f7c51bc65..5e592fb26a 100644 --- a/game/src/sandbox/gameplay/optimize_bus.rs +++ b/game/src/sandbox/gameplay/optimize_bus.rs @@ -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 { 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(); diff --git a/game/src/sandbox/gameplay/play_scenario.rs b/game/src/sandbox/gameplay/play_scenario.rs index 7741fa3ff0..75fd01d6b0 100644 --- a/game/src/sandbox/gameplay/play_scenario.rs +++ b/game/src/sandbox/gameplay/play_scenario.rs @@ -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 { menu.event(ctx); diff --git a/game/src/sandbox/mod.rs b/game/src/sandbox/mod.rs index 773632bf78..511ab9dd62 100644 --- a/game/src/sandbox/mod.rs +++ b/game/src/sandbox/mod.rs @@ -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, )); } diff --git a/game/src/sandbox/overlays.rs b/game/src/sandbox/overlays.rs index fb5d480ac7..b4432c5aef 100644 --- a/game/src/sandbox/overlays.rs +++ b/game/src/sandbox/overlays.rs @@ -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 { + pub fn event(&mut self, ctx: &mut EventCtx, ui: &UI) -> Option { 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, ), ) diff --git a/game/src/ui.rs b/game/src/ui.rs index dd45949504..01d9a6ab48 100644 --- a/game/src/ui.rs +++ b/game/src/ui.rs @@ -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, + // Only exists in some gameplay modes. Must be carefully reset otherwise. + prebaked: Option, 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) { + 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();