enum for trip phases

This commit is contained in:
Dustin Carlino 2020-03-03 12:42:51 -08:00
parent 08cd956faa
commit cc1ee8384a
9 changed files with 102 additions and 71 deletions

View File

@ -221,9 +221,9 @@ f9f0a109966db097617a13122ecaa6f3 data/system/scenarios/downtown/weekday.bin
dd54763cfda7fce4c401ae122c6daf57 data/system/scenarios/huge_seattle/weekday.bin
47dea892a1c4331da02494d15ce02a02 data/system/scenarios/caphill/weekday.bin
7d6a8e8f5d716ce8674ed63d27f2da51 data/system/scenarios/montlake/weekday.bin
678efca4f16d5d8ce6bd88efd3afe957 data/system/prebaked_results/23rd/weekday.bin
d14e39816482a53c2d05e593f5f47249 data/system/prebaked_results/signal_single/tutorial lvl1.bin
22a6458bcf4bbb1cd875e12bcf012c08 data/system/prebaked_results/signal_single/tutorial lvl2.bin
460bd68fcc0c4686db7d654de372f46d data/system/prebaked_results/montlake/car vs bike contention.bin
12b13a7c7fd8cb2592607aa79b55558b data/system/prebaked_results/montlake/weekday.bin
160ff09f5c38d96fe83c4e9fcddfb019 data/system/prebaked_results/montlake/car vs bus contention.bin
b50d41d25ba40504df5a56945769bb27 data/system/prebaked_results/23rd/weekday.bin
c83401e693ea9bb2c437ecdcc33fadbf data/system/prebaked_results/signal_single/tutorial lvl1.bin
e8cdc329b7c10914df88ea3d4df6abd0 data/system/prebaked_results/signal_single/tutorial lvl2.bin
b8137879ec00add4cd2a39e8c985420f data/system/prebaked_results/montlake/car vs bike contention.bin
029227cdea45492954e3b1666b0dc5b9 data/system/prebaked_results/montlake/weekday.bin
994677ade10b0d021f3a0eb91696265c data/system/prebaked_results/montlake/car vs bus contention.bin

View File

@ -14,7 +14,9 @@ use ezgui::{
};
use geom::{Angle, Circle, Distance, Duration, Polygon, Pt2D, Statistic, Time};
use map_model::{IntersectionID, IntersectionType, RoadID};
use sim::{AgentID, CarID, TripEnd, TripID, TripMode, TripResult, TripStart, VehicleType};
use sim::{
AgentID, CarID, TripEnd, TripID, TripMode, TripPhaseType, TripResult, TripStart, VehicleType,
};
use std::collections::{BTreeSet, HashMap};
pub struct InfoPanel {
@ -1036,10 +1038,16 @@ fn trip_details(
let mut timeline = Vec::new();
let num_phases = phases.len();
for (idx, p) in phases.into_iter().enumerate() {
// TODO based on segment type
let color = rotating_color_map(timeline.len());
let color = match p.phase_type {
TripPhaseType::Driving => Color::hex("#D63220"),
TripPhaseType::Walking => Color::hex("#DF8C3D"),
TripPhaseType::Parking => Color::hex("#4E30A6"),
// TODO The others
_ => rotating_color_map(timeline.len()),
}
.alpha(0.7);
let mut txt = Text::from(Line(&p.description));
let mut txt = Text::from(Line(&p.phase_type.describe(&app.primary.map)));
txt.add(Line(format!(
"- Started at {}",
p.start_time.ampm_tostring()
@ -1070,27 +1078,24 @@ fn trip_details(
);
}
}
// TODO Hardcoded layouting...
normal.add_svg(
ctx.prerender,
if p.description == "driving" {
"../data/system/assets/timeline/driving.svg"
} else if p.description == "walking" {
"../data/system/assets/timeline/walking.svg"
} else if p.description == "parking on the current lane"
|| p.description == "parking somewhere else"
{
"../data/system/assets/timeline/parking.svg"
} else {
// TODO Placeholder
"../data/system/assets/timeline/parking.svg"
},
Pt2D::new(0.5 * phase_width, -20.0),
1.0,
Angle::ZERO,
);
if let Some(icon) = match p.phase_type {
TripPhaseType::Driving => Some("../data/system/assets/timeline/driving.svg"),
TripPhaseType::Walking => Some("../data/system/assets/timeline/walking.svg"),
TripPhaseType::Parking => Some("../data/system/assets/timeline/parking.svg"),
// TODO Add in more
_ => None,
} {
normal.add_svg(
ctx.prerender,
icon,
// TODO Hardcoded layouting...
Pt2D::new(0.5 * phase_width, -20.0),
1.0,
Angle::ZERO,
);
}
let mut hovered = GeomBatch::from(vec![(colors::HOVERING, rect.clone())]);
let mut hovered = GeomBatch::from(vec![(color.alpha(1.0), rect.clone())]);
for (c, p) in normal.clone().consume().into_iter().skip(1) {
hovered.push(c, p);
}

View File

@ -1,4 +1,4 @@
use crate::{CarID, Event, TripID, TripMode};
use crate::{CarID, Event, TripID, TripMode, TripPhaseType};
use abstutil::Counter;
use derivative::Derivative;
use geom::{Distance, Duration, DurationHistogram, PercentageHistogram, Time};
@ -21,7 +21,7 @@ pub struct Analytics {
// Finish time, ID, mode (or None as aborted), trip duration
pub finished_trips: Vec<(Time, TripID, Option<TripMode>, Duration)>,
// TODO This subsumes finished_trips
pub trip_log: Vec<(Time, TripID, Option<PathRequest>, String)>,
pub trip_log: Vec<(Time, TripID, Option<PathRequest>, TripPhaseType)>,
pub intersection_delays: BTreeMap<IntersectionID, Vec<(Time, Duration)>>,
// After we restore from a savestate, don't record anything. This is only going to make sense
@ -148,16 +148,15 @@ impl Analytics {
// TODO Kinda hacky, but these all consume the event, so kinda bundle em.
match ev {
Event::TripPhaseStarting(id, _, maybe_req, metadata) => {
self.trip_log.push((time, id, maybe_req, metadata));
Event::TripPhaseStarting(id, _, maybe_req, phase_type) => {
self.trip_log.push((time, id, maybe_req, phase_type));
}
Event::TripAborted(id, _) => {
self.trip_log
.push((time, id, None, format!("trip aborted for some reason")));
self.trip_log.push((time, id, None, TripPhaseType::Aborted));
}
Event::TripFinished(id, _, _) => {
self.trip_log
.push((time, id, None, format!("trip finished")));
.push((time, id, None, TripPhaseType::Finished));
}
Event::PathAmended(path) => {
self.record_demand(&path, map);
@ -420,14 +419,14 @@ impl Analytics {
pub fn get_trip_phases(&self, trip: TripID, map: &Map) -> Vec<TripPhase> {
let mut phases: Vec<TripPhase> = Vec::new();
for (t, id, maybe_req, md) in &self.trip_log {
for (t, id, maybe_req, phase_type) in &self.trip_log {
if *id != trip {
continue;
}
if let Some(ref mut last) = phases.last_mut() {
last.end_time = Some(*t);
}
if md == "trip finished" || md == "trip aborted for some reason" {
if *phase_type == TripPhaseType::Finished || *phase_type == TripPhaseType::Aborted {
break;
}
phases.push(TripPhase {
@ -437,7 +436,7 @@ impl Analytics {
path: maybe_req
.as_ref()
.map(|req| (req.start.dist_along(), map.pathfind(req.clone()).unwrap())),
description: md.clone(),
phase_type: *phase_type,
})
}
phases
@ -445,16 +444,16 @@ impl Analytics {
fn get_all_trip_phases(&self) -> BTreeMap<TripID, Vec<TripPhase>> {
let mut trips = BTreeMap::new();
for (t, id, _, md) in &self.trip_log {
for (t, id, _, phase_type) in &self.trip_log {
let phases: &mut Vec<TripPhase> = trips.entry(*id).or_insert_with(Vec::new);
if let Some(ref mut last) = phases.last_mut() {
last.end_time = Some(*t);
}
if md == "trip finished" {
if *phase_type == TripPhaseType::Finished {
continue;
}
// Remove aborted trips
if md == "trip aborted for some reason" {
if *phase_type == TripPhaseType::Aborted {
trips.remove(id);
continue;
}
@ -463,7 +462,7 @@ impl Analytics {
end_time: None,
// Don't compute any paths
path: None,
description: md.clone(),
phase_type: *phase_type,
})
}
trips
@ -482,17 +481,14 @@ impl Analytics {
let mut overhead = Duration::ZERO;
for p in phases {
let dt = p.end_time.unwrap() - p.start_time;
// TODO New enum instead of strings, if there'll be more analyses like this
if p.description.starts_with("CarID(") {
driving_time += dt;
} else if p.description == "parking somewhere else"
|| p.description == "parking on the current lane"
{
overhead += dt;
} else if p.description.starts_with("PedestrianID(") {
overhead += dt;
} else {
// Waiting for a bus. Irrelevant.
match p.phase_type {
TripPhaseType::Driving => {
driving_time += dt;
}
TripPhaseType::Parking | TripPhaseType::Walking => {
overhead += dt;
}
_ => {}
}
}
// Only interested in trips with both
@ -615,7 +611,7 @@ pub struct TripPhase {
pub end_time: Option<Time>,
// Plumb along start distance
pub path: Option<(Distance, Path)>,
pub description: String,
pub phase_type: TripPhaseType,
}
struct Window {

View File

@ -1,7 +1,7 @@
use crate::{AgentID, CarID, ParkingSpot, PedestrianID, TripID, TripMode};
use geom::Duration;
use map_model::{
BuildingID, BusRouteID, BusStopID, IntersectionID, LaneID, Path, PathRequest, Traversable,
BuildingID, BusRouteID, BusStopID, IntersectionID, LaneID, Map, Path, PathRequest, Traversable,
};
use serde_derive::{Deserialize, Serialize};
@ -27,9 +27,36 @@ pub enum Event {
TripFinished(TripID, TripMode, Duration),
TripAborted(TripID, TripMode),
TripPhaseStarting(TripID, TripMode, Option<PathRequest>, String),
TripPhaseStarting(TripID, TripMode, Option<PathRequest>, TripPhaseType),
// Just use for parking replanning. Not happy about copying the full path in here, but the way
// to plumb info into Analytics is Event.
PathAmended(Path),
}
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum TripPhaseType {
Driving,
Walking,
Biking,
Parking,
WaitingForBus(BusRouteID),
RidingBus(BusRouteID),
Aborted,
Finished,
}
impl TripPhaseType {
pub fn describe(self, map: &Map) -> String {
match self {
TripPhaseType::Driving => "driving".to_string(),
TripPhaseType::Walking => "walking".to_string(),
TripPhaseType::Biking => "biking".to_string(),
TripPhaseType::Parking => "parking".to_string(),
TripPhaseType::WaitingForBus(r) => format!("waiting for bus {}", map.get_br(r).name),
TripPhaseType::RidingBus(r) => format!("riding bus {}", map.get_br(r).name),
TripPhaseType::Aborted => "trip aborted due to some bug".to_string(),
TripPhaseType::Finished => "trip finished".to_string(),
}
}
}

View File

@ -10,7 +10,7 @@ mod transit;
mod trips;
pub use self::analytics::{Analytics, TripPhase};
pub use self::events::Event;
pub use self::events::{Event, TripPhaseType};
pub use self::make::{
ABTest, BorderSpawnOverTime, OriginDestination, Scenario, SeedParkedCars, SimFlags,
SpawnOverTime, SpawnTrip, TripSpawner, TripSpec,

View File

@ -1,5 +1,7 @@
use crate::mechanics::Queue;
use crate::{Event, ParkingSimState, ParkingSpot, SidewalkSpot, TripID, TripMode, Vehicle};
use crate::{
Event, ParkingSimState, ParkingSpot, SidewalkSpot, TripID, TripMode, TripPhaseType, Vehicle,
};
use geom::Distance;
use map_model::{
BuildingID, IntersectionID, LaneID, Map, Path, PathConstraints, PathRequest, PathStep,
@ -200,7 +202,7 @@ impl Router {
end: new_pos,
constraints: PathConstraints::Car,
}),
format!("parking on the current lane"),
TripPhaseType::Parking,
));
*spot = Some((new_spot, new_pos.dist_along()));
} else {
@ -221,7 +223,7 @@ impl Router {
end: new_pos,
constraints: PathConstraints::Car,
}),
format!("parking somewhere else"),
TripPhaseType::Parking,
));
} else {
println!(

View File

@ -3,8 +3,8 @@ use crate::{
DrawPedestrianInput, DrivingGoal, DrivingSimState, Event, GetDrawAgents, IntersectionSimState,
ParkedCar, ParkingSimState, ParkingSpot, PedestrianID, Router, Scheduler, SidewalkPOI,
SidewalkSpot, TransitSimState, TripCount, TripEnd, TripID, TripLeg, TripManager, TripMode,
TripPositions, TripResult, TripSpawner, TripSpec, TripStart, UnzoomedAgent, VehicleSpec,
VehicleType, WalkingSimState, BUS_LENGTH,
TripPhaseType, TripPositions, TripResult, TripSpawner, TripSpec, TripStart, UnzoomedAgent,
VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH,
};
use abstutil::Timer;
use derivative::Derivative;
@ -440,9 +440,9 @@ impl Sim {
},
Some(create_car.req.clone()),
if create_car.vehicle.id.1 == VehicleType::Car {
"driving".to_string()
TripPhaseType::Driving
} else {
"biking".to_string()
TripPhaseType::Biking
},
));
self.analytics
@ -524,7 +524,7 @@ impl Sim {
create_ped.trip,
TripMode::Walk,
Some(create_ped.req.clone()),
"walking".to_string(),
TripPhaseType::Walking,
));
self.analytics.record_demand(&create_ped.path, map);

View File

@ -1,5 +1,6 @@
use crate::{
CarID, Event, PedestrianID, Router, Scheduler, TripManager, TripMode, WalkingSimState,
CarID, Event, PedestrianID, Router, Scheduler, TripManager, TripMode, TripPhaseType,
WalkingSimState,
};
use abstutil::{deserialize_btreemap, serialize_btreemap};
use geom::{Distance, Time};
@ -192,7 +193,7 @@ impl TransitSimState {
end: map.get_bs(stop2).driving_pos,
constraints: PathConstraints::Bus,
}),
format!("riding bus {}", map.get_br(route).name),
TripPhaseType::RidingBus(route),
));
} else {
still_waiting.push((ped, route, stop2, started_waiting));

View File

@ -1,7 +1,7 @@
use crate::{
AgentID, CarID, Command, CreateCar, CreatePedestrian, DrivingGoal, Event, ParkingSimState,
ParkingSpot, PedestrianID, Scheduler, SidewalkPOI, SidewalkSpot, TransitSimState, TripID,
Vehicle, VehicleType, WalkingSimState,
TripPhaseType, Vehicle, VehicleType, WalkingSimState,
};
use abstutil::{deserialize_btreemap, serialize_btreemap, Counter};
use geom::{Speed, Time};
@ -353,7 +353,7 @@ impl TripManager {
trip.id,
trip.mode,
None,
format!("waiting for bus {}", map.get_br(route).name),
TripPhaseType::WaitingForBus(route),
));
if transit.ped_waiting_for_bus(now, ped, stop, route, stop2) {
trip.legs.pop_front();