#![allow(
clippy::unwrap_used,
clippy::missing_docs_in_private_items,
clippy::missing_const_for_fn
)]
use std::collections::HashMap;
use elevator_core::dispatch::{
BuiltinStrategy, DispatchDecision, DispatchManifest, DispatchStrategy, ElevatorGroup,
};
use elevator_core::entity::EntityId;
use elevator_core::ids::GroupId;
use elevator_core::prelude::*;
use elevator_core::stop::StopConfig;
use elevator_core::world::World;
#[derive(Default)]
struct RoundRobin {
next_index: usize,
last_served_tick: HashMap<EntityId, u64>,
}
impl DispatchStrategy for RoundRobin {
fn decide(
&mut self,
_elevator: EntityId,
_elevator_position: f64,
_group: &ElevatorGroup,
_manifest: &DispatchManifest,
_world: &World,
) -> DispatchDecision {
DispatchDecision::Idle
}
fn decide_all(
&mut self,
elevators: &[(EntityId, f64)],
group: &ElevatorGroup,
manifest: &DispatchManifest,
_world: &World,
) -> Vec<(EntityId, DispatchDecision)> {
let demand_stops: Vec<EntityId> = group
.stop_entities()
.iter()
.copied()
.filter(|&s| manifest.has_demand(s))
.collect();
let mut results = Vec::with_capacity(elevators.len());
for (i, &(eid, _)) in elevators.iter().enumerate() {
let decision = if demand_stops.is_empty() {
DispatchDecision::Idle
} else {
let stop = demand_stops[(self.next_index + i) % demand_stops.len()];
DispatchDecision::GoToStop(stop)
};
results.push((eid, decision));
}
if !demand_stops.is_empty() {
self.next_index = (self.next_index + 1) % demand_stops.len();
}
results
}
fn notify_removed(&mut self, elevator: EntityId) {
self.last_served_tick.remove(&elevator);
}
}
fn main() {
let mut sim = SimulationBuilder::demo()
.stops(vec![
StopConfig {
id: StopId(0),
name: "Lobby".into(),
position: 0.0,
},
StopConfig {
id: StopId(1),
name: "Mezzanine".into(),
position: 4.0,
},
StopConfig {
id: StopId(2),
name: "Roof".into(),
position: 8.0,
},
])
.build()
.unwrap();
sim.set_dispatch(
GroupId(0),
Box::new(RoundRobin::default()),
BuiltinStrategy::Custom("round_robin".into()),
);
sim.spawn_rider_by_stop_id(StopId(0), StopId(2), 70.0)
.unwrap();
sim.spawn_rider_by_stop_id(StopId(1), StopId(0), 72.0)
.unwrap();
sim.spawn_rider_by_stop_id(StopId(2), StopId(1), 80.0)
.unwrap();
for _ in 0..5000 {
sim.step();
}
let m = sim.metrics();
println!("Delivered: {}", m.total_delivered());
println!("Avg wait: {:.1} ticks", m.avg_wait_time());
println!("Avg ride: {:.1} ticks", m.avg_ride_time());
println!("Total dist: {:.1} units", m.total_distance());
match sim.strategy_id(GroupId(0)) {
Some(BuiltinStrategy::Custom(name)) => {
println!("Strategy name: {name} (will round-trip through snapshots)");
}
other => println!("Strategy name: {other:?}"),
}
}