use crate::components::Route;
use super::{DispatchStrategy, RankContext, pair_can_do_work};
pub struct NearestCarDispatch;
impl NearestCarDispatch {
#[must_use]
pub const fn new() -> Self {
Self
}
}
impl Default for NearestCarDispatch {
fn default() -> Self {
Self::new()
}
}
impl DispatchStrategy for NearestCarDispatch {
fn rank(&mut self, ctx: &RankContext<'_>) -> Option<f64> {
if !pair_is_useful(ctx) {
return None;
}
Some((ctx.car_position - ctx.stop_position).abs())
}
fn builtin_id(&self) -> Option<super::BuiltinStrategy> {
Some(super::BuiltinStrategy::NearestCar)
}
}
fn pair_is_useful(ctx: &RankContext<'_>) -> bool {
if !pair_can_do_work(ctx) {
return false;
}
let Some(car) = ctx.world.elevator(ctx.car) else {
return false;
};
let can_exit_here = car
.riders()
.iter()
.any(|&rid| ctx.world.route(rid).and_then(Route::current_destination) == Some(ctx.stop));
if can_exit_here || car.riders().is_empty() {
return true;
}
let has_routed_rider = car.riders().iter().any(|&rid| {
ctx.world
.route(rid)
.and_then(Route::current_destination)
.is_some()
});
if !has_routed_rider {
return true;
}
let to_cand = ctx.stop_position - ctx.car_position;
car.riders().iter().any(|&rid| {
let Some(dest) = ctx.world.route(rid).and_then(Route::current_destination) else {
return false;
};
let Some(dest_pos) = ctx.world.stop_position(dest) else {
return false;
};
let to_dest = dest_pos - ctx.car_position;
to_dest * to_cand >= 0.0 && to_cand.abs() <= to_dest.abs()
})
}