use crate::builder::SimulationBuilder;
use crate::components::ElevatorPhase;
use crate::events::Event;
use crate::stop::StopId;
#[test]
fn is_elevator_returns_true_for_elevators() {
let sim = SimulationBuilder::demo().build().unwrap();
let elevator_id = sim
.world()
.iter_elevators()
.next()
.map(|(id, _, _)| id)
.unwrap();
assert!(sim.is_elevator(elevator_id));
assert!(!sim.is_rider(elevator_id));
assert!(!sim.is_stop(elevator_id));
}
#[test]
fn is_stop_returns_true_for_stops() {
let sim = SimulationBuilder::demo().build().unwrap();
let stop_id = sim.stop_entity(StopId(0)).unwrap();
assert!(sim.is_stop(stop_id));
assert!(!sim.is_elevator(stop_id));
assert!(!sim.is_rider(stop_id));
}
#[test]
fn is_rider_returns_true_for_riders() {
let mut sim = SimulationBuilder::demo().build().unwrap();
let rider = sim.spawn_rider(StopId(0), StopId(1), 75.0).unwrap();
assert!(sim.is_rider(rider));
assert!(!sim.is_elevator(rider));
assert!(!sim.is_stop(rider));
}
#[test]
fn idle_elevator_count_starts_at_one() {
let sim = SimulationBuilder::demo().build().unwrap();
assert_eq!(sim.idle_elevator_count(), 1);
}
#[test]
fn idle_elevator_count_decreases_when_moving() {
let mut sim = SimulationBuilder::demo().build().unwrap();
sim.spawn_rider(StopId(0), StopId(1), 75.0).unwrap();
for _ in 0..500 {
sim.step();
if sim.idle_elevator_count() == 0 {
break;
}
}
assert!(sim.idle_elevator_count() <= 1);
}
#[test]
fn elevator_load_starts_at_zero() {
let sim = SimulationBuilder::demo().build().unwrap();
let elevator_id = sim
.world()
.iter_elevators()
.next()
.map(|(id, _, _)| id)
.unwrap();
assert_eq!(sim.elevator_load(elevator_id), Some(0.0));
}
#[test]
fn elevator_load_returns_none_for_non_elevator() {
let sim = SimulationBuilder::demo().build().unwrap();
let stop_id = sim.stop_entity(StopId(0)).unwrap();
assert_eq!(sim.elevator_load(stop_id), None);
}
#[test]
fn elevators_in_phase_counts_correctly() {
let sim = SimulationBuilder::demo().build().unwrap();
assert_eq!(sim.elevators_in_phase(ElevatorPhase::Idle), 1);
assert_eq!(sim.elevators_in_phase(ElevatorPhase::Loading), 0);
assert_eq!(sim.elevators_in_phase(ElevatorPhase::DoorOpening), 0);
}
#[test]
fn disabled_elevators_excluded_from_counts() {
let mut sim = SimulationBuilder::demo().build().unwrap();
let elevator_id = sim
.world()
.iter_elevators()
.next()
.map(|(id, _, _)| id)
.unwrap();
assert_eq!(sim.idle_elevator_count(), 1);
assert_eq!(sim.elevators_in_phase(ElevatorPhase::Idle), 1);
sim.disable(elevator_id).unwrap();
assert_eq!(sim.idle_elevator_count(), 0);
assert_eq!(sim.elevators_in_phase(ElevatorPhase::Idle), 0);
}
#[test]
fn capacity_changed_emitted_on_disable_with_load() {
let mut sim = SimulationBuilder::demo().build().unwrap();
let rider = sim.spawn_rider(StopId(0), StopId(1), 75.0).unwrap();
for _ in 0..500 {
sim.step();
if sim.world().rider(rider).is_some_and(|r| {
matches!(
r.phase,
crate::components::RiderPhase::Riding(_)
| crate::components::RiderPhase::Boarding(_)
)
}) {
break;
}
}
let elevator_id = sim
.world()
.iter_elevators()
.next()
.map(|(id, _, _)| id)
.unwrap();
if sim.elevator_load(elevator_id).unwrap_or(0.0) > 0.0 {
sim.drain_events(); sim.disable(elevator_id).unwrap();
let found = sim.drain_events().iter().any(|e| {
matches!(
e,
Event::CapacityChanged {
elevator,
current_load,
..
} if *elevator == elevator_id && **current_load == 0.0
)
});
assert!(
found,
"disable() with riders aboard should emit CapacityChanged with load=0"
);
}
}
#[test]
fn capacity_changed_emitted_on_boarding() {
let mut sim = SimulationBuilder::demo().build().unwrap();
sim.spawn_rider(StopId(0), StopId(1), 75.0).unwrap();
let mut found_capacity_event = false;
for _ in 0..500 {
sim.step();
for event in sim.drain_events() {
if let Event::CapacityChanged {
current_load,
capacity,
..
} = event
{
assert!(*current_load >= 0.0);
assert!(*capacity > 0.0);
found_capacity_event = true;
}
}
if found_capacity_event {
break;
}
}
assert!(
found_capacity_event,
"Should have emitted CapacityChanged on boarding"
);
}
#[test]
fn capacity_changed_emitted_on_exit() {
let mut sim = SimulationBuilder::demo().build().unwrap();
sim.spawn_rider(StopId(0), StopId(1), 75.0).unwrap();
let mut capacity_events = Vec::new();
for _ in 0..1000 {
sim.step();
for event in sim.drain_events() {
if let Event::CapacityChanged {
current_load,
capacity,
..
} = &event
{
capacity_events.push((**current_load, **capacity));
}
}
if sim.metrics().total_delivered() > 0 {
break;
}
}
assert!(
capacity_events.len() >= 2,
"Expected at least 2 CapacityChanged events (board + exit), got {}",
capacity_events.len()
);
let (last_load, _) = capacity_events.last().unwrap();
assert!(
(*last_load - 0.0).abs() < f64::EPSILON,
"After exit, load should be 0.0, got {last_load}"
);
}