diff --git a/MV3302ClassCode/src/mv3302/Ship.java b/MV3302ClassCode/src/mv3302/Ship.java index 23d4cf6b147201d58c0cf0e1ddb0a5d065cd78ab..657255459080faf29696bf8f205aad11d9b401b9 100644 --- a/MV3302ClassCode/src/mv3302/Ship.java +++ b/MV3302ClassCode/src/mv3302/Ship.java @@ -7,6 +7,9 @@ package mv3302; import simkit.Entity; /** + * The Ship class extends the Entity class from the Simkit library and + * represents a ship object that can be used in a simulation. It keeps track of + * the remaining time it takes to unload its cargo. * * @author dansl */ @@ -14,11 +17,23 @@ public final class Ship extends Entity { private double remainingUnloadingTime; + /** + * Constructs a new Ship object with the specified remaining unloading time. + * + * @param remainingUnloadingTime the time remaining to unload the ship's + * cargo. + */ public Ship(double remainingUnloadingTime) { super(); setRemainingUnloadingTime(remainingUnloadingTime); } + /** + * Reduces the remaining unloading time of the ship based on the elapsed + * time and the given rate. + * @param rate the rate at which the ship is being unloaded. + * @throws IllegalArgumentException if the rate is less than 0. + */ public void work(double rate) { if (rate < 0.0) { throw new IllegalArgumentException("Input Rate must be > 0.0: " + rate); diff --git a/MV3302ClassCode/src/mv3302/ShipArrivalProcess.java b/MV3302ClassCode/src/mv3302/ShipArrivalProcess.java index 251236a69cc98495ec8d6b75afea059dec42f3d9..e53c63941de1c83d5aa23925bc961ac7d9c58583 100644 --- a/MV3302ClassCode/src/mv3302/ShipArrivalProcess.java +++ b/MV3302ClassCode/src/mv3302/ShipArrivalProcess.java @@ -7,6 +7,9 @@ package mv3302; import simkit.random.RandomVariate; /** + * The ShipArrivalProcess class extends the ArrivalProcess class and represents + * the arrival process for ships in a simulation. It generates ships at random + * intervals and assigns random unloading times to each ship. * * @author dansl */ @@ -16,19 +19,29 @@ public final class ShipArrivalProcess extends ArrivalProcess { private RandomVariate unloadingTimeGenerator; + /** + * Constructs a new ShipArrivalProcess with no generators set. + */ public ShipArrivalProcess() { } + /** + * Constructs a new ShipArrivalProcess with the given generators for + * interarrival times and unloading times. + * + * @param interarrivalTimeGenerator the generator for interarrival times + * @param unloadingTimeGenerator the generator for unloading times + */ public ShipArrivalProcess(RandomVariate interarrivalTimeGenerator, RandomVariate unloadingTimeGenerator) { super(interarrivalTimeGenerator); setInterarrivalTimeGenerator(interarrivalTimeGenerator); setUnloadingTimeGenerator(unloadingTimeGenerator); } -// public void doRun(){ -// waitDelay(Arrival) -// } - + /** + * Generates a new ship with a random unloading time and schedules its + * arrival in the simulation. + */ @Override public void doArrival() { super.doArrival(); @@ -36,7 +49,6 @@ public final class ShipArrivalProcess extends ArrivalProcess { waitDelay("ShipArrival", 0.0, ship); } - /** * @return the unloadingTimeGenerator */ diff --git a/MV3302ClassCode/src/mv3302/TwoCranesBerth.java b/MV3302ClassCode/src/mv3302/TwoCranesBerth.java index 9e60dbbbbe980a6adc0e4bda08b41867021221ee..982539d92074d07e334a94e92c864b86049e596b 100644 --- a/MV3302ClassCode/src/mv3302/TwoCranesBerth.java +++ b/MV3302ClassCode/src/mv3302/TwoCranesBerth.java @@ -10,8 +10,12 @@ import java.util.TreeSet; import simkit.SimEntityBase; /** + * The TwoCranesBerth class models a container terminal berth with two cranes. + * It keeps track of ships waiting to unload, ships in the berths, and their + * corresponding wait times and time in system. The class extends SimEntityBase. * * @author dansl + * */ public class TwoCranesBerth extends SimEntityBase { @@ -20,11 +24,17 @@ public class TwoCranesBerth extends SimEntityBase { protected double delayInQueue; protected double timeInSystem; + /** + * Initializes the queue and the berths as empty. + */ public TwoCranesBerth() { queue = new TreeSet<>(); berths = new TreeSet<>(); } + /** + * Clears the queue, sets the delay and time in system to NaN. + */ @Override public void reset() { getQueue().clear(); @@ -32,6 +42,10 @@ public class TwoCranesBerth extends SimEntityBase { timeInSystem = NaN; } + /** + * Clears the queue and the berths, sets the delay and time in system to + * NaN. + */ public void doRun() { queue.clear(); berths.clear(); @@ -39,6 +53,15 @@ public class TwoCranesBerth extends SimEntityBase { timeInSystem = NaN; } + /** + * Adds a ship to the queue, stamps its arrival time, and fires a property + * change event for the queue. If there is only one ship in the berths, it + * waits for a delay to simulate the switch to one crane. If the berths are + * empty, it waits for a delay to simulate the start of the unloading + * process with two cranes. + * + * @param ship the ship that has arrived at the berth + */ public void doArrival(Ship ship) { ship.stampTime(); SortedSet<Ship> oldQueue = getQueue(); @@ -47,12 +70,20 @@ public class TwoCranesBerth extends SimEntityBase { if (berths.size() == 1) { waitDelay("SwitchTo1Crane", 0.0); } - if (berths.isEmpty()){ + if (berths.isEmpty()) { waitDelay("StartUnload2Cranes", 0.0); } } - - public void doSwitchTo1Crane(){ + + /** + * Unloads a ship with one crane. Removes the ship from the berths, updates + * the time in system, and waits for the next ship to start unloading. If + * there are no more ships in the queue, it waits for a delay to simulate + * the switch to two cranes. + * + * @param ship the ship being unloaded + */ + public void doSwitchTo1Crane() { Ship ship = berths.first(); ship.work(2); ship.stampTime(); @@ -60,8 +91,12 @@ public class TwoCranesBerth extends SimEntityBase { waitDelay("StartUnload1Crane", 0.0); waitDelay("EndUnload1Crane", ship.getRemainingUnloadingTime(), ship); } - - public void doStartUnload1Crane(){ + + /** + * Starts unloading a ship with one crane and updates the queue, berths, and + * delayInQueue properties. + */ + public void doStartUnload1Crane() { SortedSet<Ship> oldQueue = getQueue(); Ship ship = queue.first(); queue.remove(ship); @@ -75,8 +110,12 @@ public class TwoCranesBerth extends SimEntityBase { firePropertyChange("berths", oldBerths, getBerths()); waitDelay("EndUnload1Crane", ship.getRemainingUnloadingTime(), ship); } - - public void doStartUnload2Cranes(){ + + /** + * Starts unloading a ship with two cranes and updates the queue, berths, + * and delayInQueue properties. + */ + public void doStartUnload2Cranes() { SortedSet<Ship> oldQueue = getQueue(); Ship ship = queue.first(); queue.remove(ship); @@ -88,25 +127,36 @@ public class TwoCranesBerth extends SimEntityBase { SortedSet<Ship> oldBerths = getBerths(); berths.add(ship); firePropertyChange("berths", oldBerths, getBerths()); - waitDelay("EndUnload2Cranes", ship.getRemainingUnloadingTime()/2); + waitDelay("EndUnload2Cranes", ship.getRemainingUnloadingTime() / 2); } - - public void doEndUnload1Crane(Ship ship){ + + /** + * Ends the unloading of a ship with one crane, updates the berths and + * timeInSystem properties, and checks if there are any remaining ships in + * the queue to unload. + * + * @param ship The ship that is finishing unloading. + */ + public void doEndUnload1Crane(Ship ship) { SortedSet<Ship> oldBerths = getBerths(); berths.remove(ship); firePropertyChange("berths", oldBerths, getBerths()); double oldTimeInSystem = getTimeInSystem(); timeInSystem = ship.getAge(); firePropertyChange("timeInSystem", oldTimeInSystem, getTimeInSystem()); - if (!queue.isEmpty()){ + if (!queue.isEmpty()) { waitDelay("StartUnload1Crane", 0.0); } - if (queue.isEmpty()){ + if (queue.isEmpty()) { waitDelay("SwitchTo2Cranes", 0.0); } } - - public void doEndUnload2Cranes(){ + + /** + * Ends the unloading of a ship with two cranes and updates the berths and + * timeInSystem properties. + */ + public void doEndUnload2Cranes() { SortedSet<Ship> oldBerths = getBerths(); Ship ship = berths.first(); berths.remove(ship); @@ -115,15 +165,18 @@ public class TwoCranesBerth extends SimEntityBase { timeInSystem = ship.getAge(); firePropertyChange("timeInSystem", oldTimeInSystem, getTimeInSystem()); } - - public void doSwitchTo2Cranes(){ + + /** + * Switches to two cranes unloading and updates the ship's time stamps. + */ + public void doSwitchTo2Cranes() { Ship ship = berths.first(); ship.work(1); ship.stampTime(); - waitDelay("EndUnload2Cranes", ship.getRemainingUnloadingTime()/2); + waitDelay("EndUnload2Cranes", ship.getRemainingUnloadingTime() / 2); interrupt("EndUnload1Crane", ship); } - + /** * @return the queue */ diff --git a/MV3302ClassCode/src/mv3302/run/testShipArrivalProcess.java b/MV3302ClassCode/src/mv3302/run/testShipArrivalProcess.java index a037bd38f13ec63e50f8a5d58e67e49dbca10854..6d755c09298612c36d67f8f02774356a0d8360a5 100644 --- a/MV3302ClassCode/src/mv3302/run/testShipArrivalProcess.java +++ b/MV3302ClassCode/src/mv3302/run/testShipArrivalProcess.java @@ -11,34 +11,30 @@ import simkit.Schedule; import simkit.random.RandomVariate; import simkit.random.RandomVariateFactory; import simkit.stat.CollectionSizeTimeVaryingStats; -import simkit.stat.MultipleSimpleStatsTally; import simkit.stat.SimpleStatsTally; -import simkit.util.SimplePropertyDumper; /** + * A test class that simulates the arrival and unloading of ships at a two-crane + * berth. It initializes the required objects, listens to the events triggered + * by these objects, and collects statistical data during the simulation. * * @author dansl */ public class testShipArrivalProcess { /** - * @param args the command line arguments + * Runs the simulation of ship arrivals and unloading at a two-crane berth, + * and prints the collected statistical data at the end of the simulation. */ public static void main(String[] args) { -// Ship ship = new Ship(5.0); -// -// System.out.println(ship.getRemainingUnloadingTime()); -// ship.work(2); -// System.out.println(ship.getRemainingUnloadingTime()); - RandomVariate interarrivalTimeGenerator = RandomVariateFactory.getInstance("Exponential", .7); RandomVariate unloadingTimeGenerator = RandomVariateFactory.getInstance("Uniform", 0.5, 1.5); ShipArrivalProcess shipArrivalProcess = new ShipArrivalProcess(interarrivalTimeGenerator, unloadingTimeGenerator); System.out.println(shipArrivalProcess); - + TwoCranesBerth twoCranesBerth = new TwoCranesBerth(); System.out.println(twoCranesBerth); - + // TwoCranesBerth will "hear" ShipArrivalProcess(Arrival) events shipArrivalProcess.addSimEventListener(twoCranesBerth); @@ -48,37 +44,40 @@ public class testShipArrivalProcess { adapter.connect(shipArrivalProcess, twoCranesBerth); // This was used for debugging model - SimplePropertyDumper simplePropertyDumper = new SimplePropertyDumper(true); +// SimplePropertyDumper simplePropertyDumper = new SimplePropertyDumper(true); +// +// twoCranesBerth.addPropertyChangeListener(simplePropertyDumper); +// shipArrivalProcess.addPropertyChangeListener(simplePropertyDumper); + // Tally statistics are computed in the same way by "listening" + SimpleStatsTally timeInSystemStat = new SimpleStatsTally("timeInSystem"); + twoCranesBerth.addPropertyChangeListener(timeInSystemStat); + + SimpleStatsTally delayInQueueStat = new SimpleStatsTally("delayInQueue"); + twoCranesBerth.addPropertyChangeListener(delayInQueueStat); - twoCranesBerth.addPropertyChangeListener(simplePropertyDumper); - shipArrivalProcess.addPropertyChangeListener(simplePropertyDumper); - + CollectionSizeTimeVaryingStats numberInBerthsStat = new CollectionSizeTimeVaryingStats("berths"); + twoCranesBerth.addPropertyChangeListener(numberInBerthsStat); + + CollectionSizeTimeVaryingStats numberInQueueStat = new CollectionSizeTimeVaryingStats("queue"); + twoCranesBerth.addPropertyChangeListener(numberInQueueStat); // Was "true" when debugging model - Schedule.setVerbose(true); + Schedule.setVerbose(false); double stopTime = 3650.0; Schedule.stopAtTime(stopTime); // Initialized & run Schedule.reset(); - Schedule.startSimulation(); + Schedule.startSimulation(); - // Tally statistics are computed in the same way by "listening" - SimpleStatsTally timeInSystemStat = new SimpleStatsTally("timeInSystem"); - twoCranesBerth.addPropertyChangeListener(timeInSystemStat); - - CollectionSizeTimeVaryingStats numberInQueueStat = new CollectionSizeTimeVaryingStats("queue"); - twoCranesBerth.addPropertyChangeListener(numberInQueueStat); - - System.out.printf("%nSimulation ended at time %,.2f%n%n", Schedule.getSimTime()); - - System.out.printf("Number of Ships Arriving: %,d%n", shipArrivalProcess.getNumberArrivals()); - System.out.printf("Number of Ships Unloaded: %,d%n", timeInSystemStat.getCount()); - System.out.printf("Maximum # in Queue: %,d%n", numberInQueueStat.getCount()); -// System.out.printf("Average # in Queue: %,.4f%n", numberInQueueStat.getMean()); -// System.out.printf("Average # Busy Berths: %,.4f%n", numberInQueueStat.getMean()); - System.out.printf("Average Time in System: %,.4f%n", timeInSystemStat.getMean()); -// System.out.printf("Average Delay in Queue: %,.4f%n", delayInQueueStat.getMean()); + + System.out.printf("Number of Ships Arriving:\t %,d%n", shipArrivalProcess.getNumberArrivals()); + System.out.printf("Number of Ships Unloaded:\t %,d%n", timeInSystemStat.getCount()); + System.out.printf("Maximum # in Queue:\t\t %,.0f%n", numberInQueueStat.getMaxObs()); + System.out.printf("Average # in Queue:\t\t %,.4f%n", numberInQueueStat.getMean()); + System.out.printf("Average # Busy Berths:\t\t %,.4f%n", numberInBerthsStat.getMean()); + System.out.printf("Average Time in System:\t\t %,.4f%n", timeInSystemStat.getMean()); + System.out.printf("Average Delay in Queue:\t\t %,.4f%n", delayInQueueStat.getMean()); } - + }