use std::collections::HashMap;
use crate::entity::EntityId;
use crate::world::World;
use super::sweep::{self, SweepDirection, SweepMode};
use super::{DispatchManifest, DispatchStrategy, ElevatorGroup, RankContext};
pub struct ScanDispatch {
direction: HashMap<EntityId, SweepDirection>,
mode: HashMap<EntityId, SweepMode>,
}
impl ScanDispatch {
#[must_use]
pub fn new() -> Self {
Self {
direction: HashMap::new(),
mode: HashMap::new(),
}
}
fn direction_for(&self, car: EntityId) -> SweepDirection {
self.direction
.get(&car)
.copied()
.unwrap_or(SweepDirection::Up)
}
fn mode_for(&self, car: EntityId) -> SweepMode {
self.mode.get(&car).copied().unwrap_or(SweepMode::Strict)
}
}
impl Default for ScanDispatch {
fn default() -> Self {
Self::new()
}
}
impl DispatchStrategy for ScanDispatch {
fn prepare_car(
&mut self,
car: EntityId,
car_position: f64,
group: &ElevatorGroup,
manifest: &DispatchManifest,
world: &World,
) {
let current = self.direction_for(car);
if sweep::strict_demand_ahead(current, car_position, group, manifest, world) {
self.mode.insert(car, SweepMode::Strict);
} else {
self.direction.insert(car, current.reversed());
self.mode.insert(car, SweepMode::Lenient);
}
}
fn rank(&mut self, ctx: &RankContext<'_>) -> Option<f64> {
sweep::rank(
self.mode_for(ctx.car),
self.direction_for(ctx.car),
ctx.car_position,
ctx.stop_position,
)
}
fn notify_removed(&mut self, elevator: EntityId) {
self.direction.remove(&elevator);
self.mode.remove(&elevator);
}
}