avoid a few crashes, mostly involving trips that were aborted in the

baseline
This commit is contained in:
Dustin Carlino 2020-04-19 12:40:21 -07:00
parent d80513235d
commit 5cf0b72bac
8 changed files with 54 additions and 15 deletions

View File

@ -6,6 +6,7 @@ use crate::sandbox::SandboxMode;
use ezgui::{EventCtx, GfxCtx, Warper, Wizard};
use geom::Pt2D;
use map_model::{AreaID, BuildingID, IntersectionID, LaneID, RoadID};
use maplit::btreemap;
use sim::{PedestrianID, PersonID, TripID};
use std::collections::BTreeMap;
@ -110,6 +111,7 @@ fn inner_warp(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Transitio
'p' => ID::Pedestrian(PedestrianID(idx)),
'P' => {
let id = PersonID(idx);
app.primary.sim.lookup_person(id)?;
return Some(Transition::PopWithData(Box::new(move |state, app, ctx| {
// Other states pretty much don't use info panels.
if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() {
@ -128,7 +130,22 @@ fn inner_warp(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Transitio
let c = app.primary.sim.lookup_car_id(idx)?;
ID::Car(c)
}
't' => ID::from_agent(app.primary.sim.trip_to_agent(TripID(idx)).ok()?),
't' => {
let trip = TripID(idx);
let person = app.primary.sim.trip_to_person(trip);
return Some(Transition::PopWithData(Box::new(move |state, app, ctx| {
// Other states pretty much don't use info panels.
if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() {
let mut actions = s.contextual_actions();
s.controls.common.as_mut().unwrap().launch_info_panel(
ctx,
app,
Tab::PersonTrips(person, btreemap! {trip => true}),
&mut actions,
);
}
})));
}
'T' => {
let t = app.primary.map.lookup_turn_by_idx(idx)?;
ID::Turn(t)

View File

@ -65,7 +65,11 @@ pub fn trips(
// TODO No details. Weird case.
assert!(wheres_waldo);
wheres_waldo = false;
("ongoing", Color::hex("#7FFA4D"), None)
(
"ongoing",
Color::hex("#7FFA4D"),
open_trips.get(t).map(|_| Widget::nothing()),
)
}
TripResult::TripDone => {
assert!(wheres_waldo);
@ -79,7 +83,11 @@ pub fn trips(
}
TripResult::TripAborted => {
// Aborted trips can happen anywhere in the schedule right now
("cancelled", Color::hex("#EB3223"), None)
(
"cancelled",
Color::hex("#EB3223"),
open_trips.get(t).map(|_| Widget::nothing()),
)
}
TripResult::TripDoesntExist => unreachable!(),
};

View File

@ -111,15 +111,16 @@ pub fn future(ctx: &mut EventCtx, app: &App, trip: TripID, details: &mut Details
let mut col = Vec::new();
if app.has_prebaked().is_some() {
let phases = app.prebaked().get_trip_phases(trip, &app.primary.map);
let estimated_trip_time =
phases.last().as_ref().and_then(|p| p.end_time).unwrap() - start_time;
if let Some(estimated_trip_time) = app
.has_prebaked()
.and_then(|_| app.prebaked().finished_trip_time(trip))
{
col.extend(make_table(
ctx,
vec![("Estimated trip time", estimated_trip_time.to_string())],
));
let phases = app.prebaked().get_trip_phases(trip, &app.primary.map);
col.push(make_timeline(ctx, app, trip, details, phases, None));
} else {
// TODO Warp buttons. make_table is showing its age.

View File

@ -129,7 +129,12 @@ fn make(ctx: &mut EventCtx, app: &App, sort: SortBy, descending: bool) -> Compos
let (_, waiting) = sim.finished_trip_time(*id).unwrap();
let (departure, _, _, _) = sim.trip_info(*id);
let duration_before = if app.has_prebaked().is_some() {
app.prebaked().finished_trip_time(*id).unwrap()
if let Some(dt) = app.prebaked().finished_trip_time(*id) {
dt
} else {
// Aborted
continue;
}
} else {
Duration::ZERO
};

View File

@ -178,6 +178,7 @@ fn get_score(app: &App, trips: &Vec<TripID>) -> (Duration, Duration, usize) {
if let Some((total, _)) = app.primary.sim.finished_trip_time(*t) {
done += 1;
after += total;
// Assume all trips completed before changes
before += app.prebaked().finished_trip_time(*t).unwrap();
}
}

View File

@ -225,12 +225,16 @@ impl Analytics {
(all, num_aborted, per_mode)
}
// Ignores the current time.
// Ignores the current time. Returns None for aborted trips.
pub fn finished_trip_time(&self, trip: TripID) -> Option<Duration> {
// TODO This is so inefficient!
for (_, id, _, dt) in &self.finished_trips {
for (_, id, maybe_mode, dt) in &self.finished_trips {
if *id == trip {
return Some(*dt);
if maybe_mode.is_some() {
return Some(*dt);
} else {
return None;
}
}
}
None

View File

@ -988,9 +988,12 @@ impl Sim {
self.parking.get_car_owned_by(id)
}
pub fn get_person(&self, id: PersonID) -> &Person {
pub fn lookup_person(&self, id: PersonID) -> Option<&Person> {
self.trips.get_person(id)
}
pub fn get_person(&self, id: PersonID) -> &Person {
self.trips.get_person(id).unwrap()
}
pub fn get_all_people(&self) -> &Vec<Person> {
self.trips.get_all_people()
}
@ -1059,7 +1062,7 @@ impl Sim {
TripResult::ModeChange
}
pub fn get_canonical_pt_per_person(&self, p: PersonID, map: &Map) -> Option<Pt2D> {
match self.trips.get_person(p).state {
match self.trips.get_person(p)?.state {
PersonState::Inside(b) => Some(map.get_b(b).polygon.center()),
PersonState::Trip(t) => self.get_canonical_pt_per_trip(t, map).ok(),
PersonState::OffMap | PersonState::Limbo => None,

View File

@ -699,8 +699,8 @@ impl TripManager {
people
}
pub fn get_person(&self, p: PersonID) -> &Person {
&self.people[p.0]
pub fn get_person(&self, p: PersonID) -> Option<&Person> {
self.people.get(p.0)
}
pub fn get_all_people(&self) -> &Vec<Person> {
&self.people