show blank plots, rather than skipping out when there's no data. handle

the current time and lots of edge cases
This commit is contained in:
Dustin Carlino 2019-11-05 16:23:58 -08:00
parent 21724aa826
commit af7112592f
3 changed files with 50 additions and 52 deletions

View File

@ -12,11 +12,11 @@ pub struct Plot {
}
impl Plot {
pub fn new<T: Ord + PartialEq + Copy + Yvalue<T>>(
pub fn new<T: Ord + PartialEq + Copy + core::fmt::Debug + Yvalue<T>>(
title: &str,
series: Vec<Series<T>>,
ctx: &EventCtx,
) -> Option<Plot> {
) -> 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);

View File

@ -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<Plot> {
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 {

View File

@ -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<Plot> {
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<TripMode>)> = vec![
(
"walking",
@ -389,6 +378,13 @@ fn trip_stats(ui: &UI, ctx: &mut EventCtx) -> Option<Plot> {
}
}
}
// 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",