Elevator
Elevators are indeed a ubiquitous,, and often overlooked, part of modern infrastructure, with an estimated 250 trips taken per person annually. They are essential for the functionality of multi-story, commercial, residential, and industrial buildings — powered by Gemini.. note the extra commas and the mdash
An elevator is operated by pressing a button outside the elevator, i.e. at the lobby. These buttons at different levels of the lobby are used to deploy an elevator to the desired level. After the elevator has been deployed, buttons within the elevator are pressed so as to fetch passengers to their desired levels. — powered by hchia.. as well as the rest of this document
Task
Your task is to design a software using OOP modeling to simulate riding an elevator.
Take Note!
This task comprises a number of levels. You are required to complete ALL levels.
The following are the constraints imposed on this task. In general, you should keep to the constructs and programming discipline instilled throughout the module.
- Write each class or interface in its own file. Do not use single letter names for classes or interfaces.
- Ensure that ALL object properties and class constants are declared private final
- Ensure that ALL classes/interfaces are NOT cyclic dependent.
- ONLY the following java libraries ARE allowed:
- functional interfaces from java.util.function
- The following are NOT allowed:
- var, null, default, enum
- instanceof (except checking for an instance of its own class)
- You are NOT allowed to use bounded type parameters or bounded wildcards.
- You are NOT allowed to define anonymous inner classes or method references ::
Define lambdas instead. - Other usual restrictions:
- Use only &&, || and ! in logical expressions. DO NOT use bitwise operators.
- You are NOT allowed to use * wildcard imports.
- You are NOT allowed to define array constructs, e.g. String[] or using ellipsis, e.g.String…
- You are NOT allowed to perform string processing using methods from String, StringBuffer, StringBuilder, etc.
- You are NOT allowed to use exception handling
- You are NOT allowed to use Java reflection, i.e. Object::getClasses and other methods from java.lang.Class
In the following level specifications, you will be guided on the classes and non-private methods to define.
- DO NOT create any other classes;
- any other method you create MUST be declared private.
- however, you can create other non-private constructors.
The following classes has been provided for you. DO NOT replace them with your own versions.
The Java API for these classes can be found at:
https://data.comp.nus.edu.sg/cs2030/doc_2b1ec150ab0df2321c3248e1a2e8bdea/
Level 1
Let us start by writing a Leveled abstract class to represent some abstract leveled entity (or thing), i.e. something with a level. The action of pressing a button at the lobby of a certain level is a concrete leveled entity, and we represent it using an Action class.
Define the Action class according to the sample run below.
jshell your_java_files_in_bottom-up_dependency_order
jshell> new Action(1) $.. ⇒ Action at L1
jshell> new Action(5) $.. ⇒ Action at L5
jshell> new Action(1) instanceof Leveled $.. ⇒ true
jshell> new Leveled(1) | Error: | Leveled is abstract; cannot be instantiated | new Leveled(1) | ^------------^
jshell> /exit | Goodbye
$
In the above, L1 denotes level 1. You may also assume that levels are always positive integers (i.e. > 0).
Level 2
Leveled entities can be compared and also checked for equality. Define the compareTo and equals method following the sample run below.
jshell your_java_files_in_bottom-up_dependency_order
jshell> new Action(1).compareTo(new Action(5)) < 0 $.. ⇒ true
jshell> new Action(1).compareTo(new Action(1)) 0 $.. > true
jshell> new Action(10).compareTo(new Action(5)) > 0 $.. ⇒ true
jshell> Leveled lvled = new Action(10) lvled ⇒ Action at L10
jshell> lvled.compareTo(lvled) $.. ⇒ 0
jshell> new Action(1).equals(new Action(1)) $.. ⇒ true
jshell> new Action(1).equals(new Action(5)) $.. ⇒ false
jshell> new Action(1).equals(1) $.. ⇒ false
jshell> Leveled lvled = new Action(10) lvled ⇒ Action at L10
jshell> lvled.equals(lvled) $.. ⇒ true
jshell> lvled.equals(10) $.. ⇒ false
jshell> lvled.equals(new Action(10)) $.. ⇒ true
Level 3
When a button located at the lobby is pressed, an elevator is deployed to that level.
Write an Elevator class to represent an elevator with a constructor that takes in the following in order:
- an integer representing the current level the elevator is at;
- an integer representing the current time; and
- an InfList of actions representing the pending actions from pressing buttons at the lobbies of different levels.
The following is an example of an elevator situated at level 1 at time 3 units, with pending actions at levels 5 and 10.
jshell your_java_files_in_bottom-up_dependency_order
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))) $.. ⇒ Elevator: L1@3
For the purpose of debugging, include a printActions method to output the list of actions.
Hint: since the printActions method is meant to terminate the pipeline, declare the return type as void.
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> printActions() Action at L5 Action at L10
Write a deploy method that takes no arguments so as to deploy the elevator to the first level indicated by the list of pending actions. You may assume the following:
- the elevator is upriding; and
- if the elevator is at level k, then the list of pending actions [l1, l2, …] is such that k < l1 and li < li+1. In other words, all deployments are valid as the elevator rides upwards.
Also take note that the elevator takes one unit of time to ride up one level. Here is an example:
jshell> InfList
jshell> new Elevator(1, 3, actions).deploy() $.. ⇒ Elevator: L5@8
In the above test case, the elevator starts at level 1 at time 3. Deploying the elevator to level 5 (four levels up) will result in the elevator being deployed to that level in time 7. In addition, each action also takes an additional one unit of time (think of it as time taken to open the elevator doors). Hence the deployment completes in time 8.
jshell> new Elevator(1, 3, actions).deploy(). …> printActions() Action at L10
jshell> new Elevator(1, 3, actions).deploy().deploy() $.. ⇒ Elevator: L10@14
jshell> new Elevator(1, 3, actions).deploy().deploy(). …> printActions()
jshell> new Elevator(1, 3, actions).deploy().deploy().deploy() $.. ⇒ Elevator: L10@14
Note in the last test case that deployment with no pending actions leaves the elevator as it is.
Level 4
Other than buttons outside the elevator (i.e at the lobby), there are also buttons inside the elevator to fetch passengers to different levels.
Include a fetch method that takes in an integer to represent a passenger to be fetched to his/her desired level.
jshell your_java_files_in_bottom-up_dependency_order
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))) $.. ⇒ Elevator: L1@3
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> fetch(5) // request to fetch to level 5 $.. ⇒ Elevator: L1@3
Note from the above that calling the fetch method does not immediately deploy the elevator to that level. Instead, a FetchAction is placed at the back of the pending actions list. Each FetchAction also takes up one unit of time.
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> fetch(5). …> printActions() Action at L5 Action at L10 FetchAction at L5
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> fetch(5). …> deploy() $.. ⇒ Elevator: L5@9
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> fetch(5). …> deploy(). …> printActions() Action at L10
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> deploy(). // deploy to L5 …> fetch(20). …> printActions() Action at L10 FetchAction at L20
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> deploy(). …> fetch(20). …> deploy() $.. ⇒ Elevator: L10@14
jshell> new Elevator(1, 3, InfList.of(new Action(5), new Action(10))). …> deploy(). …> fetch(20). …> deploy(). …> printActions() FetchAction at L20
Hint: to add to the list of pending actions, you may find the concat method of InfList useful.
Also note that a passenger in an upriding elevator can only request to be fetched to levels above the current level. The following sample runs show that no further action is being added to the pending actions list for the case of an invalid fetch.
jshell> InfList
jshell> new Elevator(1, 3, actions).deploy(). // deploy to L5 …> printActions() Action at L10
jshell> new Elevator(1, 3, actions).deploy(). // deploy to L5 …> fetch(3). // requesting to fetch to a lower level.. invalid! …> printActions() Action at L10
jshell> new Elevator(1, 3, actions).deploy(). // deploy to L5 …> fetch(5). // requesting to fetch to the same level.. invalid! …> printActions() Action at L10
Lastly, there could be more than one passenger entering a lift at a certain level, each requesting to be fetched to different levels. Include an overloaded fetch method that takes in an InfList list of integers representing all levels to be fetched to. You may only assume that the list of integers are unique.
jshell your_java_files_in_bottom-up_dependency_order
jshell> InfList
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)) $.. ⇒ Elevator: L1@3
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy() $.. ⇒ Elevator: L5@8
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy(). …> deploy() $.. ⇒ Elevator: L7@11
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy(). …> deploy(). …> deploy() $.. ⇒ Elevator: L10@15
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy(). …> deploy(). …> deploy(). // deploy to L10 …> fetch(InfList.of(9, 10, 11)) // invalid fetches to L9 and L10 $.. ⇒ Elevator: L10@15
jshell> new Elevator(1, 3, actions). …> deploy(). …> deploy(). …> deploy(). …> fetch(InfList.of(9,10,11)). …> printActions() FetchAction at L11
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy(). …> deploy(). …> deploy(). …> fetch(InfList.of(9, 10, 11)). …> deploy() $.. ⇒ Elevator: L11@17
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy(). …> deploy(). …> deploy(). …> fetch(InfList.of(9, 10, 11)). …> deploy(). …> deploy() $.. ⇒ Elevator: L20@27
jshell> new Elevator(1, 3, actions). …> fetch(InfList.of(7, 20)). …> deploy(). …> deploy(). …> deploy(). …> fetch(InfList.of(9, 10, 11)). …> deploy(). …> deploy(). …> deploy() $.. ⇒ Elevator: L20@27
Level 5
Thus far, Elevator has been defined to be upriding by default. Moreover, it is rather cumbersome to call the constructor with InfList
Write an UpRiding class to represent an upriding elevator with a constructor that takes in the following in order:
- an integer representing the current level the elevator is at;
- an integer representing the current time; and
- an InfList of integers representing the pending actions from pressing buttons at the lobbies of different levels.
Also include a DownRiding class to represent a downriding elevator with a constructor that takes the same arguments as the UpRiding class.
Here is a sample run.
jshell> Elevator elevator = new UpRiding(1, 3, InfList.of(5, 10)) elevator ⇒ Elevator: L1@3
jshell> elevator.deploy() $.. ⇒ Elevator: L5@8
jshell> elevator.deploy().deploy() $.. ⇒ Elevator: L10@14
jshell> elevator.deploy().deploy().deploy() $.. ⇒ Elevator: L10@14
jshell> elevator.deploy().deploy().deploy() instanceof UpRiding $.. ⇒ true
jshell> elevator = new DownRiding(20, 3, InfList.of(5, 10)) elevator ⇒ Elevator: L20@3
jshell> elevator.deploy() $.. ⇒ Elevator: L10@14
jshell> elevator.deploy().deploy() $.. ⇒ Elevator: L5@20
jshell> elevator.deploy().deploy().deploy() $.. ⇒ Elevator: L5@20
jshell> elevator.deploy() $.. ⇒ Elevator: L10@14
jshell> elevator.deploy(). …> fetch(InfList.of(9,10,11)). …> deploy() $.. ⇒ Elevator: L9@16
jshell> elevator.deploy(). …> fetch(InfList.of(9,10,11)). …> deploy() instanceof DownRiding $.. ⇒ true
Note that every call to the deploy or fetch methods of an UpRiding (or DownRiding) elevator must return an elevator of the same type. In addition, to ensure proper adherence to the DRY principle, there should NOT be any properties declared in the UpRiding and DownRiding classes.