Skip to main content

elevator_core/components/
car_call.rs

1//! Car calls: the floor buttons riders press from inside a cab.
2//!
3//! When a rider boards in [`HallCallMode::Classic`](
4//! crate::dispatch::HallCallMode) the cab doesn't yet know where they want
5//! to go — the hall call only conveyed direction. At that point the rider
6//! "presses a floor button" and a [`CarCall`] is registered on the car.
7//! Dispatch reads the list to plan intermediate stops on the way to the
8//! sweep's far end.
9//!
10//! In `Destination` mode car calls are unused: the kiosk entry at the
11//! hall reveals the destination up front, and the car's
12//! [`DestinationQueue`](crate::components::DestinationQueue) is populated
13//! directly by [`DestinationDispatch`](crate::dispatch::DestinationDispatch).
14
15use serde::{Deserialize, Serialize};
16
17use crate::entity::EntityId;
18
19/// A floor button press inside `car` requesting service to `floor`.
20///
21/// Stored as a list attached to each elevator. One `CarCall` per
22/// `(car, floor)` pair — subsequent presses for the same floor increase
23/// `pending_riders` rather than duplicating the call.
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25#[non_exhaustive]
26pub struct CarCall {
27    /// Elevator the button was pressed inside.
28    pub car: EntityId,
29    /// Stop the button requests.
30    pub floor: EntityId,
31    /// Tick the button was pressed.
32    pub press_tick: u64,
33    /// Tick dispatch first sees this call (after ack latency).
34    /// `None` while still pending acknowledgement.
35    pub acknowledged_at: Option<u64>,
36    /// Ticks the controller takes to acknowledge this call. Populated
37    /// from the serving group's `ack_latency_ticks` on first press.
38    pub ack_latency_ticks: u32,
39    /// Riders who pressed the button (usually one; aggregated if multiple
40    /// riders heading to the same floor board together).
41    pub pending_riders: Vec<EntityId>,
42}
43
44impl CarCall {
45    /// Create a new unacknowledged car call.
46    #[must_use]
47    pub const fn new(car: EntityId, floor: EntityId, press_tick: u64) -> Self {
48        Self {
49            car,
50            floor,
51            press_tick,
52            acknowledged_at: None,
53            ack_latency_ticks: 0,
54            pending_riders: Vec::new(),
55        }
56    }
57
58    /// Returns `true` once the ack latency has elapsed and dispatch can
59    /// plan around this call.
60    #[must_use]
61    pub const fn is_acknowledged(&self) -> bool {
62        self.acknowledged_at.is_some()
63    }
64}