Lab2-lift
This commit is contained in:
parent
974547157c
commit
09cd85f364
7 changed files with 327 additions and 35 deletions
38
lift/src/LiftMain.java
Normal file
38
lift/src/LiftMain.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import lift.LiftMonitor;
|
||||||
|
import lift.LiftThread;
|
||||||
|
import lift.LiftView;
|
||||||
|
import lift.PassengerThread;
|
||||||
|
|
||||||
|
public class LiftMain {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Could be read from args
|
||||||
|
final int NBR_FLOORS = 12, MAX_PASSENGERS = 4;
|
||||||
|
|
||||||
|
LiftView view = new LiftView(NBR_FLOORS, MAX_PASSENGERS);
|
||||||
|
|
||||||
|
// LiftMonitor passed to all threads
|
||||||
|
LiftMonitor monitor = new LiftMonitor(view, NBR_FLOORS);
|
||||||
|
|
||||||
|
// Static array since the number of passengers is fixed
|
||||||
|
PassengerThread[] pass_threads = new PassengerThread[20];
|
||||||
|
|
||||||
|
for (PassengerThread p : pass_threads) {
|
||||||
|
p = new PassengerThread(view, monitor);
|
||||||
|
p.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
LiftThread lift = new LiftThread(view, monitor);
|
||||||
|
lift.start();
|
||||||
|
|
||||||
|
// Rejoin all threads, in practice this is redundant
|
||||||
|
try {
|
||||||
|
// Passenger threads first
|
||||||
|
for (PassengerThread p : pass_threads) {
|
||||||
|
p.join();
|
||||||
|
}
|
||||||
|
lift.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,30 +1,27 @@
|
||||||
|
|
||||||
import lift.LiftView;
|
import lift.LiftView;
|
||||||
import lift.Passenger;
|
import lift.Passenger;
|
||||||
|
|
||||||
public class OnePersonRidesLift {
|
public class OnePersonRidesLift {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final int NBR_FLOORS = 7, MAX_PASSENGERS = 4;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
LiftView view = new LiftView(NBR_FLOORS, MAX_PASSENGERS);
|
||||||
|
Passenger pass = view.createPassenger();
|
||||||
|
int fromFloor = pass.getStartFloor();
|
||||||
|
int toFloor = pass.getDestinationFloor();
|
||||||
|
|
||||||
final int NBR_FLOORS = 7, MAX_PASSENGERS = 4;
|
pass.begin(); // walk in (from left)
|
||||||
|
if (fromFloor != 0) {
|
||||||
LiftView view = new LiftView(NBR_FLOORS, MAX_PASSENGERS);
|
view.moveLift(0, fromFloor);
|
||||||
Passenger pass = view.createPassenger();
|
|
||||||
int fromFloor = pass.getStartFloor();
|
|
||||||
int toFloor = pass.getDestinationFloor();
|
|
||||||
|
|
||||||
pass.begin(); // walk in (from left)
|
|
||||||
if (fromFloor != 0) {
|
|
||||||
view.moveLift(0, fromFloor);
|
|
||||||
}
|
|
||||||
view.openDoors(fromFloor);
|
|
||||||
pass.enterLift(); // step inside
|
|
||||||
|
|
||||||
view.closeDoors();
|
|
||||||
view.moveLift(fromFloor, toFloor); // ride lift
|
|
||||||
view.openDoors(toFloor);
|
|
||||||
|
|
||||||
pass.exitLift(); // leave lift
|
|
||||||
pass.end(); // walk out (to the right)
|
|
||||||
}
|
}
|
||||||
}
|
view.openDoors(fromFloor);
|
||||||
|
pass.enterLift(); // step inside
|
||||||
|
|
||||||
|
view.closeDoors();
|
||||||
|
view.moveLift(fromFloor, toFloor); // ride lift
|
||||||
|
view.openDoors(toFloor);
|
||||||
|
|
||||||
|
pass.exitLift(); // leave lift
|
||||||
|
pass.end(); // walk out (to the right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
25
lift/src/lift/Door.java
Normal file
25
lift/src/lift/Door.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package lift;
|
||||||
|
|
||||||
|
class Door {
|
||||||
|
private boolean open;
|
||||||
|
|
||||||
|
/** Create a new closed door */
|
||||||
|
public Door() {
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if door is open */
|
||||||
|
public boolean isOpen() {
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Open the door */
|
||||||
|
public void open() {
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Close the door */
|
||||||
|
public void close() {
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
}
|
175
lift/src/lift/LiftMonitor.java
Normal file
175
lift/src/lift/LiftMonitor.java
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
package lift;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
UP,
|
||||||
|
DOWN,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lift monitor. Handles lift motion and various state. */
|
||||||
|
public class LiftMonitor {
|
||||||
|
/** the floor the lift is currently on */
|
||||||
|
private int floor;
|
||||||
|
/** Number of floors */
|
||||||
|
private int nfloors;
|
||||||
|
/** true if the lift is moving, false if standing still with doors open */
|
||||||
|
private boolean moving;
|
||||||
|
/** Current direction of the lift */
|
||||||
|
private Direction direction;
|
||||||
|
/** number of passengers waiting to enter the lift at the various floors */
|
||||||
|
private int[] waitEntry;
|
||||||
|
/** number of passengers (in lift) waiting to leave at the various floors */
|
||||||
|
private int[] waitExit;
|
||||||
|
/** number of passengers currently in the lift */
|
||||||
|
private int load;
|
||||||
|
/** view object passed from main */
|
||||||
|
private LiftView view;
|
||||||
|
/** State (open/closed) of door on current floor */
|
||||||
|
private Door door;
|
||||||
|
/** Counter of number of passengers currently entering the elevator */
|
||||||
|
private int passengersEntering;
|
||||||
|
/** Counter of number of passengers currently exiting the elevator */
|
||||||
|
private int passengersExiting;
|
||||||
|
|
||||||
|
/** Create new LiftMonitor */
|
||||||
|
public LiftMonitor(LiftView v, int floors) {
|
||||||
|
floor = 0;
|
||||||
|
nfloors = floors;
|
||||||
|
moving = true;
|
||||||
|
direction = Direction.UP;
|
||||||
|
door = new Door();
|
||||||
|
waitEntry = new int[nfloors];
|
||||||
|
waitExit = new int[nfloors];
|
||||||
|
load = 0;
|
||||||
|
view = v;
|
||||||
|
passengersEntering = 0;
|
||||||
|
passengersExiting = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Increases the number of waiting passengers on given floor */
|
||||||
|
public synchronized void increaseWaitEntry(int passengerFloor) {
|
||||||
|
waitEntry[passengerFloor]++;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handles passengers waiting to enter arriving lift */
|
||||||
|
public synchronized void enterLift(int passengerFloor,
|
||||||
|
int passengerDestination) {
|
||||||
|
while (floor != passengerFloor || load == 4 || moving ||
|
||||||
|
passengersEntering == 4) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new Error("Monitor.enterLift interrupted " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waitEntry[floor]--;
|
||||||
|
waitExit[passengerDestination]++;
|
||||||
|
load++;
|
||||||
|
passengersEntering++;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called after passengers has completed entry animation */
|
||||||
|
public synchronized void enterCompleted() {
|
||||||
|
passengersEntering--;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Handles passengers waiting to exit lift */
|
||||||
|
public synchronized void exitLift(int passengerDestination) {
|
||||||
|
while (floor != passengerDestination) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new Error("Monitor.exitLift interrupted " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waitExit[passengerDestination]--;
|
||||||
|
load--;
|
||||||
|
passengersExiting++;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called after passengers has completed exit animation */
|
||||||
|
public synchronized void exitCompleted() {
|
||||||
|
passengersExiting--;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the conditions when the elevator is to wait for passengers
|
||||||
|
* entering/exiting the lift and waiting when there are no passengers waiting
|
||||||
|
* on any floor.
|
||||||
|
*/
|
||||||
|
public synchronized int[] liftContinue() {
|
||||||
|
|
||||||
|
while (Arrays.stream(waitEntry).sum() == 0 &&
|
||||||
|
Arrays.stream(waitExit).sum() == 0) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new Error("LiftContinue no passengers interrupted " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Stops the elevator to allow passengers to enter or exit */
|
||||||
|
while (waitEntry[floor] > 0 && load != 4 || waitExit[floor] > 0 ||
|
||||||
|
passengersEntering > 0 || passengersExiting > 0) {
|
||||||
|
if (!door.isOpen()) {
|
||||||
|
view.openDoors(floor);
|
||||||
|
door.open();
|
||||||
|
}
|
||||||
|
moving = false;
|
||||||
|
notifyAll();
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new Error("Monitor.liftContinue interrupted " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!moving)
|
||||||
|
view.closeDoors();
|
||||||
|
|
||||||
|
if (door.isOpen())
|
||||||
|
door.close();
|
||||||
|
|
||||||
|
moving = true;
|
||||||
|
|
||||||
|
calculateDirection();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the elevators current position and next position to the LiftThread
|
||||||
|
*/
|
||||||
|
int[] movingPositions = new int[2];
|
||||||
|
movingPositions[0] = floor;
|
||||||
|
movingPositions[1] = floor + (direction == Direction.UP ? 1 : -1);
|
||||||
|
return movingPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Moves the elevator in the given direction */
|
||||||
|
public synchronized void incrementFloor() {
|
||||||
|
floor = floor + (direction == Direction.UP ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles calculation of elevator direction
|
||||||
|
* Changes the direction of the elevator if there are no passengers that wants
|
||||||
|
* to enter or exit on floors either above or below the elevator
|
||||||
|
*/
|
||||||
|
private void calculateDirection() {
|
||||||
|
if (Arrays.stream(waitEntry, floor, nfloors).sum() == 0 &&
|
||||||
|
Arrays.stream(waitExit, floor, nfloors).sum() == 0 && floor != 0) {
|
||||||
|
direction = Direction.DOWN;
|
||||||
|
} else if (Arrays.stream(waitEntry, 0, floor + 1).sum() == 0 &&
|
||||||
|
Arrays.stream(waitExit, 0, floor + 1).sum() == 0 && floor != 6) {
|
||||||
|
direction = Direction.UP;
|
||||||
|
} else if (floor == nfloors - 1) {
|
||||||
|
direction = Direction.DOWN;
|
||||||
|
} else if (floor == 0) {
|
||||||
|
direction = Direction.UP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
lift/src/lift/LiftThread.java
Normal file
20
lift/src/lift/LiftThread.java
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package lift;
|
||||||
|
|
||||||
|
/** Thread responsible for lift movement and rendering */
|
||||||
|
public class LiftThread extends Thread {
|
||||||
|
private LiftView view;
|
||||||
|
private LiftMonitor monitor;
|
||||||
|
|
||||||
|
public LiftThread(LiftView v, LiftMonitor m) {
|
||||||
|
view = v;
|
||||||
|
monitor = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
int[] elevatorPositions = monitor.liftContinue();
|
||||||
|
view.moveLift(elevatorPositions[0], elevatorPositions[1]);
|
||||||
|
monitor.incrementFloor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +1,24 @@
|
||||||
package lift;
|
package lift;
|
||||||
|
|
||||||
public interface Passenger {
|
public interface Passenger {
|
||||||
/** @return the floor the passenger starts at */
|
/** @return the floor the passenger starts at */
|
||||||
int getStartFloor();
|
int getStartFloor();
|
||||||
|
|
||||||
/** @return the floor the passenger is going to */
|
/** @return the floor the passenger is going to */
|
||||||
int getDestinationFloor();
|
int getDestinationFloor();
|
||||||
|
|
||||||
/** First, delay for 0..45 seconds. Then animate the passenger's walk, on the entry floor, to the lift. */
|
/**
|
||||||
void begin();
|
* First, delay for 0..45 seconds. Then animate the passenger's walk, on the
|
||||||
|
* entry floor, to the lift.
|
||||||
|
*/
|
||||||
|
void begin();
|
||||||
|
|
||||||
/** Animate the passenger's walk from the entry floor into the lift. */
|
/** Animate the passenger's walk from the entry floor into the lift. */
|
||||||
void enterLift();
|
void enterLift();
|
||||||
|
|
||||||
/** Animate the passenger's walk out of the lift, to the exit floor. */
|
/** Animate the passenger's walk out of the lift, to the exit floor. */
|
||||||
void exitLift();
|
void exitLift();
|
||||||
|
|
||||||
/** Animate the passenger's walk, on the exit floor, out of view. */
|
/** Animate the passenger's walk, on the exit floor, out of view. */
|
||||||
void end();
|
void end();
|
||||||
}
|
}
|
||||||
|
|
34
lift/src/lift/PassengerThread.java
Normal file
34
lift/src/lift/PassengerThread.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package lift;
|
||||||
|
|
||||||
|
/** Responsible for a single passenger. */
|
||||||
|
public class PassengerThread extends Thread {
|
||||||
|
private LiftView view;
|
||||||
|
private LiftMonitor monitor;
|
||||||
|
|
||||||
|
public PassengerThread(LiftView v, LiftMonitor m) {
|
||||||
|
view = v;
|
||||||
|
monitor = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Drives a passenger through the lift phases */
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
Passenger p = view.createPassenger();
|
||||||
|
p.begin();
|
||||||
|
|
||||||
|
// Walk towards the lift
|
||||||
|
monitor.increaseWaitEntry(p.getStartFloor());
|
||||||
|
monitor.enterLift(p.getStartFloor(), p.getDestinationFloor());
|
||||||
|
p.enterLift();
|
||||||
|
|
||||||
|
// Passenger is now inside the lift, now exit
|
||||||
|
monitor.enterCompleted();
|
||||||
|
monitor.exitLift(p.getDestinationFloor());
|
||||||
|
p.exitLift();
|
||||||
|
|
||||||
|
// Despawn
|
||||||
|
monitor.exitCompleted();
|
||||||
|
p.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue