mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 12:43:38 +03:00
cleaning up trip_details
This commit is contained in:
parent
5948f226a6
commit
1f0b225b6b
@ -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))),
|
||||
])
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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()))
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user