Question: We recognize two important entities in this project: 1. Elevators. An Elevator has four attributes: a current Door, indicating where in the building the elevator
We recognize two important entities in this project:
1. Elevators. An Elevator has four attributes: a current Door, indicating where in the building the elevator is currently present; a current state, indicating what the elevator is doing at this point in the simulation; a current direction, either UP, DOWN, or NOT_MOVING, that controls the direction the elevator will move with each simulation step; and a set of passengers that each has a destination Door that they want to reach. We will assume in this project that all passengers are intelligent and aware, i.e., they will only enter an elevator moving in a direction that will take them to their destination, and they will always exit the elevator when their destination is reached.
2. Buildings. A Building has a number of floors. Each floor has a list of passengers waiting for an elevator, and each floor is reachable by all elevators in the building. Speaking of which, a building also has a list of Elevators!
Modeling the Problem
We must translate the nouns and verbs in our problem description and analysis to Java code. In object oriented design, we typically turn nouns into classes and verbs into methods. To keep this project simple, we will take some shortcuts that will cause problems later on:
We will represent passengers as a single integer each, with that integer representing the passenger's destination floor. Any noun that refers to passengers among its attributes will use a collection of integers to represent those passengers.
The Doors of a building will be represented as a ArrayList. Each integer in the list is one passenger waiting on that floor. The building itself, which has a collection of Doors, will represent its Doors as a ArrayList<>, i.e., a list of "floors".
We will not model the "up"/"down" buttons on each floor of the building. If a floor has a passenger whose destination is larger than the floor, we will assume that the "up" button has been pressed and stop any elevator that is moving upwards.
We will not model the "request a stop" buttons inside the elevator, one per floor. If an elevator has a passenger with a destination equal to the current floor, it will open its doors to release that passenger.
We will not dispatch elevators that are currently idle to a floor with a waiting passenger. Elevators will move up and down only to service the passengers that are in the elevator. (This is not a good behavior. A passenger on the top floor will only be picked up if an elevator gains a passenger taking it to the top floor. An elevator that unloads its final passenger will not move until a new passenger enters it.)
Elevators and floors will have infinite capacities.
Once a passenger leaves an elevator, it will no longer be represented in the simulation.
Modeling an Elevator:
Create a Java class named Elevator to implement an individual elevator in the simulation. This class will have fields for the four attributes identified above, plus two more for convenience:
The current floor. We don't know at compile time how many floors will be in the building.
The passengers currently on the elevator. Each passenger is an integer, as described previously. You must choose a data structure to represent this group of passengers; ask for help if you are uncertain.
The current direction. An elevator can only have one of three directions: UP, DOWN, or NOT_MOVING. An integer would be inappropriate for this field; an enum is the correct representation.
The current state of the elevator. An elevator's current state defines what it will do when the next tick of the simulation occurs; these behaviors can be defined by a finite state machine, in which there is a single well-defined operation to perform when updating an elevator given its current state. Create an enum to represent the state of the elevator, with these cases: IDLE_STATE, DOORS_OPENING, UNLOADING_PASSENGERS, LOADING_PASSENGERS, DOORS_CLOSING, ACCELERATING, MOVING, DECELERATING. The elevator then needs a field of this enum type to represent its current state. The integer number of the elevator, to distinguish it from other elevators in the building.
A reference to the building the elevator is in, as a Building variable. More on this class below. You should write accessors for any field that the public (other entities in the system) has a reasonable need to know about. You should only write mutators for fields that the public should be able to change outside of the elevator's control. (Hint: the answer is probably "none of them.")
Next we need some methods.
The most important elevator method is public void tick(), which updates the elevator's state by one tick of the simulation. The exact behavior of an elevator during one tick is defined in terms of its current state:
IDLE_STATE: transition to ACCELERATING if it has at least one passenger; an empty idle elevator will transition to DOORS_OPENING if the current floor has any passengers waiting. If neither are these are true, the elevator stays idle.
DOORS_OPENING: if at least one of the elevator's passengers has a destination floor equal to the current floor, the elevator will transition to UNLOADING_PASSENGERS. Otherwise, it will LOAD_PASSENGERS.
UNLOADING_PASSENGERS: to unload passengers, the elevator removes any passenger whose destination is equal to the current floor. Then, the elevator direction becomes NOT_MOVING if there are no more passengers. Then, the elevator then LOAD_PASSENGERS only if its direction is NOT_MOVING, or there is at least one passenger waiting on the current floor whose destination floor is in the same direction as the elevator is currently moving. Otherwise, the elevator next will CLOSE_DOORS. For example, an elevator moving UP, currently on floor 5, and in the UNLOADING_PASSENGERS state will transition to LOAD_PASSENGERS if floor 5 has a passenger going to floors 6 or higher. If there is no such passenger, it will next transition to CLOSING_DOORS.
LOADING_PASSENGERS: loop over the passengers waiting on the current floor. For each passenger that is waiting, move the passenger into the elevator if their destination is in the same direction as the elevator's current direction. If the elevator starts this tick in the NOT_MOVING direction, then the first passenger waiting on the oor gets moved into the elevator and sets the new direction. Then proceed with examining the remaining passengers. Example: oor 3 has passengers with destinations of 5, 2, 8, 9, 2, 1. An elevator whose direction is DOWN would load passengers 2, 2, and 1. An elevator that is NOT_MOVING would load 5, setting its direction to UP, then load 8 and 9. After loading passengers, the elevator transitions to CLOSING_DOORS.
CLOSING_DOORS: if there is at least one passenger, transition to ACCELERATING. Otherwise, transition to IDLE_STATE.
ACCELERATING: transition to MOVING.
MOVING: determine the "next floor" by adding or subtracting 1 from the current floor, depending on the elevator's direction. Set the current floor to "next floor". Transition to DECELERATING only if there is a passenger on the elevator whose destination is the next floor, OR there is a passenger waiting on the next floor whose destination is in the same direction of travel as the elevator. Otherwise, stay in the MOVING state.
DECELERATING: transition to DOORS_OPENING. If there are no passengers, set direction to NOT_MOVING.
public String toString(): returns a string representing the overall state of the elevator, of the form: "Elevator [Number] - Floor [CurrentFloor] - [CurrentState] - [CurrentDirection] - Passengers [Passengers]" where each value in [] is replaced by its corresponding field of the elevator, and [Passengers] is replaced by a comma-separated list of integers, each integer representing one passenger's destination floor, in the order the passengers entered the elevator.
A constructor that takes an elevator number and a reference to the Building that the elevator is in, and saves them in the elevator's fields. Also initializes the current state to IDLE_STATE, and the current direction to NOT_MOVING.
Modeling a Building:
Create a Java class called Building to represent an entire building with many floors and many elevators. Add fields to represent these values: a collection of elevators. Elevators are numbered, and the order they appear in the collection is important. Choose the appropriate collection type.
a list of floors, as defined earlier under "Modeling the Problem" We expect that floor number x occurs at index x 1 in this list. That's it! A building is just a list of floors and elevators. Much more important are its methods:
public ArrayList getFloor(int floorNumber): returns the floor with the given number.
public void tick(): like elevators, buildings also update their state in ticks. A building does not use a finite state machine, however; it simply "spawns"/creates new passengers based on the rolls of a random number generator, then ticks all of its elevators. Code this behavior: - Iterate through each floor of the building in increasing order starting with floor 1. For each floor x, generate a random number from 0 to 19 inclusive. If that number is 0, you will spawn a new passenger on floor x.
To spawn a passenger, generate a random number from 1 to n inclusive, where n is the number of floors in the building; repeatedly generate such a number until you get one that is not equal to x. That number is the destination floor of the new passenger. Add their destination to x's list of passengers, and print a message of "Adding passenger with destination [D] to floor [F]", replacing [D] and [F] with the destination and x respectively.
After spawning passengers, tick each elevator in the building in order by number.
You must use the static random number generator defined by the Simulation class, below.
public String toString(): returns a string representing the state of the building, all its floors, and all its elevators. This is too complicated to explain in writing; here is a picture:
10: | | | 9
9: | | |
8: | | | 7 1
7: | | | 2 5
6: | | |
5: | | |
4: | X | |
3: | | |
2: | | |
1: | | X |
Elevator 1 - Floor 4 - DOORS_CLOSING - MOVING_UP - Passengers [8, 7, 8, 6, 9, 9]
Elevator 2 - Floor 1 - IDLE_STATE - NOT_MOVING - Passengers []
Things to note: The leftmost column numbers each floor in the building. The floors are right-padded, so that their right-most digits align, hence the space before the floors 1 through 9. The next two columns show two elevators. The first is on floor 4, the second on floor 1. The rightmost column shows the passengers waiting on each floor, in the order they were spawned. The final two rows of output are the toString() values of the two elevators, showing their number, position, state, direction, and passengers.
A constructor that takes a number of floors and number of elevators. The list of floors is initialized with one empty list per floor; the list of elevators is initialized by constructing the number of elevators requested.
Executing the Simulation
Finally, write a class named Simulation which will "drive" the simulation.
Add a static field mRandom of type Random. You will initialize this value in the main.
Add a static method getRandom(), which returns the mRandom variable, and will be used to generate random numbers in the Building class.
Add a main method which performs the following: First, ask the user to enter a seed value, which is an integer 0 or greater. After scanning this value, initialize the mRandom static variable by constructing a Random instance with the chosen seed value as a parameter. We call this seeding the generator. Next, ask the user to input a number of floors and a number of elevators. You may assume both of these are positive. Construct a Building object with the given number of floors and elevators. Print the simulation by outputting the building's toString() result. Ask the user to enter a number of ticks to simulate. If they enter 0, print the simulation and quit the program. Otherwise, use a loop to call the tick() method of your building as many times as was requested, and print the simulation after every tick. Repeat the last step until the user enters 0 ticks to quit.
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
