use super::dispatch_tests::{spawn_elevator, test_group, test_world};
use crate::components::{ElevatorPhase, Route, Weight};
use crate::dispatch::etd::EtdDispatch;
use crate::dispatch::nearest_car::NearestCarDispatch;
use crate::dispatch::{self, DispatchDecision, DispatchManifest, DispatchStrategy, RiderInfo};
#[test]
fn etd_skips_pickup_whose_riders_are_all_direction_filtered() {
let (mut world, stops) = test_world();
let elev = spawn_elevator(&mut world, 8.0);
{
let car = world.elevator_mut(elev).unwrap();
car.going_up = false;
car.going_down = true;
car.phase = ElevatorPhase::MovingToStop(stops[0]);
}
let aboard = world.spawn();
world.elevator_mut(elev).unwrap().riders.push(aboard);
world.set_route(
aboard,
Route::direct(stops[3], stops[0], crate::ids::GroupId(0)),
);
let group = test_group(&stops, vec![elev]);
let mut manifest = DispatchManifest::default();
let up_waiter = world.spawn();
manifest
.waiting_at_stop
.entry(stops[2])
.or_default()
.push(RiderInfo {
id: up_waiter,
destination: Some(stops[3]),
weight: Weight::from(70.0),
wait_ticks: 0,
});
manifest
.riding_to_stop
.entry(stops[0])
.or_default()
.push(RiderInfo {
id: aboard,
destination: Some(stops[0]),
weight: Weight::from(70.0),
wait_ticks: 0,
});
let mut etd = EtdDispatch::new();
etd.pre_dispatch(&group, &manifest, &mut world);
let decisions = dispatch::assign(&mut etd, &[(elev, 8.0)], &group, &manifest, &world).decisions;
assert_eq!(
decisions[0].1,
DispatchDecision::GoToStop(stops[0]),
"car must continue to the aboard rider's destination, not self-assign to a \
waypoint whose only waiting rider is direction-filtered"
);
}
#[test]
fn nearest_car_skips_pickup_whose_riders_are_all_direction_filtered() {
let (mut world, stops) = test_world();
let elev = spawn_elevator(&mut world, 8.0);
{
let car = world.elevator_mut(elev).unwrap();
car.going_up = false;
car.going_down = true;
car.phase = ElevatorPhase::MovingToStop(stops[0]);
}
let aboard = world.spawn();
world.elevator_mut(elev).unwrap().riders.push(aboard);
world.set_route(
aboard,
Route::direct(stops[3], stops[0], crate::ids::GroupId(0)),
);
let group = test_group(&stops, vec![elev]);
let mut manifest = DispatchManifest::default();
let up_waiter = world.spawn();
manifest
.waiting_at_stop
.entry(stops[2])
.or_default()
.push(RiderInfo {
id: up_waiter,
destination: Some(stops[3]),
weight: Weight::from(70.0),
wait_ticks: 0,
});
manifest
.riding_to_stop
.entry(stops[0])
.or_default()
.push(RiderInfo {
id: aboard,
destination: Some(stops[0]),
weight: Weight::from(70.0),
wait_ticks: 0,
});
let mut nc = NearestCarDispatch::new();
nc.pre_dispatch(&group, &manifest, &mut world);
let decisions = dispatch::assign(&mut nc, &[(elev, 8.0)], &group, &manifest, &world).decisions;
assert_eq!(
decisions[0].1,
DispatchDecision::GoToStop(stops[0]),
"NearestCar must honor the direction filter too"
);
}
#[test]
fn pickup_of_matching_direction_rider_still_passes() {
let (mut world, stops) = test_world();
let elev = spawn_elevator(&mut world, 8.0);
{
let car = world.elevator_mut(elev).unwrap();
car.going_up = false;
car.going_down = true;
car.phase = ElevatorPhase::MovingToStop(stops[0]);
}
let aboard = world.spawn();
world.elevator_mut(elev).unwrap().riders.push(aboard);
world.set_route(
aboard,
Route::direct(stops[3], stops[0], crate::ids::GroupId(0)),
);
let group = test_group(&stops, vec![elev]);
let mut manifest = DispatchManifest::default();
let down_waiter = world.spawn();
manifest
.waiting_at_stop
.entry(stops[2])
.or_default()
.push(RiderInfo {
id: down_waiter,
destination: Some(stops[1]),
weight: Weight::from(70.0),
wait_ticks: 0,
});
manifest
.riding_to_stop
.entry(stops[0])
.or_default()
.push(RiderInfo {
id: aboard,
destination: Some(stops[0]),
weight: Weight::from(70.0),
wait_ticks: 0,
});
let mut etd = EtdDispatch::new();
etd.pre_dispatch(&group, &manifest, &mut world);
let decisions = dispatch::assign(&mut etd, &[(elev, 8.0)], &group, &manifest, &world).decisions;
assert!(
matches!(decisions[0].1, DispatchDecision::GoToStop(_)),
"a same-direction waiter must not be spuriously filtered; got {:?}",
decisions[0].1
);
}