Skip to content
Snippets Groups Projects
TwoCraneBerths.java 6.57 KiB
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;
    }
}