Project 1: Elevator Controller - Spring 2025

Due: Tuesday Mar 4, before 9:00 pm

Objectives

  • Implementing a linked list data structure.
  • Using auxiliary data structures to implement the requirements.
  • Practice C++ dynamic memory management, i.e. avoiding memory leaks, avoiding double free, protection against wrong accesses in memory (segmentation fault), etc.
  • To practice writing unit tests.
  • To practice working in a Linux environment.
  • To practice analyzing and understanding a project requirements.

Introduction

An elevator controller must ensure safety, efficiency, and reliability of the elevator while operating under different circumstances. This controller is a system consisting of multiple hardware and software components. The software component of the controller provides many functions including the following:

  • It is an interface between the controller hardware components and the operators of the system.
  • It sets, resets, and monitors access to floors.
  • It sets, resets, and monitors the emergencies.
  • It schedules the travel based on predefined strategies while there are many travelers.
  • It collects data for maintenance purposes.

The following state diagram represents elevator operations.

Assignment

Your assignment is to implement the core classes (CentCom and Elevator) of controller software which consist of multiple linked lists.

For this project, you are provided with the skeleton .h and .cpp files and a sample driver:

  • centcom.h - Interface for the CentCom, Elevator, and Floor classes.
  • centcom.cpp - will be completed and submitted.
  • driver.cpp - a sample driver program. It contains 4 different scenarios.
  • driver.txt - sample output from driver.cpp. It shows the output of scenario 1 in driver.cpp.

Additionally, you are responsible for thoroughly testing your program. Your test program, mytest.cpp, must be submitted along with other files. For grading purposes, your implementation will be tested on input data of varying sizes, including very large data. Your submission will also be checked for memory leaks and memory errors.

The Rules

  • When the elevator is idle the door is open.
  • When the elevator is moving in a direction it does not change the direction until all floors in the original direction are reached.
  • When the elevator is moving in a direction it stops at the requested floors in the order of floors not in the order of requests.
  • The elevator does not stop at a secured floor. A secured floor should not be added to the requests.
  • The elevator does not move if the emergency button is pushed. This situation can only be cleared by an operator. After the emergency is cleared the elevator continues to process the requests. While the elevator is on hold and there are more requests the current direction does not change. The elevator needs to continue after the problem is resolved.
  • If at a floor the elevator is overloaded it cannot move. Once the load is reduced the elevator continues to process the requests. While the elevator is on hold and there are more requests the current direction does not change. The elevator needs to continue after the problem is resolved.

Specifications

There are three classes in this project.

The Floor Class

The Floor class is a node in the linked list and it stores the information for a Floor. Every node has a pointer to the next node in the linked list and a pointer to the previous node in the list. These pointers are stored in the m_next and m_previous member variables. There is no required implementation for the Floor class. The implementation of this class is provided.

The Elevator Class

The Elevator class stores the information for an elevator and it implements a doubly linked list. You need to implement the class. The class can be tested independently, however, in the application the class can be used by the class CentCom. The Floor nodes are stored in the linked list which is presented by the pointer to its first node and its last node. The pointer to the first node is stored in the m_ground member variable and the pointer to the last node is stored in the m_top member variable. The member variable m_ground carries the lowest floor number and the member variable m_top carries the highest floor number. The floor numbers are to be in the ascending order, in other words the linked list is sorted from smallest to largest number. The list does not hold duplicate floor numbers. The floor numbers can be negative numbers indicating the underground floors.

The Elevator class holds two other doubly linked lists named m_upRequests and m_downRequests. Each of these member variables stores a list of travel requests in a specific direction.

Elevator::Elevator(int ID)
The constructor creates an empty object and initializes all member variables to their respective default values.
Elevator::~Elevator()
The destructor deallocates all memory in the object and reinitializes all member variables.
void Elevator::clear()
This function deallocates all memory in the object and reinitializes all member variables.
void Elevator::setUp(int firstFloor, int lastFloor)
This function sets up the elevator to its required floors if the current object is empty, otherwise it does not modify the object.
bool Elevator::insertFloor(int floor)
This function inserts floors at the head of the main linked list. If the floor is inserted the function returns true otherwise it returns false. This function is part of the class public interface. You are allowed to use private helper functions to perform the job.
bool Elevator::pushButton(int floor)
This function registers (inserts) a Floor object in one of the requests lists, i.e. m_upRequests or m_downRequests. If the request is registered the function returns true, otherwise it returns false. For example, if the requested floor is a secure floor and the elevator is not allowed to stop at that floor, there is no need to register the request. Possible scenarios for using this function are:
  • A passenger enters the elevator and pushes a specific floor button in order to travel to that floor.
  • A passenger waiting outside pushes the call buttons to stop the elevator and to enter.
This function is part of the public interface. You are allowed to create private helper functions to perform the functionality.
bool Elevator::processNextRequest()
This function processes the next registered request. For example, if the elevator is in floor 2 and there has been a request registered previously to go to floor 4, this function moves the elevator from floor 2 to floor 4. If the request is processed and completed, the function returns true, otherwise it returns false. As an example, if the elevator is overloaded at a floor, it cannot move to the next requested floor until the problem is resolved.
void Elevator::enter(int load)
This function adds the new load specified by the parameter load to the current load of the elevator.
int Elevator::exit(int load)
This function reduces the elevator load by the amount of the load parameter. The elevator load cannot be negative. The function returns the current load of the elevator. If the load is negative the function returns zero.
void Elevator::pushEmergency(bool pushed)
This function sets the emergency state in the elevator. A sample scenario would be pushing the emergency button in the car by a passenger.
bool Elevator::checkSecure(int floor)
This function returns the truth value of secure state for a floor. For the error cases the function returns false.
void Elevator::dump()
This function prints out the state of the elevator. Note: The implementation for this function is provided to you. The purpose of this function is to facilitate debugging.

The CentCom Class

The CentCom class stores a list of elevators (objects of the type Elevator) in a building. The member variable m_elevatorsList is an array that stores pointers to Elevator objects. The array will be created dynamically once the application runs.

CentCom::CentCom(int numElevators,int buildingID)
The constructor creates the object. It initializes all member variables. It creates memory if required. The building ID is a unique ID and cannot be a negative number. The elevator IDs are used as array index numbers. For example, the elevator 1 will be stored in the index number 1 in the array.
CentCom::~CentCom()
The destructor removes all memory and re-initializes all member variables to their default values.
bool CentCom::addElevator(int ID, int bottomFloor, int topFloor)
This function creates and stores an elevator in the current CentCom object. If an elevator with ID exists, this function creates a new elevator and overwrites the current one. If the elevator is created the function returns true, otherwise it returns false.
Elevator* CentCom::getElevator(int ID)
This function returns the Elevator object specified by ID parameter, if the object does not exist the function returns nullptr.
bool CentCom::setSecure(int ID, int floorNum, bool yes_no)
This function sets or re-sets the specific floor in the specific elevator as a secure floor. If the function works correctly it returns true. For the error cases the function returns false.
bool CentCom::clearEmergency(int ID)
This function re-sets the emergency state of the specific elevator. If the function works correctly it returns true. For the error cases the function returns false.

Additional Requirements

  • The class declarations (CentCom,Elevator and Floor) and provided function implementations in centcom.cpp may not be modified in any way. You are not allowed to add a member variable. No additional libraries may be used.
  • You are not allowed to use STL template containers in the project classes.
  • You are allowed to use STL template containers in your test functions.
  • The class functions must be written in centcom.cpp; in particular, they must not be written “in-line.”
  • Private helper functions may be added, but must be declared in the private section of the project class. There is a comment indicating where private helper function declarations should be written.

Testing

  • The test file name must be mytest.cpp; the file name must be in lower case, a file name like myTest.cpp is not acceptable.
  • The test file must contain the declaration and implementation of your Tester class and the main() function as well as all your test cases, i.e. calls to your test functions.
  • You are responsible for adequately testing your work before submission. The following section presents a non-exhaustive list of tests to perform on your implementation.
  • You must write a separate function for every test case.
  • Every test function must return true/false depending on passing or failing the test. Visual outputs are not accepted as test results.
  • The dump() function should not be called in the test functions. The dump() function is only provided to facilitate debugging.
  • Tests cannot be interactive. The test file mytest.cpp must compile and run to completion.
  • An example of declaring, implementing, and calling a test function, and outputting the test results was provided in the driver.cpp file of project 0.
  • The testing guidelines page provides information that helps you to write more effective test cases.

Note: Testing incrementally makes finding bugs easier. Once you finish a function and it is testable, make sure it is working correctly.

Testing CentCom and Elevator Class

  • Test CentCom constructor for a normal case.
  • Test CentCom constructor for an error case.
  • Test CentCom::addElevator() for a normal case.
  • Test CentCom::addElevator() for an error case.
  • Test Elevator::setUp() for an error case.
  • Test Elevator::insertFloor() for an error case.
  • Test Elevator::pushButton() for a normal scenario.
  • Test Elevator::pushButton() for an error scenario.
  • Test Elevator::processNextRequest() for a normal scenario.
  • Test Elevator::processNextRequest() for an error scenario.

Testing For Memory Leaks / Memory Errors

  • Run your test program in valgrind; check that there are no memory leaks or errors.
    Note: If valgrind finds memory errors, compile your code with the -g option to enable debugging support and then re-run valgrind with the -s and --track-origins=yes options. valgrind will show you the line numbers where the errors are detected and can usually tell you which line is causing the error.
  • Never ignore warnings. They are a major source of errors in a program.

What to Submit

You must submit the following files to the proj1 submit directory:

  • centcom.h
  • centcom.cpp
  • mytest.cpp (Note: This file contains the declaration and implementation of your Tester class as well as all your test cases.)

If you followed the instructions in the Project Submission page to set up your directories, you can submit your code using the following command:

   cp centcom.h centcom.cpp mytest.cpp ~/cs341proj/proj1/

Grading Rubric

For details of grading rubric please refer to Project Grading Policy