mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
info panel for bus stop has number of people waiting currently, time spent waiting
This commit is contained in:
parent
9aac76ee39
commit
fd2fbf6a5e
@ -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) => {
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user