Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

API Reference

This chapter is a quick-reference for the public API of the elevator-core crate. It covers every public type, method, and enum variant you are likely to reach for when building on the simulation. For full rustdoc with source links, inline examples, and trait impls, see docs.rs/elevator-core.


Prelude

use elevator_core::prelude::*; re-exports these items. Anything else must be imported from its module explicitly.

CategoryItems
Builder & simSimulationBuilder, Simulation, RiderBuilder
ComponentsRider, RiderPhase, Elevator, ElevatorPhase, Stop, Line, Position, Velocity, FloorPosition, Route, Patience, Preferences, AccessControl, Orientation, ServiceMode
ConfigSimConfig, GroupConfig, LineConfig
Dispatch traitsDispatchStrategy, RepositionStrategy
Reposition strategiesNearestIdle, ReturnToLobby, SpreadEvenly, DemandWeighted
IdentityEntityId, StopId, GroupId
Errors & eventsSimError, RejectionReason, RejectionContext, Event, EventBus
MiscMetrics, TimeAdapter

Not in the prelude (import explicitly):

  • elevator_core::dispatch::scan::ScanDispatch, dispatch::look::LookDispatch, dispatch::nearest_car::NearestCarDispatch, dispatch::etd::EtdDispatch
  • elevator_core::config::{ElevatorConfig, StopConfig}
  • elevator_core::traffic::* (feature-gated behind traffic)
  • elevator_core::snapshot::WorldSnapshot
  • elevator_core::world::World (parameter type for custom dispatch)

SimulationBuilder

Fluent builder for constructing a Simulation. Starts with a minimal valid config (2 stops, 1 elevator, SCAN dispatch, 60 TPS). Override any part before calling build().

MethodSignatureDescription
new() -> SelfCreate a builder with minimal defaults
from_config(SimConfig) -> SelfCreate a builder from an existing config
stops(Vec<StopConfig>) -> SelfReplace all stops
stop(StopId, impl Into<String>, f64) -> SelfAdd a single stop
elevators(Vec<ElevatorConfig>) -> SelfReplace all elevators
elevator(ElevatorConfig) -> SelfAdd a single elevator
ticks_per_second(f64) -> SelfSet the tick rate
building_name(impl Into<String>) -> SelfSet the building name
dispatch(impl DispatchStrategy) -> SelfSet dispatch for the default group
dispatch_for_group(GroupId, impl DispatchStrategy) -> SelfSet dispatch for a specific group
before(Phase, impl Fn(&mut World)) -> SelfRegister a before-phase hook
after(Phase, impl Fn(&mut World)) -> SelfRegister an after-phase hook
before_group(Phase, GroupId, impl Fn(&mut World)) -> SelfBefore-phase hook for a specific group
after_group(Phase, GroupId, impl Fn(&mut World)) -> SelfAfter-phase hook for a specific group
line(LineConfig) -> SelfAdd a single line configuration (switches to explicit topology mode)
lines(Vec<LineConfig>) -> SelfReplace all lines
group(GroupConfig) -> SelfAdd a single group configuration
groups(Vec<GroupConfig>) -> SelfReplace all groups
with_ext::<T>(&str) -> SelfPre-register an extension type for snapshot deserialization
build() -> Result<Simulation, SimError>Validate config and build the simulation

Simulation

The core simulation state. Advance it by calling step(), or run individual phases for fine-grained control.

Stepping

MethodSignatureDescription
step(&mut self)Run all 8 phases and advance the tick counter
advance_tick(&mut self)Increment tick counter and flush events to output buffer
run_advance_transient(&mut self)Run the advance-transient phase (with hooks)
run_dispatch(&mut self)Run the dispatch phase (with hooks)
run_reposition(&mut self)Run the reposition phase (with hooks)
run_advance_queue(&mut self)Run the advance-queue phase — reconcile DestinationQueue (with hooks)
run_movement(&mut self)Run the movement phase (with hooks)
run_doors(&mut self)Run the doors phase (with hooks)
run_loading(&mut self)Run the loading phase (with hooks)
run_metrics(&mut self)Run the metrics phase (with hooks)
phase_context(&self) -> PhaseContextBuild the tick/dt context for the current tick

Rider Management

MethodSignatureDescription
spawn_rider(&mut self, EntityId, EntityId, f64) -> Result<EntityId, SimError>Spawn a rider at origin heading to destination; auto-detects group (returns AmbiguousRoute if multiple groups serve both stops)
spawn_rider_with_route(&mut self, EntityId, EntityId, f64, Route) -> Result<EntityId, SimError>Spawn a rider with an explicit route
spawn_rider_by_stop_id(&mut self, StopId, StopId, f64) -> Result<EntityId, SimError>Spawn a rider using config StopIds
spawn_rider_in_group(&mut self, EntityId, EntityId, f64, GroupId) -> Result<EntityId, SimError>Spawn a rider in a specific group
spawn_rider_in_group_by_stop_id(&mut self, StopId, StopId, f64, GroupId) -> Result<EntityId, SimError>Spawn a rider in a specific group using config StopIds
reroute(&mut self, EntityId, EntityId) -> Result<(), SimError>Change a waiting rider’s destination
set_rider_route(&mut self, EntityId, Route) -> Result<(), SimError>Replace a rider’s entire remaining route

Events

MethodSignatureDescription
drain_events(&mut self) -> Vec<Event>Drain all pending events from completed ticks
pending_events(&self) -> &[Event]Peek at pending events without draining
events_mut(&mut self) -> &mut EventBusGet a mutable reference to the internal event bus

Metrics and Tagging

MethodSignatureDescription
metrics(&self) -> &MetricsGet current aggregate metrics
metrics_mut(&mut self) -> &mut MetricsGet mutable access to metrics
metrics_for_tag(&self, &str) -> Option<&TaggedMetric>Query per-tag metric accumulator
tag_entity(&mut self, EntityId, impl Into<String>)Attach a metric tag to an entity
untag_entity(&mut self, EntityId, &str)Remove a metric tag from an entity
all_tags(&self) -> Vec<&str>List all registered metric tags

Dynamic Topology

MethodSignatureDescription
add_stop(&mut self, String, f64, EntityId) -> Result<EntityId, SimError>Add a new stop to a line at runtime
add_elevator(&mut self, &ElevatorParams, EntityId, f64) -> Result<EntityId, SimError>Add a new elevator to a line at runtime
add_line(&mut self, &LineParams) -> Result<EntityId, SimError>Add a new line to a group at runtime
remove_line(&mut self, EntityId) -> Result<(), SimError>Remove a line and disable its elevators
add_group(&mut self, impl Into<String>, impl DispatchStrategy) -> GroupIdCreate a new dispatch group
assign_line_to_group(&mut self, EntityId, GroupId) -> Result<GroupId, SimError>Reassign a line to a different group; returns old GroupId
add_stop_to_line(&mut self, EntityId, EntityId) -> Result<(), SimError>Add an existing stop to a line’s served-stop list
remove_stop_from_line(&mut self, EntityId, EntityId) -> Result<(), SimError>Remove a stop from a line’s served-stop list
disable(&mut self, EntityId) -> Result<(), SimError>Disable an entity (skipped by all systems; ejects riders from elevators)
enable(&mut self, EntityId) -> Result<(), SimError>Re-enable a disabled entity
is_disabled(&self, EntityId) -> boolCheck if an entity is disabled

Topology Queries

MethodSignatureDescription
all_lines(&self) -> Vec<EntityId>All line entities in the simulation
line_count(&self) -> usizeNumber of lines in the simulation
lines_in_group(&self, GroupId) -> Vec<EntityId>Line entities belonging to a group
elevators_on_line(&self, EntityId) -> Vec<EntityId>Elevator entities on a line
stops_served_by_line(&self, EntityId) -> Vec<EntityId>Stop entities served by a line
line_for_elevator(&self, EntityId) -> Option<EntityId>Find the line an elevator belongs to
lines_serving_stop(&self, EntityId) -> Vec<EntityId>Lines that serve a given stop
groups_serving_stop(&self, EntityId) -> Vec<GroupId>Groups that serve a given stop
reachable_stops_from(&self, EntityId) -> Vec<EntityId>All stops reachable from a stop (via any line/transfer)
transfer_points(&self) -> Vec<EntityId>Stops served by more than one group
shortest_route(&self, EntityId, EntityId) -> Option<Route>Compute the shortest route between two stops

Accessors

MethodSignatureDescription
world(&self) -> &WorldShared reference to the ECS world
world_mut(&mut self) -> &mut WorldMutable reference to the ECS world
current_tick(&self) -> u64Current simulation tick
dt(&self) -> f64Time delta per tick in seconds
groups(&self) -> &[ElevatorGroup]Get the elevator groups
stop_entity(&self, StopId) -> Option<EntityId>Resolve a config StopId to its runtime EntityId
stop_lookup_iter(&self) -> impl Iterator<Item = (&StopId, &EntityId)>Iterate the stop ID to entity ID mapping
time(&self) -> &TimeAdapterTick-to-wall-clock time converter
strategy_id(&self, GroupId) -> Option<&BuiltinStrategy>Get the dispatch strategy identifier for a group
dispatchers(&self) -> &BTreeMap<GroupId, Box<dyn DispatchStrategy>>Get the dispatch strategies map
dispatchers_mut(&mut self) -> &mut BTreeMap<GroupId, Box<dyn DispatchStrategy>>Get the dispatch strategies map mutably

Inspection Queries

MethodSignatureDescription
is_elevator(&self, EntityId) -> boolCheck if an entity has an Elevator component
is_rider(&self, EntityId) -> boolCheck if an entity has a Rider component
is_stop(&self, EntityId) -> boolCheck if an entity has a Stop component
is_disabled(&self, EntityId) -> boolCheck if an entity is disabled
idle_elevator_count(&self) -> usizeCount of elevators in Idle phase (excludes disabled)
elevators_in_phase(&self, ElevatorPhase) -> usizeCount of elevators in a given phase (excludes disabled)
elevator_load(&self, EntityId) -> Option<f64>Current weight aboard an elevator
elevator_going_up(&self, EntityId) -> Option<bool>Up-direction indicator lamp state (None if not an elevator)
elevator_going_down(&self, EntityId) -> Option<bool>Down-direction indicator lamp state (None if not an elevator)
elevator_move_count(&self, EntityId) -> Option<u64>Per-elevator count of rounded-floor transitions (None if not an elevator)
braking_distance(&self, EntityId) -> Option<f64>Distance required to brake to a stop from the current velocity at the elevator’s deceleration (v² / 2a). Some(0.0) when stationary; None if not an elevator
future_stop_position(&self, EntityId) -> Option<f64>Current position plus signed braking distance in the direction of travel — where the elevator would come to rest if braking began now

Dispatch

MethodSignatureDescription
set_dispatch(&mut self, GroupId, Box<dyn DispatchStrategy>, BuiltinStrategy)Replace the dispatch strategy for a group

Hooks (Post-Build)

MethodSignatureDescription
add_before_hook(&mut self, Phase, impl Fn(&mut World))Register a hook to run before a phase
add_after_hook(&mut self, Phase, impl Fn(&mut World))Register a hook to run after a phase
add_before_group_hook(&mut self, Phase, GroupId, impl Fn(&mut World))Before-phase hook for a specific group
add_after_group_hook(&mut self, Phase, GroupId, impl Fn(&mut World))After-phase hook for a specific group

Snapshots

MethodSignatureDescription
snapshot(&self) -> WorldSnapshotCreate a serializable snapshot of the current state
load_extensions(&mut self)Deserialize extension components from a pending snapshot

ElevatorParams

Parameters for add_elevator at runtime. All fields are public.

FieldTypeDefaultDescription
max_speedf642.0Maximum travel speed
accelerationf641.5Acceleration rate
decelerationf642.0Deceleration rate
weight_capacityf64800.0Maximum weight the car can carry
door_transition_ticksu325Ticks for a door open/close transition
door_open_ticksu3210Ticks the door stays fully open

LineParams

Parameters for add_line at runtime. All fields are public.

FieldTypeDescription
nameStringHuman-readable name
groupGroupIdDispatch group to add this line to
orientationOrientationPhysical orientation (defaults to Vertical)
min_positionf64Lowest reachable position on the line axis
max_positionf64Highest reachable position on the line axis
positionOption<FloorPosition>Optional floor-plan position
max_carsOption<usize>Maximum cars on this line (None = unlimited)

Constructor: LineParams::new(name, group) — defaults orientation to Vertical, positions to 0.0, no floor-plan position, unlimited cars.


World

Central entity/component storage using the struct-of-arrays pattern. Built-in components are accessed via typed methods; custom data goes through extension storage.

Entity Lifecycle

MethodSignatureDescription
new() -> SelfCreate an empty world
spawn(&mut self) -> EntityIdAllocate a new entity (no components attached)
despawn(&mut self, EntityId)Remove an entity and all its components
is_alive(&self, EntityId) -> boolCheck if an entity is alive
entity_count(&self) -> usizeNumber of live entities

Component Accessors

Each built-in component has a getter, mutable getter, and setter. The pattern is the same for all:

ComponentGetGet MutSet
Positionposition(EntityId) -> Option<&Position>position_mut(EntityId)set_position(EntityId, Position)
Velocityvelocity(EntityId) -> Option<&Velocity>velocity_mut(EntityId)set_velocity(EntityId, Velocity)
Elevatorelevator(EntityId) -> Option<&Elevator>elevator_mut(EntityId)set_elevator(EntityId, Elevator)
Riderrider(EntityId) -> Option<&Rider>rider_mut(EntityId)set_rider(EntityId, Rider)
Stopstop(EntityId) -> Option<&Stop>stop_mut(EntityId)set_stop(EntityId, Stop)
Routeroute(EntityId) -> Option<&Route>route_mut(EntityId)set_route(EntityId, Route)
Lineline(EntityId) -> Option<&Line>line_mut(EntityId)set_line(EntityId, Line)
Patiencepatience(EntityId) -> Option<&Patience>patience_mut(EntityId)set_patience(EntityId, Patience)
Preferencespreferences(EntityId) -> Option<&Preferences>set_preferences(EntityId, Preferences)

Iteration Helpers

MethodSignatureDescription
iter_elevators(&self) -> impl Iterator<Item = (EntityId, &Position, &Elevator)>Iterate all elevator entities
iter_riders(&self) -> impl Iterator<Item = (EntityId, &Rider)>Iterate all rider entities
iter_riders_mut(&mut self) -> impl Iterator<Item = (EntityId, &mut Rider)>Iterate all rider entities mutably
iter_stops(&self) -> impl Iterator<Item = (EntityId, &Stop)>Iterate all stop entities
elevator_ids(&self) -> Vec<EntityId>All elevator entity IDs
rider_ids(&self) -> Vec<EntityId>All rider entity IDs
stop_ids(&self) -> Vec<EntityId>All stop entity IDs
elevator_ids_into(&self, &mut Vec<EntityId>)Fill a buffer with elevator IDs (no allocation)

Stop Lookup

MethodSignatureDescription
find_stop_at_position(&self, f64) -> Option<EntityId>Find the stop at an exact position (within epsilon)
find_nearest_stop(&self, f64) -> Option<EntityId>Find the stop nearest to a position
stop_position(&self, EntityId) -> Option<f64>Get a stop’s position by entity ID

Extension Storage

Extensions let games attach custom typed data to simulation entities. Extension types must implement Serialize + DeserializeOwned for snapshot support.

MethodSignatureDescription
insert_ext<T>(&mut self, EntityId, T, &str)Insert a custom component for an entity
get_ext<T: Clone>(&self, EntityId) -> Option<T>Get a clone of a custom component
get_ext_mut<T>(&mut self, EntityId) -> Option<&mut T>Get a mutable reference to a custom component
remove_ext<T>(&mut self, EntityId) -> Option<T>Remove a custom component
register_ext<T>(&mut self, &str)Register an extension type for snapshot deserialization
query_ext_mut<T>(&mut self) -> ExtQueryMut<T>Create a mutable extension query builder

Global Resources

Resources are type-keyed singletons not attached to any entity. Useful for event channels, score trackers, or any shared state.

MethodSignatureDescription
insert_resource<T>(&mut self, T)Insert a global resource (replaces existing)
resource<T>(&self) -> Option<&T>Get a shared reference to a resource
resource_mut<T>(&mut self) -> Option<&mut T>Get a mutable reference to a resource
remove_resource<T>(&mut self) -> Option<T>Remove a resource, returning it

Query Builder

The query builder provides ECS-style iteration over entities by component composition.

#![allow(unused)]
fn main() {
// All riders with a position
for (id, rider, pos) in world.query::<(EntityId, &Rider, &Position)>().iter() {
    // ...
}

// Entities with Position but without Route
for (id, pos) in world.query::<(EntityId, &Position)>()
    .without::<Route>()
    .iter()
{
    // ...
}

// Extension components (cloned)
for (id, vip) in world.query::<(EntityId, &Ext<VipTag>)>().iter() {
    // ...
}
}
TypeDescription
QueryBuilder<Q>Returned by world.query::<Q>(). Chain .with::<C>() / .without::<C>() filters, then .iter()
ExtQueryMut<T>Returned by world.query_ext_mut::<T>(). Call .for_each_mut(|id, val| ...) for mutable iteration
Ext<T>Query fetch marker for extension components (cloned)
ExtMut<T>Query fetch marker for mutable extension access
With<C>Filter: entity must have component C
Without<C>Filter: entity must not have component C
ExtWith<T>Filter: entity must have extension T
ExtWithout<T>Filter: entity must not have extension T

Disabled Entities

MethodSignatureDescription
disable(&mut self, EntityId)Mark an entity as disabled (skipped by systems)
enable(&mut self, EntityId)Re-enable a disabled entity
is_disabled(&self, EntityId) -> boolCheck if an entity is disabled

Dispatch

DispatchStrategy Trait

#![allow(unused)]
fn main() {
pub trait DispatchStrategy: Send + Sync {
    fn decide(
        &mut self,
        elevator: EntityId,
        elevator_position: f64,
        group: &ElevatorGroup,
        manifest: &DispatchManifest,
        world: &World,
    ) -> DispatchDecision;

    // Optional: batch decision for all idle elevators (default calls decide per elevator)
    fn decide_all(...) -> Vec<(EntityId, DispatchDecision)>;

    // Optional: cleanup when an elevator is removed (default no-op)
    fn notify_removed(&mut self, elevator: EntityId);
}
}

DispatchDecision

VariantDescription
GoToStop(EntityId)Send the elevator to the specified stop
IdleRemain idle

DispatchManifest

Contains per-rider metadata grouped by stop. Passed to dispatch strategies each tick.

Field / MethodTypeDescription
waiting_at_stopBTreeMap<EntityId, Vec<RiderInfo>>Riders waiting at each stop
riding_to_stopBTreeMap<EntityId, Vec<RiderInfo>>Riders aboard elevators, grouped by destination
waiting_count_at(EntityId) -> usizeNumber of riders waiting at a stop
total_weight_at(EntityId) -> f64Total weight of riders waiting at a stop
riding_count_to(EntityId) -> usizeNumber of riders heading to a stop
has_demand(EntityId) -> boolWhether a stop has any demand

RiderInfo

Metadata about a single rider, available to dispatch strategies.

FieldTypeDescription
idEntityIdRider entity ID
destinationOption<EntityId>Rider’s destination stop entity
weightf64Rider weight
wait_ticksu64Ticks this rider has been waiting

ElevatorGroup

Runtime representation of a dispatch group containing one or more lines. The flat elevator_entities() and stop_entities() accessors are derived caches (union of all lines’ elevators/stops), rebuilt automatically via rebuild_caches().

GetterReturn TypeDescription
id()GroupIdUnique group identifier
name()&strHuman-readable group name
lines()&[LineInfo]Lines belonging to this group
elevator_entities()&[EntityId]Derived cache: all elevator entities across lines
stop_entities()&[EntityId]Derived cache: all stop entities across lines

LineInfo

Per-line relationship data within an ElevatorGroup. Denormalized cache maintained by Simulation; the source of truth for intrinsic line properties is the Line component in World.

GetterReturn TypeDescription
entity()EntityIdLine entity ID
elevators()&[EntityId]Elevator entities on this line
serves()&[EntityId]Stop entities served by this line

Built-in Strategies

StrategyConstructorDescription
ScanDispatchScanDispatch::new()SCAN algorithm – sweeps end-to-end before reversing
LookDispatchLookDispatch::new()LOOK algorithm – reverses at last request, not shaft end
NearestCarDispatchNearestCarDispatch::new()Assigns each call to the closest idle elevator
EtdDispatchEtdDispatch::new()Estimated Time to Destination – minimizes total cost

BuiltinStrategy Enum

Serializable identifier for dispatch strategies (used in snapshots and configs).

VariantDescription
ScanSCAN algorithm
LookLOOK algorithm
NearestCarNearest-car algorithm
EtdEstimated Time to Destination
Custom(String)Custom strategy identified by name

The instantiate() method creates a boxed DispatchStrategy from a variant (returns None for Custom).


Events

Events are emitted during tick execution and buffered for consumers. Drain them with sim.drain_events().

Elevator Events

VariantFieldsDescription
ElevatorDepartedelevator: EntityId, from_stop: EntityId, tick: u64An elevator departed from a stop
ElevatorArrivedelevator: EntityId, at_stop: EntityId, tick: u64An elevator arrived at a stop
DoorOpenedelevator: EntityId, tick: u64Doors finished opening
DoorClosedelevator: EntityId, tick: u64Doors finished closing
PassingFloorelevator: EntityId, stop: EntityId, moving_up: bool, tick: u64Elevator passed a stop without stopping
ElevatorIdleelevator: EntityId, at_stop: Option<EntityId>, tick: u64Elevator became idle
CapacityChangedelevator: EntityId, current_load: OrderedFloat<f64>, capacity: OrderedFloat<f64>, tick: u64Elevator load changed after board or exit
DirectionIndicatorChangedelevator: EntityId, going_up: bool, going_down: bool, tick: u64Direction indicator lamps changed (dispatch-driven)

Rider Events

VariantFieldsDescription
RiderSpawnedrider: EntityId, origin: EntityId, destination: EntityId, tick: u64A rider appeared at a stop
RiderBoardedrider: EntityId, elevator: EntityId, tick: u64A rider boarded an elevator
RiderExitedrider: EntityId, elevator: EntityId, stop: EntityId, tick: u64A rider exited an elevator
RiderRejectedrider: EntityId, elevator: EntityId, reason: RejectionReason, context: Option<RejectionContext>, tick: u64A rider was rejected from boarding
RiderAbandonedrider: EntityId, stop: EntityId, tick: u64A rider gave up waiting
RiderEjectedrider: EntityId, elevator: EntityId, stop: EntityId, tick: u64A rider was ejected from a disabled/despawned elevator
RiderReroutedrider: EntityId, new_destination: EntityId, tick: u64A rider was manually rerouted

Dispatch Events

VariantFieldsDescription
ElevatorAssignedelevator: EntityId, stop: EntityId, tick: u64An elevator was assigned to serve a stop

Topology Events

VariantFieldsDescription
StopAddedstop: EntityId, line: EntityId, group: GroupId, tick: u64A new stop was added at runtime
ElevatorAddedelevator: EntityId, line: EntityId, group: GroupId, tick: u64A new elevator was added at runtime
LineAddedline: EntityId, group: GroupId, tick: u64A new line was added to the simulation
LineRemovedline: EntityId, group: GroupId, tick: u64A line was removed from the simulation
LineReassignedline: EntityId, old_group: GroupId, new_group: GroupId, tick: u64A line was reassigned to a different group
ElevatorReassignedelevator: EntityId, old_line: EntityId, new_line: EntityId, tick: u64An elevator was reassigned to a different line
EntityDisabledentity: EntityId, tick: u64An entity was disabled
EntityEnabledentity: EntityId, tick: u64An entity was re-enabled
RouteInvalidatedrider: EntityId, affected_stop: EntityId, reason: RouteInvalidReason, tick: u64A rider’s route was invalidated by topology change

RouteInvalidReason

VariantDescription
StopDisabledA stop on the route was disabled
NoAlternativeNo alternative stop is available in the same group

EventBus

Internal event bus used by the simulation. Games typically interact through sim.drain_events() instead.

MethodSignatureDescription
emit(&mut self, Event)Push an event
drain(&mut self) -> Vec<Event>Return and clear all pending events
peek(&self) -> &[Event]View pending events without clearing

EventChannel<T>

Typed event channel for game-specific events. Insert as a world resource.

MethodSignatureDescription
new() -> SelfCreate an empty channel
emit(&mut self, T)Emit an event
drain(&mut self) -> Vec<T>Drain all pending events
peek(&self) -> &[T]Peek at pending events
is_empty(&self) -> boolCheck if channel is empty
len(&self) -> usizeNumber of pending events

Metrics

Metrics (Global)

Aggregated simulation metrics, updated each tick. Query via sim.metrics().

GetterReturn TypeDescription
avg_wait_time()f64Average wait time in ticks (spawn to board)
avg_ride_time()f64Average ride time in ticks (board to exit)
max_wait_time()u64Maximum wait time observed (ticks)
throughput()u64Riders delivered in the current throughput window
total_delivered()u64Total riders delivered
total_abandoned()u64Total riders who abandoned
total_spawned()u64Total riders spawned
abandonment_rate()f64Abandonment rate (0.0 - 1.0)
total_distance()f64Total distance traveled by all elevators
total_moves()u64Total rounded-floor transitions across all elevators
throughput_window_ticks()u64Window size for throughput calculation (default: 3600)

Builder method: Metrics::new().with_throughput_window(window_ticks).

TaggedMetric

Per-tag metric accumulator. Same core metrics as Metrics but scoped to entities sharing a tag. Query via sim.metrics_for_tag("zone:lobby").

GetterReturn TypeDescription
avg_wait_time()f64Average wait time for tagged riders
total_delivered()u64Total delivered with this tag
total_abandoned()u64Total abandoned with this tag
total_spawned()u64Total spawned with this tag
max_wait_time()u64Maximum wait time for tagged riders

MetricTags

Tag storage and per-tag accumulators. Stored as a world resource.

MethodSignatureDescription
tag(&mut self, EntityId, impl Into<String>)Attach a tag to an entity
untag(&mut self, EntityId, &str)Remove a tag from an entity
tags_for(&self, EntityId) -> &[String]Get all tags for an entity
metric(&self, &str) -> Option<&TaggedMetric>Get the metric accumulator for a tag
all_tags(&self) -> impl Iterator<Item = &str>Iterate all registered tags

Configuration

All config types derive Serialize + Deserialize and are loadable from RON files.

SimConfig

FieldTypeDescription
buildingBuildingConfigBuilding layout (stops)
elevatorsVec<ElevatorConfig>Elevator cars to install
simulationSimulationParamsGlobal timing parameters
passenger_spawningPassengerSpawnConfigSpawning parameters (advisory, for game layer)

BuildingConfig

FieldTypeDescription
nameStringHuman-readable building name
stopsVec<StopConfig>Ordered list of stops (at least one required)

StopConfig

FieldTypeDescription
idStopIdUnique stop identifier
nameStringHuman-readable stop name
positionf64Absolute position along the shaft axis

ElevatorConfig

FieldTypeDescription
idu32Numeric identifier (mapped to EntityId at init)
nameStringHuman-readable elevator name
max_speedf64Maximum travel speed (distance units/second)
accelerationf64Acceleration rate (distance units/second^2)
decelerationf64Deceleration rate (distance units/second^2)
weight_capacityf64Maximum weight the car can carry
starting_stopStopIdStop where the elevator starts
door_open_ticksu32Ticks doors remain fully open
door_transition_ticksu32Ticks for a door open/close transition

SimulationParams

FieldTypeDescription
ticks_per_secondf64Simulation ticks per real-time second

PassengerSpawnConfig

FieldTypeDescription
mean_interval_ticksu32Mean interval between spawns (for Poisson traffic generators)
weight_range(f64, f64)(min, max) weight range for randomly spawned passengers

LineConfig

FieldTypeDescription
idu32Unique line identifier (within the config)
nameStringHuman-readable name
servesVec<StopId>Stops served by this line
elevatorsVec<ElevatorConfig>Elevators on this line
orientationOrientationPhysical orientation (defaults to Vertical)
positionOption<FloorPosition>Optional floor-plan position
min_positionOption<f64>Lowest reachable position (auto-computed from stops if None)
max_positionOption<f64>Highest reachable position (auto-computed from stops if None)
max_carsOption<usize>Max cars on this line (None = unlimited)

GroupConfig

FieldTypeDescription
idu32Unique group identifier
nameStringHuman-readable name
linesVec<u32>Line IDs belonging to this group (references LineConfig::id)
dispatchBuiltinStrategyDispatch strategy for this group

Components

Entity components are the data attached to simulation entities. Built-in components are managed by the simulation; games add custom data via extensions.

Component Types

ComponentDescription
PositionPosition along the shaft axis (accessed via value() getter)
VelocityVelocity along the shaft axis, signed (accessed via value() getter)
ElevatorElevator car state and physics parameters
RiderRider core data (weight, phase, origin, timing)
StopStop data (accessed via name() and position() getters)
RouteMulti-leg route with legs: Vec<RouteLeg> and current_leg: usize
LinePhysical path component (shaft, tether, track)
PatienceWait-limit tracking (max_wait_ticks: u64, waited_ticks: u64)
PreferencesBoarding preferences (skip_full_elevator: bool, max_crowding_factor: f64)

ElevatorPhase

VariantDescription
IdleParked with no pending requests
MovingToStop(EntityId)Travelling toward a specific stop
DoorOpeningDoors are currently opening
LoadingDoors open; riders may board or exit
DoorClosingDoors are currently closing
StoppedStopped at a floor (doors closed, awaiting dispatch)

Elevator Getters

GetterReturn TypeDescription
phase()ElevatorPhaseCurrent operational phase
door()&DoorStateDoor finite-state machine
max_speed()f64Maximum travel speed
acceleration()f64Acceleration rate
deceleration()f64Deceleration rate
weight_capacity()f64Maximum weight capacity
current_load()f64Total weight currently aboard
riders()&[EntityId]Entity IDs of riders aboard
target_stop()Option<EntityId>Stop the car is heading toward
door_transition_ticks()u32Ticks for a door transition
door_open_ticks()u32Ticks the door stays open
line()EntityIdLine entity this car belongs to
going_up()boolUp-direction indicator lamp (set by dispatch; both lamps lit when idle)
going_down()boolDown-direction indicator lamp (set by dispatch; both lamps lit when idle)
move_count()u64Count of rounded-floor transitions (passing-floor crossings + arrivals)

Line Getters

GetterReturn TypeDescription
name()&strHuman-readable name
group()GroupIdDispatch group this line belongs to
orientation()OrientationPhysical orientation
position()Option<&FloorPosition>Optional floor-plan position
min_position()f64Lowest reachable position along the line axis
max_position()f64Highest reachable position along the line axis
max_cars()Option<usize>Maximum number of cars allowed on this line

Direction

Direction of movement along a line axis.

VariantDescription
UpMoving toward higher positions
DownMoving toward lower positions

Method: reversed() returns the opposite direction.

RiderPhase

VariantDescription
WaitingWaiting at a stop
Boarding(EntityId)Boarding an elevator (transient, one tick)
Riding(EntityId)Riding in an elevator
Exiting(EntityId)Exiting an elevator (transient, one tick)
WalkingWalking between transfer stops
ArrivedReached final destination
AbandonedGave up waiting

Rider Getters

GetterReturn TypeDescription
weight()f64Weight contributed to elevator load
phase()RiderPhaseCurrent lifecycle phase
current_stop()Option<EntityId>Stop the rider is at (while Waiting/Arrived/Abandoned)
spawn_tick()u64Tick when this rider was spawned
board_tick()Option<u64>Tick when this rider boarded (for ride-time metrics)

Route and RouteLeg

Field / MethodTypeDescription
legsVec<RouteLeg>Ordered legs of the route
current_legusizeIndex of the leg currently being traversed
direct(from, to, GroupId)-> RouteCreate a single-leg route
current()-> Option<&RouteLeg>Get the current leg
advance()-> boolAdvance to the next leg
is_complete()-> boolWhether all legs have been completed
current_destination()-> Option<EntityId>Destination of the current leg

RouteLeg Fields

FieldTypeDescription
fromEntityIdOrigin stop entity
toEntityIdDestination stop entity
viaTransportModeHow to travel this leg

TransportMode

VariantDescription
Group(GroupId)Use any elevator in the given dispatch group
Line(EntityId)Use a specific line (pinned routing)
WalkWalk between adjacent stops

Identifiers

TypeWrapsDescription
EntityIdGenerational SlotMap keyUniversal entity identifier, used across all component storages. Allocated by world.spawn()
StopIdStopId(u32)Config-level stop identifier. Mapped to an EntityId at construction time via sim.stop_entity(StopId)
GroupIdGroupId(u32)Elevator group identifier. GroupId(0) is the default group

Error Types

SimError

VariantFieldsDescription
InvalidConfigfield: &'static str, reason: StringConfiguration is invalid
EntityNotFoundEntityIdA referenced entity does not exist
StopNotFoundStopIdA referenced stop ID does not exist
GroupNotFoundGroupIdA referenced group does not exist
InvalidStateentity: EntityId, reason: StringOperation attempted on entity in wrong state
LineNotFoundEntityIdA referenced line entity does not exist
NoRouteorigin: EntityId, destination: EntityIdNo route exists between origin and destination across any group
AmbiguousRouteorigin: EntityId, destination: EntityIdMultiple groups serve both origin and destination — caller must specify

SimError implements std::error::Error and Display. It also has From<EntityId>, From<StopId>, and From<GroupId> conversions.

RejectionReason

VariantDescription
OverCapacityRider’s weight exceeds remaining elevator capacity
PreferenceBasedRider’s boarding preferences prevented boarding

RejectionContext

Numeric details of a rejection. Fields use OrderedFloat<f64> (for Eq on the event).

FieldTypeDescription
attempted_weightOrderedFloat<f64>Weight the rider attempted to add
current_loadOrderedFloat<f64>Current load on the elevator
capacityOrderedFloat<f64>Maximum weight capacity

Snapshots

WorldSnapshot

Serializable snapshot of the entire simulation state. Capture with sim.snapshot(), restore with snapshot.restore(custom_factory).

FieldTypeDescription
ticku64Simulation tick at capture time
dtf64Time delta per tick
entitiesVec<EntitySnapshot>All entity data
groupsVec<GroupSnapshot>Elevator group data
stop_lookupHashMap<StopId, usize>Stop ID to entity index mapping
metricsMetricsGlobal metrics at capture time
metric_tagsMetricTagsPer-tag metrics and entity-tag associations
extensionsHashMap<String, HashMap<EntityId, String>>Serialized extension data
ticks_per_secondf64Tick rate for TimeAdapter reconstruction
MethodSignatureDescription
restore(self, Option<&dyn Fn(&str) -> Option<Box<dyn DispatchStrategy>>>) -> SimulationRestore a simulation from this snapshot

Built-in strategies are auto-restored. For custom strategies, provide a factory function.


TimeAdapter

Converts between simulation ticks and wall-clock time. Access via sim.time().

MethodSignatureDescription
new(f64) -> SelfCreate with the given tick rate
ticks_to_seconds(u64) -> f64Convert ticks to seconds
seconds_to_ticks(f64) -> u64Convert seconds to ticks (rounded)
duration_to_ticks(Duration) -> u64Convert a Duration to ticks (rounded)
ticks_to_duration(u64) -> DurationConvert ticks to a Duration
ticks_per_second() -> f64The configured tick rate

Phase

Simulation phase identifiers for hook registration.

VariantDescription
AdvanceTransientAdvance transient rider states (Boarding to Riding, Exiting to Arrived)
DispatchAssign idle elevators to stops via dispatch strategy
MovementUpdate elevator position and velocity
DoorsTick door finite-state machines
LoadingBoard and exit riders
MetricsAggregate metrics from tick events

Traffic Generation

Available when the traffic feature is enabled (on by default). See the Traffic Generation chapter for a guided walkthrough.

TrafficPattern

Preset origin/destination distributions.

VariantDescription
UniformEqual probability for all pairs
UpPeak80% from lobby, 20% inter-floor
DownPeak80% to lobby, 20% inter-floor
Lunchtime40% upper→mid, 40% mid→upper, 20% random
Mixed30% up-peak, 30% down-peak, 40% inter-floor
MethodSignatureDescription
sample(&self, &[EntityId], &mut impl Rng) -> Option<(EntityId, EntityId)>Sample a pair from entity IDs
sample_stop_ids(&self, &[StopId], &mut impl Rng) -> Option<(StopId, StopId)>Sample a pair from config stop IDs

TrafficSchedule

Time-varying pattern selection.

MethodSignatureDescription
new(Vec<(Range<u64>, TrafficPattern)>) -> SelfBuild from segment list
with_fallback(self, TrafficPattern) -> SelfSet the out-of-range fallback
constant(TrafficPattern) -> SelfSchedule with a single pattern for all ticks
office_day(ticks_per_hour: u64) -> Self9-hour office day preset
pattern_at(&self, u64) -> &TrafficPatternGet the active pattern at a tick
sample(&self, u64, &[EntityId], &mut impl Rng) -> Option<(EntityId, EntityId)>Sample using the active pattern
sample_stop_ids(&self, u64, &[StopId], &mut impl Rng) -> Option<(StopId, StopId)>Same, by stop ID

TrafficSource

Trait for external traffic generators.

pub trait TrafficSource {
    fn generate(&mut self, tick: u64) -> Vec<SpawnRequest>;
}

SpawnRequest

pub struct SpawnRequest {
    pub origin: StopId,
    pub destination: StopId,
    pub weight: f64,
}

PoissonSource

Poisson-arrival traffic generator.

MethodSignatureDescription
new(Vec<StopId>, TrafficSchedule, u32, (f64, f64)) -> SelfBuild with stops, schedule, mean interval, weight range
from_config(&SimConfig) -> SelfBuild from simulation config
with_schedule(self, TrafficSchedule) -> SelfReplace the schedule
with_mean_interval(self, u32) -> SelfReplace the mean arrival interval
with_weight_range(self, (f64, f64)) -> SelfReplace the weight range (min/max auto-swapped)
generate(&mut self, u64) -> Vec<SpawnRequest>Generate spawn requests for a tick (from TrafficSource)