diff --git a/game/src/edit/mod.rs b/game/src/edit/mod.rs index be8169cc71..5ebd6eea9b 100644 --- a/game/src/edit/mod.rs +++ b/game/src/edit/mod.rs @@ -2,7 +2,7 @@ use std::collections::BTreeSet; use maplit::btreeset; -use abstutil::Timer; +use abstutil::{prettyprint_usize, Timer}; use geom::Speed; use map_model::{EditCmd, IntersectionID, LaneID, LaneType, MapEdits}; use widgetry::{ @@ -98,8 +98,25 @@ impl EditMode { app.primary .sim .handle_live_edited_traffic_signals(&app.primary.map); - app.primary.sim.handle_live_edits(&app.primary.map); - Transition::Pop + let (trips, parked_cars) = app.primary.sim.handle_live_edits(&app.primary.map); + if trips == 0 && parked_cars == 0 { + Transition::Pop + } else { + Transition::Replace(PopupMsg::new( + ctx, + "Map changes complete", + vec![ + format!( + "Your edits interrupted {} trips and displaced {} parked cars", + prettyprint_usize(trips), + prettyprint_usize(parked_cars) + ), + "Simulation results won't be finalized unless you restart from \ + midnight with your changes" + .to_string(), + ], + )) + } } else { Transition::Multi(vec![ Transition::Pop, diff --git a/sim/src/sim/mod.rs b/sim/src/sim/mod.rs index 5fea73507a..011c7346e5 100644 --- a/sim/src/sim/mod.rs +++ b/sim/src/sim/mod.rs @@ -885,10 +885,13 @@ impl Sim { .handle_live_edited_traffic_signals(self.time, map, &mut self.scheduler) } - pub fn handle_live_edits(&mut self, map: &Map) { + /// Respond to arbitrary map edits without resetting the simulation. Returns the number of + /// (trips cancelled, parked cars displaced). + pub fn handle_live_edits(&mut self, map: &Map) -> (usize, usize) { self.edits_name = map.get_edits().edits_name.clone(); - let affected = self.find_trips_affected_by_live_edits(map); + let (affected, num_parked_cars) = self.find_trips_affected_by_live_edits(map); + let num_trips_cancelled = affected.len(); // V1: Just cancel every trip crossing an affected area. // (V2 is probably rerouting everyone, only cancelling when that fails) @@ -932,9 +935,12 @@ impl Sim { self.driving.handle_live_edits(map); self.intersections.handle_live_edits(map); + + (num_trips_cancelled, num_parked_cars) } - fn find_trips_affected_by_live_edits(&mut self, map: &Map) -> Vec<(AgentID, TripID)> { + /// Returns (trips affected, number of parked cars displaced) + fn find_trips_affected_by_live_edits(&mut self, map: &Map) -> (Vec<(AgentID, TripID)>, usize) { let mut affected: Vec<(AgentID, TripID)> = Vec::new(); // TODO Handle changes to access restrictions @@ -964,9 +970,10 @@ impl Sim { } } - { + let num_evicted = { let (evicted_cars, cars_parking_in_the_void) = self.parking.handle_live_edits(map, &mut Timer::throwaway()); + let num_evicted = evicted_cars.len(); affected.extend(self.walking.find_trips_to_parking(evicted_cars)); for car in cars_parking_in_the_void { let a = AgentID::Car(car); @@ -980,9 +987,10 @@ impl Sim { all_spots.extend(avail); affected.extend(self.driving.find_trips_to_edited_parking(all_spots)); } - } + num_evicted + }; - affected + (affected, num_evicted) } }