properly update followers that're Crossing and become unblocked

This commit is contained in:
Dustin Carlino 2019-03-03 18:23:38 -08:00
parent ab52e9ac38
commit 2ac973f245

View File

@ -141,42 +141,44 @@ impl DrivingSimState {
// Handle cars on their last step. Some of them will vanish or finish parking; others will
// start.
// TODO Inside here, need to mutate cars and a single queue. Clone keys to awkwardly work
// with borrow checker.
for on in self.queues.keys().cloned().collect::<Vec<Traversable>>() {
if self.queues[&on]
.cars
.iter()
.any(|id| self.cars[id].router.last_step())
{
for queue in self.queues.values_mut() {
let mut any_last_step = false;
for id in &queue.cars {
if self.cars[id].router.last_step() {
any_last_step = true;
break;
}
}
if !any_last_step {
continue;
}
// This car might have reached the router's end distance, but maybe not -- might
// actually be stuck behind other cars. We have to calculate the distances right
// now to be sure.
// actually be stuck behind other cars. We have to calculate the distances right now to
// be sure.
// TODO This calculates distances a little unnecessarily -- might just be a car
// parking.
let mut delete_indices = Vec::new();
for (idx, (id, dist)) in self.queues[&on]
.get_car_positions(time, &self.cars)
.into_iter()
.enumerate()
{
let car = self.cars.get_mut(&id).unwrap();
let dists = queue.get_car_positions(time, &self.cars);
for (idx, (id, dist)) in dists.iter().enumerate() {
let car = self.cars.get_mut(id).unwrap();
if !car.router.last_step() {
continue;
}
match car.state {
CarState::Crossing(_, _) | CarState::Unparking(_, _) => {}
CarState::Queued => {
match car
.router
.maybe_handle_end(dist, &car.vehicle, parking, map)
.maybe_handle_end(*dist, &car.vehicle, parking, map)
{
Some(ActionAtEnd::VanishAtBorder(i)) => {
trips.car_or_bike_reached_border(time, car.vehicle.id, i);
delete_indices.push((idx, dist));
delete_indices.push(idx);
}
Some(ActionAtEnd::StartParking(spot)) => {
car.state = CarState::Parking(
dist,
*dist,
spot,
TimeInterval::new(time, time + TIME_TO_PARK),
);
@ -186,10 +188,10 @@ impl DrivingSimState {
parking.reserve_spot(spot);
}
Some(ActionAtEnd::GotoLaneEnd) => {
car.state = car.crossing_state(dist, time, map);
car.state = car.crossing_state(*dist, time, map);
}
Some(ActionAtEnd::StopBiking(bike_rack)) => {
delete_indices.push((idx, dist));
delete_indices.push(idx);
trips.bike_reached_end(
time,
car.vehicle.id,
@ -208,7 +210,7 @@ impl DrivingSimState {
map,
);
car.state = CarState::Idling(
dist,
*dist,
TimeInterval::new(time, time + TIME_TO_WAIT_AT_STOP),
);
}
@ -217,7 +219,7 @@ impl DrivingSimState {
}
CarState::Parking(_, spot, ref time_int) => {
if time > time_int.end {
delete_indices.push((idx, dist));
delete_indices.push(idx);
parking.add_parked_car(ParkedCar {
vehicle: car.vehicle.clone(),
spot,
@ -238,43 +240,38 @@ impl DrivingSimState {
car.state = car.crossing_state(dist, time, map);
}
}
_ => {}
}
}
// Remove the finished cars starting from the end of the queue, so indices aren't
// messed up.
// Remove the finished cars starting from the end of the queue (the beginning of the
// traversable), so indices aren't messed up.
delete_indices.reverse();
for (idx, leader_dist) in delete_indices {
let queue = self.queues.get_mut(&on).unwrap();
let leader = self.cars.remove(&queue.cars.remove(idx).unwrap()).unwrap();
for idx in delete_indices {
self.cars.remove(&queue.cars.remove(idx).unwrap());
// Update the follower so that they don't suddenly jump forwards.
if idx != queue.cars.len() {
let mut follower = self.cars.get_mut(&queue.cars[idx]).unwrap();
// TODO If the leader vanished at a border node, this still jumps a bit --
// the lead car's back is still sticking out. Need to still be bound by
// them, even though they don't exist! If the leader just parked, then
// we're fine.
let (follower_id, follower_dist) = dists[idx + 1];
let mut follower = self.cars.get_mut(&follower_id).unwrap();
// TODO If the leader vanished at a border node, this still jumps a bit -- the
// lead car's back is still sticking out. Need to still be bound by them, even
// though they don't exist! If the leader just parked, then we're fine.
match follower.state {
CarState::Queued => {
follower.state = follower.crossing_state(
// Since the follower was Queued, this must be where they are
leader_dist - leader.vehicle.length - FOLLOWING_DISTANCE,
time,
map,
);
CarState::Queued | CarState::Crossing(_, _) => {
// If the follower was still Crossing, they might not've been blocked
// by leader yet. In that case, recalculating their Crossing state is a
// no-op. But if they were blocked, then this will prevent them from
// jumping forwards.
follower.state = follower.crossing_state(follower_dist, time, map);
}
// They weren't blocked
CarState::Crossing(_, _)
| CarState::Unparking(_, _)
CarState::Unparking(_, _)
| CarState::Parking(_, _, _)
| CarState::Idling(_, _) => {}
}
}
}
}
}
// Figure out where everybody wants to go next.
let mut head_cars_ready_to_advance: Vec<Traversable> = Vec::new();
@ -323,7 +320,8 @@ impl DrivingSimState {
map,
);
}
// They weren't blocked
// They weren't blocked. Note that there's no way the Crossing state could jump
// forwards here; the leader vanished from the end of the traversable.
CarState::Crossing(_, _)
| CarState::Unparking(_, _)
| CarState::Parking(_, _, _)