Skip to main content

SimulationBuilder

Struct SimulationBuilder 

Source
pub struct SimulationBuilder { /* private fields */ }
Expand description

Fluent builder for constructing a Simulation.

Builds a SimConfig internally and delegates to Simulation::new(). Provides a more ergonomic API for programmatic construction compared to assembling a config struct manually.

§Constructors

  • SimulationBuilder::new — empty builder. You must add at least one stop and at least one elevator before .build(), or it errors. ScanDispatch is the default strategy, 60 ticks/s the default rate.
  • SimulationBuilder::demo — pre-populated with two stops (Ground at 0.0, Top at 10.0) and one elevator, for doctests and quick prototyping. Override any piece with the fluent methods.

Implementations§

Source§

impl SimulationBuilder

Source

pub fn new() -> Self

Create an empty builder — no stops, no elevators, ScanDispatch as the default strategy, and 60 ticks per second.

You must add at least one stop and at least one elevator (via stops / stop and elevators / elevator) before build, or the build fails with SimError::InvalidConfig.

If you want a quick, already-valid sim for prototyping or examples, use demo.

use elevator_core::prelude::*;
use elevator_core::config::ElevatorConfig;
use elevator_core::stop::StopConfig;

// An empty builder errors on build — you must configure it first.
assert!(SimulationBuilder::new().build().is_err());

// Minimum valid configuration: at least one stop and one elevator.
let sim = SimulationBuilder::new()
    .stops(vec![
        StopConfig { id: StopId(0), name: "Ground".into(), position: 0.0 },
        StopConfig { id: StopId(1), name: "Top".into(), position: 10.0 },
    ])
    .elevator(ElevatorConfig {
        id: 0,
        name: "Main".into(),
        max_speed: 2.0,
        acceleration: 1.5,
        deceleration: 2.0,
        weight_capacity: 800.0,
        starting_stop: StopId(0),
        door_open_ticks: 10,
        door_transition_ticks: 5,
        restricted_stops: Vec::new(),
        service_mode: None,
        inspection_speed_factor: 0.25,
    })
    .build()
    .unwrap();
assert_eq!(sim.current_tick(), 0);
Source

pub fn demo() -> Self

Pre-populated builder for zero-config examples, doctests, and quick prototyping where the building layout isn’t the point.

Provides two stops (Ground at 0.0, Top at 10.0) and one elevator with SCAN dispatch. Use this when you want a working Simulation in one call and don’t care about the specific stops.

use elevator_core::prelude::*;

let sim = SimulationBuilder::demo().build().unwrap();
assert_eq!(sim.current_tick(), 0);

If you need a specific stop layout or elevator physics, use new and configure every field explicitly — it reads more clearly than threading overrides on top of demo’s defaults. .stop() is a push onto the current stops list, so calling it after demo() appends to the two defaults rather than replacing them.

Source

pub fn from_config(config: SimConfig) -> Self

Create a builder from an existing SimConfig.

Uses ScanDispatch as the default strategy. Call .dispatch() to override.

Source

pub fn stops(self, stops: Vec<StopConfig>) -> Self

Replace all stops with the given list.

Clears any previously added stops.

Source

pub fn stop(self, id: StopId, name: impl Into<String>, position: f64) -> Self

Add a single stop to the building.

Source

pub fn elevators(self, elevators: Vec<ElevatorConfig>) -> Self

Replace all elevators with the given list.

Clears any previously added elevators.

Source

pub fn elevator(self, config: ElevatorConfig) -> Self

Add a single elevator configuration.

Source

pub fn line(self, config: LineConfig) -> Self

Add a single line configuration.

Switches from legacy flat-elevator mode to explicit topology.

Source

pub fn lines(self, lines: Vec<LineConfig>) -> Self

Replace all lines with the given list.

Switches from legacy flat-elevator mode to explicit topology.

Source

pub fn group(self, config: GroupConfig) -> Self

Add a single group configuration.

Source

pub fn groups(self, groups: Vec<GroupConfig>) -> Self

Replace all groups with the given list.

Source

pub const fn ticks_per_second(self, tps: f64) -> Self

Set the simulation tick rate (ticks per second).

Source

pub fn building_name(self, name: impl Into<String>) -> Self

Set the building name.

Source

pub fn dispatch(self, strategy: impl DispatchStrategy + 'static) -> Self

Set the default dispatch strategy for the default group.

Source

pub fn dispatch_for_group( self, group: GroupId, strategy: impl DispatchStrategy + 'static, ) -> Self

Set a dispatch strategy for a specific group.

Source

pub fn before( self, phase: Phase, hook: impl Fn(&mut World) + Send + Sync + 'static, ) -> Self

Register a hook to run before a simulation phase.

Source

pub fn after( self, phase: Phase, hook: impl Fn(&mut World) + Send + Sync + 'static, ) -> Self

Register a hook to run after a simulation phase.

Source

pub fn before_group( self, phase: Phase, group: GroupId, hook: impl Fn(&mut World) + Send + Sync + 'static, ) -> Self

Register a hook to run before a phase for a specific group.

Source

pub fn after_group( self, phase: Phase, group: GroupId, hook: impl Fn(&mut World) + Send + Sync + 'static, ) -> Self

Register a hook to run after a phase for a specific group.

Source

pub fn reposition( self, strategy: impl RepositionStrategy + 'static, id: BuiltinReposition, ) -> Self

Set a reposition strategy for the default group.

Enables the reposition phase, which runs after dispatch to move idle elevators for better coverage.

Source

pub fn reposition_for_group( self, group: GroupId, strategy: impl RepositionStrategy + 'static, id: BuiltinReposition, ) -> Self

Set a reposition strategy for a specific group.

Source

pub fn with_ext<T: 'static + Send + Sync + Serialize + DeserializeOwned>( self, name: &str, ) -> Self

Pre-register an extension type for snapshot deserialization.

Extensions registered here will be available immediately after build() without needing to call register_ext manually.

Source

pub fn validate(&self) -> Result<(), SimError>

Validate the configuration without building the simulation.

Runs the same validation as build() but does not allocate entities or construct the simulation. Useful for CLI tools, config editors, and dry-run checks.

§Errors

Returns SimError::InvalidConfig if the configuration is invalid.

Source

pub fn build(self) -> Result<Simulation, SimError>

Build the simulation, validating the configuration.

Returns Err(SimError) if the configuration is invalid.

§Errors

Returns SimError::InvalidConfig if the assembled configuration is invalid.

§Examples
use elevator_core::prelude::*;
use elevator_core::stop::StopConfig;

let mut sim = SimulationBuilder::demo()
    .stops(vec![
        StopConfig { id: StopId(0), name: "Lobby".into(), position: 0.0 },
        StopConfig { id: StopId(1), name: "Roof".into(), position: 20.0 },
    ])
    .build()
    .unwrap();

sim.spawn_rider_by_stop_id(StopId(0), StopId(1), 75.0).unwrap();

for _ in 0..1000 {
    sim.step();
}

assert!(sim.metrics().total_delivered() > 0);

Trait Implementations§

Source§

impl Default for SimulationBuilder

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.