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…
	
	Add table
		Add a link
		
	
		Reference in a new issue