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}