diff --git a/game/src/common/plot.rs b/game/src/common/plot.rs index d16fbb1673..59db24e854 100644 --- a/game/src/common/plot.rs +++ b/game/src/common/plot.rs @@ -12,11 +12,11 @@ pub struct Plot { } impl Plot { - pub fn new>( + pub fn new>( title: &str, series: Vec>, ctx: &EventCtx, - ) -> Option { + ) -> Plot { let mut batch = GeomBatch::new(); let mut labels = MultiText::new(); @@ -36,17 +36,26 @@ impl Plot { // Assume min_x is Duration::ZERO and min_y is 0 let max_x = series .iter() - .map(|s| s.pts.iter().map(|(t, _)| *t).max().unwrap()) + .map(|s| { + s.pts + .iter() + .map(|(t, _)| *t) + .max() + .unwrap_or(Duration::ZERO) + }) .max() - .unwrap(); + .unwrap_or(Duration::ZERO); let max_y = series .iter() - .map(|s| s.pts.iter().map(|(_, cnt)| *cnt).max().unwrap()) + .map(|s| { + s.pts + .iter() + .map(|(_, value)| *value) + .max() + .unwrap_or(T::zero()) + }) .max() - .unwrap(); - if max_x == Duration::ZERO { - return None; - } + .unwrap_or(T::zero()); let num_x_labels = 5; for i in 0..num_x_labels { @@ -73,33 +82,34 @@ impl Plot { ); for s in series { - let mut pts = Vec::new(); - if max_y == T::zero() { - pts.push(Pt2D::new(x1, y2)); - pts.push(Pt2D::new(x2, y2)); - } else { - for (t, y) in s.pts { - let percent_x = t / max_x; - let percent_y = y.to_percent(max_y); - pts.push(Pt2D::new( - x1 + (x2 - x1) * percent_x, - // Y inversion! :D - y2 - (y2 - y1) * percent_y, - )); - } + if max_x == Duration::ZERO { + continue; + } + let mut pts = Vec::new(); + for (t, y) in s.pts { + let percent_x = t / max_x; + let percent_y = y.to_percent(max_y); + pts.push(Pt2D::new( + x1 + (x2 - x1) * percent_x, + // Y inversion! :D + y2 - (y2 - y1) * percent_y, + )); + } + pts.dedup(); + if pts.len() >= 2 { + batch.push( + s.color, + PolyLine::new(pts).make_polygons(Distance::meters(5.0)), + ); } - batch.push( - s.color, - PolyLine::new(pts).make_polygons(Distance::meters(5.0)), - ); } - Some(Plot { + Plot { draw: ctx.prerender.upload(batch), labels, legend, rect: ScreenRectangle { x1, y1, x2, y2 }, - }) + } } pub fn draw(&self, g: &mut GfxCtx) { self.legend.draw(g); diff --git a/game/src/sandbox/gameplay.rs b/game/src/sandbox/gameplay.rs index b8fef53d75..d2618a4873 100644 --- a/game/src/sandbox/gameplay.rs +++ b/game/src/sandbox/gameplay.rs @@ -276,12 +276,7 @@ impl GameplayState { }, *time != ui.primary.sim.time(), ) { - if let Some(s) = bus_delays(route, ui, ctx) { - *overlays = Overlays::BusDelaysOverTime(s); - } else { - println!("No route delay info yet"); - *overlays = Overlays::Inactive; - } + *overlays = Overlays::BusDelaysOverTime(bus_delays(route, ui, ctx)); } // TODO Expensive @@ -425,15 +420,12 @@ fn bus_route_panel(id: BusRouteID, ui: &UI, stat: Statistic, prebaked: &Analytic txt } -fn bus_delays(route: BusRouteID, ui: &UI, ctx: &mut EventCtx) -> Option { +fn bus_delays(route: BusRouteID, ui: &UI, ctx: &mut EventCtx) -> Plot { let delays_per_stop = ui .primary .sim .get_analytics() .bus_arrivals_over_time(ui.primary.sim.time(), route); - if delays_per_stop.is_empty() { - return None; - } let mut series = Vec::new(); for (stop, delays) in delays_per_stop { diff --git a/game/src/sandbox/overlays.rs b/game/src/sandbox/overlays.rs index 3932beaf4c..8c945a1497 100644 --- a/game/src/sandbox/overlays.rs +++ b/game/src/sandbox/overlays.rs @@ -121,14 +121,7 @@ impl Overlays { Overlays::IntersectionDelay(time, calculate_intersection_delay(ctx, ui)) } "cumulative throughput" => Overlays::Throughput(time, calculate_thruput(ctx, ui)), - "finished trips" => { - if let Some(s) = trip_stats(ui, ctx) { - Overlays::FinishedTrips(time, s) - } else { - println!("No data on finished trips yet"); - Overlays::Inactive - } - } + "finished trips" => Overlays::FinishedTrips(time, trip_stats(ui, ctx)), "chokepoints" => Overlays::Chokepoints(time, calculate_chokepoints(ctx, ui)), "bike network" => Overlays::BikeNetwork(calculate_bike_network(ctx, ui)), _ => unreachable!(), @@ -343,11 +336,7 @@ fn calculate_bike_network(ctx: &mut EventCtx, ui: &UI) -> RoadColorer { colorer.build(ctx, &ui.primary.map) } -fn trip_stats(ui: &UI, ctx: &mut EventCtx) -> Option { - if ui.primary.sim.get_analytics().finished_trips.is_empty() { - return None; - } - +fn trip_stats(ui: &UI, ctx: &mut EventCtx) -> Plot { let lines: Vec<(&str, Color, Option)> = vec![ ( "walking", @@ -389,6 +378,13 @@ fn trip_stats(ui: &UI, ctx: &mut EventCtx) -> Option { } } } + // Don't forget the last batch + for (_, _, mode) in &lines { + pts_per_mode + .get_mut(mode) + .unwrap() + .push((ui.primary.sim.time(), counts.get(*mode))); + } Plot::new( "finished trips",