be more precise with building entry/exit events. they can also happen when a car parks inside a building's garage. also emit events at the start of day to get rid of the weird initial case.

This commit is contained in:
Dustin Carlino 2020-03-30 22:31:36 -07:00
parent 7f35d06c96
commit b16aceaa9a
6 changed files with 35 additions and 34 deletions

View File

@ -224,9 +224,9 @@ af8cefc0c99972082ab3ce3363412d47 data/system/scenarios/downtown/weekday.bin
e780764fe58e760ca76f017c1fd87244 data/system/scenarios/huge_seattle/weekday.bin e780764fe58e760ca76f017c1fd87244 data/system/scenarios/huge_seattle/weekday.bin
cd85737ea5e775f7c67b1d82c08b64fe data/system/scenarios/caphill/weekday.bin cd85737ea5e775f7c67b1d82c08b64fe data/system/scenarios/caphill/weekday.bin
b6367e75ae8bb7e824beb57a845c15e0 data/system/scenarios/montlake/weekday.bin b6367e75ae8bb7e824beb57a845c15e0 data/system/scenarios/montlake/weekday.bin
7051db6adccc82f47a1eca38bca758ee data/system/prebaked_results/23rd/weekday.bin b284a19e12b63bb660cc36bc86344bcc data/system/prebaked_results/23rd/weekday.bin
1adfeaed9d4095b3048999ec745de780 data/system/prebaked_results/signal_single/tutorial lvl1.bin 1adfeaed9d4095b3048999ec745de780 data/system/prebaked_results/signal_single/tutorial lvl1.bin
1c5a9a6f69b5f8b7ad9615af9c0ecc8c data/system/prebaked_results/signal_single/tutorial lvl2.bin 1c5a9a6f69b5f8b7ad9615af9c0ecc8c data/system/prebaked_results/signal_single/tutorial lvl2.bin
1e26ae48f3b5f31f55ab34b7a1d8c162 data/system/prebaked_results/montlake/car vs bike contention.bin 1e26ae48f3b5f31f55ab34b7a1d8c162 data/system/prebaked_results/montlake/car vs bike contention.bin
bce8e96ccc3ac8fdae1039ce2f3aa89a data/system/prebaked_results/montlake/weekday.bin d59fc84ef83a2773c3c48c7f8f01a5a4 data/system/prebaked_results/montlake/weekday.bin
f15bffa5c937d56515dc2a59770f7510 data/system/prebaked_results/montlake/car vs bus contention.bin f15bffa5c937d56515dc2a59770f7510 data/system/prebaked_results/montlake/car vs bus contention.bin

View File

@ -151,10 +151,10 @@ impl Analytics {
} }
// Building transitions // Building transitions
if let Event::PedEntersBuilding(_, p, b) = ev { if let Event::PersonEntersBuilding(p, b) = ev {
self.building_transitions.push((time, p, b, false)); self.building_transitions.push((time, p, b, false));
} }
if let Event::PedLeavesBuilding(_, p, b) = ev { if let Event::PersonLeavesBuilding(p, b) = ev {
self.building_transitions.push((time, p, b, true)); self.building_transitions.push((time, p, b, true));
} }

View File

@ -19,9 +19,10 @@ pub enum Event {
PedEntersBus(PedestrianID, CarID, BusRouteID), PedEntersBus(PedestrianID, CarID, BusRouteID),
PedLeavesBus(PedestrianID, CarID, BusRouteID), PedLeavesBus(PedestrianID, CarID, BusRouteID),
PersonEntersBuilding(PersonID, BuildingID),
PersonLeavesBuilding(PersonID, BuildingID),
PedReachedParkingSpot(PedestrianID, ParkingSpot), PedReachedParkingSpot(PedestrianID, ParkingSpot),
PedEntersBuilding(PedestrianID, PersonID, BuildingID),
PedLeavesBuilding(PedestrianID, PersonID, BuildingID),
PedReachedBorder(PedestrianID, IntersectionID), PedReachedBorder(PedestrianID, IntersectionID),
PedReachedBusStop(PedestrianID, BusStopID, BusRouteID), PedReachedBusStop(PedestrianID, BusStopID, BusRouteID),

View File

@ -29,26 +29,6 @@ impl PandemicModel {
bldg_occupants: BTreeMap::new(), bldg_occupants: BTreeMap::new(),
}; };
// Kind of a messy way of figuring out where people are originally.
// TODO Before anyone leaves a building, there are 0 people as seen by this model. Very
// weird.
let mut seen_ppl = BTreeSet::new();
for (_, p, b, left) in &analytics.building_transitions {
if *left && !seen_ppl.contains(p) {
seen_ppl.insert(*p);
state
.bldg_occupants
.entry(*b)
.or_insert_with(Vec::new)
.push((*p, Time::START_OF_DAY));
// Make up some initial infection state
if rng.gen_bool(0.1) {
state.infected.insert(*p);
}
}
}
// Now track people's movements through buildings // Now track people's movements through buildings
for (time, person, bldg, left) in &analytics.building_transitions { for (time, person, bldg, left) in &analytics.building_transitions {
if *time > now { if *time > now {
@ -97,6 +77,13 @@ impl PandemicModel {
.entry(*bldg) .entry(*bldg)
.or_insert_with(Vec::new) .or_insert_with(Vec::new)
.push((*person, *time)); .push((*person, *time));
// Bit of a hack to seed initial state per person here, but eh
if *time == Time::START_OF_DAY {
if rng.gen_bool(0.1) {
state.infected.insert(*person);
}
}
} }
} }

View File

@ -141,6 +141,10 @@ impl Sim {
timer, timer,
retry_if_no_room, retry_if_no_room,
); );
// TODO Should do this for everything, not just the one that I know records something ;)
for ev in self.trips.collect_events() {
self.analytics.event(ev, self.time, map);
}
} }
// TODO Friend method pattern :( // TODO Friend method pattern :(
pub(crate) fn spawner_parking(&self) -> &ParkingSimState { pub(crate) fn spawner_parking(&self) -> &ParkingSimState {
@ -396,6 +400,13 @@ impl Sim {
.agent_starting_trip_leg(AgentID::Car(create_car.vehicle.id), trip); .agent_starting_trip_leg(AgentID::Car(create_car.vehicle.id), trip);
} }
if let Some(parked_car) = create_car.maybe_parked_car { if let Some(parked_car) = create_car.maybe_parked_car {
if let ParkingSpot::Offstreet(b, _) = parked_car.spot {
// Buses don't start in parking garages, so trip must exist
events.push(Event::PersonLeavesBuilding(
self.trip_to_person(create_car.trip.unwrap()),
b,
));
}
self.parking.remove_parked_car(parked_car); self.parking.remove_parked_car(parked_car);
} }
if let Some(trip) = create_car.trip { if let Some(trip) = create_car.trip {
@ -516,11 +527,7 @@ impl Sim {
} }
_ => { _ => {
if let SidewalkPOI::Building(b) = &create_ped.start.connection { if let SidewalkPOI::Building(b) = &create_ped.start.connection {
events.push(Event::PedLeavesBuilding( events.push(Event::PersonLeavesBuilding(create_ped.person, *b));
create_ped.id,
create_ped.person,
*b,
));
} }
self.walking self.walking

View File

@ -112,7 +112,11 @@ impl TripManager {
let person = &mut self.people[trip.person.0]; let person = &mut self.people[trip.person.0];
if person.trips.is_empty() { if person.trips.is_empty() {
person.state = match trip.start { person.state = match trip.start {
TripEndpoint::Bldg(b) => PersonState::Inside(b), TripEndpoint::Bldg(b) => {
self.events
.push(Event::PersonEntersBuilding(trip.person, b));
PersonState::Inside(b)
}
TripEndpoint::Border(_) => PersonState::OffMap, TripEndpoint::Border(_) => PersonState::OffMap,
}; };
} }
@ -177,6 +181,8 @@ impl TripManager {
now - trip.spawned_at, now - trip.spawned_at,
)); ));
self.people[trip.person.0].state = PersonState::Inside(b1); self.people[trip.person.0].state = PersonState::Inside(b1);
self.events
.push(Event::PersonEntersBuilding(trip.person, b1));
return; return;
} }
_ => {} _ => {}
@ -349,8 +355,6 @@ impl TripManager {
.remove(&AgentID::Pedestrian(ped)) .remove(&AgentID::Pedestrian(ped))
.unwrap() .unwrap()
.0]; .0];
self.events
.push(Event::PedEntersBuilding(ped, trip.person, bldg));
trip.assert_walking_leg(ped, SidewalkSpot::building(bldg, map)); trip.assert_walking_leg(ped, SidewalkSpot::building(bldg, map));
assert!(trip.legs.is_empty()); assert!(trip.legs.is_empty());
assert!(!trip.finished_at.is_some()); assert!(!trip.finished_at.is_some());
@ -362,6 +366,8 @@ impl TripManager {
now - trip.spawned_at, now - trip.spawned_at,
)); ));
self.people[trip.person.0].state = PersonState::Inside(bldg); self.people[trip.person.0].state = PersonState::Inside(bldg);
self.events
.push(Event::PersonEntersBuilding(trip.person, bldg));
} }
// If no route is returned, the pedestrian boarded a bus immediately. // If no route is returned, the pedestrian boarded a bus immediately.