info panel for bus stop has number of people waiting currently, time spent waiting

This commit is contained in:
Dustin Carlino 2020-01-04 10:11:22 -06:00
parent 9aac76ee39
commit fd2fbf6a5e
6 changed files with 53 additions and 30 deletions

View File

@ -261,7 +261,7 @@ fn info_for(id: ID, ui: &UI) -> Text {
}
ID::BusStop(id) => {
let all_arrivals = &sim.get_analytics().bus_arrivals;
let passengers = &sim.get_analytics().total_bus_passengers;
let mut waiting = sim.peds_waiting_stats(id);
for r in map.get_routes_serving_stop(id) {
txt.add_appended(vec![Line("- Route "), Line(&r.name).fg(name_color)]);
let arrivals: Vec<(Time, CarID)> = all_arrivals
@ -278,10 +278,9 @@ fn info_for(id: ID, ui: &UI) -> Text {
} else {
txt.add(Line(" No arrivals yet"));
}
txt.add(Line(format!(
" {} passengers total (any stop)",
prettyprint_usize(passengers.get(r.id))
)));
if let Some(hgram) = waiting.remove(&r.id) {
txt.add(Line(format!(" Waiting: {}", hgram.describe())));
}
}
}
ID::Area(id) => {

View File

@ -14,8 +14,6 @@ pub struct Analytics {
#[serde(skip_serializing, skip_deserializing)]
pub(crate) test_expectations: VecDeque<Event>,
pub bus_arrivals: Vec<(Time, CarID, BusRouteID, BusStopID)>,
#[serde(skip_serializing, skip_deserializing)]
pub total_bus_passengers: Counter<BusRouteID>,
// TODO Hack: No TripMode means aborted
// Finish time, ID, mode (or None as aborted), trip duration
pub finished_trips: Vec<(Time, TripID, Option<TripMode>, Duration)>,
@ -55,7 +53,6 @@ impl Analytics {
},
test_expectations: VecDeque::new(),
bus_arrivals: Vec::new(),
total_bus_passengers: Counter::new(),
finished_trips: Vec::new(),
trip_log: Vec::new(),
intersection_delays: BTreeMap::new(),
@ -116,11 +113,6 @@ impl Analytics {
self.bus_arrivals.push((time, bus, route, stop));
}
// Bus passengers
if let Event::PedEntersBus(_, _, route) = ev {
self.total_bus_passengers.inc(route);
}
// Finished trips
if let Event::TripFinished(id, mode, dt) = ev {
self.finished_trips.push((time, id, Some(mode), dt));

View File

@ -140,7 +140,7 @@ impl WalkingSimState {
}
SidewalkPOI::BusStop(stop) => {
if let Some(route) =
trips.ped_reached_bus_stop(ped.id, stop, map, transit)
trips.ped_reached_bus_stop(now, ped.id, stop, map, transit)
{
ped.state = PedState::WaitingForBus(route);
ped.blocked_since = Some(now);

View File

@ -8,10 +8,10 @@ use crate::{
};
use abstutil::Timer;
use derivative::Derivative;
use geom::{Distance, Duration, PolyLine, Pt2D, Time};
use geom::{Distance, Duration, DurationHistogram, PolyLine, Pt2D, Time};
use map_model::{
BuildingID, BusRoute, BusRouteID, IntersectionID, LaneID, Map, Path, PathConstraints,
PathRequest, PathStep, Traversable,
BuildingID, BusRoute, BusRouteID, BusStopID, IntersectionID, LaneID, Map, Path,
PathConstraints, PathRequest, PathStep, Traversable,
};
use serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashSet};
@ -1022,6 +1022,10 @@ impl Sim {
pub fn trip_spec_to_path_req(&self, spec: &TripSpec, map: &Map) -> PathRequest {
spec.get_pathfinding_request(map, &self.parking)
}
pub fn peds_waiting_stats(&self, stop: BusStopID) -> BTreeMap<BusRouteID, DurationHistogram> {
self.transit.peds_waiting_stats(self.time, stop)
}
}
// Invasive debugging

View File

@ -1,6 +1,6 @@
use crate::{CarID, Event, PedestrianID, Router, Scheduler, TripManager, WalkingSimState};
use abstutil::{deserialize_btreemap, serialize_btreemap};
use geom::{Distance, Time};
use geom::{Distance, DurationHistogram, Time};
use map_model::{
BusRoute, BusRouteID, BusStopID, Map, Path, PathConstraints, PathRequest, Position,
};
@ -53,8 +53,12 @@ pub struct TransitSimState {
deserialize_with = "deserialize_btreemap"
)]
routes: BTreeMap<BusRouteID, Route>,
// Can organize this more to make querying cheaper
peds_waiting: Vec<(PedestrianID, BusStopID, BusRouteID, BusStopID)>,
// waiting at => (ped, route, bound for, started waiting)
#[serde(
serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap"
)]
peds_waiting: BTreeMap<BusStopID, Vec<(PedestrianID, BusRouteID, BusStopID, Time)>>,
events: Vec<Event>,
}
@ -64,7 +68,7 @@ impl TransitSimState {
TransitSimState {
buses: BTreeMap::new(),
routes: BTreeMap::new(),
peds_waiting: Vec::new(),
peds_waiting: BTreeMap::new(),
events: Vec::new(),
}
}
@ -153,14 +157,14 @@ impl TransitSimState {
match bus.state {
BusState::DrivingToStop(stop_idx) => {
bus.state = BusState::AtStop(stop_idx);
let stop = self.routes[&bus.route].stops[stop_idx].id;
let stop1 = self.routes[&bus.route].stops[stop_idx].id;
self.events
.push(Event::BusArrivedAtStop(id, bus.route, stop));
.push(Event::BusArrivedAtStop(id, bus.route, stop1));
// Deboard existing passengers.
let mut still_riding = Vec::new();
for (ped, stop2) in bus.passengers.drain(..) {
if stop == stop2 {
if stop1 == stop2 {
self.events.push(Event::PedLeavesBus(ped, id, bus.route));
trips.ped_left_bus(now, ped, map, scheduler);
} else {
@ -171,8 +175,10 @@ impl TransitSimState {
// Board new passengers.
let mut still_waiting = Vec::new();
for (ped, stop1, route, stop2) in self.peds_waiting.drain(..) {
if stop == stop1 && bus.route == route {
for (ped, route, stop2, started_waiting) in
self.peds_waiting.remove(&stop1).unwrap_or_else(Vec::new)
{
if bus.route == route {
bus.passengers.push((ped, stop2));
self.events.push(Event::PedEntersBus(ped, id, route));
let trip = trips.ped_boarded_bus(ped, walking);
@ -186,10 +192,10 @@ impl TransitSimState {
format!("{} riding {}", ped, route),
));
} else {
still_waiting.push((ped, stop1, route, stop2));
still_waiting.push((ped, route, stop2, started_waiting));
}
}
self.peds_waiting = still_waiting;
self.peds_waiting.insert(stop1, still_waiting);
}
BusState::AtStop(_) => unreachable!(),
};
@ -217,6 +223,7 @@ impl TransitSimState {
// If true, the pedestrian boarded a bus immediately.
pub fn ped_waiting_for_bus(
&mut self,
now: Time,
ped: PedestrianID,
stop1: BusStopID,
route_id: BusRouteID,
@ -239,7 +246,10 @@ impl TransitSimState {
}
}
self.peds_waiting.push((ped, stop1, route_id, stop2));
self.peds_waiting
.entry(stop1)
.or_insert_with(Vec::new)
.push((ped, route_id, stop2, now));
false
}
@ -262,4 +272,21 @@ impl TransitSimState {
Vec::new()
}
}
pub fn peds_waiting_stats(
&self,
now: Time,
stop: BusStopID,
) -> BTreeMap<BusRouteID, DurationHistogram> {
let mut per_route = BTreeMap::new();
if let Some(list) = self.peds_waiting.get(&stop) {
for (_, route, _, since) in list {
per_route
.entry(*route)
.or_insert_with(DurationHistogram::new)
.add(now - *since);
}
}
per_route
}
}

View File

@ -329,6 +329,7 @@ impl TripManager {
// If no route is returned, the pedestrian boarded a bus immediately.
pub fn ped_reached_bus_stop(
&mut self,
now: Time,
ped: PedestrianID,
stop: BusStopID,
map: &Map,
@ -350,7 +351,7 @@ impl TripManager {
None,
format!("{} waiting at {:?} for {}", ped, stop, route),
));
if transit.ped_waiting_for_bus(ped, stop, route, stop2) {
if transit.ped_waiting_for_bus(now, ped, stop, route, stop2) {
trip.legs.pop_front();
None
} else {