package SimkitOpenDis7Examples; import java.util.SortedSet; import java.util.TreeSet; import simkit.Priority; import simkit.SimEntityBase; /** * Model two crane berths * @author abuss@nps.edu */ public class TwoCraneBerths extends SimEntityBase { /** * Queue of Ships waiting to go into the berth */ protected SortedSet<Ship> queue; /** * Contains 0, 1, or two Ships being unloaded */ protected SortedSet<Ship> berth; /** * Time in the system for each Ship */ protected double timeInSystem; /** * Delay in the queue for each Ship */ protected double delayInQueue; /** * Instantiate queue and berth containers */ public TwoCraneBerths() { this.queue = new TreeSet<>(); this.berth = new TreeSet<>(); } /** * Clear queue and berth containers */ @Override public void reset() { super.reset(); queue.clear(); berth.clear(); timeInSystem = Double.NaN; // Not a Number delayInQueue = Double.NaN; // Not a Number } /** * Only PropertyChangeEvents */ public void doRun() { firePropertyChange("queue", getQueue()); firePropertyChange("berth", getBerth()); firePropertyChange("timeInSystem", getTimeInSystem()); firePropertyChange("delayInQueue", getDelayInQueue()); } /** * Add the given Ship to queue<br> * If berths is empty, schedule StartUnloadingTwoCranes<br> * If berths has 1 Ship, schedule SwitchToOneCrane * * @param ship Given Ship arriving to harbor */ public void doArrival(Ship ship) { ship.stampTime(); SortedSet<Ship> oldQueue = getQueue(); queue.add(ship); firePropertyChange("queue", oldQueue, getQueue()); if (berth.isEmpty()) { waitDelay("StartUnloadingTwoCranes", 0.0, Priority.HIGH); } if (berth.size() == 1) { waitDelay("SwitchToOneCrane", 0.0); } } /** * Remove the first Ship from queue<br> * DelayInQueue is elapsedTime of that Ship<br> * Add the ship to berth container<br> * Schedule EndUnloadingTwoCranes at half the remaining time */ public void doStartUnloadingTwoCranes() { SortedSet<Ship> oldQueue = getQueue(); Ship ship = queue.first(); queue.remove(ship); firePropertyChange("queue", oldQueue, getQueue()); delayInQueue = ship.getElapsedTime(); firePropertyChange("delayInQueue", getDelayInQueue()); ship.stampTime(); SortedSet<Ship> oldBerth = getBerth(); berth.add(ship); firePropertyChange("berth", oldBerth, getBerth()); waitDelay("EndUnloadingTwoCranes", 0.5 * ship.getRemainingUnloadingTime()); } /** * Remove the (one) Ship from berth<br> * TimeInSystem is the age of the Ship */ public void doEndUnloadingTwoCranes() { SortedSet<Ship> oldBerth = getBerth(); Ship ship = berth.first(); berth.remove(ship); firePropertyChange("berth", oldBerth, getBerth()); timeInSystem = ship.getAge(); firePropertyChange("timeInSystem", getTimeInSystem()); } /** * This event is when a Ship arrives to find only one other Ship being * unloaded.<br> * Credit the ship in the berth with work at a rate of 2 (since 2 cranes * have been unloading it<br> * Interrupt EndUnloadingTwoCranes<br> * Schedule EndUnloadingOneCrane with the Ship already in the berth<br> * Schedule StartUnloadingOneCrane */ public void doSwitchToOneCrane() { Ship ship = berth.first(); ship.work(2.0); ship.stampTime(); interrupt("EndUnloadingTwoCranes"); waitDelay("EndUnloadingOneCrane", ship.getRemainingUnloadingTime(), ship); waitDelay("StartUnloadingOneCrane", 0.0, Priority.HIGH); } /** * Pop the first Ship from the queue<br> * delayInQueue is elapsedTime (from Arrival event)<br> * Add that Ship to berth container<br> * Schedule EndUnloadingOneCrane with that Ship */ public void doStartUnloadingOneCrane() { SortedSet<Ship> oldQueue = getQueue(); Ship ship = queue.first(); queue.remove(ship); firePropertyChange("queue", oldQueue, getQueue()); delayInQueue = ship.getElapsedTime(); firePropertyChange("delayInQueue", getDelayInQueue()); ship.stampTime(); SortedSet<Ship> oldBerth = getBerth(); berth.add(ship); firePropertyChange("berth", oldBerth, getBerth()); waitDelay("EndUnloadingOneCrane", ship.getRemainingUnloadingTime(), ship); } /** * Remove given Ship from berth<br> * If Ships in queue, schedule StartUnloadingOneCrane<br> * If queue is empty, schedule SwitchToTwoCranes<br> * timeInSystem is age of Ship * * @param ship Given Ship */ public void doEndUnloadingOneCrane(Ship ship) { SortedSet<Ship> oldBerth = getBerth(); berth.remove(ship); firePropertyChange("berth", oldBerth, getBerth()); if (queue.size() > 0) { waitDelay("StartUnloadingOneCrane", 0.0, Priority.HIGH); } if (queue.isEmpty() && berth.size() == 1) { waitDelay("SwitchToTwoCranes", 0.0); } timeInSystem = ship.getAge(); firePropertyChange("timeInSystem", getTimeInSystem()); } /** * Credit the work of the remaining Ship in berth at unit rate<br> * Interrupt EndUnloadingOneCrane<br> * Schedule EndUnloadingTwoCranes at double the rate (i.e., half the remaining time) */ public void doSwitchToTwoCranes() { Ship ship = berth.first(); ship.work(1.0); ship.stampTime(); interrupt("EndUnloadingOneCrane", ship); waitDelay("EndUnloadingTwoCranes", 0.5 * ship.getRemainingUnloadingTime()); } /** * Get tree of sorted Ship set queue * @return Shallow copy of queue */ public SortedSet<Ship> getQueue() { return new TreeSet<>(queue); } /** * Get tree of sorted Ship set berths * @return Shallow copy of berth */ public SortedSet<Ship> getBerth() { return new TreeSet<>(berth); } /** * accessor method to get a state variable * @return The timeInSystem */ public double getTimeInSystem() { return timeInSystem; } /** * accessor method to get a state variable * @return The delayInQueue */ public double getDelayInQueue() { return delayInQueue; } }