making all plugins that compute stuff for Sim cache per time

This commit is contained in:
Dustin Carlino 2018-11-02 12:45:52 -07:00
parent af25404777
commit 82beccf86c
3 changed files with 151 additions and 111 deletions

View File

@ -4,11 +4,16 @@ use map_model::LANE_THICKNESS;
use objects::Ctx;
use piston::input::Key;
use plugins::{Plugin, PluginCtx};
use sim::{Sim, Tick};
pub enum DiffAllState {
Inactive,
// TODO Or do we want to augment DrawCars and DrawPeds, so we get automatic quadtree support?
Active(Vec<Line>),
Active {
time: Tick,
same_trips: usize,
lines: Vec<Line>,
},
}
impl DiffAllState {
@ -19,49 +24,52 @@ impl DiffAllState {
impl Plugin for DiffAllState {
fn event(&mut self, ctx: PluginCtx) -> bool {
let active = match self {
let primary_sim = &ctx.primary.sim;
let mut new_state: Option<DiffAllState> = None;
match self {
DiffAllState::Inactive => {
ctx.secondary.is_some()
if ctx.secondary.is_some()
&& ctx.primary.current_selection.is_none()
&& ctx.input.key_pressed(Key::D, "Diff all trips")
}
DiffAllState::Active(_) => {
!ctx.input.key_pressed(Key::Return, "Stop diffing all trips")
}
};
if active {
let primary_sim = &ctx.primary.sim;
let secondary_sim = ctx.secondary.as_ref().map(|(s, _)| &s.sim).unwrap();
let stats1 = primary_sim.get_stats();
let stats2 = secondary_sim.get_stats();
let mut same_trips = 0;
let mut lines: Vec<Line> = Vec::new();
for (trip, pt1) in &stats1.canonical_pt_per_trip {
if let Some(pt2) = stats2.canonical_pt_per_trip.get(trip) {
if pt1 == pt2 {
same_trips += 1;
} else {
lines.push(Line::new(*pt1, *pt2));
}
{
let secondary_sim = ctx.secondary.as_ref().map(|(s, _)| &s.sim).unwrap();
new_state = Some(diff_all(primary_sim, secondary_sim));
}
}
DiffAllState::Active { time, .. } => {
if ctx.input.key_pressed(Key::Return, "Stop diffing all trips") {
new_state = Some(DiffAllState::Inactive);
}
if *time != ctx.primary.sim.time {
let secondary_sim = ctx.secondary.as_ref().map(|(s, _)| &s.sim).unwrap();
new_state = Some(diff_all(primary_sim, secondary_sim));
}
}
};
if let Some(s) = new_state {
*self = s;
}
if let DiffAllState::Active {
same_trips,
ref lines,
..
} = self
{
ctx.osd.add_line(format!(
"{} trips same, {} trips different",
same_trips,
lines.len()
));
*self = DiffAllState::Active(lines);
true
} else {
*self = DiffAllState::Inactive;
false
}
active
}
fn draw(&self, g: &mut GfxCtx, ctx: Ctx) {
if let DiffAllState::Active(ref lines) = self {
if let DiffAllState::Active { ref lines, .. } = self {
for line in lines {
g.draw_line(
ctx.cs.get("diff agents line", Color::YELLOW),
@ -72,3 +80,24 @@ impl Plugin for DiffAllState {
}
}
}
fn diff_all(primary_sim: &Sim, secondary_sim: &Sim) -> DiffAllState {
let stats1 = primary_sim.get_stats();
let stats2 = secondary_sim.get_stats();
let mut same_trips = 0;
let mut lines: Vec<Line> = Vec::new();
for (trip, pt1) in &stats1.canonical_pt_per_trip {
if let Some(pt2) = stats2.canonical_pt_per_trip.get(trip) {
if pt1 == pt2 {
same_trips += 1;
} else {
lines.push(Line::new(*pt1, *pt2));
}
}
}
DiffAllState::Active {
time: primary_sim.time,
same_trips,
lines,
}
}

View File

@ -5,12 +5,13 @@ use map_model::{Trace, LANE_THICKNESS};
use objects::Ctx;
use piston::input::Key;
use plugins::{Plugin, PluginCtx};
use sim::TripID;
use sim::{Tick, TripID};
use std::f64;
pub enum DiffWorldsState {
Inactive,
Active {
time: Tick,
trip: TripID,
// These are all optional because mode-changes might cause temporary interruptions.
// Just point from primary world agent to secondary world agent.
@ -28,7 +29,7 @@ impl DiffWorldsState {
impl Plugin for DiffWorldsState {
fn event(&mut self, ctx: PluginCtx) -> bool {
let mut maybe_trip: Option<TripID> = None;
let mut new_state: Option<DiffWorldsState> = None;
match self {
DiffWorldsState::Inactive => {
if ctx.secondary.is_some() {
@ -38,58 +39,26 @@ impl Plugin for DiffWorldsState {
.input
.key_pressed(Key::B, &format!("Show {}'s parallel world", trip))
{
maybe_trip = Some(trip);
new_state = Some(diff_world(trip, ctx));
}
}
}
}
}
DiffWorldsState::Active { trip, .. } => {
DiffWorldsState::Active { time, trip, .. } => {
if ctx.input.key_pressed(
Key::Return,
&format!("Stop showing {}'s parallel world", trip),
) {
maybe_trip = None;
} else {
maybe_trip = Some(*trip);
new_state = Some(DiffWorldsState::Inactive);
} else if *time != ctx.primary.sim.time {
new_state = Some(diff_world(*trip, ctx));
}
}
}
if let Some(trip) = maybe_trip {
let primary_sim = &ctx.primary.sim;
let primary_map = &ctx.primary.map;
let (secondary_sim, secondary_map) = ctx
.secondary
.as_ref()
.map(|(s, _)| (&s.sim, &s.map))
.unwrap();
let pt1 = primary_sim.get_stats().canonical_pt_per_trip.get(&trip);
let pt2 = secondary_sim.get_stats().canonical_pt_per_trip.get(&trip);
let line = if pt1.is_some() && pt2.is_some() {
Some(Line::new(*pt1.unwrap(), *pt2.unwrap()))
} else {
None
};
let primary_route = primary_sim
.trip_to_agent(trip)
.and_then(|agent| primary_sim.trace_route(agent, primary_map, f64::MAX * si::M));
let secondary_route = secondary_sim.trip_to_agent(trip).and_then(|agent| {
secondary_sim.trace_route(agent, secondary_map, f64::MAX * si::M)
});
if line.is_none() || primary_route.is_none() || secondary_route.is_none() {
warn!("{} isn't present in both sims", trip);
}
*self = DiffWorldsState::Active {
trip,
line,
primary_route,
secondary_route,
};
} else {
*self = DiffWorldsState::Inactive;
if let Some(s) = new_state {
*self = s;
}
match self {
@ -130,3 +99,38 @@ impl Plugin for DiffWorldsState {
}
}
}
fn diff_world(trip: TripID, ctx: PluginCtx) -> DiffWorldsState {
let primary_sim = &ctx.primary.sim;
let primary_map = &ctx.primary.map;
let (secondary_sim, secondary_map) = ctx
.secondary
.as_ref()
.map(|(s, _)| (&s.sim, &s.map))
.unwrap();
let pt1 = primary_sim.get_stats().canonical_pt_per_trip.get(&trip);
let pt2 = secondary_sim.get_stats().canonical_pt_per_trip.get(&trip);
let line = if pt1.is_some() && pt2.is_some() {
Some(Line::new(*pt1.unwrap(), *pt2.unwrap()))
} else {
None
};
let primary_route = primary_sim
.trip_to_agent(trip)
.and_then(|agent| primary_sim.trace_route(agent, primary_map, f64::MAX * si::M));
let secondary_route = secondary_sim
.trip_to_agent(trip)
.and_then(|agent| secondary_sim.trace_route(agent, secondary_map, f64::MAX * si::M));
if line.is_none() || primary_route.is_none() || secondary_route.is_none() {
warn!("{} isn't present in both sims", trip);
}
DiffWorldsState::Active {
time: primary_sim.time,
trip,
line,
primary_route,
secondary_route,
}
}

View File

@ -4,76 +4,60 @@ use map_model::{Trace, LANE_THICKNESS};
use objects::Ctx;
use piston::input::Key;
use plugins::{Plugin, PluginCtx};
use sim::TripID;
use sim::{Tick, TripID};
use std::f64;
pub enum ShowRouteState {
Empty,
Active(TripID, Trace),
Inactive,
Active(Tick, TripID, Option<Trace>),
}
impl ShowRouteState {
pub fn new() -> ShowRouteState {
ShowRouteState::Empty
ShowRouteState::Inactive
}
}
impl Plugin for ShowRouteState {
fn event(&mut self, ctx: PluginCtx) -> bool {
let maybe_trip = match self {
ShowRouteState::Empty => ctx
.primary
.current_selection
.and_then(|id| id.agent_id())
.and_then(|agent| ctx.primary.sim.agent_to_trip(agent))
.and_then(|trip| {
let mut new_state: Option<ShowRouteState> = None;
match self {
ShowRouteState::Inactive => {
if let Some(trip) = ctx
.primary
.current_selection
.and_then(|id| id.agent_id())
.and_then(|agent| ctx.primary.sim.agent_to_trip(agent))
{
if ctx
.input
.key_pressed(Key::R, &format!("show {}'s route", trip))
{
Some(trip)
} else {
None
new_state = Some(show_route(trip, ctx));
}
}),
ShowRouteState::Active(trip, _) => {
};
}
ShowRouteState::Active(time, trip, _) => {
if ctx.input.key_pressed(Key::Return, "stop showing route") {
None
} else {
Some(*trip)
new_state = Some(ShowRouteState::Inactive);
} else if *time != ctx.primary.sim.time {
new_state = Some(show_route(*trip, ctx));
}
}
};
if let Some(trip) = maybe_trip {
if let Some(agent) = ctx.primary.sim.trip_to_agent(trip) {
// Trace along the entire route by passing in max distance
if let Some(trace) =
ctx.primary
.sim
.trace_route(agent, &ctx.primary.map, f64::MAX * si::M)
{
*self = ShowRouteState::Active(trip, trace);
} else {
warn!("{} has no trace right now", agent);
}
} else {
warn!(
"{} has no agent associated right now; is the trip done?",
trip
);
}
} else {
*self = ShowRouteState::Empty;
if let Some(s) = new_state {
*self = s;
}
match self {
ShowRouteState::Empty => false,
ShowRouteState::Inactive => false,
_ => true,
}
}
fn draw(&self, g: &mut GfxCtx, ctx: Ctx) {
if let ShowRouteState::Active(_, trace) = self {
if let ShowRouteState::Active(_, _, Some(trace)) = self {
g.draw_polygon(
ctx.cs.get("route", Color::rgba(255, 0, 0, 0.8)),
&trace.get_polyline().make_polygons_blindly(LANE_THICKNESS),
@ -81,3 +65,26 @@ impl Plugin for ShowRouteState {
}
}
}
fn show_route(trip: TripID, ctx: PluginCtx) -> ShowRouteState {
let time = ctx.primary.sim.time;
if let Some(agent) = ctx.primary.sim.trip_to_agent(trip) {
// Trace along the entire route by passing in max distance
if let Some(trace) = ctx
.primary
.sim
.trace_route(agent, &ctx.primary.map, f64::MAX * si::M)
{
ShowRouteState::Active(time, trip, Some(trace))
} else {
warn!("{} has no trace right now", agent);
ShowRouteState::Active(time, trip, None)
}
} else {
warn!(
"{} has no agent associated right now; is the trip done?",
trip
);
ShowRouteState::Active(time, trip, None)
}
}