use crate::entity::EntityId;
use crate::world::World;
use super::{BuiltinStrategy, DispatchManifest, DispatchStrategy, ElevatorGroup, RankContext};
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub struct LoopScheduleDispatch {
dwell_ticks: u32,
target_headway_ticks: u32,
}
impl LoopScheduleDispatch {
#[must_use]
pub const fn new(dwell_ticks: u32, target_headway_ticks: u32) -> Self {
Self {
dwell_ticks: if dwell_ticks == 0 { 1 } else { dwell_ticks },
target_headway_ticks: if target_headway_ticks == 0 {
1
} else {
target_headway_ticks
},
}
}
#[must_use]
pub const fn dwell_ticks(&self) -> u32 {
self.dwell_ticks
}
#[must_use]
pub const fn target_headway_ticks(&self) -> u32 {
self.target_headway_ticks
}
}
impl Default for LoopScheduleDispatch {
fn default() -> Self {
Self::new(30, 300)
}
}
impl DispatchStrategy for LoopScheduleDispatch {
fn pre_dispatch(
&mut self,
group: &ElevatorGroup,
_manifest: &DispatchManifest,
world: &mut World,
) {
for line in group.lines() {
if !world
.line(line.entity())
.is_some_and(crate::components::Line::is_loop)
{
continue;
}
for &eid in line.elevators() {
if let Some(car) = world.elevator_mut(eid) {
car.door_open_ticks = self.dwell_ticks;
}
}
}
}
fn rank(&self, _ctx: &RankContext<'_>) -> Option<f64> {
None
}
fn builtin_id(&self) -> Option<BuiltinStrategy> {
Some(BuiltinStrategy::LoopSchedule)
}
fn snapshot_config(&self) -> Option<String> {
ron::to_string(self).ok()
}
fn restore_config(&mut self, config: &str) -> Result<(), String> {
let restored: Self = ron::from_str(config).map_err(|e| e.to_string())?;
*self = restored;
Ok(())
}
fn notify_removed(&mut self, _elevator: EntityId) {
}
}