mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-29 17:34:58 +03:00
tab-ify lanes and intersections, in a really messy quick way
This commit is contained in:
parent
8b1f66a3ed
commit
cbc214ed38
@ -123,6 +123,7 @@ pub fn info(
|
||||
inner.extend(person::info(ctx, app, ppl[idx], None, Vec::new()));
|
||||
rows.push(Widget::col(inner).bg(colors::INNER_PANEL_BG));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
for p in app.primary.sim.get_parked_cars_by_owner(id) {
|
||||
|
@ -1,17 +1,24 @@
|
||||
use crate::app::App;
|
||||
use crate::helpers::rotating_color_map;
|
||||
use crate::info::throughput;
|
||||
use crate::info::{throughput, InfoTab};
|
||||
use abstutil::prettyprint_usize;
|
||||
use ezgui::{EventCtx, Line, Plot, PlotOptions, Series, Text, Widget};
|
||||
use ezgui::{Btn, EventCtx, Line, Plot, PlotOptions, Series, Text, Widget};
|
||||
use geom::{Duration, Statistic, Time};
|
||||
use map_model::{IntersectionID, IntersectionType};
|
||||
use sim::Analytics;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Tab {
|
||||
Throughput,
|
||||
Delay,
|
||||
}
|
||||
|
||||
pub fn info(
|
||||
ctx: &EventCtx,
|
||||
app: &App,
|
||||
id: IntersectionID,
|
||||
tab: InfoTab,
|
||||
header_btns: Widget,
|
||||
action_btns: Vec<Widget>,
|
||||
) -> Vec<Widget> {
|
||||
@ -39,46 +46,67 @@ pub fn info(
|
||||
// TODO The spacing is ignored, so use -
|
||||
txt.add(Line(format!("- {}", r)));
|
||||
}
|
||||
|
||||
rows.extend(action_btns);
|
||||
|
||||
let trip_lines = app.primary.sim.count_trips_involving_border(id).describe();
|
||||
if !trip_lines.is_empty() {
|
||||
txt.add(Line(""));
|
||||
for line in trip_lines {
|
||||
txt.add(Line(line));
|
||||
}
|
||||
}
|
||||
|
||||
txt.add(Line("Throughput").roboto_bold());
|
||||
txt.add(Line(format!(
|
||||
"Since midnight: {} agents crossed",
|
||||
prettyprint_usize(
|
||||
app.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.thruput_stats
|
||||
.count_per_intersection
|
||||
.get(id)
|
||||
)
|
||||
)));
|
||||
txt.add(Line(format!("In 20 minute buckets:")));
|
||||
rows.push(txt.draw(ctx));
|
||||
|
||||
rows.push(
|
||||
throughput(ctx, app, move |a, t| {
|
||||
a.throughput_intersection(t, id, Duration::minutes(20))
|
||||
})
|
||||
.margin(10),
|
||||
);
|
||||
// TODO Inactive
|
||||
// TODO Naming, style...
|
||||
rows.push(Widget::row(vec![
|
||||
Btn::text_bg2("Main").build_def(ctx, None),
|
||||
Btn::text_bg2("Throughput").build_def(ctx, None), // TODO temporary name
|
||||
if app.primary.map.get_i(id).is_traffic_signal() {
|
||||
Btn::text_bg2("Delay").build_def(ctx, None)
|
||||
} else {
|
||||
Widget::nothing()
|
||||
},
|
||||
]));
|
||||
|
||||
if app.primary.map.get_i(id).is_traffic_signal() {
|
||||
let mut txt = Text::from(Line(""));
|
||||
txt.add(Line("Delay").roboto_bold());
|
||||
txt.add(Line(format!("In 20 minute buckets:")));
|
||||
rows.push(txt.draw(ctx));
|
||||
match tab {
|
||||
InfoTab::Nil => {
|
||||
rows.extend(action_btns);
|
||||
|
||||
rows.push(delay(ctx, app, id, Duration::minutes(20)).margin(10));
|
||||
let trip_lines = app.primary.sim.count_trips_involving_border(id).describe();
|
||||
if !trip_lines.is_empty() {
|
||||
let mut txt = Text::new();
|
||||
for line in trip_lines {
|
||||
txt.add(Line(line));
|
||||
}
|
||||
rows.push(txt.draw(ctx));
|
||||
}
|
||||
}
|
||||
InfoTab::Intersection(Tab::Throughput) => {
|
||||
let mut txt = Text::new();
|
||||
|
||||
txt.add(Line("Throughput").roboto_bold());
|
||||
txt.add(Line(format!(
|
||||
"Since midnight: {} agents crossed",
|
||||
prettyprint_usize(
|
||||
app.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.thruput_stats
|
||||
.count_per_intersection
|
||||
.get(id)
|
||||
)
|
||||
)));
|
||||
txt.add(Line(format!("In 20 minute buckets:")));
|
||||
rows.push(txt.draw(ctx));
|
||||
|
||||
rows.push(
|
||||
throughput(ctx, app, move |a, t| {
|
||||
a.throughput_intersection(t, id, Duration::minutes(20))
|
||||
})
|
||||
.margin(10),
|
||||
);
|
||||
}
|
||||
InfoTab::Intersection(Tab::Delay) => {
|
||||
assert!(app.primary.map.get_i(id).is_traffic_signal());
|
||||
let mut txt = Text::from(Line("Delay").roboto_bold());
|
||||
txt.add(Line(format!("In 20 minute buckets:")));
|
||||
rows.push(txt.draw(ctx));
|
||||
|
||||
rows.push(delay(ctx, app, id, Duration::minutes(20)).margin(10));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
rows
|
||||
|
@ -1,21 +1,28 @@
|
||||
use crate::app::App;
|
||||
use crate::info::{make_table, throughput};
|
||||
use crate::info::{make_table, throughput, InfoTab};
|
||||
use abstutil::prettyprint_usize;
|
||||
use ezgui::{EventCtx, Line, Text, TextExt, Widget};
|
||||
use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget};
|
||||
use geom::Duration;
|
||||
use map_model::LaneID;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Tab {
|
||||
OSM,
|
||||
Debug,
|
||||
Throughput,
|
||||
}
|
||||
|
||||
pub fn info(
|
||||
ctx: &EventCtx,
|
||||
app: &App,
|
||||
id: LaneID,
|
||||
tab: InfoTab,
|
||||
header_btns: Widget,
|
||||
action_btns: Vec<Widget>,
|
||||
) -> Vec<Widget> {
|
||||
let mut rows = vec![];
|
||||
|
||||
let map = &app.primary.map;
|
||||
|
||||
let l = map.get_l(id);
|
||||
let r = map.get_r(l.parent);
|
||||
|
||||
@ -25,28 +32,45 @@ pub fn info(
|
||||
header_btns,
|
||||
]));
|
||||
rows.push(format!("@ {}", r.get_name()).draw_text(ctx));
|
||||
rows.extend(action_btns);
|
||||
|
||||
// Properties
|
||||
{
|
||||
let mut kv = Vec::new();
|
||||
// TODO Inactive
|
||||
// TODO Naming, style...
|
||||
rows.push(Widget::row(vec![
|
||||
Btn::text_bg2("Main").build_def(ctx, None),
|
||||
Btn::text_bg2("OpenStreetMap").build_def(ctx, None),
|
||||
Btn::text_bg2("Debug").build_def(ctx, None),
|
||||
Btn::text_bg2("Traffic").build_def(ctx, None),
|
||||
]));
|
||||
|
||||
if !l.is_sidewalk() {
|
||||
kv.push(("Type".to_string(), l.lane_type.describe().to_string()));
|
||||
match tab {
|
||||
InfoTab::Nil => {
|
||||
rows.extend(action_btns);
|
||||
|
||||
let mut kv = Vec::new();
|
||||
|
||||
if !l.is_sidewalk() {
|
||||
kv.push(("Type".to_string(), l.lane_type.describe().to_string()));
|
||||
}
|
||||
|
||||
if l.is_parking() {
|
||||
kv.push((
|
||||
"Parking".to_string(),
|
||||
format!("{} spots, parallel parking", l.number_parking_spots()),
|
||||
));
|
||||
} else {
|
||||
kv.push(("Speed limit".to_string(), r.get_speed_limit().to_string()));
|
||||
}
|
||||
|
||||
kv.push(("Length".to_string(), l.length().describe_rounded()));
|
||||
|
||||
rows.extend(make_table(ctx, kv));
|
||||
}
|
||||
|
||||
if l.is_parking() {
|
||||
kv.push((
|
||||
"Parking".to_string(),
|
||||
format!("{} spots, parallel parking", l.number_parking_spots()),
|
||||
));
|
||||
} else {
|
||||
kv.push(("Speed limit".to_string(), r.get_speed_limit().to_string()));
|
||||
InfoTab::Lane(Tab::OSM) => {
|
||||
rows.extend(make_table(ctx, r.osm_tags.clone().into_iter().collect()));
|
||||
}
|
||||
InfoTab::Lane(Tab::Debug) => {
|
||||
let mut kv = Vec::new();
|
||||
|
||||
kv.push(("Length".to_string(), l.length().describe_rounded()));
|
||||
|
||||
if app.opts.dev {
|
||||
kv.push(("Parent".to_string(), r.id.to_string()));
|
||||
|
||||
if l.is_driving() {
|
||||
@ -88,38 +112,35 @@ pub fn info(
|
||||
),
|
||||
));
|
||||
|
||||
for (k, v) in &r.osm_tags {
|
||||
kv.push((k.to_string(), v.to_string()));
|
||||
}
|
||||
rows.extend(make_table(ctx, kv));
|
||||
}
|
||||
InfoTab::Lane(Tab::Throughput) => {
|
||||
// Since this applies to the entire road, ignore lane type.
|
||||
let mut txt = Text::from(Line(""));
|
||||
txt.add(Line("Throughput (entire road)").roboto_bold());
|
||||
txt.add(Line(format!(
|
||||
"Since midnight: {} agents crossed",
|
||||
prettyprint_usize(
|
||||
app.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.thruput_stats
|
||||
.count_per_road
|
||||
.get(r.id)
|
||||
)
|
||||
)));
|
||||
txt.add(Line(format!("In 20 minute buckets:")));
|
||||
rows.push(txt.draw(ctx));
|
||||
|
||||
rows.extend(make_table(ctx, kv));
|
||||
}
|
||||
|
||||
if !l.is_parking() {
|
||||
let mut txt = Text::from(Line(""));
|
||||
txt.add(Line("Throughput (entire road)").roboto_bold());
|
||||
txt.add(Line(format!(
|
||||
"Since midnight: {} agents crossed",
|
||||
prettyprint_usize(
|
||||
app.primary
|
||||
.sim
|
||||
.get_analytics()
|
||||
.thruput_stats
|
||||
.count_per_road
|
||||
.get(r.id)
|
||||
)
|
||||
)));
|
||||
txt.add(Line(format!("In 20 minute buckets:")));
|
||||
rows.push(txt.draw(ctx));
|
||||
|
||||
let r = app.primary.map.get_l(id).parent;
|
||||
rows.push(
|
||||
throughput(ctx, app, move |a, t| {
|
||||
a.throughput_road(t, r, Duration::minutes(20))
|
||||
})
|
||||
.margin(10),
|
||||
);
|
||||
let r = app.primary.map.get_l(id).parent;
|
||||
rows.push(
|
||||
throughput(ctx, app, move |a, t| {
|
||||
a.throughput_road(t, r, Duration::minutes(20))
|
||||
})
|
||||
.margin(10),
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
rows
|
||||
|
@ -42,6 +42,8 @@ pub enum InfoTab {
|
||||
// If we're live updating, the people inside could change! We're choosing to freeze the list
|
||||
// here.
|
||||
BldgPeople(Vec<PersonID>, usize),
|
||||
Lane(lane::Tab),
|
||||
Intersection(intersection::Tab),
|
||||
}
|
||||
|
||||
pub struct TripDetails {
|
||||
@ -139,9 +141,12 @@ impl InfoPanel {
|
||||
.align_right();
|
||||
let (col, trip_details) = match id.clone() {
|
||||
ID::Road(_) => unreachable!(),
|
||||
ID::Lane(id) => (lane::info(ctx, app, id, header_btns, action_btns), None),
|
||||
ID::Lane(id) => (
|
||||
lane::info(ctx, app, id, tab.clone(), header_btns, action_btns),
|
||||
None,
|
||||
),
|
||||
ID::Intersection(id) => (
|
||||
intersection::info(ctx, app, id, header_btns, action_btns),
|
||||
intersection::info(ctx, app, id, tab.clone(), header_btns, action_btns),
|
||||
None,
|
||||
),
|
||||
ID::Turn(_) => unreachable!(),
|
||||
@ -407,6 +412,68 @@ impl InfoPanel {
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
// TODO For lanes. This is an insane mess...
|
||||
} else if action == "Main" {
|
||||
*self = InfoPanel::new(
|
||||
self.id.clone(),
|
||||
// TODO For both lanes and intersections...
|
||||
InfoTab::Nil,
|
||||
ctx,
|
||||
app,
|
||||
self.actions.clone(),
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
} else if action == "OpenStreetMap" {
|
||||
*self = InfoPanel::new(
|
||||
self.id.clone(),
|
||||
InfoTab::Lane(lane::Tab::OSM),
|
||||
ctx,
|
||||
app,
|
||||
self.actions.clone(),
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
} else if action == "Debug" {
|
||||
*self = InfoPanel::new(
|
||||
self.id.clone(),
|
||||
InfoTab::Lane(lane::Tab::Debug),
|
||||
ctx,
|
||||
app,
|
||||
self.actions.clone(),
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
} else if action == "Traffic" {
|
||||
*self = InfoPanel::new(
|
||||
self.id.clone(),
|
||||
InfoTab::Lane(lane::Tab::Throughput),
|
||||
ctx,
|
||||
app,
|
||||
self.actions.clone(),
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
} else if action == "Throughput" {
|
||||
*self = InfoPanel::new(
|
||||
self.id.clone(),
|
||||
InfoTab::Intersection(intersection::Tab::Throughput),
|
||||
ctx,
|
||||
app,
|
||||
self.actions.clone(),
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
} else if action == "Delay" {
|
||||
*self = InfoPanel::new(
|
||||
self.id.clone(),
|
||||
InfoTab::Intersection(intersection::Tab::Delay),
|
||||
ctx,
|
||||
app,
|
||||
self.actions.clone(),
|
||||
maybe_speed,
|
||||
);
|
||||
return (false, None);
|
||||
} else {
|
||||
app.primary.current_selection = Some(self.id.clone());
|
||||
(true, Some(Transition::ApplyObjectAction(action)))
|
||||
|
Loading…
Reference in New Issue
Block a user