namespace ElevatorDiag; public enum ElevatorState { Idle, MovingUp, MovingDown, DoorOpen, Faulted } public class Elevator { public int CurrentFloor { get; private set; } = 1; public double CurrentPosition { get; private set; } = 1.0; public ElevatorState State { get; private set; } = ElevatorState.Idle; public List TargetFloors { get; } = new(); public string? LastFault { get; private set; } private const double Speed = 0.5; // floors per tick private const int DoorHoldTicks = 3; private int _doorTimer = 0; public void RequestFloor(int floor) { if (State == ElevatorState.Faulted) return; if (!TargetFloors.Contains(floor)) { TargetFloors.Add(floor); // No automatic sort here, we'll handle direction in GetNextTarget } } public void Update() { if (State == ElevatorState.Faulted) return; if (State == ElevatorState.DoorOpen) { _doorTimer++; if (_doorTimer >= DoorHoldTicks) { _doorTimer = 0; State = ElevatorState.Idle; } return; } if (TargetFloors.Count == 0) { State = ElevatorState.Idle; return; } int target = GetNextTarget(); if (CurrentPosition < target) { State = ElevatorState.MovingUp; CurrentPosition += Speed; } else if (CurrentPosition > target) { State = ElevatorState.MovingDown; CurrentPosition -= Speed; } CurrentFloor = (int)Math.Round(CurrentPosition); if (Math.Abs(CurrentPosition - target) < 0.01) { CurrentPosition = target; CurrentFloor = target; TargetFloors.Remove(target); State = ElevatorState.DoorOpen; } } private int GetNextTarget() { // Simple logic: if moving, keep moving in same direction if targets exist if (State == ElevatorState.MovingUp) { var up = TargetFloors.Where(f => f > CurrentPosition).OrderBy(f => f).FirstOrDefault(); if (up != 0) return up; } if (State == ElevatorState.MovingDown) { var down = TargetFloors.Where(f => f < CurrentPosition).OrderByDescending(f => f).FirstOrDefault(); if (down != 0) return down; } // Closest if idle or changed direction return TargetFloors.OrderBy(f => Math.Abs(f - CurrentPosition)).First(); } public void TriggerFault(string reason) { State = ElevatorState.Faulted; LastFault = reason; } public void ResetFault() { State = ElevatorState.Idle; LastFault = null; } }