use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use crate::door::{DoorCommand, DoorState};
use crate::entity::EntityId;
pub const DOOR_COMMAND_QUEUE_CAP: usize = 16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum Direction {
Up,
Down,
Either,
}
impl std::fmt::Display for Direction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Up => write!(f, "Up"),
Self::Down => write!(f, "Down"),
Self::Either => write!(f, "Either"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum ElevatorPhase {
Idle,
MovingToStop(EntityId),
Repositioning(EntityId),
DoorOpening,
Loading,
DoorClosing,
Stopped,
}
impl ElevatorPhase {
#[must_use]
pub const fn is_moving(&self) -> bool {
matches!(self, Self::MovingToStop(_) | Self::Repositioning(_))
}
#[must_use]
pub const fn moving_target(&self) -> Option<EntityId> {
match self {
Self::MovingToStop(s) | Self::Repositioning(s) => Some(*s),
_ => None,
}
}
}
impl std::fmt::Display for ElevatorPhase {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Idle => write!(f, "Idle"),
Self::MovingToStop(id) => write!(f, "MovingToStop({id:?})"),
Self::Repositioning(id) => write!(f, "Repositioning({id:?})"),
Self::DoorOpening => write!(f, "DoorOpening"),
Self::Loading => write!(f, "Loading"),
Self::DoorClosing => write!(f, "DoorClosing"),
Self::Stopped => write!(f, "Stopped"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Elevator {
pub(crate) phase: ElevatorPhase,
pub(crate) door: DoorState,
pub(crate) max_speed: f64,
pub(crate) acceleration: f64,
pub(crate) deceleration: f64,
pub(crate) weight_capacity: f64,
pub(crate) current_load: f64,
pub(crate) riders: Vec<EntityId>,
pub(crate) target_stop: Option<EntityId>,
pub(crate) door_transition_ticks: u32,
pub(crate) door_open_ticks: u32,
#[serde(alias = "group")]
pub(crate) line: EntityId,
#[serde(default)]
pub(crate) repositioning: bool,
#[serde(default)]
pub(crate) restricted_stops: HashSet<EntityId>,
#[serde(default = "default_inspection_speed_factor")]
pub(crate) inspection_speed_factor: f64,
#[serde(default = "default_true")]
pub(crate) going_up: bool,
#[serde(default = "default_true")]
pub(crate) going_down: bool,
#[serde(default)]
pub(crate) move_count: u64,
#[serde(default)]
pub(crate) door_command_queue: Vec<DoorCommand>,
#[serde(default)]
pub(crate) manual_target_velocity: Option<f64>,
}
const fn default_inspection_speed_factor() -> f64 {
0.25
}
const fn default_true() -> bool {
true
}
impl Elevator {
#[must_use]
pub const fn phase(&self) -> ElevatorPhase {
self.phase
}
#[must_use]
pub const fn door(&self) -> &DoorState {
&self.door
}
#[must_use]
pub const fn max_speed(&self) -> f64 {
self.max_speed
}
#[must_use]
pub const fn acceleration(&self) -> f64 {
self.acceleration
}
#[must_use]
pub const fn deceleration(&self) -> f64 {
self.deceleration
}
#[must_use]
pub const fn weight_capacity(&self) -> f64 {
self.weight_capacity
}
#[must_use]
pub const fn current_load(&self) -> f64 {
self.current_load
}
#[must_use]
pub fn riders(&self) -> &[EntityId] {
&self.riders
}
#[must_use]
pub const fn target_stop(&self) -> Option<EntityId> {
self.target_stop
}
#[must_use]
pub const fn door_transition_ticks(&self) -> u32 {
self.door_transition_ticks
}
#[must_use]
pub const fn door_open_ticks(&self) -> u32 {
self.door_open_ticks
}
#[must_use]
pub const fn line(&self) -> EntityId {
self.line
}
#[must_use]
pub const fn repositioning(&self) -> bool {
self.repositioning
}
#[must_use]
pub const fn restricted_stops(&self) -> &HashSet<EntityId> {
&self.restricted_stops
}
#[must_use]
pub const fn inspection_speed_factor(&self) -> f64 {
self.inspection_speed_factor
}
#[must_use]
pub const fn going_up(&self) -> bool {
self.going_up
}
#[must_use]
pub const fn going_down(&self) -> bool {
self.going_down
}
#[must_use]
pub const fn direction(&self) -> Direction {
match (self.going_up, self.going_down) {
(true, false) => Direction::Up,
(false, true) => Direction::Down,
_ => Direction::Either,
}
}
#[must_use]
pub const fn move_count(&self) -> u64 {
self.move_count
}
#[must_use]
pub fn door_command_queue(&self) -> &[DoorCommand] {
&self.door_command_queue
}
#[must_use]
pub const fn manual_target_velocity(&self) -> Option<f64> {
self.manual_target_velocity
}
}