mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 02:33:54 +03:00
gather initial summary text for neighborhoods
This commit is contained in:
parent
2026acde32
commit
da786f9348
@ -5,12 +5,13 @@ use map_model::{LaneID, Map};
|
||||
use objects::{Ctx, DEBUG};
|
||||
use piston::input::Key;
|
||||
use plugins::{Plugin, PluginCtx};
|
||||
use sim::Neighborhood;
|
||||
use sim::{Neighborhood, Sim, Tick};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct NeighborhoodSummary {
|
||||
regions: Vec<Region>,
|
||||
active: bool,
|
||||
last_summary: Option<Tick>,
|
||||
}
|
||||
|
||||
impl NeighborhoodSummary {
|
||||
@ -22,6 +23,7 @@ impl NeighborhoodSummary {
|
||||
.map(|(idx, (_, n))| Region::new(idx, n, map))
|
||||
.collect(),
|
||||
active: false,
|
||||
last_summary: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -41,6 +43,16 @@ impl Plugin for NeighborhoodSummary {
|
||||
.unimportant_key_pressed(Key::Z, DEBUG, "show neighborhood summaries");
|
||||
}
|
||||
|
||||
if self.active && Some(ctx.primary.sim.time) != self.last_summary {
|
||||
self.last_summary = Some(ctx.primary.sim.time);
|
||||
for r in self.regions.iter_mut() {
|
||||
r.update_summary(
|
||||
&ctx.primary.sim,
|
||||
ctx.secondary.as_ref().map(|(s, _)| &s.sim),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.active
|
||||
}
|
||||
|
||||
@ -50,12 +62,9 @@ impl Plugin for NeighborhoodSummary {
|
||||
}
|
||||
|
||||
for r in &self.regions {
|
||||
// TODO some text
|
||||
g.draw_polygon(r.color, &r.polygon);
|
||||
|
||||
let mut txt = Text::new();
|
||||
txt.add_line(format!("{} has {} lanes", r.name, r.lanes.len()));
|
||||
ctx.canvas.draw_text_at(g, txt, r.center);
|
||||
// TODO ezgui should take borrows
|
||||
ctx.canvas.draw_text_at(g, r.summary.clone(), r.center);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,6 +76,7 @@ struct Region {
|
||||
center: Pt2D,
|
||||
lanes: HashSet<LaneID>,
|
||||
color: Color,
|
||||
summary: Text,
|
||||
}
|
||||
|
||||
impl Region {
|
||||
@ -84,14 +94,44 @@ impl Region {
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
let mut summary = Text::new();
|
||||
summary.add_line(format!("{} - no summary yet", n.name));
|
||||
Region {
|
||||
name: n.name.clone(),
|
||||
polygon,
|
||||
center,
|
||||
lanes,
|
||||
color: COLORS[idx % COLORS.len()],
|
||||
summary,
|
||||
}
|
||||
}
|
||||
|
||||
fn update_summary(&mut self, primary: &Sim, maybe_secondary: Option<&Sim>) {
|
||||
let mut txt = Text::new();
|
||||
txt.add_line(format!("{} has {} lanes", self.name, self.lanes.len()));
|
||||
|
||||
if let Some(secondary) = maybe_secondary {
|
||||
// TODO colors
|
||||
} else {
|
||||
let s = primary.summarize(&self.lanes);
|
||||
|
||||
txt.add_line(format!(
|
||||
"{} cars parked, {} spots free",
|
||||
s.cars_parked, s.open_parking_spots
|
||||
));
|
||||
txt.add_line(format!(
|
||||
"{} moving cars, {} stuck",
|
||||
s.moving_cars, s.stuck_cars
|
||||
));
|
||||
txt.add_line(format!(
|
||||
"{} moving peds, {} stuck",
|
||||
s.moving_peds, s.stuck_peds
|
||||
));
|
||||
txt.add_line(format!("{} buses", s.buses));
|
||||
}
|
||||
|
||||
self.summary = txt;
|
||||
}
|
||||
}
|
||||
|
||||
const COLORS: [Color; 3] = [
|
||||
|
@ -12,7 +12,7 @@ use parking::ParkingSimState;
|
||||
use rand::XorShiftRng;
|
||||
use router::Router;
|
||||
use std;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use transit::TransitSimState;
|
||||
use view::{AgentView, WorldView};
|
||||
use {
|
||||
@ -845,6 +845,29 @@ impl DrivingSimState {
|
||||
let c = &self.cars.get(&id)?;
|
||||
c.owner
|
||||
}
|
||||
|
||||
// TODO turns too
|
||||
pub fn count(&self, lanes: &HashSet<LaneID>) -> (usize, usize, usize) {
|
||||
let mut moving_cars = 0;
|
||||
let mut stuck_cars = 0;
|
||||
let mut buses = 0;
|
||||
|
||||
for l in lanes {
|
||||
for (_, car) in &self.lanes[l.0].cars_queue {
|
||||
let c = &self.cars[car];
|
||||
if c.speed <= kinematics::EPSILON_SPEED {
|
||||
stuck_cars += 1;
|
||||
} else {
|
||||
moving_cars += 1;
|
||||
}
|
||||
if c.is_bus {
|
||||
buses += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(moving_cars, stuck_cars, buses)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CreateCar {
|
||||
|
@ -61,7 +61,7 @@ pub use instrument::save_backtraces;
|
||||
use map_model::{BuildingID, LaneID, Trace, TurnID};
|
||||
use rand::{RngCore, SeedableRng, XorShiftRng};
|
||||
pub use scenario::{Neighborhood, Scenario, SeedParkedCars, SpawnOverTime};
|
||||
pub use sim::{Benchmark, Sim};
|
||||
pub use sim::{Benchmark, Sim, Summary};
|
||||
use std::fmt;
|
||||
pub use trips::ScoreSummary;
|
||||
|
||||
|
@ -2,6 +2,7 @@ use geom::{Angle, Pt2D};
|
||||
use kinematics::Vehicle;
|
||||
use map_model;
|
||||
use map_model::{BuildingID, Lane, LaneID, LaneType, Map};
|
||||
use std::collections::HashSet;
|
||||
use std::iter;
|
||||
use {CarID, Distance, DrawCarInput, ParkedCar, ParkingSpot};
|
||||
|
||||
@ -143,6 +144,23 @@ impl ParkingSimState {
|
||||
pub fn get_owner_of_car(&self, id: CarID) -> Option<BuildingID> {
|
||||
self.lookup_car(id).and_then(|p| p.owner)
|
||||
}
|
||||
|
||||
pub fn count(&self, lanes: &HashSet<LaneID>) -> (usize, usize) {
|
||||
let mut cars_parked = 0;
|
||||
let mut open_parking_spots = 0;
|
||||
|
||||
for id in lanes {
|
||||
for maybe_car in &self.lanes[id.0].occupants {
|
||||
if maybe_car.is_some() {
|
||||
cars_parked += 1;
|
||||
} else {
|
||||
open_parking_spots += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(cars_parked, open_parking_spots)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -13,6 +13,7 @@ use parking::ParkingSimState;
|
||||
use rand::{FromEntropy, SeedableRng, XorShiftRng};
|
||||
use spawn::Spawner;
|
||||
use std;
|
||||
use std::collections::HashSet;
|
||||
use std::f64;
|
||||
use std::process;
|
||||
use std::time::{Duration, Instant};
|
||||
@ -255,19 +256,6 @@ impl Sim {
|
||||
self.walking_state.get_draw_peds_on_turn(map.get_t(t))
|
||||
}
|
||||
|
||||
pub fn summary(&self) -> String {
|
||||
let (waiting_cars, active_cars) = self.driving_state.get_active_and_waiting_count();
|
||||
let (waiting_peds, active_peds) = self.walking_state.get_active_and_waiting_count();
|
||||
format!(
|
||||
"Time: {0}, {1} / {2} active cars waiting, {3} cars parked, {4} / {5} pedestrians waiting",
|
||||
self.time,
|
||||
waiting_cars,
|
||||
active_cars,
|
||||
self.parking_state.total_count(),
|
||||
waiting_peds, active_peds,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.time == Tick::zero() && self.is_done()
|
||||
}
|
||||
@ -422,6 +410,38 @@ impl Sim {
|
||||
.get_owner_of_car(id)
|
||||
.or_else(|| self.parking_state.get_owner_of_car(id))
|
||||
}
|
||||
|
||||
// TODO deprecate this, use the new Summary
|
||||
pub fn summary(&self) -> String {
|
||||
let (waiting_cars, active_cars) = self.driving_state.get_active_and_waiting_count();
|
||||
let (waiting_peds, active_peds) = self.walking_state.get_active_and_waiting_count();
|
||||
format!(
|
||||
"Time: {0}, {1} / {2} active cars waiting, {3} cars parked, {4} / {5} pedestrians waiting",
|
||||
self.time,
|
||||
waiting_cars,
|
||||
active_cars,
|
||||
self.parking_state.total_count(),
|
||||
waiting_peds, active_peds,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn summarize(&self, lanes: &HashSet<LaneID>) -> Summary {
|
||||
let (cars_parked, open_parking_spots) = self.parking_state.count(lanes);
|
||||
let (moving_cars, stuck_cars, buses) = self.driving_state.count(lanes);
|
||||
let (moving_peds, stuck_peds) = self.walking_state.count(lanes);
|
||||
|
||||
Summary {
|
||||
cars_parked,
|
||||
open_parking_spots,
|
||||
moving_cars,
|
||||
stuck_cars,
|
||||
buses,
|
||||
moving_peds,
|
||||
stuck_peds,
|
||||
// Something else has to calculate this
|
||||
trips_with_ab_test_divergence: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Benchmark {
|
||||
@ -434,3 +454,15 @@ impl Benchmark {
|
||||
self.last_real_time.elapsed() >= d
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Summary {
|
||||
pub cars_parked: usize,
|
||||
pub open_parking_spots: usize,
|
||||
pub moving_cars: usize,
|
||||
pub stuck_cars: usize,
|
||||
pub moving_peds: usize,
|
||||
pub stuck_peds: usize,
|
||||
pub buses: usize,
|
||||
// The agent in one or both worlds is in the requested set of lanes.
|
||||
pub trips_with_ab_test_divergence: usize,
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use map_model::{BuildingID, BusStopID, Lane, LaneID, Map, Trace, Traversable, Tu
|
||||
use multimap::MultiMap;
|
||||
use parking::ParkingSimState;
|
||||
use std;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::collections::{BTreeMap, HashSet, VecDeque};
|
||||
use trips::TripManager;
|
||||
use view::{AgentView, WorldView};
|
||||
use {
|
||||
@ -657,6 +657,25 @@ impl WalkingSimState {
|
||||
let p = self.peds.get(&id).unwrap();
|
||||
vec![format!("{} is part of {}", p.id, p.trip)]
|
||||
}
|
||||
|
||||
// TODO turns too
|
||||
pub fn count(&self, lanes: &HashSet<LaneID>) -> (usize, usize) {
|
||||
let mut moving_peds = 0;
|
||||
let mut stuck_peds = 0;
|
||||
|
||||
for l in lanes {
|
||||
for ped in self.peds_per_sidewalk.get_vec(&l).unwrap_or(&Vec::new()) {
|
||||
let p = &self.peds[ped];
|
||||
if p.waiting_for.is_some() {
|
||||
stuck_peds += 1;
|
||||
} else {
|
||||
moving_peds += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(moving_peds, stuck_peds)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_contraflow(map: &Map, from: LaneID, to: LaneID) -> bool {
|
||||
|
Loading…
Reference in New Issue
Block a user