gather initial summary text for neighborhoods

This commit is contained in:
Dustin Carlino 2018-10-23 14:09:07 -07:00
parent 2026acde32
commit da786f9348
6 changed files with 154 additions and 22 deletions

View File

@ -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] = [

View File

@ -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 {

View File

@ -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;

View File

@ -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)]

View File

@ -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,
}

View File

@ -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 {