cleaning up trip_details

This commit is contained in:
Dustin Carlino 2020-02-12 16:17:41 -08:00
parent 5948f226a6
commit 1f0b225b6b
8 changed files with 116 additions and 105 deletions

View File

@ -173,7 +173,8 @@ impl ColorLegend {
color,
Circle::new(Pt2D::new(radius, radius), Distance::meters(radius)).to_polygon(),
)]),
),
)
.margin(5),
ManagedWidget::draw_text(ctx, Text::from(Line(label))),
])
}

View File

@ -13,7 +13,7 @@ use ezgui::{
};
use geom::{Circle, Distance, Duration, Statistic, Time};
use map_model::{IntersectionID, RoadID};
use sim::{CarID, TripEnd, TripID, TripMode, TripStart, VehicleType};
use sim::{AgentID, CarID, TripEnd, TripID, TripMode, TripStart, VehicleType};
use std::collections::BTreeSet;
pub struct InfoPanel {
@ -50,7 +50,15 @@ impl InfoPanel {
let trip_details = if let Some(trip) = match id {
ID::Trip(t) => Some(t),
_ => id.agent_id().and_then(|a| ui.primary.sim.agent_to_trip(a)),
ID::Car(c) => {
if c.1 == VehicleType::Bus {
None
} else {
ui.primary.sim.agent_to_trip(AgentID::Car(c))
}
}
ID::Pedestrian(p) => ui.primary.sim.agent_to_trip(AgentID::Pedestrian(p)),
_ => None,
} {
let (rows, unzoomed, zoomed) = trip_details(trip, ctx, ui);
col.push(rows);
@ -748,20 +756,63 @@ fn color_for_mode(m: TripMode, ui: &UI) -> Color {
fn trip_details(trip: TripID, ctx: &mut EventCtx, ui: &UI) -> (ManagedWidget, Drawable, Drawable) {
let map = &ui.primary.map;
let phases = ui.primary.sim.get_analytics().get_trip_phases(trip, map);
let (trip_start, trip_end) = ui.primary.sim.trip_endpoints(trip);
let mut col = vec![ManagedWidget::draw_text(
ctx,
Text::from(Line(trip.to_string())),
)];
let mut col = vec![ManagedWidget::draw_text(ctx, {
let mut txt = Text::from(Line(""));
txt.add(Line("Trip timeline").roboto_bold());
txt
})];
let mut unzoomed = GeomBatch::new();
let mut zoomed = GeomBatch::new();
for (idx, p) in phases.into_iter().enumerate() {
let color = rotating_color_map(idx + 1);
// Start
{
let color = rotating_color_map(col.len() - 1);
match trip_start {
TripStart::Bldg(b) => {
let bldg = map.get_b(b);
col.push(ColorLegend::row(
ctx,
color,
format!(
"{}: leave {}",
phases[0].start_time.ampm_tostring(),
bldg.just_address(map)
),
));
unzoomed.push(color, bldg.polygon.clone());
zoomed.push(color, bldg.polygon.clone());
}
TripStart::Border(i) => {
let i = map.get_i(i);
// TODO How to name the intersection succinctly?
col.push(ColorLegend::row(
ctx,
color,
format!(
"{}: start at {}",
phases[0].start_time.ampm_tostring(),
i.id
),
));
unzoomed.push(color, i.polygon.clone());
zoomed.push(color, i.polygon.clone());
}
};
}
let mut end_time = None;
for p in phases {
let color = rotating_color_map(col.len() - 1);
col.push(ColorLegend::row(
ctx,
color,
p.describe(ui.primary.sim.time()),
if let Some(t2) = p.end_time {
format!("+{}: {}", t2 - p.start_time, p.description)
} else {
format!("ongoing: {}", p.description)
},
));
// TODO Could really cache this between live updates
@ -779,71 +830,43 @@ fn trip_details(trip: TripID, ctx: &mut EventCtx, ui: &UI) -> (ManagedWidget, Dr
);
}
}
end_time = p.end_time;
}
// Handle endpoints
let (trip_start, trip_end) = ui.primary.sim.trip_endpoints(trip);
let start_color = rotating_color_map(0);
match trip_start {
TripStart::Bldg(b) => {
let bldg = map.get_b(b);
col.insert(
1,
ColorLegend::row(ctx, start_color, format!("start at {}", bldg.get_name(map))),
);
unzoomed.push(start_color, bldg.polygon.clone());
zoomed.push(start_color, bldg.polygon.clone());
}
TripStart::Border(i) => {
let i = map.get_i(i);
col.insert(
1,
ColorLegend::row(ctx, start_color, format!("enter map via {}", i.id)),
);
unzoomed.push(start_color, i.polygon.clone());
zoomed.push(start_color, i.polygon.clone());
}
};
// Is the trip ongoing?
if let Some(pt) = ui.primary.sim.get_canonical_pt_per_trip(trip, map).ok() {
let color = rotating_color_map(col.len());
unzoomed.push(color, Circle::new(pt, Distance::meters(10.0)).to_polygon());
// Don't need anything when zoomed; the info panel already focuses on them.
col.push(ColorLegend::row(ctx, color, "currently here"));
// End
{
let color = rotating_color_map(col.len() - 1);
let time = if let Some(t) = end_time {
format!("{}: ", t.ampm_tostring())
} else {
String::new()
};
match trip_end {
TripEnd::Bldg(b) => {
let bldg = map.get_b(b);
col.push(ColorLegend::row(
ctx,
color,
format!("{}end at {}", time, bldg.just_address(map)),
));
unzoomed.push(color, bldg.polygon.clone());
zoomed.push(color, bldg.polygon.clone());
}
TripEnd::Border(i) => {
let i = map.get_i(i);
// TODO name it better
col.push(ColorLegend::row(
ctx,
color,
format!("{}end at {}", time, i.id),
));
unzoomed.push(color, i.polygon.clone());
zoomed.push(color, i.polygon.clone());
}
TripEnd::ServeBusRoute(_) => unreachable!(),
};
}
let end_color = rotating_color_map(col.len());
match trip_end {
TripEnd::Bldg(b) => {
let bldg = map.get_b(b);
col.push(ColorLegend::row(
ctx,
end_color,
format!("end at {}", bldg.get_name(map)),
));
unzoomed.push(end_color, bldg.polygon.clone());
zoomed.push(end_color, bldg.polygon.clone());
}
TripEnd::Border(i) => {
let i = map.get_i(i);
col.push(ColorLegend::row(
ctx,
end_color,
format!("leave map via {}", i.id),
));
unzoomed.push(end_color, i.polygon.clone());
zoomed.push(end_color, i.polygon.clone());
}
TripEnd::ServeBusRoute(br) => {
col.push(ColorLegend::row(
ctx,
end_color,
format!("serve route {} forever", map.get_br(br).name),
));
}
};
(
ManagedWidget::col(col),
unzoomed.upload(ctx),

View File

@ -120,7 +120,7 @@ fn dump_debug(id: ID, map: &Map, sim: &Sim, draw_map: &DrawMap) {
if let Some(t) = sim.agent_to_trip(AgentID::Car(id)) {
println!("Trip log for {}", t);
for p in sim.get_analytics().get_trip_phases(t, map) {
println!("- {}", p.describe(sim.time()));
println!("- {:?}", p);
}
}
}
@ -129,7 +129,7 @@ fn dump_debug(id: ID, map: &Map, sim: &Sim, draw_map: &DrawMap) {
if let Some(t) = sim.agent_to_trip(AgentID::Pedestrian(id)) {
println!("Trip log for {}", t);
for p in sim.get_analytics().get_trip_phases(t, map) {
println!("- {}", p.describe(sim.time()));
println!("- {:?}", p);
}
}
}

View File

@ -551,6 +551,7 @@ impl Default for Analytics {
}
}
#[derive(Debug)]
pub struct TripPhase {
pub start_time: Time,
pub end_time: Option<Time>,
@ -559,27 +560,6 @@ pub struct TripPhase {
pub description: String,
}
impl TripPhase {
pub fn describe(&self, now: Time) -> String {
if let Some(t2) = self.end_time {
format!(
"{} .. {} ({}): {}",
self.start_time,
t2,
t2 - self.start_time,
self.description
)
} else {
format!(
"{} .. ongoing ({} so far): {}",
self.start_time,
now - self.start_time,
self.description
)
}
}
}
struct Window {
times: VecDeque<Time>,
window_size: Duration,

View File

@ -3,7 +3,7 @@ use crate::mechanics::Queue;
use crate::{
ActionAtEnd, AgentID, AgentMetadata, CarID, Command, CreateCar, DistanceInterval, DrawCarInput,
Event, IntersectionSimState, ParkedCar, ParkingSimState, Scheduler, TimeInterval,
TransitSimState, TripManager, TripPositions, UnzoomedAgent, WalkingSimState,
TransitSimState, TripManager, TripPositions, UnzoomedAgent, VehicleType, WalkingSimState,
FOLLOWING_DISTANCE,
};
use abstutil::{deserialize_btreemap, serialize_btreemap};
@ -871,7 +871,7 @@ impl DrivingSimState {
) -> Option<(Vec<(String, String)>, Vec<String>)> {
let car = self.cars.get(&id)?;
let path = car.router.get_path();
let props = vec![
let mut props = vec![
(
"Owner".to_string(),
if let Some(b) = car.vehicle.owner {
@ -905,6 +905,10 @@ impl DrivingSimState {
.to_string(),
),
];
// No owner
if id.1 == VehicleType::Bus {
props.remove(0);
}
Some((props, Vec::new()))
}

View File

@ -399,7 +399,11 @@ impl Sim {
events.push(Event::TripPhaseStarting(
create_car.trip,
Some(create_car.req.clone()),
format!("{}", create_car.vehicle.id),
if create_car.vehicle.id.1 == VehicleType::Car {
"driving".to_string()
} else {
"biking".to_string()
},
));
self.analytics
.record_demand(create_car.router.get_path(), map);
@ -482,12 +486,7 @@ impl Sim {
events.push(Event::TripPhaseStarting(
create_ped.trip,
Some(create_ped.req.clone()),
format!(
"{} from {:?} to {:?}",
create_ped.id,
create_ped.start.connection,
create_ped.goal.connection
),
"walking".to_string(),
));
self.analytics.record_demand(&create_ped.path, map);
@ -871,6 +870,10 @@ impl Sim {
pub fn car_properties(&self, car: CarID, map: &Map) -> (Vec<(String, String)>, Vec<String>) {
if let Some((mut props, extra)) = self.driving.car_properties(car, self.time, map) {
if car.1 == VehicleType::Bus {
props.push((
"Route".to_string(),
map.get_br(self.transit.bus_route(car)).name.clone(),
));
let passengers = self.transit.get_passengers(car);
props.push(("Passengers".to_string(), passengers.len().to_string()));
// TODO Clean this up

View File

@ -189,7 +189,7 @@ impl TransitSimState {
end: map.get_bs(stop2).driving_pos,
constraints: PathConstraints::Bus,
}),
format!("{} riding {}", ped, route),
format!("riding bus {}", map.get_br(route).name),
));
} else {
still_waiting.push((ped, route, stop2, started_waiting));

View File

@ -352,7 +352,7 @@ impl TripManager {
self.events.push(Event::TripPhaseStarting(
trip.id,
None,
format!("{} waiting at {:?} for {}", ped, stop, route),
format!("waiting for bus {}", map.get_br(route).name),
));
if transit.ped_waiting_for_bus(now, ped, stop, route, stop2) {
trip.legs.pop_front();