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.Passenger;
|
||||
|
||||
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;
|
||||
|
||||
LiftView view = new LiftView(NBR_FLOORS, MAX_PASSENGERS);
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
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;
|
||||
|
||||
public interface Passenger {
|
||||
/** @return the floor the passenger starts at */
|
||||
int getStartFloor();
|
||||
/** @return the floor the passenger starts at */
|
||||
int getStartFloor();
|
||||
|
||||
/** @return the floor the passenger is going to */
|
||||
int getDestinationFloor();
|
||||
/** @return the floor the passenger is going to */
|
||||
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. */
|
||||
void enterLift();
|
||||
/** Animate the passenger's walk from the entry floor into the lift. */
|
||||
void enterLift();
|
||||
|
||||
/** Animate the passenger's walk out of the lift, to the exit floor. */
|
||||
void exitLift();
|
||||
/** Animate the passenger's walk out of the lift, to the exit floor. */
|
||||
void exitLift();
|
||||
|
||||
/** Animate the passenger's walk, on the exit floor, out of view. */
|
||||
void end();
|
||||
/** Animate the passenger's walk, on the exit floor, out of view. */
|
||||
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