Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Project Description The goal of this project is to design and develop C ++ code

ID: 3839061 • Letter: P

Question

Project Description

The goal of this project is to design and develop C++ code and algorithms to control a bank of elevators, which services many floors and transports people “efficiently ", that is, as per the given specifications. A second goal is to effectively employ object oriented design, through appropriate use of classes, data structures and Standard Template Libraries (STLs).

Problem Specifications

• The elevator bank has m elevators and services n floors. As an example, you may choose m = 3 and n = 10.

• Each elevator can stop at every floor.

• The direction of an elevator has three states up, down and standing. Each elevator can carry up to a max of N max persons.

• The program loops through discrete time steps t = 1; 2…T stop, where T stop is an input parameter.

• At each time step, either 0, 1 or 2 persons arrive at a floor. This information can be read from an input data file, as described in 1.3.

•An elevator takes k time step to move up or down by k floors, if it doesn't stop. For example, to move from floor 4 to floor 5 requires one time step. And to move from floor 7 to floor 3 requires 4 time steps.

• When an elevator stops at a floor, for either passenger pick up or drop off, it does so for one time step.

•When a person arrives on a floor, they are assigned the “nearest "elevator. Here nearest is defined in the number of time steps. For example, let us say a person arrives on floor 5, and wants to go up. Elevator E1 on floor 2, moving in the up direction, with no stops, is 3 time steps away. Elevator E2 on floor 6, moving in the down direction and headed for floor 3 is 6 time steps away. Therefore, the person is assigned elevator E1.

• Each arriving person has an arrival floor, destination floor and the assigned elevator as its data members.

• When a person is assigned an elevator, their arrival floor and destination floor go in the queue or the list of the elevator stops.

• Each elevator contains a list of stops, which gets updated at each time step.

• An elevator moving up (down) continues to move up (down), until it exhausts all the stops in its list.

Class Design and STLs

You must make appropriate use of classes and class objects, class data members, class methods, constructors/destructors to implement your code.

Here are some suggested classes and their data members:

• Person class with ID, arrival floor, destination floor and assigned elevator. An example ID for a person maybe P1A3D5, for person 1, arrival floor 3 and destination floor 5. This will make it easier to generate and track test input and output.

• Elevator class with direction, number of people and list of stops.

Think of the STL containers you will be utilizing. For example, a list allows for easy insertion and removal of elements, a vector can change size, and you can push and pop elements at the end of it, a deque allows for fast insertion and deletion of elements at both ends.

Input Data

•The input data consists of the arrivals on each floor, at time steps t = 1. 2… T Stop. At each time step, the program reads in each arriving person, for each floor, and processes this data. For example, for n = 10 floors, and at time step t = 1, the arrivals maybe P1A1D4 and P2A1D5 on floor 1, P1A3D1 and Pf2A3D7 on floor 3, and 0 on the remaining floors.

Program Output

Generate appropriate output for a given input test data, which displays the information, that is, people getting on and off each floor, for each time step, for say 10 consecutive time steps.

Explanation / Answer

Classes needed for Elevator System:

ElevatorManager [Singleton - This is the main elevator program which will manage n elevators in the building]
Members:
List of Elevator
Queue of Floor.Request // This maintains request for both directions. One improvement could be to keep two queues, one for each direction but it would increase complexity
MIN_FLOOR
MAX_FLOOR
Operations:
delgate()
halt() // set whole elevator system in maintenance mode or halt operation


Elevator [Represents individual elevators. There could be n elevators in a building]
Members:
Queue of Floor // this needs to be sorted so may be a PriorityQueue could be used
Direction : Enum [Enum of direction - up, down, wait, idle, maintenance]
CurrentFloor : Floor
Operations:
operate()
moveUp()
moveDown()
openDoor()
closeDoor()
callEmergencyLine()
getDirection()
getCurrentFloor()
setInMaintenanceMode()


Floor [Represents individual floors]
Members:
eNum of Floors
class Request {
currentFloor
destinationFloor
Direction [Up, Down]
}
Operation:
goUp()
goDown()

Some of the main pseudocode for above components:

  Events of the elevator : GOINGUP, GOINGDOWN, STOP   States of the elevator : ONMOVE, WAITING (between door open and close), IDLE (serving no one), UNDERMAINTENANCE    Elevator movement is usually driven by two activites:  1. Press Up or Down key (before the entry gate of elevator) and wait for the elevator to come and serve you. (Press-And-Wait, say PAW)   2. Enter inside the elevator and make request by pressing keys (Enter-And-Request, say EAR)    So it can said that PAW from outside and EAR from inside can decide the hops of the elevator. But what about direction?    Two possible types of PAW: PAWup (press Up button) and PAWdown (press Down button)    Now, EAR can be any of the three types depending upon the users behavior. These are the critical challenges in deciding the algorithm:   1.) Normal - same direction as PAW (wanted to go down and enter lower floor#)   2.) Opposite - wanted to go down BUT enter higher floor#  3.) Indecisive - Do Nothing, no key press    Now comes all the important rules:  RULE 1: If at IDLE, use FCFS to decide between the DownList front and UpList front - whoever is oldest, serve it first to ensure less waiting time.   RULE 2: When both lists (DownList and UpList) are empty, move elevator to IDLE state.   RULE 3: Elevator state change GOINGUP->STOP clears that floor# from UpList. Similarly, GOINGDOWN->STOP clears that floor from DownList.  RULE 4: Absolute Zero Skipping: GOINGxxx serves as many floors in xxxList as possible.   RULE 5: Elevator doesn't favour Opposite-EAR, and obviously can't serve Indecisive-EAR.  RULE 6: Elevator in UNDERMAINTENANCE state is shunned from all external signals.  RULE 7: In the event of Power-cuts or Fire, the elevator goes and stops at Lobby. Flooding??    To achieve RULE#5, GOINGDOWN clears all the lower floor# in DownList in ONE GO. Similarly, GOINGUP clears all the higher floor# in UpList.        Lets discuss one scenario to clear the above concepts:  Say, an elevator is resting at floor 7 is at IDLE state,       DownList :       UpList :     IDLE@7 - PAWdown@12 then PAWup@9 then PAWdown@13      DownList : 12, 13 (older requests at lower index.Push new requests at front.)      UpList : 9       Using RULE#2, in the above case,       Event: GOINGUP to Pick@12.      WAITING@12  - 12 cleared following RULE#3    MeanWhile, PAWup@8 then PAWup@10 then PAWdown@10, so updated lists are:      DownList : 13, 10       UpList : 9, 8, 10    So here, in the current situation, if the EAR is  1.) Normal, GOINGDOWN(towards new EAR) is triggered.  2.) Opposite/Indecisive, GOINGDOWN(towards 9) is triggered and add the new EAR in UpList.            Below is one way to design Elevator System. Each elevator uses Queue (it could be Blocking Queue) to store floor requests. Also there is a central ElevatorManager which monitors all Elevator queues and it can delegate requests to a certain elevator depending upon some business rules. It's the job of ElevatorManager to efficiently delegate requests to the relevant elevator. Below pseudocode does not optimize the delegation algorithm but it shows how actual delegation could be done to a list of elevators.  

Classes needed for Elevator System:

ElevatorManager [Singleton - This is the main elevator program which will manage n elevators in the building]
Members:
List of Elevator
Queue of Floor.Request // This maintains request for both directions. One improvement could be to keep two queues, one for each direction but it would increase complexity
MIN_FLOOR
MAX_FLOOR
Operations:
delgate()
halt() // set whole elevator system in maintenance mode or halt operation


Elevator [Represents individual elevators. There could be n elevators in a building]
Members:
Queue of Floor // this needs to be sorted so may be a PriorityQueue could be used
Direction : Enum [Enum of direction - up, down, wait, idle, maintenance]
CurrentFloor : Floor
Operations:
operate()
moveUp()
moveDown()
openDoor()
closeDoor()
callEmergencyLine()
getDirection()
getCurrentFloor()
setInMaintenanceMode()


Floor [Represents individual floors]
Members:
eNum of Floors
class Request {
currentFloor
destinationFloor
Direction [Up, Down]
}
Operation:
goUp()
goDown()

Some of the main pseudocode for above components:

  class Floor {      goUp() {          ElevatorManager.queue.offer(new Request(currentFloor, destinationFloor, up));      }           goDown() {          ElevatorManager.queue.offer(new Request(currentFloor, destinationFloor, down));      }  }    ElevatorManager {      delegate() {                      Elevator idleElevator;           Elevator elevatorMovingInSameDirection;             while(!halt()) {                 if(queue.peek() != null) {                    Request req = queue.peek();                  boolean startAgain = false;                   for(Elevator elevator : elevators) {                                             if(req.currentFloor == elevator.currentFloor && req.direction == elevator.direction) {                          elevator.queue.offer(req.destinationFloor);                          queue.poll();                             startAgain = true;                          break;                      }                                             if(elevator.direction == "idle")) {                          idleElevator = elevator;     }                                              if(elevator.direction == req.direction) {                                if(req.direction == "Up" && req.currentFloor - elevator.currentFloor > 0) {                                elevatorMovingInSameDirection = elevator;                          }                                                      if(req.direction == "Down" && req.currentFloor - elevator.currentFloor < 0) {                              elevatorMovingInSameDirection = elevator;                          }                      }                    }                      if(!startAgain && idleElevator != null) {                      idleElevator.queue.offer(req.destinationFloor);                      queue.poll();                  }                  if(!startAgain && elevatorMovingInSameDirection != null) {                      elevatorMovingInSameDirection.queue.offer(req.destinationFloor);                      queue.poll();                  }                  }          }      }  }      Elevator {        moveUp() {          this.currentFloor += 1;      }        moveDown() {          this.currentFloor -= 1;      }        operate() {            while(queue.peek() != null) {                Floor nextFloorInQueue = queue.peek();                while(this.currentFloor != nextFloorInQueue.request.destinationFloor) {                  if(this.direction == "Up") {                      moveUp();                  } else if(this.direction == "down") {                      moveDown();                  }              }                queue.poll();               open();                 Direction backUpDirection = this.direction;               this.direction = "idle";                 Thread.sleep(10000);                close();               this.direction = backUpDirection;          }            this.direction = "idle"; }  }