1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
//! # elevator-core
//!
//! Engine-agnostic, tick-based elevator simulation library for Rust.
//!
//! This crate provides the building blocks for modeling vertical transportation
//! systems — from a 3-story office building to an orbital space elevator.
//! Stops sit at arbitrary positions rather than uniform floors, and the
//! simulation is driven by a deterministic 7-phase tick loop.
//!
//! ## Key capabilities
//!
//! - **Pluggable dispatch** — four built-in algorithms ([`dispatch::scan::ScanDispatch`],
//! [`dispatch::look::LookDispatch`], [`dispatch::nearest_car::NearestCarDispatch`],
//! [`dispatch::etd::EtdDispatch`]) plus the [`dispatch::DispatchStrategy`] trait
//! for custom implementations.
//! - **Trapezoidal motion profiles** — realistic acceleration, cruise, and
//! deceleration computed per-tick.
//! - **Extension components** — attach arbitrary `Serialize + DeserializeOwned`
//! data to any entity via [`world::World::insert_ext`] without modifying the
//! library.
//! - **Lifecycle hooks** — inject logic before or after any of the seven
//! simulation phases. See [`hooks::Phase`].
//! - **Metrics and events** — query aggregate wait/ride times through
//! [`metrics::Metrics`] and react to fine-grained tick events via
//! [`events::Event`].
//! - **Snapshot save/load** — capture and restore full simulation state with
//! [`snapshot::WorldSnapshot`].
//! - **Zero `unsafe` code** — enforced by `#![forbid(unsafe_code)]`.
//!
//! ## Quick start
//!
//! ```rust
//! use elevator_core::prelude::*;
//! use elevator_core::stop::StopConfig;
//!
//! let mut sim = SimulationBuilder::new()
//! .stops(vec![
//! StopConfig { id: StopId(0), name: "Ground".into(), position: 0.0 },
//! StopConfig { id: StopId(1), name: "Floor 2".into(), position: 4.0 },
//! StopConfig { id: StopId(2), name: "Floor 3".into(), position: 8.0 },
//! ])
//! .build()
//! .unwrap();
//!
//! sim.spawn_rider_by_stop_id(StopId(0), StopId(2), 75.0).unwrap();
//!
//! for _ in 0..1000 {
//! sim.step();
//! }
//!
//! assert!(sim.metrics().total_delivered() > 0);
//! ```
//!
//! ## Crate layout
//!
//! | Module | Purpose |
//! |--------|---------|
//! | [`builder`] | Fluent [`SimulationBuilder`](builder::SimulationBuilder) API |
//! | [`sim`] | Top-level [`Simulation`](sim::Simulation) runner and tick loop |
//! | [`dispatch`] | Dispatch strategies and the [`DispatchStrategy`](dispatch::DispatchStrategy) trait |
//! | [`world`] | ECS-style [`World`](world::World) with typed component storage |
//! | [`components`] | Data types: [`Elevator`](components::Elevator), [`Rider`](components::Rider), [`Stop`](components::Stop), etc. |
//! | [`events`] | [`Event`](events::Event) variants and the [`EventBus`](events::EventBus) |
//! | [`metrics`] | Aggregate [`Metrics`](metrics::Metrics) (wait time, throughput, etc.) |
//! | [`config`] | RON-deserializable [`SimConfig`](config::SimConfig) |
//! | [`hooks`] | Lifecycle hook registration by [`Phase`](hooks::Phase) |
//! | [`query`] | Entity query builder for filtering by component composition |
//!
//! ## Architecture overview
//!
//! ### 7-phase tick loop
//!
//! Each call to [`Simulation::step()`](sim::Simulation::step) runs these
//! phases in order:
//!
//! 1. **`AdvanceTransient`** — transitions `Boarding→Riding`, `Exiting→Arrived`,
//! teleports walkers.
//! 2. **Dispatch** — builds a [`DispatchManifest`](dispatch::DispatchManifest)
//! and calls each group's [`DispatchStrategy`](dispatch::DispatchStrategy).
//! 3. **Reposition** — optional phase; moves idle elevators via
//! [`RepositionStrategy`](dispatch::RepositionStrategy) for better coverage.
//! 4. **Movement** — applies trapezoidal velocity profiles, detects stop arrivals
//! and emits [`PassingFloor`](events::Event::PassingFloor) events.
//! 5. **Doors** — ticks the [`DoorState`](door::DoorState) FSM per elevator.
//! 6. **Loading** — boards/exits riders with capacity and preference checks.
//! 7. **Metrics** — aggregates wait/ride times into [`Metrics`](metrics::Metrics)
//! and per-tag accumulators.
//!
//! ### Component relationships
//!
//! ```text
//! Group ──contains──▶ Line ──has──▶ Elevator ──carries──▶ Rider
//! │ │ │ │
//! └── DispatchStrategy └── Position └── Route (optional)
//! RepositionStrategy Velocity Patience
//! │ DoorState Preferences
//! └── Stop (served stops along the shaft)
//! ```
//!
//! ### Rider lifecycle
//!
//! Riders progress through phases managed by the simulation:
//!
//! ```text
//! Waiting → Boarding → Riding → Exiting → Arrived
//! ↑ (1 tick) (1 tick) │
//! │ ├── settle_rider() → Resident
//! │ │ │
//! │ └── despawn_rider() │
//! │ │
//! └──────── reroute_rider() ────────────────────────────────────────┘
//!
//! Waiting ──(patience exceeded)──→ Abandoned ──→ settle/despawn
//! ```
//!
//! - **`Arrived`** / **`Abandoned`**: terminal states; consumer must explicitly
//! settle or despawn the rider.
//! - **`Resident`**: parked at a stop, invisible to dispatch and loading.
//! Query with [`Simulation::residents_at()`](sim::Simulation::residents_at).
//! - **Population queries**: O(1) via maintained reverse index —
//! [`residents_at`](sim::Simulation::residents_at),
//! [`waiting_at`](sim::Simulation::waiting_at),
//! [`abandoned_at`](sim::Simulation::abandoned_at).
//!
//! ### Extension storage
//!
//! Games attach custom data to any entity without modifying the library:
//!
//! ```rust,ignore
//! // Attach a VIP flag to a rider.
//! world.insert_ext(rider_id, VipTag { priority: 1 }, "vip_tag");
//!
//! // Query it alongside built-in components.
//! for (id, rider, vip) in world.query::<(EntityId, &Rider, &Ext<VipTag>)>().iter() {
//! // ...
//! }
//! ```
//!
//! Extensions participate in snapshots via `serialize_extensions()` /
//! `register_ext::<T>(name)` + `load_extensions()`.
//!
//! ### Snapshot lifecycle
//!
//! 1. Capture: `sim.snapshot()` → [`WorldSnapshot`](snapshot::WorldSnapshot)
//! 2. Serialize: serde (RON, JSON, bincode, etc.)
//! 3. Deserialize + restore: `snapshot.restore(factory)` → new `Simulation`
//! 4. Re-register extensions: `world.register_ext::<T>(name)` per type
//! 5. Load extension data: `sim.load_extensions()`
//!
//! ### Performance
//!
//! | Operation | Complexity |
//! |-----------|-----------|
//! | Entity iteration | O(n) via `SlotMap` secondary maps |
//! | Stop-passing detection | O(log n) via `SortedStops` binary search |
//! | Dispatch manifest build | O(riders) per group |
//! | Population queries | O(1) via `RiderIndex` reverse index |
//! | Topology graph queries | O(V+E) BFS, lazy rebuild |
//!
//! For narrative guides, tutorials, and architecture walkthroughs, see the
//! [mdBook documentation](https://andymai.github.io/elevator-core/).
/// Entity-component data types for the simulation.
/// Entity identity and allocation.
/// Simulation error types.
/// Typed identifiers for groups and other sim concepts.
/// ECS-style query builder for iterating entities by component composition.
/// Tick-loop system phases (dispatch, reposition, movement, doors, loading, metrics).
/// Central entity/component storage.
/// Fluent builder for constructing a Simulation programmatically.
/// Building and elevator configuration (RON deserialization).
/// Pluggable dispatch strategies (SCAN, LOOK, nearest-car, ETD).
/// Door finite-state machine.
/// Simplified energy modeling for elevators.
/// Simulation event bus and event types.
/// Lifecycle hooks for injecting logic before/after simulation phases.
/// Aggregate simulation metrics.
/// Trapezoidal velocity-profile movement math.
pub
/// Phase-partitioned reverse index for rider population queries.
/// Scenario replay from recorded event streams.
/// Top-level simulation runner.
/// World snapshot for save/load.
/// Stop configuration helpers.
/// Tag-based per-entity metrics.
/// Tick-to-wall-clock time conversion.
/// Topology graph for cross-line connectivity queries.
/// Traffic generation (arrival patterns).
/// Register multiple extension types for snapshot deserialization in one call.
///
/// Eliminates the manual `register_ext` ceremony after snapshot restore.
///
/// # Example
///
/// ```ignore
/// register_extensions!(sim.world_mut(), VipTag => "vip_tag", Priority => "priority");
/// ```
/// Common imports for consumers of this library.
///
/// `use elevator_core::prelude::*;` pulls in the types you need for the vast
/// majority of simulations — building a sim, stepping it, spawning riders,
/// reading events and metrics, and writing custom dispatch strategies.
///
/// # Contents
///
/// - **Builder & simulation:** [`SimulationBuilder`], [`Simulation`],
/// [`RiderBuilder`]
/// - **Components:** [`Rider`], [`RiderPhase`], [`Elevator`], [`ElevatorPhase`],
/// [`Stop`], [`Line`], [`Position`], [`Velocity`], [`FloorPosition`],
/// [`Route`], [`Patience`], [`Preferences`], [`AccessControl`],
/// [`Orientation`], [`ServiceMode`]
/// - **Config:** [`SimConfig`], [`GroupConfig`], [`LineConfig`]
/// - **Dispatch:** [`DispatchStrategy`], [`RepositionStrategy`], plus the
/// built-in reposition strategies [`NearestIdle`], [`ReturnToLobby`],
/// [`SpreadEvenly`], [`DemandWeighted`]
/// - **Identity:** [`EntityId`], [`StopId`], [`GroupId`]
/// - **Errors & events:** [`SimError`], [`RejectionReason`],
/// [`RejectionContext`], [`Event`], [`EventBus`]
/// - **Misc:** [`Metrics`], [`TimeAdapter`]
///
/// # Not included (import explicitly)
///
/// - Concrete dispatch implementations: `dispatch::scan::ScanDispatch`,
/// `dispatch::look::LookDispatch`, `dispatch::nearest_car::NearestCarDispatch`,
/// `dispatch::etd::EtdDispatch`
/// - `ElevatorConfig` and `StopConfig` from [`crate::config`]
/// - Traffic generation types from [`crate::traffic`] (feature-gated)
/// - Snapshot types from [`crate::snapshot`]
/// - The [`World`](crate::world::World) type (accessed via `sim.world()`,
/// but required as a parameter when implementing custom dispatch)