From 0dddd1d6c15430c3cf925107f8aa8f66aa421290 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Wed, 17 Jun 2020 14:01:05 -0700 Subject: [PATCH] one last pass for polishing all layers. layout and text tweaks --- game/src/common/colors.rs | 8 ++--- game/src/layer/elevation.rs | 8 +++-- game/src/layer/map.rs | 25 ++++++++++----- game/src/layer/parking.rs | 36 +++++++++++----------- game/src/layer/traffic.rs | 61 +++++++++++++++++++++++++------------ 5 files changed, 85 insertions(+), 53 deletions(-) diff --git a/game/src/common/colors.rs b/game/src/common/colors.rs index e4be817fdb..e6ce840e66 100644 --- a/game/src/common/colors.rs +++ b/game/src/common/colors.rs @@ -276,7 +276,7 @@ impl<'a> ColorNetwork<'a> { .push(color.alpha(0.4), self.map.get_pl(pl).polygon.clone()); } - pub fn road_percentiles(&mut self, counter: Counter, scale: &ColorScale) { + pub fn ranked_roads(&mut self, counter: Counter, scale: &ColorScale) { let roads = counter.sorted_asc(); let len = roads.len() as f64; for (idx, list) in roads.into_iter().enumerate() { @@ -286,11 +286,7 @@ impl<'a> ColorNetwork<'a> { } } } - pub fn intersection_percentiles( - &mut self, - counter: Counter, - scale: &ColorScale, - ) { + pub fn ranked_intersections(&mut self, counter: Counter, scale: &ColorScale) { let intersections = counter.sorted_asc(); let len = intersections.len() as f64; for (idx, list) in intersections.into_iter().enumerate() { diff --git a/game/src/layer/elevation.rs b/game/src/layer/elevation.rs index ad5105ab46..f85ea5b943 100644 --- a/game/src/layer/elevation.rs +++ b/game/src/layer/elevation.rs @@ -3,7 +3,7 @@ use crate::common::{ColorLegend, ColorNetwork}; use crate::layer::{Layer, LayerOutcome}; use ezgui::{ hotkey, Btn, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, - TextExt, VerticalAlignment, Widget, + Line, Text, TextExt, VerticalAlignment, Widget, }; use geom::{ArrowCap, Distance, PolyLine}; @@ -102,7 +102,11 @@ impl Elevation { .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), - format!("Steepest road: {:.0}%", max * 100.0).draw_text(ctx), + Text::from_multiline(vec![ + Line(format!("Steepest road: {:.0}% grade", max * 100.0)), + Line("Note: elevation data is currently wrong!").secondary(), + ]) + .draw(ctx), ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["flat", "steep"]), ]) .padding(5) diff --git a/game/src/layer/map.rs b/game/src/layer/map.rs index efb5b548a6..c6062b8f8a 100644 --- a/game/src/layer/map.rs +++ b/game/src/layer/map.rs @@ -108,14 +108,25 @@ impl BikeNetwork { ]), Text::from_multiline(vec![ Line(format!("{} lanes", num_lanes)), - Line(format!("total distance of {}", total_dist)), + Line(format!( + "total distance of {}", + total_dist.describe_rounded() + )), ]) .draw(ctx) .margin_below(10), Line("Throughput on bike lanes").draw(ctx), - ColorLegend::gradient(ctx, &app.cs.good_to_bad_green, vec!["0%ile", "100%ile"]), + ColorLegend::gradient( + ctx, + &app.cs.good_to_bad_green, + vec!["lowest count", "highest"], + ), Line("Throughput on unprotected roads").draw(ctx), - ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0%ile", "100%ile"]), + ColorLegend::gradient( + ctx, + &app.cs.good_to_bad_red, + vec!["lowest count", "highest"], + ), ]) .padding(5) .bg(app.cs.panel_bg), @@ -124,10 +135,10 @@ impl BikeNetwork { .build(ctx); let mut colorer = ColorNetwork::new(app); - colorer.road_percentiles(on_bike_lanes, &app.cs.good_to_bad_green); - colorer.road_percentiles(off_bike_lanes, &app.cs.good_to_bad_red); - colorer.intersection_percentiles(intersections_on, &app.cs.good_to_bad_green); - colorer.intersection_percentiles(intersections_off, &app.cs.good_to_bad_red); + colorer.ranked_roads(on_bike_lanes, &app.cs.good_to_bad_green); + colorer.ranked_roads(off_bike_lanes, &app.cs.good_to_bad_red); + colorer.ranked_intersections(intersections_on, &app.cs.good_to_bad_green); + colorer.ranked_intersections(intersections_off, &app.cs.good_to_bad_red); let (unzoomed, zoomed) = colorer.build(ctx); BikeNetwork { diff --git a/game/src/layer/parking.rs b/game/src/layer/parking.rs index 6d703c556b..9dc138a874 100644 --- a/game/src/layer/parking.rs +++ b/game/src/layer/parking.rs @@ -174,31 +174,31 @@ impl Occupancy { 100.0 * (has_car as f64) / (total_ppl as f64) } )), - Line(""), Line(format!( - "{} public spots filled", - prettyprint_usize(filled_spots.len()) + "{} / {} public spots filled", + prettyprint_usize(filled_spots.len()), + prettyprint_usize(filled_spots.len() + avail_spots.len()) )), Line(format!( - "{} public spots available ", - prettyprint_usize(avail_spots.len()) - )), - Line(""), - Line(format!( - "{} private spots filled", - prettyprint_usize(filled_private_spots) - )), - Line(format!( - "{} private spots available ", - prettyprint_usize(avail_private_spots) + "{} / {} private spots filled", + prettyprint_usize(filled_private_spots), + prettyprint_usize(filled_private_spots + avail_private_spots) )), ]) .draw(ctx) .margin_below(10), - Checkbox::text(ctx, "On-street spots", None, onstreet).margin_below(5), - Checkbox::text(ctx, "Public garages", None, garages).margin_below(5), - Checkbox::text(ctx, "Parking lots", None, lots).margin_below(10), - Checkbox::text(ctx, "Private buildings", None, private_bldgs).margin_below(10), + Widget::row(vec![ + Checkbox::text(ctx, "On-street spots", None, onstreet).margin_right(15), + Checkbox::text(ctx, "Parking lots", None, lots), + ]) + .evenly_spaced() + .margin_below(10), + Widget::row(vec![ + Checkbox::text(ctx, "Public garages", None, garages).margin_right(15), + Checkbox::text(ctx, "Private buildings", None, private_bldgs), + ]) + .evenly_spaced() + .margin_below(10), ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0%", "100%"]), ]) .padding(5) diff --git a/game/src/layer/traffic.rs b/game/src/layer/traffic.rs index bd9bee0304..69a0474477 100644 --- a/game/src/layer/traffic.rs +++ b/game/src/layer/traffic.rs @@ -4,7 +4,7 @@ use crate::layer::{Layer, LayerOutcome}; use abstutil::Counter; use ezgui::{ hotkey, Btn, Checkbox, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx, - HorizontalAlignment, Key, Outcome, TextExt, VerticalAlignment, Widget, + HorizontalAlignment, Key, Line, Outcome, Text, TextExt, VerticalAlignment, Widget, }; use geom::{Distance, Duration, Polygon, Time}; use map_model::{IntersectionID, Map, Traversable}; @@ -74,8 +74,17 @@ impl Backpressure { .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), - // TODO Explain - ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0%ile", "100%ile"]), + Text::from( + Line("This counts all active trips passing through a road in the future") + .secondary(), + ) + .wrap_to_pct(ctx, 15) + .draw(ctx), + ColorLegend::gradient( + ctx, + &app.cs.good_to_bad_red, + vec!["lowest count", "highest"], + ), ]) .padding(5) .bg(app.cs.panel_bg), @@ -84,8 +93,8 @@ impl Backpressure { .build(ctx); let mut colorer = ColorNetwork::new(app); - colorer.road_percentiles(cnt_per_r, &app.cs.good_to_bad_red); - colorer.intersection_percentiles(cnt_per_i, &app.cs.good_to_bad_red); + colorer.ranked_roads(cnt_per_r, &app.cs.good_to_bad_red); + colorer.ranked_intersections(cnt_per_i, &app.cs.good_to_bad_red); let (unzoomed, zoomed) = colorer.build(ctx); Backpressure { @@ -167,13 +176,19 @@ impl Throughput { .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), - // TODO Explain. What roads see the most movement? + Text::from(Line("This counts all people crossing since midnight").secondary()) + .wrap_to_pct(ctx, 15) + .draw(ctx), if app.has_prebaked().is_some() { Checkbox::text(ctx, "Compare before edits", None, false).margin_below(5) } else { Widget::nothing() }, - ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0%ile", "100%ile"]), + ColorLegend::gradient( + ctx, + &app.cs.good_to_bad_red, + vec!["lowest count", "highest"], + ), ]) .padding(5) .bg(app.cs.panel_bg), @@ -183,11 +198,11 @@ impl Throughput { let mut colorer = ColorNetwork::new(app); let stats = &app.primary.sim.get_analytics(); - colorer.road_percentiles( + colorer.ranked_roads( stats.road_thruput.all_total_counts(), &app.cs.good_to_bad_red, ); - colorer.intersection_percentiles( + colorer.ranked_intersections( stats.intersection_thruput.all_total_counts(), &app.cs.good_to_bad_red, ); @@ -256,13 +271,13 @@ impl Throughput { Widget::row(vec![ Widget::draw_svg(ctx, "../data/system/assets/tools/layers.svg") .margin_right(10), - "Throughput (percent change)".draw_text(ctx), + "Relative Throughput".draw_text(ctx), Btn::plaintext("X") .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), Checkbox::text(ctx, "Compare before edits", None, true).margin_below(5), - scale.make_legend(ctx, vec!["less", "-50%", "0%", "50%", "more"]), + scale.make_legend(ctx, vec!["less traffic", "same", "more"]), ]) .padding(5) .bg(app.cs.panel_bg), @@ -503,15 +518,13 @@ impl TrafficJams { ); let mut zoomed = GeomBatch::new(); let mut cnt = 0; - // TODO Maybe look for intersections with delay > 5m, then expand out while roads have - // delay of at least 1m? for (epicenter, boundary) in cluster_jams( &app.primary.map, app.primary.sim.delayed_intersections(Duration::minutes(5)), ) { cnt += 1; unzoomed.push(Color::RED, boundary.to_outline(Distance::meters(5.0))); - unzoomed.push(Color::RED.alpha(0.7), boundary.clone()); + unzoomed.push(Color::RED.alpha(0.5), boundary.clone()); unzoomed.push(Color::WHITE, epicenter.clone()); zoomed.push( @@ -532,6 +545,11 @@ impl TrafficJams { .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), + Text::from( + Line("A jam starts when delay exceeds 5 mins, then spreads out").secondary(), + ) + .wrap_to_pct(ctx, 15) + .draw(ctx), format!("{} jams detected", cnt).draw_text(ctx), ]) .padding(5) @@ -574,12 +592,7 @@ fn cluster_jams(map: &Map, problems: Vec<(IntersectionID, Time)>) -> Vec<(Polygo .map(|jam| { ( map.get_i(jam.epicenter).polygon.clone(), - Polygon::convex_hull( - jam.members - .into_iter() - .map(|i| map.get_i(i).polygon.clone()) - .collect(), - ), + Polygon::convex_hull(jam.all_polygons(map)), ) }) .collect() @@ -595,4 +608,12 @@ impl Jam { } false } + + fn all_polygons(self, map: &Map) -> Vec { + let mut polygons = Vec::new(); + for i in self.members { + polygons.push(map.get_i(i).polygon.clone()); + } + polygons + } }