pub struct Simulation { /* private fields */ }Expand description
The core simulation state, advanced by calling step().
Implementations§
Source§impl Simulation
impl Simulation
Sourcepub fn new(
config: &SimConfig,
dispatch: impl DispatchStrategy + 'static,
) -> Result<Self, SimError>
pub fn new( config: &SimConfig, dispatch: impl DispatchStrategy + 'static, ) -> Result<Self, SimError>
Create a new simulation from config and a dispatch strategy.
Returns Err if the config is invalid (zero stops, duplicate IDs,
negative speeds, etc.).
§Errors
Returns SimError::InvalidConfig if the configuration has zero stops,
duplicate stop IDs, zero elevators, non-positive physics parameters,
invalid starting stops, or non-positive tick rate.
Sourcepub fn set_dispatch(
&mut self,
group: GroupId,
strategy: Box<dyn DispatchStrategy>,
id: BuiltinStrategy,
)
pub fn set_dispatch( &mut self, group: GroupId, strategy: Box<dyn DispatchStrategy>, id: BuiltinStrategy, )
Replace the dispatch strategy for a group.
The id parameter identifies the strategy for snapshot serialization.
Use BuiltinStrategy::Custom("name") for custom strategies.
Sourcepub fn set_reposition(
&mut self,
group: GroupId,
strategy: Box<dyn RepositionStrategy>,
id: BuiltinReposition,
)
pub fn set_reposition( &mut self, group: GroupId, strategy: Box<dyn RepositionStrategy>, id: BuiltinReposition, )
Set the reposition strategy for a group.
Enables the reposition phase for this group. Idle elevators will be repositioned according to the strategy after each dispatch phase.
Sourcepub fn remove_reposition(&mut self, group: GroupId)
pub fn remove_reposition(&mut self, group: GroupId)
Remove the reposition strategy for a group, disabling repositioning.
Sourcepub fn reposition_id(&self, group: GroupId) -> Option<&BuiltinReposition>
pub fn reposition_id(&self, group: GroupId) -> Option<&BuiltinReposition>
Get the reposition strategy identifier for a group.
Sourcepub fn add_before_hook(
&mut self,
phase: Phase,
hook: impl Fn(&mut World) + Send + Sync + 'static,
)
pub fn add_before_hook( &mut self, phase: Phase, hook: impl Fn(&mut World) + Send + Sync + 'static, )
Register a hook to run before a simulation phase.
Hooks are called in registration order. The hook receives mutable access to the world, allowing entity inspection or modification.
Sourcepub fn add_after_hook(
&mut self,
phase: Phase,
hook: impl Fn(&mut World) + Send + Sync + 'static,
)
pub fn add_after_hook( &mut self, phase: Phase, hook: impl Fn(&mut World) + Send + Sync + 'static, )
Register a hook to run after a simulation phase.
Hooks are called in registration order. The hook receives mutable access to the world, allowing entity inspection or modification.
Source§impl Simulation
impl Simulation
Sourcepub fn load_extensions(&mut self)
pub fn load_extensions(&mut self)
Deserialize extension components from a snapshot.
Call this after restoring from a snapshot and registering all
extension types via world.register_ext::<T>(name).
let mut sim = snapshot.restore(None);
sim.world_mut().register_ext::<VipTag>("vip_tag");
sim.load_extensions();Sourcepub fn reroute(
&mut self,
rider: EntityId,
new_destination: EntityId,
) -> Result<(), SimError>
pub fn reroute( &mut self, rider: EntityId, new_destination: EntityId, ) -> Result<(), SimError>
Change a rider’s destination mid-route.
Replaces remaining route legs with a single direct leg to new_destination,
keeping the rider’s current stop as origin.
Returns Err if the rider does not exist or is not in Waiting phase
(riding/boarding riders cannot be rerouted until they exit).
§Errors
Returns SimError::EntityNotFound if rider does not exist.
Returns SimError::InvalidState if the rider is not in
RiderPhase::Waiting or has no current stop.
Sourcepub fn set_rider_route(
&mut self,
rider: EntityId,
route: Route,
) -> Result<(), SimError>
pub fn set_rider_route( &mut self, rider: EntityId, route: Route, ) -> Result<(), SimError>
Replace a rider’s entire remaining route.
§Errors
Returns SimError::EntityNotFound if rider does not exist.
Sourcepub fn settle_rider(&mut self, id: EntityId) -> Result<(), SimError>
pub fn settle_rider(&mut self, id: EntityId) -> Result<(), SimError>
Transition an Arrived or Abandoned rider to Resident at their
current stop.
Resident riders are parked — invisible to dispatch and loading, but
queryable via residents_at(). They can later
be given a new route via reroute_rider().
§Errors
Returns SimError::EntityNotFound if id does not exist.
Returns SimError::InvalidState if the rider is not in
Arrived or Abandoned phase, or has no current stop.
Sourcepub fn reroute_rider(
&mut self,
id: EntityId,
route: Route,
) -> Result<(), SimError>
pub fn reroute_rider( &mut self, id: EntityId, route: Route, ) -> Result<(), SimError>
Give a Resident rider a new route, transitioning them to Waiting.
The rider begins waiting at their current stop for an elevator
matching the route’s transport mode. If the rider has a
Patience component, its
waited_ticks is reset to zero.
§Errors
Returns SimError::EntityNotFound if id does not exist.
Returns SimError::InvalidState if the rider is not in Resident phase,
the route has no legs, or the route’s first leg origin does not match the
rider’s current stop.
Sourcepub fn despawn_rider(&mut self, id: EntityId) -> Result<(), SimError>
pub fn despawn_rider(&mut self, id: EntityId) -> Result<(), SimError>
Remove a rider from the simulation entirely.
Cleans up the population index, metric tags, and elevator cross-references
(if the rider is currently aboard). Emits Event::RiderDespawned.
All rider removal should go through this method rather than calling
world.despawn() directly, to keep the population index consistent.
§Errors
Returns SimError::EntityNotFound if id does not exist or is
not a rider.
Sourcepub fn set_rider_access(
&mut self,
rider: EntityId,
allowed_stops: HashSet<EntityId>,
) -> Result<(), SimError>
pub fn set_rider_access( &mut self, rider: EntityId, allowed_stops: HashSet<EntityId>, ) -> Result<(), SimError>
Set the allowed stops for a rider.
When set, the rider will only be allowed to board elevators that
can take them to a stop in the allowed set. See
AccessControl for details.
§Errors
Returns SimError::EntityNotFound if the rider does not exist.
Sourcepub fn set_elevator_restricted_stops(
&mut self,
elevator: EntityId,
restricted_stops: HashSet<EntityId>,
) -> Result<(), SimError>
pub fn set_elevator_restricted_stops( &mut self, elevator: EntityId, restricted_stops: HashSet<EntityId>, ) -> Result<(), SimError>
Set the restricted stops for an elevator.
Riders whose current destination is in this set will be rejected
with RejectionReason::AccessDenied
during the loading phase.
§Errors
Returns SimError::EntityNotFound if the elevator does not exist.
Sourcepub fn residents_at(
&self,
stop: EntityId,
) -> impl Iterator<Item = EntityId> + '_
pub fn residents_at( &self, stop: EntityId, ) -> impl Iterator<Item = EntityId> + '_
Iterate over resident rider IDs at a stop (O(1) lookup).
Sourcepub fn resident_count_at(&self, stop: EntityId) -> usize
pub fn resident_count_at(&self, stop: EntityId) -> usize
Count of residents at a stop (O(1)).
Sourcepub fn waiting_at(&self, stop: EntityId) -> impl Iterator<Item = EntityId> + '_
pub fn waiting_at(&self, stop: EntityId) -> impl Iterator<Item = EntityId> + '_
Iterate over waiting rider IDs at a stop (O(1) lookup).
Sourcepub fn waiting_count_at(&self, stop: EntityId) -> usize
pub fn waiting_count_at(&self, stop: EntityId) -> usize
Count of waiting riders at a stop (O(1)).
Sourcepub fn abandoned_at(
&self,
stop: EntityId,
) -> impl Iterator<Item = EntityId> + '_
pub fn abandoned_at( &self, stop: EntityId, ) -> impl Iterator<Item = EntityId> + '_
Iterate over abandoned rider IDs at a stop (O(1) lookup).
Sourcepub fn abandoned_count_at(&self, stop: EntityId) -> usize
pub fn abandoned_count_at(&self, stop: EntityId) -> usize
Count of abandoned riders at a stop (O(1)).
Sourcepub fn riders_on(&self, elevator: EntityId) -> &[EntityId]
pub fn riders_on(&self, elevator: EntityId) -> &[EntityId]
Get the rider entities currently aboard an elevator.
Returns an empty slice if the elevator does not exist.
Sourcepub fn occupancy(&self, elevator: EntityId) -> usize
pub fn occupancy(&self, elevator: EntityId) -> usize
Get the number of riders aboard an elevator.
Returns 0 if the elevator does not exist.
Sourcepub fn disable(&mut self, id: EntityId) -> Result<(), SimError>
pub fn disable(&mut self, id: EntityId) -> Result<(), SimError>
Disable an entity. Disabled entities are skipped by all systems.
If the entity is an elevator in motion, it is reset to Idle with
zero velocity to prevent stale target references on re-enable.
Note on residents: disabling a stop does not automatically handle
Resident riders parked there. Callers should listen for
Event::EntityDisabled and manually reroute or despawn any
residents at the affected stop.
Emits EntityDisabled. Returns Err if the entity does not exist.
§Errors
Returns SimError::EntityNotFound if id does not refer to a
living entity.
Sourcepub fn enable(&mut self, id: EntityId) -> Result<(), SimError>
pub fn enable(&mut self, id: EntityId) -> Result<(), SimError>
Re-enable a disabled entity.
Emits EntityEnabled. Returns Err if the entity does not exist.
§Errors
Returns SimError::EntityNotFound if id does not refer to a
living entity.
Sourcepub fn is_disabled(&self, id: EntityId) -> bool
pub fn is_disabled(&self, id: EntityId) -> bool
Check if an entity is disabled.
Sourcepub fn is_elevator(&self, id: EntityId) -> bool
pub fn is_elevator(&self, id: EntityId) -> bool
Check if an entity is an elevator.
use elevator_core::prelude::*;
let sim = SimulationBuilder::demo().build().unwrap();
let stop = sim.stop_entity(StopId(0)).unwrap();
assert!(!sim.is_elevator(stop));
assert!(sim.is_stop(stop));Sourcepub fn idle_elevator_count(&self) -> usize
pub fn idle_elevator_count(&self) -> usize
Count of elevators currently in the Idle phase.
Excludes disabled elevators (whose phase is reset to Idle on disable).
use elevator_core::prelude::*;
let sim = SimulationBuilder::demo().build().unwrap();
assert_eq!(sim.idle_elevator_count(), 1);Sourcepub fn elevator_load(&self, id: EntityId) -> Option<f64>
pub fn elevator_load(&self, id: EntityId) -> Option<f64>
Current total weight aboard an elevator, or None if the entity is
not an elevator.
use elevator_core::prelude::*;
let sim = SimulationBuilder::demo().build().unwrap();
let stop = sim.stop_entity(StopId(0)).unwrap();
assert_eq!(sim.elevator_load(stop), None); // not an elevatorSourcepub fn elevator_going_up(&self, id: EntityId) -> Option<bool>
pub fn elevator_going_up(&self, id: EntityId) -> Option<bool>
Whether the elevator’s up-direction indicator lamp is lit.
Returns None if the entity is not an elevator. See
Elevator::going_up for semantics.
Sourcepub fn elevator_going_down(&self, id: EntityId) -> Option<bool>
pub fn elevator_going_down(&self, id: EntityId) -> Option<bool>
Whether the elevator’s down-direction indicator lamp is lit.
Returns None if the entity is not an elevator. See
Elevator::going_down for semantics.
Sourcepub fn elevator_direction(&self, id: EntityId) -> Option<Direction>
pub fn elevator_direction(&self, id: EntityId) -> Option<Direction>
Direction the elevator is currently signalling, derived from the
indicator-lamp pair. Returns None if the entity is not an elevator.
Sourcepub fn elevator_move_count(&self, id: EntityId) -> Option<u64>
pub fn elevator_move_count(&self, id: EntityId) -> Option<u64>
Count of rounded-floor transitions for an elevator (passing-floor
crossings plus arrivals). Returns None if the entity is not an
elevator.
Sourcepub fn braking_distance(&self, id: EntityId) -> Option<f64>
pub fn braking_distance(&self, id: EntityId) -> Option<f64>
Distance the elevator would travel while braking to a stop from its current velocity, at its configured deceleration rate.
Uses the standard v² / (2·a) kinematic formula. A stationary
elevator returns Some(0.0). Returns None if the entity is not
an elevator or lacks a velocity component.
Useful for writing opportunistic dispatch strategies (e.g. “stop at this floor if we can brake in time”) without duplicating the physics computation.
Sourcepub fn future_stop_position(&self, id: EntityId) -> Option<f64>
pub fn future_stop_position(&self, id: EntityId) -> Option<f64>
The position where the elevator would come to rest if it began braking this instant. Current position plus a signed braking distance in the direction of travel.
Returns None if the entity is not an elevator or lacks the required
components.
Sourcepub fn elevators_in_phase(&self, phase: ElevatorPhase) -> usize
pub fn elevators_in_phase(&self, phase: ElevatorPhase) -> usize
Count of elevators currently in the given phase.
Excludes disabled elevators (whose phase is reset to Idle on disable).
use elevator_core::prelude::*;
let sim = SimulationBuilder::demo().build().unwrap();
assert_eq!(sim.elevators_in_phase(ElevatorPhase::Idle), 1);
assert_eq!(sim.elevators_in_phase(ElevatorPhase::Loading), 0);Sourcepub fn set_service_mode(
&mut self,
elevator: EntityId,
mode: ServiceMode,
) -> Result<(), SimError>
pub fn set_service_mode( &mut self, elevator: EntityId, mode: ServiceMode, ) -> Result<(), SimError>
Set the service mode for an elevator.
Emits Event::ServiceModeChanged if the mode actually changes.
§Errors
Returns SimError::EntityNotFound if the elevator does not exist.
Sourcepub fn service_mode(&self, elevator: EntityId) -> ServiceMode
pub fn service_mode(&self, elevator: EntityId) -> ServiceMode
Get the current service mode for an elevator.
Source§impl Simulation
impl Simulation
Sourcepub fn add_stop(
&mut self,
name: String,
position: f64,
line: EntityId,
) -> Result<EntityId, SimError>
pub fn add_stop( &mut self, name: String, position: f64, line: EntityId, ) -> Result<EntityId, SimError>
Add a new stop to a group at runtime. Returns its EntityId.
Runtime-added stops have no StopId — they are identified purely
by EntityId. The stop_lookup (config StopId → EntityId)
is not updated.
§Errors
Returns SimError::LineNotFound if the line entity does not exist.
Sourcepub fn add_elevator(
&mut self,
params: &ElevatorParams,
line: EntityId,
starting_position: f64,
) -> Result<EntityId, SimError>
pub fn add_elevator( &mut self, params: &ElevatorParams, line: EntityId, starting_position: f64, ) -> Result<EntityId, SimError>
Add a new elevator to a line at runtime. Returns its EntityId.
§Errors
Returns SimError::LineNotFound if the line entity does not exist.
Sourcepub fn add_line(&mut self, params: &LineParams) -> Result<EntityId, SimError>
pub fn add_line(&mut self, params: &LineParams) -> Result<EntityId, SimError>
Add a new line to a group. Returns the line entity.
§Errors
Returns SimError::GroupNotFound if the specified group does not exist.
Sourcepub fn remove_line(&mut self, line: EntityId) -> Result<(), SimError>
pub fn remove_line(&mut self, line: EntityId) -> Result<(), SimError>
Remove a line and all its elevators from the simulation.
Elevators on the line are disabled (not despawned) so riders are properly ejected to the nearest stop.
§Errors
Returns SimError::LineNotFound if the line entity is not found
in any group.
Sourcepub fn remove_elevator(&mut self, elevator: EntityId) -> Result<(), SimError>
pub fn remove_elevator(&mut self, elevator: EntityId) -> Result<(), SimError>
Remove an elevator from the simulation.
The elevator is disabled first (ejecting any riders), then removed from its line and despawned from the world.
§Errors
Returns SimError::EntityNotFound if the elevator does not exist.
Sourcepub fn remove_stop(&mut self, stop: EntityId) -> Result<(), SimError>
pub fn remove_stop(&mut self, stop: EntityId) -> Result<(), SimError>
Remove a stop from the simulation.
The stop is disabled first (invalidating routes that reference it), then removed from all lines and despawned from the world.
§Errors
Returns SimError::EntityNotFound if the stop does not exist.
Sourcepub fn add_group(
&mut self,
name: impl Into<String>,
dispatch: impl DispatchStrategy + 'static,
) -> GroupId
pub fn add_group( &mut self, name: impl Into<String>, dispatch: impl DispatchStrategy + 'static, ) -> GroupId
Create a new dispatch group. Returns the group ID.
Sourcepub fn assign_line_to_group(
&mut self,
line: EntityId,
new_group: GroupId,
) -> Result<GroupId, SimError>
pub fn assign_line_to_group( &mut self, line: EntityId, new_group: GroupId, ) -> Result<GroupId, SimError>
Reassign a line to a different group. Returns the old GroupId.
§Errors
Returns SimError::LineNotFound if the line is not found in any group.
Returns SimError::GroupNotFound if new_group does not exist.
Sourcepub fn reassign_elevator_to_line(
&mut self,
elevator: EntityId,
new_line: EntityId,
) -> Result<(), SimError>
pub fn reassign_elevator_to_line( &mut self, elevator: EntityId, new_line: EntityId, ) -> Result<(), SimError>
Reassign an elevator to a different line (swing-car pattern).
The elevator is moved from its current line to the target line.
Both lines must be in the same group, or you must reassign the
line first via assign_line_to_group.
§Errors
Returns SimError::EntityNotFound if the elevator does not exist.
Returns SimError::LineNotFound if the target line is not found in any group.
Sourcepub fn add_stop_to_line(
&mut self,
stop: EntityId,
line: EntityId,
) -> Result<(), SimError>
pub fn add_stop_to_line( &mut self, stop: EntityId, line: EntityId, ) -> Result<(), SimError>
Add a stop to a line’s served stops.
§Errors
Returns SimError::EntityNotFound if the stop does not exist.
Returns SimError::LineNotFound if the line is not found in any group.
Sourcepub fn remove_stop_from_line(
&mut self,
stop: EntityId,
line: EntityId,
) -> Result<(), SimError>
pub fn remove_stop_from_line( &mut self, stop: EntityId, line: EntityId, ) -> Result<(), SimError>
Remove a stop from a line’s served stops.
§Errors
Returns SimError::LineNotFound if the line is not found in any group.
Sourcepub fn line_count(&self) -> usize
pub fn line_count(&self) -> usize
Number of lines in the simulation.
Sourcepub fn lines_in_group(&self, group: GroupId) -> Vec<EntityId>
pub fn lines_in_group(&self, group: GroupId) -> Vec<EntityId>
Get all line entities in a group.
Sourcepub fn elevators_on_line(&self, line: EntityId) -> Vec<EntityId>
pub fn elevators_on_line(&self, line: EntityId) -> Vec<EntityId>
Get elevator entities on a specific line.
Sourcepub fn stops_served_by_line(&self, line: EntityId) -> Vec<EntityId>
pub fn stops_served_by_line(&self, line: EntityId) -> Vec<EntityId>
Get stop entities served by a specific line.
Sourcepub fn line_for_elevator(&self, elevator: EntityId) -> Option<EntityId>
pub fn line_for_elevator(&self, elevator: EntityId) -> Option<EntityId>
Get the line entity for an elevator.
Sourcepub fn iter_repositioning_elevators(
&self,
) -> impl Iterator<Item = EntityId> + '_
pub fn iter_repositioning_elevators( &self, ) -> impl Iterator<Item = EntityId> + '_
Iterate over elevators currently repositioning.
Sourcepub fn lines_serving_stop(&self, stop: EntityId) -> Vec<EntityId>
pub fn lines_serving_stop(&self, stop: EntityId) -> Vec<EntityId>
Get all line entities that serve a given stop.
Sourcepub fn groups_serving_stop(&self, stop: EntityId) -> Vec<GroupId>
pub fn groups_serving_stop(&self, stop: EntityId) -> Vec<GroupId>
Get all group IDs that serve a given stop.
Sourcepub fn reachable_stops_from(&self, stop: EntityId) -> Vec<EntityId>
pub fn reachable_stops_from(&self, stop: EntityId) -> Vec<EntityId>
All stops reachable from a given stop through the line/group topology.
Sourcepub fn transfer_points(&self) -> Vec<EntityId>
pub fn transfer_points(&self) -> Vec<EntityId>
Stops that serve as transfer points between groups.
Source§impl Simulation
impl Simulation
Sourcepub const fn world_mut(&mut self) -> &mut World
pub const fn world_mut(&mut self) -> &mut World
Get a mutable reference to the world.
Exposed for advanced use cases (manual rider management, custom
component attachment). Prefer spawn_rider / spawn_rider_by_stop_id
for standard operations.
Sourcepub const fn current_tick(&self) -> u64
pub const fn current_tick(&self) -> u64
Current simulation tick.
Sourcepub const fn time(&self) -> &TimeAdapter
pub const fn time(&self) -> &TimeAdapter
The time adapter for tick↔wall-clock conversion.
Sourcepub fn groups(&self) -> &[ElevatorGroup]
pub fn groups(&self) -> &[ElevatorGroup]
Get the elevator groups.
Sourcepub fn stop_entity(&self, id: StopId) -> Option<EntityId>
pub fn stop_entity(&self, id: StopId) -> Option<EntityId>
Resolve a config StopId to its runtime EntityId.
Sourcepub fn strategy_id(&self, group: GroupId) -> Option<&BuiltinStrategy>
pub fn strategy_id(&self, group: GroupId) -> Option<&BuiltinStrategy>
Get the strategy identifier for a group.
Sourcepub fn stop_lookup_iter(&self) -> impl Iterator<Item = (&StopId, &EntityId)>
pub fn stop_lookup_iter(&self) -> impl Iterator<Item = (&StopId, &EntityId)>
Iterate over the stop ID → entity ID mapping.
Sourcepub fn pending_events(&self) -> &[Event]
pub fn pending_events(&self) -> &[Event]
Peek at events pending for consumer retrieval.
Sourcepub fn destination_queue(&self, elev: EntityId) -> Option<&[EntityId]>
pub fn destination_queue(&self, elev: EntityId) -> Option<&[EntityId]>
Read-only view of an elevator’s destination queue (FIFO of target
stop EntityIds).
Returns None if elev is not an elevator entity. Returns
Some(&[]) for elevators with an empty queue.
Sourcepub fn push_destination(
&mut self,
elev: EntityId,
stop: EntityId,
) -> Result<(), SimError>
pub fn push_destination( &mut self, elev: EntityId, stop: EntityId, ) -> Result<(), SimError>
Push a stop onto the back of an elevator’s destination queue.
Adjacent duplicates are suppressed: if the last entry already equals
stop, the queue is unchanged and no event is emitted.
Otherwise emits Event::DestinationQueued.
§Errors
SimError::InvalidStateifelevis not an elevator.SimError::InvalidStateifstopis not a stop.
Sourcepub fn push_destination_front(
&mut self,
elev: EntityId,
stop: EntityId,
) -> Result<(), SimError>
pub fn push_destination_front( &mut self, elev: EntityId, stop: EntityId, ) -> Result<(), SimError>
Insert a stop at the front of an elevator’s destination queue — “go here next, before anything else in the queue”.
On the next AdvanceQueue phase (between Dispatch and Movement),
the elevator redirects to this new front if it differs from the
current target.
Adjacent duplicates are suppressed: if the first entry already equals
stop, the queue is unchanged and no event is emitted.
§Errors
SimError::InvalidStateifelevis not an elevator.SimError::InvalidStateifstopis not a stop.
Sourcepub fn clear_destinations(&mut self, elev: EntityId) -> Result<(), SimError>
pub fn clear_destinations(&mut self, elev: EntityId) -> Result<(), SimError>
Clear an elevator’s destination queue.
TODO: clearing does not currently abort an in-flight movement — the elevator will finish its current leg and then go idle (since the queue is empty). A future change can add a phase transition to cancel mid-flight.
§Errors
Returns SimError::InvalidState if elev is not an elevator.
Sourcepub fn tag_entity(&mut self, id: EntityId, tag: impl Into<String>)
pub fn tag_entity(&mut self, id: EntityId, tag: impl Into<String>)
Attach a metric tag to an entity (rider, stop, elevator, etc.).
Tags enable per-tag metric breakdowns. An entity can have multiple tags. Riders automatically inherit tags from their origin stop when spawned.
Sourcepub fn untag_entity(&mut self, id: EntityId, tag: &str)
pub fn untag_entity(&mut self, id: EntityId, tag: &str)
Remove a metric tag from an entity.
Sourcepub fn metrics_for_tag(&self, tag: &str) -> Option<&TaggedMetric>
pub fn metrics_for_tag(&self, tag: &str) -> Option<&TaggedMetric>
Query the metric accumulator for a specific tag.
List all registered metric tags.
Sourcepub const fn build_rider(
&mut self,
origin: EntityId,
destination: EntityId,
) -> RiderBuilder<'_>
pub const fn build_rider( &mut self, origin: EntityId, destination: EntityId, ) -> RiderBuilder<'_>
Create a rider builder for fluent rider spawning.
use elevator_core::prelude::*;
let mut sim = SimulationBuilder::demo().build().unwrap();
let s0 = sim.stop_entity(StopId(0)).unwrap();
let s1 = sim.stop_entity(StopId(1)).unwrap();
let rider = sim.build_rider(s0, s1)
.weight(80.0)
.spawn()
.unwrap();Sourcepub fn build_rider_by_stop_id(
&mut self,
origin: StopId,
destination: StopId,
) -> Result<RiderBuilder<'_>, SimError>
pub fn build_rider_by_stop_id( &mut self, origin: StopId, destination: StopId, ) -> Result<RiderBuilder<'_>, SimError>
Create a rider builder using config StopIds.
§Errors
Returns SimError::StopNotFound if either stop ID is unknown.
use elevator_core::prelude::*;
let mut sim = SimulationBuilder::demo().build().unwrap();
let rider = sim.build_rider_by_stop_id(StopId(0), StopId(1))
.unwrap()
.weight(80.0)
.spawn()
.unwrap();Sourcepub fn spawn_rider(
&mut self,
origin: EntityId,
destination: EntityId,
weight: f64,
) -> Result<EntityId, SimError>
pub fn spawn_rider( &mut self, origin: EntityId, destination: EntityId, weight: f64, ) -> Result<EntityId, SimError>
Spawn a rider at the given origin stop entity, headed to destination stop entity.
Auto-detects the elevator group by finding groups that serve both origin and destination stops.
§Errors
Returns SimError::NoRoute if no group serves both stops.
Returns SimError::AmbiguousRoute if multiple groups serve both stops.
Sourcepub fn spawn_rider_with_route(
&mut self,
origin: EntityId,
destination: EntityId,
weight: f64,
route: Route,
) -> Result<EntityId, SimError>
pub fn spawn_rider_with_route( &mut self, origin: EntityId, destination: EntityId, weight: f64, route: Route, ) -> Result<EntityId, SimError>
Spawn a rider with an explicit route.
Same as spawn_rider but uses the provided route
instead of auto-detecting the group.
§Errors
Returns SimError::EntityNotFound if origin does not exist.
Returns SimError::InvalidState if origin doesn’t match the route’s
first leg from.
Sourcepub fn spawn_rider_by_stop_id(
&mut self,
origin: StopId,
destination: StopId,
weight: f64,
) -> Result<EntityId, SimError>
pub fn spawn_rider_by_stop_id( &mut self, origin: StopId, destination: StopId, weight: f64, ) -> Result<EntityId, SimError>
Convenience: spawn a rider by config StopId.
Returns Err if either stop ID is not found.
§Errors
Returns SimError::StopNotFound if the origin or destination stop ID
is not in the building configuration.
use elevator_core::prelude::*;
// Default builder has StopId(0) and StopId(1).
let mut sim = SimulationBuilder::demo().build().unwrap();
let rider = sim.spawn_rider_by_stop_id(StopId(0), StopId(1), 80.0).unwrap();
sim.step(); // metrics are updated during the tick
assert_eq!(sim.metrics().total_spawned(), 1);Sourcepub fn spawn_rider_in_group(
&mut self,
origin: EntityId,
destination: EntityId,
weight: f64,
group: GroupId,
) -> Result<EntityId, SimError>
pub fn spawn_rider_in_group( &mut self, origin: EntityId, destination: EntityId, weight: f64, group: GroupId, ) -> Result<EntityId, SimError>
Spawn a rider using a specific group for routing.
Like spawn_rider but skips auto-detection —
uses the given group directly. Useful when the caller already knows
the group, or to resolve an AmbiguousRoute.
§Errors
Returns SimError::GroupNotFound if the group does not exist.
Sourcepub fn spawn_rider_in_group_by_stop_id(
&mut self,
origin: StopId,
destination: StopId,
weight: f64,
group: GroupId,
) -> Result<EntityId, SimError>
pub fn spawn_rider_in_group_by_stop_id( &mut self, origin: StopId, destination: StopId, weight: f64, group: GroupId, ) -> Result<EntityId, SimError>
Convenience: spawn a rider by config StopId in a specific group.
§Errors
Returns SimError::StopNotFound if a stop ID is unknown, or
SimError::GroupNotFound if the group does not exist.
Sourcepub fn drain_events(&mut self) -> Vec<Event>
pub fn drain_events(&mut self) -> Vec<Event>
Drain all pending events from completed ticks.
Events emitted during step() (or per-phase methods) are buffered
and made available here after advance_tick() is called.
Events emitted outside the tick loop (e.g., spawn_rider, disable)
are also included.
use elevator_core::prelude::*;
let mut sim = SimulationBuilder::demo().build().unwrap();
sim.spawn_rider_by_stop_id(StopId(0), StopId(1), 70.0).unwrap();
sim.step();
let events = sim.drain_events();
assert!(!events.is_empty());Sourcepub fn drain_events_where(
&mut self,
predicate: impl Fn(&Event) -> bool,
) -> Vec<Event>
pub fn drain_events_where( &mut self, predicate: impl Fn(&Event) -> bool, ) -> Vec<Event>
Drain only events matching a predicate.
Events that don’t match the predicate remain in the buffer
and will be returned by future drain_events or
drain_events_where calls.
use elevator_core::prelude::*;
let mut sim = SimulationBuilder::demo().build().unwrap();
sim.spawn_rider_by_stop_id(StopId(0), StopId(1), 70.0).unwrap();
sim.step();
let spawns: Vec<Event> = sim.drain_events_where(|e| {
matches!(e, Event::RiderSpawned { .. })
});Sourcepub fn dispatchers(&self) -> &BTreeMap<GroupId, Box<dyn DispatchStrategy>>
pub fn dispatchers(&self) -> &BTreeMap<GroupId, Box<dyn DispatchStrategy>>
Get the dispatch strategies map (for advanced sub-stepping).
Sourcepub fn dispatchers_mut(
&mut self,
) -> &mut BTreeMap<GroupId, Box<dyn DispatchStrategy>>
pub fn dispatchers_mut( &mut self, ) -> &mut BTreeMap<GroupId, Box<dyn DispatchStrategy>>
Get the dispatch strategies map mutably (for advanced sub-stepping).
Sourcepub const fn events_mut(&mut self) -> &mut EventBus
pub const fn events_mut(&mut self) -> &mut EventBus
Get a mutable reference to the event bus.
Sourcepub const fn metrics_mut(&mut self) -> &mut Metrics
pub const fn metrics_mut(&mut self) -> &mut Metrics
Get a mutable reference to the metrics.
Sourcepub const fn phase_context(&self) -> PhaseContext
pub const fn phase_context(&self) -> PhaseContext
Build the PhaseContext for the current tick.
Sourcepub fn run_advance_transient(&mut self)
pub fn run_advance_transient(&mut self)
Run only the advance_transient phase (with hooks).
Sourcepub fn run_dispatch(&mut self)
pub fn run_dispatch(&mut self)
Run only the dispatch phase (with hooks).
Sourcepub fn run_movement(&mut self)
pub fn run_movement(&mut self)
Run only the movement phase (with hooks).
Sourcepub fn run_loading(&mut self)
pub fn run_loading(&mut self)
Run only the loading phase (with hooks).
Sourcepub fn run_advance_queue(&mut self)
pub fn run_advance_queue(&mut self)
Run only the advance-queue phase (with hooks).
Reconciles each elevator’s phase/target with the front of its
DestinationQueue. Runs
between Reposition and Movement.
Sourcepub fn run_reposition(&mut self)
pub fn run_reposition(&mut self)
Run only the reposition phase (with hooks).
Only runs if at least one group has a RepositionStrategy configured.
Idle elevators with no pending dispatch assignment are repositioned
according to their group’s strategy.
Sourcepub fn run_metrics(&mut self)
pub fn run_metrics(&mut self)
Run only the metrics phase (with hooks).
Sourcepub fn advance_tick(&mut self)
pub fn advance_tick(&mut self)
Increment the tick counter and flush events to the output buffer.
Call after running all desired phases. Events emitted during this tick
are moved to the output buffer and available via drain_events().
Sourcepub fn step(&mut self)
pub fn step(&mut self)
Advance the simulation by one tick.
Events from this tick are buffered internally and available via
drain_events(). The metrics system only processes events from
the current tick, regardless of whether the consumer drains them.
use elevator_core::prelude::*;
let mut sim = SimulationBuilder::demo().build().unwrap();
sim.step();
assert_eq!(sim.current_tick(), 1);Source§impl Simulation
impl Simulation
Sourcepub fn snapshot(&self) -> WorldSnapshot
pub fn snapshot(&self) -> WorldSnapshot
Create a serializable snapshot of the current simulation state.
The snapshot captures all entities, components, groups, metrics, and the tick counter. Extension components and custom resources are NOT included — games must serialize those separately.