Skip to content

Advanced Project 5 — Elevator Simulation

Difficulty: Advanced · Estimated effort: 2–3 weeks · Prerequisites: Module 10 — Copying and Resource Management, Module 13 — Exception Handling, Module 15 — SOLID and Design Patterns · Demanded pattern decisions: state, strategy

This is one of the designated integration projects, and one of the projects that requires a design-pattern decision: at least two patterns must be named and justified by a requirement, and one alternative must be considered and declined in writing.

No complete solution is provided. The state model is the design decision, and it is yours.


1. Scenario

A property company wants to test lift configurations before fitting them: how long people wait, how often the cars are idle, and what happens at the morning peak. Passengers arrive at floors, press up or down, wait, board, ride and leave. Cars open, close, move and are held open.

The simulation must be deterministic given a seed, so two configurations can be compared fairly, and it must record an event log detailed enough to answer "why was car 2 idle for four minutes?"


2. Problem statement

Build a discrete-event simulation of a lift system: buildings with floors, cars with doors and movement, passengers with requests, a dispatcher choosing which car serves which request, and an event loop advancing simulated time. States and transitions must be explicit, illegal transitions impossible, and the whole run reproducible from a seed.


3. User requirements

  • [ ] Configure a building: floors, cars, capacity, speed, door times.
  • [ ] Generate passenger arrivals deterministically from a seed and a rate.
  • [ ] Run the simulation for a simulated period and see it complete.
  • [ ] Get statistics: average and worst wait, average ride time, car utilisation.
  • [ ] Read an event log of every state change, in time order.
  • [ ] Compare two dispatcher rules on the same arrivals.

4. Functional requirements

  • [ ] Building, Floor, Car and Passenger types with their own invariants.
  • [ ] An explicit state model for a car: idle, moving, doors opening, doors open, doors closing.
  • [ ] A Dispatcher interface with at least two implementations (nearest car; directional scan with a turnaround rule).
  • [ ] A Scheduler-style event loop over injected simulation time, with no wall-clock reads.
  • [ ] Capacity enforced: a car cannot carry more than its limit, and boarding is refused when full.
  • [ ] Statistics computed from the log, not from counters incremented by hand.
  • [ ] A configuration file, with typed errors for impossible buildings (zero cars, negative speed).

5. Non-functional requirements

  • [ ] Illegal transitions are impossible to perform, not merely detected — the state type enforces which operations are available.
  • [ ] A car never moves with its doors open, and never opens its doors while moving; tested across a full run.
  • [ ] Passengers are conserved: every arrival either completes a journey or is waiting at the end, and the two counts account for everyone.
  • [ ] Identical seed and configuration produce an identical event log, byte for byte.
  • [ ] Builds warning-free with g++ -std=c++17 -Wall -Wextra -Werror.

6. Suggested features

  • A morning-peak profile: arrival rates per floor that vary over the simulated period.
  • Priority for passengers who have waited too long, and a report on whether it helped.
  • A record-and-replay mode: write the event log, replay it to rebuild the statistics.
  • A second dispatcher that considers predicted future demand, with the comparison table.

7. OOP concepts involved

Concept Required Where it appears
Multiple classes yes Building, floors, cars, passengers, dispatchers, event loop, event log, statistics
Relationships yes Building ◆ floors and cars; passenger ──> car while riding; dispatcher ──> cars it does not own
Encapsulation yes Car state, door state and occupancy cannot be set from outside; every change is a transition
Inheritance or composition yes Dispatchers behind an interface; consider whether car states deserve types and answer in the report
Polymorphism yes Dispatcher and, if you take the pattern route, state behaviour dispatch
The STL yes std::vector for floors and cars, std::map for statistics, std::stable_sort/priority queue for events
Exception handling yes Invalid configuration and illegal transition attempts throw distinct types

8. Suggested design considerations

The pattern decision you must make and justify

State, for the car. Elevator doors and movement have genuinely different legal operations per phase: you cannot move with the doors open, and you cannot open while moving. A state object makes the illegal operation unavailable, while a switch on an enum makes it merely discouraged. The alternative — an enum plus guard conditions — is a real choice, and you must say which requirement decided it.

Strategy, for the dispatcher. Which car serves a request is the thing that varies, and the requirement that earns the strategy is compare two rules on identical arrivals. The alternative is a function pointer or a lambda: lighter. Choose one and justify. The one you decline is the declined-pattern item.

Ideas worth weighing and recording: observer, so a car notifies the log of its state changes versus the log being written by the loop (the observer is arguably earned because it keeps the car from knowing about the log); command, for queueing requests as objects (worth considering, probably not earned).

Other design points

Simulated time is data. Every event carries its time; nothing reads a clock. This is what makes a full day's simulation run in milliseconds and makes results reproducible.

Derive statistics from the log. Counters incremented by hand drift from the log and then nobody can explain a discrepancy. One source of truth: the log.

Passenger conservation is the acceptance test. If the numbers do not add up at the end, the simulation is wrong somewhere, and finding out where is the point of the invariant.


9. Minimum viable version

One car, four floors, arrivals from a fixed list, movement and door transitions, and a printed event log. One dispatcher, no statistics.


10. Intermediate extension

Add capacities, the second dispatcher and the statistics derived from the log, plus passenger conservation checked at the end of every run. Then compare the two dispatchers on identical arrivals and report the difference in average wait.


11. Advanced extension

Add the peak profile, the record-and-replay mode, and a state-object design for the car (or the written justification for keeping the enum, with the line count of the transition logic as evidence). Then write the design note: the patterns, the declined alternative, and the decision you would reverse — with its cost.


12. Testing checklist

  • [ ] A single passenger's journey appears in the log with sensible times
  • [ ] A car never moves with the doors open — checked for every event in a long run
  • [ ] A car never opens its doors while moving — checked the same way
  • [ ] Capacity is never exceeded; a full car refuses boarding and the passenger waits
  • [ ] Attempting to board a car on another floor is impossible, or refused with a message
  • [ ] Passenger conservation holds at the end of the run, for several seeds and configurations
  • [ ] The same seed and configuration produce byte-identical logs, twice
  • [ ] A different seed produces a different log (checked over several seeds)
  • [ ] A request is served by exactly one car, never by two
  • [ ] Statistics recomputed from the log match the statistics printed at run time
  • [ ] A building with zero cars or negative speed is refused before the run starts
  • [ ] Zero arrivals produces an idle log and zero-length waits, not a crash

13. Documentation checklist

  • [ ] The state diagram for a car, with every legal transition and the trigger for each
  • [ ] The class diagram with ownership and the injected dispatcher
  • [ ] Both dispatcher rules stated precisely enough to implement from the description
  • [ ] The configuration file format and the impossible configurations it rejects
  • [ ] The comparison table for the two dispatchers, with the seed used

14. Self-evaluation rubric

Criterion Excellent looks like Weight
State modelling Illegal transitions unavailable; state diagram matches the code 25%
Reproducibility Seeded, clock-injected, byte-identical logs 20%
Pattern decisions State and strategy justified; the declined alternative argued 20%
Invariants Capacity, door safety and passenger conservation verified, not asserted 20%
Evidence Statistics derived from the log; dispatcher comparison on identical arrivals 10%
Documentation State diagram, class diagram and comparison table written down 5%

Related: Advanced projects · Project roadmap · All projects · Module 15 — SOLID and Design Patterns