Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • stefan.goericke.gy/NetworkedGraphicsMV3500
  • william.mahan/NetworkedGraphicsMV3500
  • alexander.white/NetworkedGraphicsMV3500
  • kyle.britt/NetworkedGraphicsMV3500
  • christopher.garibay/NetworkedGraphicsMV3500
  • christopher.cannon/NetworkedGraphicsMV3500
  • galoeffe/NetworkedGraphicsMV3500
  • dlcain1/NetworkedGraphicsMV3500
  • jmfurr/NetworkedGraphicsMV3500
  • jrjackso1/NetworkedGraphicsMV3500
  • kjmaroon1/NetworkedGraphicsMV3500
  • cdtacket/NetworkedGraphicsMV3500
12 results
Show changes
Showing
with 2837 additions and 0 deletions
package mv3302;
import static java.lang.Double.NaN;
import java.util.SortedSet;
import java.util.TreeSet;
import simkit.Entity;
import static simkit.Priority.HIGH;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;
/**
* Implementation of the multiple server queue model using<code>Entity</code>
* objects to represent individual customers. This allows the model to
* explicitly tally measures such as delay in queue and time in system.
*
* @author ahbuss
*/
public class EntityServer extends SimEntityBase {
/**
* Number of servers (k)
*/
private int totalNumberServers;
/**
* Generates service times ({t<sub>S</sub>})
*/
private RandomVariate serviceTimeGenerator;
/**
* # of available servers (S)
*/
protected int numberAvailableServers;
/**
* Container of waiting customers (q)
*/
protected SortedSet<Entity> queue;
/**
* time a given customer spends in queue (D - a transient state)
*/
protected double delayInQueue;
/**
* time a given customer spends in the system (W - a transient state)
*/
protected double timeInSystem;
/**
* Total number who complete service
*/
protected int numberServed;
/**
* Instantiate an EntityServer with the given titalNumberServers and
* serviceTimeGenerator. Note: should call <code>this()</code> to ensure
* that <code>queue</code> is instantiated
*
* @param totalNumberServers
* @param serviceTimeGenerator
*/
public EntityServer(int totalNumberServers, RandomVariate serviceTimeGenerator) {
this();
setTotalNumberServers(totalNumberServers);
setServiceTimeGenerator(serviceTimeGenerator);
}
/**
* Instantiate the <code>queue</code>state variable
*/
public EntityServer() {
this.queue = new TreeSet<>();
}
/**
* Initialize state variables:<ul>
* <li>Empty <code>queue</code>
* <li>set numberAvailableServers to totalNumberServers
* <li>Set numberServed to 0
* <li>Set delayInQueue to NaN
* <li>Set timeInSystem to NaN </ul>
*/
@Override
public void reset() {
super.reset();
queue.clear();
numberAvailableServers = getTotalNumberServers();
numberServed = 0;
delayInQueue = NaN;
timeInSystem = NaN;
}
/**
* Fire property changes for time-varying states
*/
public void doRun() {
firePropertyChange("queue", getQueue());
firePropertyChange("numberAvailableServers", getNumberAvailableServers());
firePropertyChange("numberServed", getNumberServed());
}
/**
* Stamp time and add customer to <code>queue</code><br>
* if available server, schedule StartService with delay of 0.0
*
* @param customer Arriving customer
*/
public void doArrival(Entity customer) {
customer.stampTime();
var oldQueue = getQueue();
queue.add(customer);
firePropertyChange("queue", oldQueue, getQueue());
if (numberAvailableServers > 0) {
waitDelay("StartService", 0.0, HIGH);
}
}
/**
* Decrement numbervailableServers<br>
* Remove first customer from <code>queue</code><br>
* Compute delayInQueue as elapsed time<br>
* Schedule EndSrevice with delay generated by serviceTimeGenerator
*/
public void doStartService() {
var oldNumberAvailableServers = getNumberAvailableServers();
numberAvailableServers -= 1;
firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
var oldQueue = getQueue();
var customer = queue.first();
queue.remove(customer);
firePropertyChange("queue", oldQueue, getQueue());
delayInQueue = customer.getElapsedTime();
firePropertyChange("delayInQueue", getDelayInQueue());
waitDelay("EndService", serviceTimeGenerator, customer);
}
/**
* Increment numberAvailableServers<br>
* Compute timeInSystem as customer's elapsedTime<br>
* Increment numberServed<br>
* If customer(s) in <code>queue</code>, schedule StartService with delay of 0.0
*
* @param customer Given customer completing service
*/
public void doEndService(Entity customer) {
var oldNumberAvailableServers = getNumberAvailableServers();
numberAvailableServers += 1;
firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
timeInSystem = customer.getElapsedTime();
firePropertyChange("timeInSystem", getTimeInSystem());
var oldNumberServed = getNumberServed();
numberServed += 1;
firePropertyChange("numberServed", oldNumberServed, getNumberServed());
if (!queue.isEmpty()) {
waitDelay("StartService", 0.0, HIGH);
}
}
/**
* @return the totalNumberServers
*/
public int getTotalNumberServers() {
return totalNumberServers;
}
/**
* @param totalNumberServers the totalNumberServers to set
* @throws IllegalArgumentException if totalNumberServers &le; 0
*/
public void setTotalNumberServers(int totalNumberServers) {
if (totalNumberServers <= 0) {
throw new IllegalArgumentException("totalNumberServers must be > 0: " + totalNumberServers);
}
this.totalNumberServers = totalNumberServers;
}
/**
* @return the serviceTimeGenerator
*/
public RandomVariate getServiceTimeGenerator() {
return serviceTimeGenerator;
}
/**
* @param serviceTimeGenerator the serviceTimeGenerator to set
*/
public void setServiceTimeGenerator(RandomVariate serviceTimeGenerator) {
this.serviceTimeGenerator = serviceTimeGenerator;
}
/**
* @return the numberAvailableServers
*/
public int getNumberAvailableServers() {
return numberAvailableServers;
}
/**
* @return the queue
*/
public SortedSet<Entity> getQueue() {
return new TreeSet<>(queue);
}
/**
* @return the numberServed
*/
public int getNumberServed() {
return numberServed;
}
/**
* @return the delayInQueue
*/
public double getDelayInQueue() {
return delayInQueue;
}
/**
* @return the timeInSystem
*/
public double getTimeInSystem() {
return timeInSystem;
}
}
package mv3302;
import simkit.Entity;
/**
* Instantiates a Part by extending the Entity Simkit base. Tracks the value of
* the totalDelayInQueue.
*
*/
public class Part extends Entity {
private double totalDelayInQueue;
private int next;
/**
* Zero Argument constructor method that makes a call to it's super.
* Initializes the value of the parts delay in queue time to 0.
*
*/
public Part() {
this.totalDelayInQueue = 0.0;
}
/**
* Returns the totalDelayInQueue value
*
* @return
*/
public double getTotalDelayInQueue() {
return this.totalDelayInQueue;
}
public void advance() {
this.next += 1;
}
/**
* Method passes in the increment delay value and adds it to the
* totalDelayInQueue variable
*/
public void incrementDelayInQueue(double incrementDelay) {
this.totalDelayInQueue += incrementDelay;
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package mv3302;
import simkit.random.RandomVariate;
/**
*PartArrivalProcess class extends ArrivalProcess instantiating an inter-arrival time
* for each part entered into the system. Arrives the part to the Arrival method of the
* super.
* @author dansl
*/
public class PartArrivalProcess extends ArrivalProcess{
public int numberPartsArrived;
/**
* Zero-argument constructor
*/
public PartArrivalProcess() {
super();
}
/**
* Instantiate with the given parameters
*
* @param interarrivalTimes Given inter arrival times
*/
public PartArrivalProcess(RandomVariate interarrivalTimes) {
super(interarrivalTimes);
}
/**
* Schedule next Arrival<br>
* Schedule Arrival(index)
*/
@Override
public void doArrival() {
super.doArrival();
Part part = new Part();
numberPartsArrived +=1;
waitDelay("Arrival", 0.0, part, 0);
}
/**
* @return the numberPartsArrived
*/
public int getNumberPartsArrived() {
return numberPartsArrived;
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package mv3302;
import static java.lang.Double.NaN;
import java.util.SortedSet;
import java.util.TreeSet;
import static simkit.Priority.HIGH;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;
/**
* Implementation of the multiple server queue model using<code>Customer</code>
* objects to represent individual customers. This allows the model to
* explicitly tally measures such as delay in queue and time in system.
*/
public final class ServerWithReneges extends SimEntityBase {
/**
* Number of servers (k)
*/
private int totalNumberServers;
/**
* # of available servers (S)
*/
protected int numberAvailableServers;
/**
* Container of waiting customers (q)
*/
protected SortedSet<Customer> queue;
/**
* time a given customer spends in queue (D - a transient state)
*/
protected double delayInQueueServed = NaN;
/**
* time a given customer will spend in the queue before reneging
*/
private double delayInQueueReneged;
/**
* time a given customer spends in the system (W - a transient state)
*/
protected double timeInSystem = NaN;
private int numberReneges;
private int numberServed;
/**
* Generates service times ({t<sub>S</sub>})
*/
private RandomVariate serviceTimeGenerator;
/**
* Instantiate a ServerWithReneges with the given totalNumberServers and
* serviceTimeGenerator. Note: should call <code>this()<</code> to ensure
* that <code>queue</code> is instantiated
*
* @param totalNumberServers
* @param serviceTimeGenerator
*/
public ServerWithReneges(int totalNumberServers, RandomVariate serviceTimeGenerator) {
this();
setTotalNumberServers(totalNumberServers);
setServiceTimeGenerator(serviceTimeGenerator);
}
/**
* Instantiate the <code>queue</code>state variable
*/
public ServerWithReneges() {
this.queue = new TreeSet<>();
}
/**
* Initialize state variables:<ul>
* <li>Empty <code>queue</code>
* <li>set numberAvailableServers to totalNumberServers
* <li>Set numberServed to 0
* <li>Set delayInQueue to NaN
* <li>Set timeInSystem to NaN </ul>
*/
@Override
public void reset() {
super.reset();
queue.clear();
numberAvailableServers = getTotalNumberServers();
delayInQueueServed = NaN;
delayInQueueReneged = 0.0;
timeInSystem = NaN;
numberReneges = 0;
numberServed = 0;
}
/**
* Fire property changes for time-varying states
*/
public void doRun() {
firePropertyChange("queue", getQueue());
firePropertyChange("numberAvailableServers", getNumberAvailableServers());
firePropertyChange("numberReneges", getNumberReneges());
}
/**
* Stamp time and add customer to <code>queue</code><br>
* if available server, schedule StartService with delay of 0.0
*
* @param customer Arriving customer
*/
public void doArrival(Customer customer) {
customer.stampTime();
SortedSet<Customer> oldQueue = getQueue();
queue.add(customer);
firePropertyChange("queue", oldQueue, getQueue());
waitDelay("Renege", 0.0, customer);
if (numberAvailableServers > 0) {
waitDelay("StartService", 0.0, HIGH);
}
}
/**
* Decrement numberAvailableServers<br>
* Remove first customer from <code>queue</code><br>
* Compute delayInQueueServed as elapsed time<br>
* Schedule EndService with delay generated by serviceTimeGenerator
*/
public void doStartService() {
Customer customer = queue.first();
SortedSet<Customer> oldQueue = getQueue();
queue.remove(customer);
firePropertyChange("queue", oldQueue, getQueue());
int oldNumberAvailableServers = getNumberAvailableServers();
numberAvailableServers -= 1;
firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
delayInQueueServed = customer.getElapsedTime();
firePropertyChange("delayInQueueServed", getDelayInQueueServed());
interrupt("Renege", customer);
waitDelay("EndService", serviceTimeGenerator, customer);
}
/**
* Remove customer from the queue, increment the numberReneges, fires
* property changes for the total number of reneges, and captures
* delayInQueueReneged values as elapsedTime
*/
public void doRenege(Customer customer) {
delayInQueueReneged = customer.getElapsedTime();
firePropertyChange("delayInQueueReneged", getDelayInQueueReneged());
SortedSet<Customer> oldQueue = getQueue();
queue.remove(customer);
firePropertyChange("queue", oldQueue, getQueue());
double oldNumberReneges = getNumberReneges();
numberReneges += 1;
firePropertyChange("numberReneges", oldNumberReneges, getNumberReneges());
}
/**
* Increment numberAvailableServers<br>
* Compute timeInSystem as customer's elapsedTime<br>
* Increment numberServed<br>
* If customer(s) in <code>queue</code>, schedule StartService with delay of
* 0.0
*
* @param customer Given customer completing service
*/
public void doEndService(Customer customer) {
int oldNumberAvailableServers = getNumberAvailableServers();
numberAvailableServers += 1;
firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
timeInSystem = customer.getElapsedTime();
firePropertyChange("timeInSystem", getTimeInSystem());
numberServed += 1;
if (!queue.isEmpty()) {
waitDelay("StartService", 0.0, HIGH);
}
}
/**
* @return the totalNumberServers
*/
public int getTotalNumberServers() {
return totalNumberServers;
}
/**
* @param totalNumberServers the totalNumberServers to set
* @throws IllegalArgumentException if totalNumberServers &le; 0
*/
public void setTotalNumberServers(int totalNumberServers) {
if (totalNumberServers <= 0) {
throw new IllegalArgumentException("totalNumberServers must be > 0: " + totalNumberServers);
}
this.totalNumberServers = totalNumberServers;
}
/**
* @return the serviceTimeGenerator
*/
public RandomVariate getServiceTimeGenerator() {
return serviceTimeGenerator;
}
/**
* @param serviceTimeGenerator the serviceTimeGenerator to set
*/
public void setServiceTimeGenerator(RandomVariate serviceTimeGenerator) {
this.serviceTimeGenerator = serviceTimeGenerator;
}
/**
* @return the numberAvailableServers
*/
public int getNumberAvailableServers() {
return numberAvailableServers;
}
/**
* @return the queue
*/
public SortedSet<Customer> getQueue() {
return new TreeSet<>(queue);
}
/**
* @return the delayInQueue
*/
public double getDelayInQueueServed() {
return delayInQueueServed;
}
/**
* @return the timeInSystem
*/
public double getTimeInSystem() {
return timeInSystem;
}
/**
* @return the delayInQueueReneged
*/
public double getDelayInQueueReneged() {
return delayInQueueReneged;
}
public double getNumberReneges() {
return numberReneges;
}
/**
* @return the numberServed
*/
public int getNumberServed() {
return numberServed;
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
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
*/
public final class Ship extends Entity {
protected 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);
}
remainingUnloadingTime -= getElapsedTime() * rate;
}
/**
* @return the remainingUnloadingTime
*/
public double getRemainingUnloadingTime() {
return remainingUnloadingTime;
}
/**
* @param remainingUnloadingTime the remainingUnloadingTime to set
*/
public void setRemainingUnloadingTime(double remainingUnloadingTime) {
this.remainingUnloadingTime = remainingUnloadingTime;
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
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
*/
public final class ShipArrivalProcess extends ArrivalProcess {
private RandomVariate interarrivalTimeGenerator;
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);
}
/**
* Generates a new ship with a random unloading time and schedules its
* arrival in the simulation.
*/
@Override
public void doArrival() {
super.doArrival();
Ship ship = new Ship(unloadingTimeGenerator.generate());
waitDelay("ShipArrival", 0.0, ship);
}
/**
* @return the unloadingTimeGenerator
*/
public RandomVariate getUnloadingTimeGenerator() {
return unloadingTimeGenerator;
}
/**
* @param unloadingTimeGenerator the unloadingTimeGenerator to set
*/
public void setUnloadingTimeGenerator(RandomVariate unloadingTimeGenerator) {
this.unloadingTimeGenerator = unloadingTimeGenerator;
}
}
package mv3302;
import mv3302.sensor.SimpleConstantRateSensor;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;
import simkit.smd.Mover;
/**
* The SimpleConstantRateMediator class represents a mediator that manages the
* interactions between a Mover object and a SimpleConstantRateSensor object. It
* extends the SimEntityBase class, which provides basic simulation entity
* functionality.
*/
public final class SimpleConstantRateMediator extends SimEntityBase {
/**
* Constructs a SimpleConstantRateMediator object with the specified
* exponential generator.
*
* @param exponentialGenerator the exponential generator to be used by the
* mediator
*/
public SimpleConstantRateMediator(RandomVariate exponentialGenerator1) {
setExponentialGenerator(exponentialGenerator1);
}
protected RandomVariate exponentialGenerator;
/**
* Constructs a SimpleConstantRateMediator object with the specified
* exponential generator.
*
* @param exponentialGenerator the exponential generator to be used by the
* mediator
*/
public void SimpleConstantRateMediator(RandomVariate exponentialGenerator) {
setExponentialGenerator(exponentialGenerator);
}
/**
* Performs the necessary actions when a Mover object enters the range of a
* SimpleConstantRateSensor object. If the target is not already detected by
* the sensor, it waits for a detection delay generated by the exponential
* generator.
*
* @param target the Mover object that entered the sensor's range
* @param sensor the SimpleConstantRateSensor object that detected the
* target
*/
public void doEnterRange(Mover target, SimpleConstantRateSensor sensor) {
if (!sensor.getContacts().contains(target)) {
sensor.waitDelay("Detection", exponentialGenerator.generate(), target);
}
}
/**
* Performs the necessary actions when a Mover object exits the range of a
* SimpleConstantRateSensor object. If the target is not already undetected
* by the sensor, it waits for an undetection delay generated by the
* exponential generator.
*
* @param target the Mover object that exited the sensor's range
* @param sensor the SimpleConstantRateSensor object that lost contact with
* the target
*/
public void doExitRange(Mover target, SimpleConstantRateSensor sensor) {
if (!sensor.getContacts().contains(target)) {
sensor.waitDelay("Undetection", exponentialGenerator.generate(), target);
}
}
/**
* Retrieves the exponential generator used by the mediator.
*
* @return the exponential generator used by the mediator
*/
public RandomVariate getExponentialGenerator() {
return exponentialGenerator;
}
/**
* Sets the exponential generator for the mediator.
*
* @param exponentialGenerator the exponential generator to be set
*/
public void setExponentialGenerator(RandomVariate exponentialGenerator) {
this.exponentialGenerator = exponentialGenerator;
}
}
package mv3302;
import mv3302.sensor.SimpleConstantTimeSensor;
import simkit.SimEntityBase;
import simkit.smd.Mover;
/**
* The SimpleConstantTimeMediator class represents a mediator between a target
* Mover object and a SimpleConstantTimeSensor object. It extends the
* SimEntityBase class, which provides basic simulation entity functionality.
*/
public class SimpleConstantTimeMediator extends SimEntityBase {
/**
* Performs the necessary actions when the target Mover enters the range of
* the sensor.
*
* @param target The Mover object that entered the range of the sensor.
* @param sensor The SimpleConstantTimeSensor object responsible for
* detecting the target.
*/
public void doEnterRange(Mover target, SimpleConstantTimeSensor sensor) {
if (!sensor.getContacts().contains(target)) {
sensor.waitDelay("Detection", sensor.getTimeToDetect(), target);
}
}
/**
* Performs the necessary actions when the target Mover exits the range of
* the sensor.
*
* @param target The Mover object that exited the range of the sensor.
* @param sensor The SimpleConstantTimeSensor object responsible for
* detecting the target.
*/
public void doExitRange(Mover target, SimpleConstantTimeSensor sensor) {
if (!sensor.getContacts().contains(target)) {
sensor.waitDelay("Undetection", 0.0, target);
}
}
}
package mv3302;
import mv3302.sensor.SimpleCookieCutterSensor;
import simkit.SimEntityBase;
import simkit.smd.Mover;
/**
* The SimpleCookieCutterMediator class represents a mediator that interacts
* with a SimpleCookieCutterSensor to handle the detection and undetection of a
* Mover object. It extends the SimEntityBase class, which is a base class for
* simulation entities in SimKit.
*/
public class SimpleCookieCutterMediator extends SimEntityBase {
/**
* Handles the event when a Mover enters the range of the
* SimpleCookieCutterSensor. If the Mover is not already in the sensor's
* contacts, it waits for a "Detection" event to occur.
*
* @param target The Mover object that entered the sensor's range.
* @param sensor The SimpleCookieCutterSensor responsible for detection.
*/
public void doEnterRange(Mover target, SimpleCookieCutterSensor sensor) {
if (!sensor.getContacts().contains(target)) {
sensor.waitDelay("Detection", 0.0, target);
}
}
/**
* Handles the event when a Mover exits the range of the
* SimpleCookieCutterSensor. If the Mover is not already in the sensor's
* contacts, it waits for an "Undetection" event to occur. If the Mover is
* still not detected, it interrupts the ongoing "Detection" event.
*
* @param target The Mover object that exited the sensor's range.
* @param sensor The SimpleCookieCutterSensor responsible for detection.
*/
public void doExitRange(Mover target, SimpleCookieCutterSensor sensor) {
if (!sensor.getContacts().contains(target)) {
sensor.waitDelay("Undetection", 0.0, target);
}
if (!sensor.getContacts().contains(target)) {
interrupt("Detection", 0.0, target);
}
}
}
package mv3302;
import java.awt.geom.Point2D;
import static mv3302.SimplestMover.NaP;
import simkit.Schedule;
import simkit.SimEntityBase;
import simkit.smd.Mover;
/**
* A simple implementation of the DES "Mover" concept.
*
* @author ahbuss
*/
public class SimpleMover extends SimEntityBase implements Mover {
/**
* Start here
*/
private Point2D initialLocation;
/**
* All movement will be at this speed
*/
private double maxSpeed;
/**
* Current velocity vector
*/
protected Point2D velocity;
/**
* Location where SimpleMover last stopped
*/
protected Point2D lastStopLocation;
/**
* Current destination
*/
protected Point2D destination;
/**
* simTime when move starts (or when it stops)
*/
protected double startMoveTime;
/**
* Instantiate Point2D states by cloning NaP
*/
public SimpleMover() {
lastStopLocation = (Point2D) NaP.clone();
velocity = (Point2D) NaP.clone();
destination = (Point2D) NaP.clone();
}
/**
* Instantiate with the given parameters
*
* @param initialLocation Given initial location
* @param maxSpeed Given maxSpeed
*/
public SimpleMover(Point2D initialLocation, double maxSpeed) {
this();
setInitialLocation(initialLocation);
setMaxSpeed(maxSpeed);
}
/**
* set destination location to NaP<br>
* set lastStopLocation to initialLocation<br>
* set velocity to (0.0, 0.0)<br>
* set startMoveTime to 0.0
*
*/
@Override
public void reset() {
super.reset();
destination = (Point2D) NaP.clone();
lastStopLocation = getInitialLocation();
velocity.setLocation(0.0, 0.0);
startMoveTime = 0.0;
}
/**
* Nothing scheduled - waiting to hear MoveTo event
*/
public void doRun() {
firePropertyChange("startMoveTime", getStartMoveTime());
firePropertyChange("lastStopLocation", getLastStopLocation());
firePropertyChange("velocity", getVelocity());
firePropertyChange("destination", getDestination());
}
/**
* To be "heard" from a mover manager.<br>
* set destination to the given argument<br>
* schedule StartMove if non-zero travel distance
*
* @param destination Given new destination
*/
public void doMoveTo(Point2D destination) {
Point2D oldDestination = getDestination();
this.destination = destination;
firePropertyChange("destination", oldDestination, getDestination());
if (lastStopLocation.distance(destination) > 0.0) {
waitDelay("StartMove", 0.0, this);
}
}
/**
* set velocity per the new destination and maxSpeed<br>
* set startMoveTime to current simTime<br>
* schedule EndMove with delay of travel time
*
* @param mover Should be "this" Mover
*/
@Override
public void doStartMove(Mover mover) {
Point2D oldVelocity = getVelocity();
velocity = new Point2D.Double(
destination.getX() - lastStopLocation.getX(),
destination.getY() - lastStopLocation.getY()
);
double distance = lastStopLocation.distance(destination);
velocity.setLocation(velocity.getX() * maxSpeed / distance,
velocity.getY() * maxSpeed / distance);
firePropertyChange("velocity", oldVelocity, getVelocity());
double oldStartMoveTime = getStartMoveTime();
startMoveTime = Schedule.getSimTime();
firePropertyChange("startMoveTime", oldStartMoveTime, getStartMoveTime());
double travelTime = distance / maxSpeed;
waitDelay("EndMove", travelTime, mover);
}
/**
* Set lastStopLocation coordinates to destination<br>
* set velocity to (0.0, 0.0)<br>
* set destination of NaP
*
* @param mover Should be "this" Mover
*/
public void doEndMove(Mover mover) {
Point2D oldLastStopLocation = getLastStopLocation();
lastStopLocation.setLocation(destination);
firePropertyChange("lastStopLocation", oldLastStopLocation, getLastStopLocation());
Point2D oldVelocity = getVelocity();
velocity.setLocation(0.0, 0.0);
firePropertyChange("velocity", oldVelocity, getVelocity());
Point2D oldDestination = getDestination();
destination.setLocation(NaP);
firePropertyChange("destination", oldDestination, getDestination());
}
/**
* Scheduled when Mover "stops" for a period of time.<br>
* Set lastStopLocation to currentLocation<br>
* setVelocity to (0.0, 0.0)
*
* @param mover Should be "this" Mover
*/
@Override
public void doStop(Mover mover) {
Point2D oldLastStopLocation = getLastStopLocation();
lastStopLocation.setLocation(getCurrentLocation());
firePropertyChange("lastStopLocation", oldLastStopLocation, getLastStopLocation());
Point2D oldVelocity = getVelocity();
velocity.setLocation(0.0, 0.0);
firePropertyChange("velocity", oldVelocity, getVelocity());
}
/**
* to be "heard" from Mover Manager when stopping<br>
* Schedule Stop
*/
public void doOrderStop() {
waitDelay("Stop", 0.0, this);
}
/**
* "Implicit" state - determined using the linear equation of motion.
*
* @return The current location of this Mover
*/
@Override
public Point2D getCurrentLocation() {
Point2D currentLocation = (Point2D) NaP.clone();
double elapsedTime = Schedule.getSimTime() - getStartMoveTime();
currentLocation.setLocation(lastStopLocation.getX() + elapsedTime * velocity.getX(),
lastStopLocation.getY() + elapsedTime * velocity.getY());
return currentLocation;
}
/**
*
* @return the maxSpeed
*/
@Override
public double getMaxSpeed() {
return this.maxSpeed;
}
/**
*
* @return copy of velocity
*/
@Override
public Point2D getVelocity() {
return (Point2D) velocity.clone();
}
/**
* @return copy of the initialLocation
*/
public Point2D getInitialLocation() {
return (Point2D) initialLocation;
}
/**
* @param initialLocation the initialLocation to set
*/
public void setInitialLocation(Point2D initialLocation) {
this.initialLocation = (Point2D) initialLocation.clone();
}
/**
* @param maxSpeed the maxSpeed to set
* @throws IllegalArgumentException if maxSpeed &lt; 0.0
*/
public void setMaxSpeed(double maxSpeed) {
if (maxSpeed < 0.0) {
throw new IllegalArgumentException("maxSpeed must be 0.0: " + maxSpeed);
}
this.maxSpeed = maxSpeed;
}
/**
* @return copy of the lastStopLocation
*/
public Point2D getLastStopLocation() {
return (Point2D) lastStopLocation;
}
/**
* @return copy of the destination
*/
public Point2D getDestination() {
return (Point2D) destination.clone();
}
/**
* @return the startMoveTime
*/
public double getStartMoveTime() {
return startMoveTime;
}
/**
*
* @return Name currentLocation velocity
*/
@Override
public String toString() {
return String.format("%s %s %s", getName(), getCurrentLocation(), getVelocity());
}
/**
*
* @return super toString()
*/
public String paramString() {
return super.toString();
}
}
package mv3302;
import java.awt.geom.Point2D;
import static mv3302.SimplestMover.NaP;
import simkit.SimEntityBase;
import simkit.smd.Mover;
/**
* Simple Path Mover Manager. Directs a listening Mover to each wayPoint in
* order until the last, when it "stops"
*
* @author ahbuss
*/
public class SimplePathMoverManager extends SimEntityBase {
/**
* If true, start immediately
*/
private boolean startOnRun;
/**
* Given list of wayPoints
*/
private Point2D[] path;
/**
* index of next wayPoint
*/
protected int nextIndex;
/**
* next destination
*/
protected Point2D nextDestination;
/**
* Instantiate nextDestination as copy of NaP
*/
public SimplePathMoverManager() {
nextDestination = (Point2D) NaP.clone();
}
/**
* Instantiate with the given parameters
*
* @param path Given path
* @param startOnRun if true, start on Run event
*/
public SimplePathMoverManager(Point2D[] path, boolean startOnRun) {
this();
setPath(path);
setStartOnRun(startOnRun);
}
/**
* Set nextIndex to -1<br>
* set nextDestination to NaP coordinates
*/
@Override
public void reset() {
super.reset();
nextIndex = -1;
nextDestination.setLocation(NaP);
}
/**
* If startOnRun is true, schedule NextWayPoint
*/
public void doRun() {
firePropertyChange("nextIndex", getNextIndex());
if (isStartOnRun()) {
waitDelay("NextWayPoint", 0.0);
}
}
/**
* Increment nextIndex<br>
* set nextDestination to path[nextIndex]<br>
* schedule MoveTo with nextDestination
*/
public void doNextWayPoint() {
int oldNextIndex = getNextIndex();
nextIndex += 1;
firePropertyChange("nextIndex", oldNextIndex, getNextIndex());
Point2D oldDestination = getNextDestination();
nextDestination.setLocation(path[nextIndex]);
firePropertyChange("nextDestination", oldDestination, getNextDestination());
waitDelay("MoveTo", 0.0, getNextDestination());
}
/**
* If more way points on path, schedule NextWayPoint<br>
* Else schedule OrderStop
*
* @param mover Given Mover (should be the one this is listening to)
*/
public void doEndMove(Mover mover) {
if (nextIndex < path.length - 1) {
waitDelay("NextWayPoint", 0.0);
}
if (nextIndex == path.length - 1) {
waitDelay("OrderStop", 0.0);
}
}
/**
* @return the startOnRun
*/
public boolean isStartOnRun() {
return startOnRun;
}
/**
* @param startOnRun the startOnRun to set
*/
public void setStartOnRun(boolean startOnRun) {
this.startOnRun = startOnRun;
}
/**
* @return topy of he path
*/
public Point2D[] getPath() {
return path.clone();
}
/**
*
* @param index Given index
* @return path[index]
*/
public Point2D getPath(int index) {
return path[index];
}
/**
* @param path the path to set
*/
public void setPath(Point2D[] path) {
this.path = path.clone();
}
/**
*
* @param index Given index
* @param path Given waypoint
*/
public void setPath(int index, Point2D path) {
this.path[index] = path;
}
/**
* @return the nextIndex
*/
public int getNextIndex() {
return nextIndex;
}
/**
* @return copy of the nextDestination
*/
public Point2D getNextDestination() {
return (Point2D) nextDestination.clone();
}
}
package mv3302;
import java.awt.geom.Point2D;
import simkit.smd.Mover;
/**
* Similar to PathMoverManager; directs a Mover to a sequence of way points.
* Instead of stopping at the end, return to the first and cycle through again
* until stopped by an external component.
*
* @author dansl
*/
public class SimplePatrolMoverManager extends SimplePathMoverManager {
/**
* Zero argument constructor
*/
public SimplePatrolMoverManager() {
}
/**
* Instantiate with the given parameters
*
* @param path Given path
* @param startOnRun if true, start on Run event
*/
public SimplePatrolMoverManager(Point2D[] path, boolean startOnRun) {
super(path, startOnRun);
}
/**
* Always schedule NextWayPoint
*
* @param mover Given Mover
*/
@Override
public void doEndMove(Mover mover) {
waitDelay("NextWaypoint", 0.0);
}
/**
* Increment nextIndext and set modulo the length of the path<br>
* setNextDestination<br>
* Schedule MoveTo
*/
public void doNextWaypoint() {
int oldNextIndex = getNextIndex();
nextIndex = (nextIndex + 1) % getPath().length;
firePropertyChange("nextIndex", oldNextIndex, getNextIndex());
Point2D oldDestination = getNextDestination();
nextDestination.setLocation(getPath(nextIndex));
firePropertyChange("nextDestination", oldDestination, getNextDestination());
waitDelay("MoveTo", 0.0, getNextDestination());
}
}
package mv3302;
import java.awt.geom.Point2D;
import static mv3302.SimplestMover.NaP;
import simkit.SimEntity;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;
/**
* A MoverManager that generates a random destination and directs a Mover there.
* When the Mover reaches that destination, generate the next, etc.
*
* @author ahbuss
*/
public class SimpleRandomMoverManager extends SimEntityBase {
/**
* Generates the coordinates
*/
private RandomVariate[] coordinateGenerator;
/**
* If true, start on the Run event
*/
private boolean startOnRun;
/**
* Next destination
*/
protected Point2D nextWayPoint;
/**
* set nextWayPoint to clone of NaP
*/
public SimpleRandomMoverManager() {
this.nextWayPoint = (Point2D) NaP.clone();
}
/**
*
* @param coordinateGenerator Given coordinate generators
* @param startOnRun if true, start in Run event
*/
public SimpleRandomMoverManager(RandomVariate[] coordinateGenerator, boolean startOnRun) {
this();
this.setCoordinateGenerator(coordinateGenerator);
this.setStartOnRun(startOnRun);
}
/**
* set nextWayPoint to NaP coordinates
*/
@Override
public void reset() {
super.reset();
nextWayPoint.setLocation(NaP);
}
/**
* If startOnRun, schedule Start event
*/
public void doRun() {
firePropertyChange("nextWayPoint", getNextWayPoint());
if (isStartOnRun()) {
waitDelay("Start", 0.0);
}
}
/**
* Generate nextWaypoint<br>
* schedule MoveTo
*/
public void doStart() {
nextWayPoint = new Point2D.Double(coordinateGenerator[0].generate(), coordinateGenerator[1].generate());
firePropertyChange("nextWaypoint", getNextWayPoint());
waitDelay("MoveTo", 0.0, nextWayPoint);
}
/**
* To be "heard" from Mover. generate nextWayPoint and schedule MoveTo
*
* @param mover Given Mover
*/
public void doEndMove(SimEntity mover) {
nextWayPoint = new Point2D.Double(coordinateGenerator[0].generate(), coordinateGenerator[1].generate());
firePropertyChange("nextWaypoint", getNextWayPoint());
waitDelay("MoveTo", 0.0, nextWayPoint);
}
/**
* Schedule OrderStop (which should "Stop" the Mover listening)
*/
public void doStop() {
waitDelay("OrderStop", 0.0);
}
/**
* @return copy of the coordinateGenerator
*/
public RandomVariate[] getCoordinateGenerator() {
return coordinateGenerator.clone();
}
/**
* @param coordinateGenerator the coordinateGenerator to set (copy of)
*/
public void setCoordinateGenerator(RandomVariate[] coordinateGenerator) {
this.coordinateGenerator = coordinateGenerator.clone();
}
/**
* @return the startOnRun
*/
public boolean isStartOnRun() {
return startOnRun;
}
/**
* @param startOnRun the startOnRun to set
*/
public void setStartOnRun(boolean startOnRun) {
this.startOnRun = startOnRun;
}
/**
* @return the nextWayPoint
*/
public Point2D getNextWayPoint() {
return nextWayPoint;
}
}
package mv3302;
import java.awt.geom.Point2D;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
import java.util.List;
import simkit.SimEntityBase;
import static simkit.smd.Math2D.ZERO;
import simkit.smd.Mover;
import simkit.smd.Sensor;
/**
The SimpleReferee class represents a referee in a simulation. It extends the SimEntityBase class,
which provides basic functionality for simulation entities.
*/
public final class SimpleReferee extends SimEntityBase {
private List<Sensor> sensors;
private List<Mover> targets;
/**
Constructs a SimpleReferee object with an empty list of sensors and targets.
*/
public SimpleReferee() {
}
/**
Constructs a SimpleReferee object with the specified lists of sensors and targets.
@param sensors the list of sensors to set
@param targets the list of targets to set
*/
public SimpleReferee(List<Sensor> sensors, List<Mover> targets) {
setSensors(sensors);
setTargets(targets);
}
/**
Performs the run logic for the referee. If there are sensors present, it waits for the "InitSensor"
event with zero delay.
*/
public void doRun() {
if (!sensors.isEmpty()) {
waitDelay("InitSensor", 0.0, 0);
}
}
/**
Initializes a sensor at the specified index. Adds the sensor as a simulation event listener.
If there are more sensors to initialize, it waits for the "InitSensor" event for the next index.
@param i the index of the sensor to initialize
*/
public void doInitSensor(int i) {
sensors.get(i).addSimEventListener(this);
if (i < sensors.size() - 1) {
waitDelay("InitSensor", 0.0, i + 1);
}
waitDelay("InitTarget", 0.0, i, 0);
}
/**
Initializes a target at the specified indices. Adds the target as a simulation event listener.
If there are more targets to initialize, it waits for the "InitTarget" event for the next indices.
Checks if the target is within range of the sensor and waits for the "EnterRange" event if necessary.
@param i the index of the sensor
@param j the index of the target
*/
public void doInitTarget(int i, int j) {
targets.get(j).addSimEventListener(this);
if (j < targets.size() - 1) {
waitDelay("InitTarget", 0.0, i, j + 1);
}
if (targets.get(j).getCurrentLocation().distance(sensors.get(i).getCurrentLocation()) < sensors.get(i).getMaxRange()) {
if (!targets.get(j).equals(sensors.get(i).getMover())) {
waitDelay("EnterRange", 0.0, targets.get(j), sensors.get(i));
}
}
}
/**
Updates a sensor with a target. Checks if the sensor and target are different and calculates
the enter and exit times. Handles different cases based on the number of times calculated.
If there are more sensors to update, it waits for the "UpdateSensor" event for the next index.
@param i the index of the sensor
@param target the target to update the sensor with
*/
public void doUpdateSensor(int i, Mover target) {
Sensor sensor = sensors.get(i);
if (!sensor.equals(target)) {
double[] times = getEnterExitTimes(target, sensor);
switch (times.length) {
case 0 -> {
}
case 1 -> {
interrupt("ExitRange", target, sensor);
waitDelay("ExitRange", times[0], target, sensor);
}
case 2 -> {
interrupt("EnterRange", target, sensor);
waitDelay("EnterRange", times[0], target, sensor);
}
}
}
if (i < sensors.size() - 1) {
waitDelay("UpdateSensor", 0.0, i + 1, target);
}
}
/**
* Notifies the referee that a target is starting to move. Initiates the "UpdateSensor" event
* with zero delay for the specified target.
*
* @param target the target that is starting to move
*/
public void doStartMove(Mover target) {
waitDelay("UpdateSensor", 0.0, 0, target);
}
/**
* Notifies the referee that a target has stopped. Initiates the "UpdateSensor" event
* with zero delay for the specified target.
*
* @param target the target that has stopped
*/
public void doStop(Mover target) {
waitDelay("UpdateSensor", 0.0, 0, target);
}
/**
* Updates a target with a sensor. Checks if the target and sensor are different and calculates
* the enter and exit times. Handles different cases based on the number of times calculated.
* If there are more targets to update, it waits for the "UpdateTarget" event for the next index.
*
* @param i the index of the target
* @param sensor the sensor to update the target with
*/
public void doUpdateTarget(int i, Sensor sensor) {
Mover target = targets.get(i);
double[] times = getEnterExitTimes(target, sensor);
switch (times.length) {
case 0 -> {
}
case 1 -> {
interrupt("ExitRange", target, sensor);
waitDelay("ExitRange", times[0], target, sensor);
}
case 2 -> {
interrupt("EnterRange", target, sensor);
waitDelay("EnterRange", times[0], target, sensor);
}
}
if (i < targets.size() - 1) {
waitDelay("UpdateTarget", i + 1, sensor);
}
}
/**
* Notifies the referee that a sensor is starting to move. Initiates the "UpdateTarget" event
* with zero delay for the specified sensor.
*
* @param sensor the sensor that is starting to move
*/
public void doStartMove(Sensor sensor) {
waitDelay("UpdateTarget", 0.0, 0, sensor);
}
/**
* Notifies the referee that a sensor has stopped. Initiates the "UpdateTarget" event
* with zero delay for the specified sensor.
*
* @param sensor the sensor that has stopped
*/
public void doStop(Sensor sensor) {
waitDelay("UpdateTarget", 0.0, 0, sensor);
}
/**
* Performs the actions when a target enters the range of a sensor. Calculates the enter and exit times
* and waits for the "ExitRange" event if necessary.
*
* @param target the target that entered the range
* @param sensor the sensor that detected the target
*/
public void doEnterRange(Mover target, Sensor sensor) {
double[] times = getEnterExitTimes(target, sensor);
if (times.length == 1) {
waitDelay("ExitRange", times[0], target, sensor);
} else if (times.length == 2) {
waitDelay("ExitRange", times[1], target, sensor);
}
}
/**
* Performs the actions when a target exits the range of a sensor.
*
* @param target the target that exited the range
* @param sensor the sensor that lost track of the target
*/
public void doExitRange(Mover target, Sensor sensor) {
}
/**
* Calculates the enter and exit times for a target and a sensor based on their relative locations
* and velocities. Returns an array of the calculated times.
*
* @param target the target to calculate times for
* @param sensor the sensor to calculate times for
* @return an array of the enter and exit times, or an empty array if no times were calculated
*/
private double[] getEnterExitTimes(Mover target, Sensor sensor) {
double[] times;
Point2D relativeLocation = new Point2D.Double(
target.getCurrentLocation().getX() - sensor.getCurrentLocation().getX(),
target.getCurrentLocation().getY() - sensor.getCurrentLocation().getY()
);
Point2D relativeVelocity = new Point2D.Double(
target.getVelocity().getX() - sensor.getVelocity().getX(),
target.getVelocity().getY() - sensor.getVelocity().getY()
);
double velocitySquared = relativeVelocity.distanceSq(ZERO);
double distanceSqured = relativeLocation.distanceSq(ZERO);
double innerProduct = relativeLocation.getX() * relativeVelocity.getX()
+ relativeLocation.getY() * relativeVelocity.getY();
double determinant = velocitySquared * (sensor.getMaxRange() * sensor.getMaxRange()
- distanceSqured) + innerProduct * innerProduct;
if (determinant < 0.0) {
times = new double[0];
} else {
double first = -innerProduct / velocitySquared;
double smallerRoot = first - sqrt(determinant) / velocitySquared;
double biggerRoot = first + sqrt(determinant) / velocitySquared;
if (smallerRoot > 0.0) {
times = new double[]{smallerRoot, biggerRoot};
} else if (biggerRoot > 0) {
times = new double[]{biggerRoot};
} else {
times = new double[0];
}
}
return times;
}
/**
* Returns a new list containing the sensors in the simulation.
* @return a list of sensors
*/
public List<Sensor> getSensors() {
return new ArrayList<>(sensors);
}
/**
* Sets the list of sensors for the simulation.
*
* @param sensors the list of sensors to set
*/
public void setSensors(List<Sensor> sensors) {
this.sensors = new ArrayList<>(sensors);
}
/**
* Returns a new list containing the targets in the simulation.
*
* @return a list of targets
*/
public List<Mover> getTargets() {
return new ArrayList<>(targets);
}
/**
* Sets the list of targets for the simulation.
*
* @param targets the list of targets to set
*/
public void setTargets(List<Mover> targets) {
this.targets = new ArrayList<>(targets);
}
}
\ No newline at end of file
package mv3302;
import simkit.Priority;
import simkit.SimEntityBase;
import simkit.random.RandomVariate;
/**
* Class that simulates a simple server by extending SimEntityBase
*
* @author dansl
*/
public class SimpleServer extends SimEntityBase {
// Instance variables to hold the changing states during the simulation
protected int numberInQueue;
protected int numberAvailableServers;
protected int numberServed;
// Instance variables that hold the build settings of the simulation
private int totalNumberServers;
private RandomVariate serviceTimeGenerator;
/**
* Constructor method for the SimpleServer class; initializes the number of
* servers and service times for the simulation
*
* @param numberServers
* @param serviceTime
*/
public SimpleServer(int numberServers, RandomVariate serviceTime) {
totalNumberServers = numberServers;
serviceTimeGenerator = serviceTime;
}
/**
* Getter method for number of customers in the queue
*
* @return the numberInQueue
*/
public int getNumberInQueue() {
return numberInQueue;
}
/**
* Getter method for the number of servers available in the simulation
*
* @return the numberAvailableServers
*/
public int getNumberAvailableServers() {
return numberAvailableServers;
}
/**
* Getter method returns the total number of customers complete through the
* processing process
*
* @return the numberServed
*/
public int getNumberServed() {
return numberServed;
}
/**
* Getter method that returns the total number of servers in the simulation
*
* @return the totalNumberServers
*/
public int getTotalNumberServers() {
return totalNumberServers;
}
/**
* Setter method sets the total number of servers the simulation will use
*
* @param totalNumberServers
* @throws IllegalArgumentException if totalNumberServers <= 0 @ param
* totalNumberServers the totalNumberServers
*/
public void setTotalNumberServers(int totalNumberServers) {
if (totalNumberServers <= 0) {
throw new IllegalArgumentException("totalNumberServers must be > 0: "
+ totalNumberServers);
}
this.totalNumberServers = totalNumberServers;
}
/**
* Getter method that returns a service time value
*
* @return the serviceTimeGenerator
*/
public RandomVariate getServiceTimeGenerator() {
return serviceTimeGenerator;
}
/**
* setter method that sets a service time value
*
* @param serviceTimeGenerator the serviceTimeGenerator to set
*/
public void setServiceTimeGenerator(RandomVariate serviceTimeGenerator) {
this.serviceTimeGenerator = serviceTimeGenerator;
}
/**
* Reset method that returns the simulation to it's original state
*/
@Override
public void reset() {
super.reset();
numberInQueue = 0;
numberAvailableServers = totalNumberServers;
numberServed = 0;
}
/**
* Run method fires the state changes to update the listeners
*/
public void doRun() {
firePropertyChange("numberInQueue", getNumberInQueue());
firePropertyChange("numberAvailableServers", getNumberAvailableServers());
firePropertyChange("numberServed", getNumberServed());
}
/**
* Creates an arrival event, alters the total number of arrivals and
* schedules the next event
*/
public void doArrival() {
int oldNumberInQueue = getNumberInQueue();
numberInQueue = numberInQueue + 1;
firePropertyChange("numberInQueue", oldNumberInQueue, getNumberInQueue());
if (getNumberAvailableServers() > 0) {
waitDelay("StartService", 0.0, Priority.HIGH);
}
}
/**
* Method decreases the number of customers waiting in the queue and the
* number of available servers. Method then fires those changes for the
* listeners then schedules the EndService
*/
public void doStartService() {
int oldNumberInQueue = getNumberInQueue();
int oldNumberAvailableServers = getNumberAvailableServers();
numberAvailableServers = numberAvailableServers - 1;
numberInQueue = numberInQueue - 1;
firePropertyChange("numberInQueue", oldNumberInQueue, getNumberInQueue());
firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
waitDelay("EndService", getServiceTimeGenerator());
}
/**
* Method increases the number of customers that have been served and the
* number of available servers. Method then fires those changes for the
* listeners and schedules the StartService as long as the queue is greater
* than one.
*/
public void doEndService() {
int oldNumberAvailableServers = getNumberAvailableServers();
numberAvailableServers = numberAvailableServers + 1;
int oldNumberServed = getNumberServed();
numberServed = numberServed + 1;
firePropertyChange("numberAvailableServers", oldNumberAvailableServers, getNumberAvailableServers());
firePropertyChange("numberServed", oldNumberServed, getNumberServed());
if (getNumberInQueue() > 0) {
waitDelay("StartService", 0.0, Priority.HIGH);
}
}
}
package mv3302;
import java.awt.geom.Point2D;
import static java.lang.Double.NaN;
import simkit.Schedule;
import simkit.SimEntityBase;
/**
*
* @author ahbuss
*/
public class SimplestMover extends SimEntityBase {
public static final Point2D NaP = new Point2D.Double(NaN, NaN);
private Point2D initialLocation;
private double maxSpeed;
protected Point2D lastStopLocation;
protected Point2D velocity;
protected Point2D destination;
protected double startMoveTime;
public SimplestMover() {
lastStopLocation = (Point2D) NaP.clone();
velocity = (Point2D) NaP.clone();
destination = (Point2D) NaP.clone();
}
public SimplestMover(Point2D initialLocation, double maxSpeed) {
this();
setInitialLocation(initialLocation);
setMaxSpeed(maxSpeed);
}
@Override
public void reset() {
super.reset();
lastStopLocation.setLocation(initialLocation);
velocity.setLocation(0.0, 0.0);
destination.setLocation(NaP);
startMoveTime = 0.0;
}
public void doRun() {
firePropertyChange("lastStopLocation", getLastStopLocation());
firePropertyChange("velocity", getVelocity());
firePropertyChange("destination", getDestination());
firePropertyChange("startMoveTime", getStartMoveTime());
}
public void doMoveTo(Point2D newDestination) {
Point2D oldDestination = getDestination();
this.destination.setLocation(newDestination);
firePropertyChange("destination", oldDestination, getDestination());
if (lastStopLocation.distance(destination) > 0.0) {
waitDelay("StartMove", 0.0);
}
}
public void doStartMove() {
double oldStartMoveTime = getStartMoveTime();
startMoveTime = Schedule.getSimTime();
firePropertyChange("startMoveTime", oldStartMoveTime, getStartMoveTime());
double distance = lastStopLocation.distance(destination);
double a = getMaxSpeed() / distance;
Point2D oldVelocity = getVelocity();
velocity.setLocation(destination.getX() - lastStopLocation.getX(), destination.getY() - lastStopLocation.getY());
velocity.setLocation(a * velocity.getX(), a * velocity.getY());
firePropertyChange("velocity", oldVelocity, getVelocity());
waitDelay("EndMove", 1.0 / a);
}
public void doEndMove() {
double oldStartMoveTime = getStartMoveTime();
startMoveTime = Schedule.getSimTime();
firePropertyChange("startMoveTime", oldStartMoveTime, getStartMoveTime());
Point2D oldLastStopLocation = getLastStopLocation();
lastStopLocation.setLocation(destination);
firePropertyChange("lastStopLocation", oldLastStopLocation, getLastStopLocation());
Point2D oldVelocity = getVelocity();
velocity.setLocation(0.0, 0.0);
firePropertyChange("velocity", oldVelocity, getVelocity());
}
/**
* @return the initialLocation
*/
public Point2D getInitialLocation() {
return (Point2D) initialLocation.clone();
}
/**
* @param initialLocation the initialLocation to set
*/
public void setInitialLocation(Point2D initialLocation) {
this.initialLocation = (Point2D) initialLocation.clone();
}
/**
* @return the maxSpeed
*/
public double getMaxSpeed() {
return maxSpeed;
}
/**
* @param maxSpeed the maxSpeed to set
*/
public void setMaxSpeed(double maxSpeed) {
if (maxSpeed < 0.0) {
throw new IllegalArgumentException("maxSpeed must be >= 0.0: " + maxSpeed);
}
this.maxSpeed = maxSpeed;
}
/**
* @return the lastStopLocation
*/
public Point2D getLastStopLocation() {
return (Point2D) lastStopLocation.clone();
}
/**
* @return the velocity
*/
public Point2D getVelocity() {
return (Point2D) velocity.clone();
}
/**
* @return the destination
*/
public Point2D getDestination() {
return (Point2D) destination.clone();
}
/**
* @return the startMoveTime
*/
public double getStartMoveTime() {
return startMoveTime;
}
public Point2D getCurrentLocation() {
double elapsedTime = Schedule.getSimTime() - getStartMoveTime();
return new Point2D.Double(lastStopLocation.getX() + elapsedTime * velocity.getX() ,
lastStopLocation.getY() + elapsedTime * velocity.getY());
}
@Override
public String toString() {
return String.format("%s %s", getName(), getCurrentLocation());
}
public String paramString() {
return super.toString();
}
}
package mv3302;
/**
* The StoppedPartArrivalProcess class extends the PartArrivalProcess class and
* represents a process that stops the arrival of parts for a specified
* duration. It overrides the doRun() method to wait for a specified stop time
* before resuming the arrival of parts. It also provides methods to schedule
* the next arrival and get/set the stop time.
*
* @author dansl
*/
public final class StoppedPartArrivalProcess extends PartArrivalProcess {
private int stopTime;
/**
* Zero-argument constructor
*/
public StoppedPartArrivalProcess() {
super();
}
/**
* Constructs a StoppedPartArrivalProcess object with the given stop time.
*
* @param stopTime The duration for which the arrival of parts should be
* stopped.
*/
public StoppedPartArrivalProcess(int stopTime) {
this.stopTime = stopTime;
}
/**
* Overrides the doRun() method from the parent class. Pauses the arrival of
* parts for the specified stop time.
*/
@Override
public void doRun() {
waitDelay("StopArrivals", getStopTime());
}
/**
* Schedule the next arrival after stopping. This method schedules the
* Arrival(index) process.
*/
public void doStopArrivals() {
interrupt("Arrival");
}
/**
* @return the stopTime
*/
public int getStopTime() {
return stopTime;
}
/**
* @param stopTime the stopTime to set
*/
public void setStopTime(int stopTime) {
this.stopTime = stopTime;
}
}
package mv3302;
import simkit.*;
import java.util.*;
import simkit.random.RandomVariate;
public class TransferLineComponent extends SimEntityBase {
private int[] totalNumberMachines;
private RandomVariate[] processingTimeGenerator;
protected int[] numberAvailableMachines;
protected List<SortedSet<Part>> queue;
protected double[] delayInQueue;
protected double[] timeAtStation;
protected double totalDelayInQueue;
protected double totalTimeInSystem;
protected int numberComplete;
/**
* Constructor method for TransferLineComponent that passes in Array values
* of processingTimeGenerator and totalNumberMachines as sets them
* accordingly. Sets the values of numberAvailableMachines to
* totalNumberMachines. Sets the length of the delayInQueue and
* timeAtStation arrays to the length of totalNumberMachines. Instantiates
* the value of the queue to an empty array with elements as treesets the
* length of elements in totalNumberMachines
*
* @param processingTimeGenerator
* @param totalNumberMachines
*/
public TransferLineComponent(RandomVariate[] processingTimeGenerator, int[] totalNumberMachines) {
this();
this.setProcessingTimeGenerator(processingTimeGenerator);
this.setTotalNumberMachines(totalNumberMachines);
numberAvailableMachines = totalNumberMachines.clone();
delayInQueue = new double[totalNumberMachines.length];
timeAtStation = new double[totalNumberMachines.length];
queue = new ArrayList<>();
for (int station = 0; station < totalNumberMachines.length; ++station) {
queue.add(new TreeSet<>());
}
}
/**
* Zero Argument constructor method that makes a call to it's super.
*
*/
public TransferLineComponent() {
super();
}
/**
* Reset method resets all values to their base before the start of the next
* machine run. resets the numberOfAvailable machines back to the same
* property as the totalNumberMachines. Also resets the values contained
* within the delayInQueue and timeAtStation array back to the default NaN
* value. Clears the contents of the queue.
*/
@Override
public void reset() {
super.reset();
numberAvailableMachines = getTotalNumberMachines().clone();
Arrays.fill(delayInQueue, Double.NaN);
Arrays.fill(timeAtStation, Double.NaN);
}
/**
* Do run method instantiates the total delay in queue and time in system
* variables to NaN value. Fires Property changes for total delay in queue,
* total delay in system and number of available machines. Schedules next
* Init Event.
*/
public void doRun() {
totalDelayInQueue = Double.NaN;
totalTimeInSystem = Double.NaN;
// firePropertyChange("totalDelayInQueue", getTotalDelayInQueue());
// firePropertyChange("totalDelayInSystem", getTotalTimeInSystem());
// firePropertyChange("numberAvailableMachines", getNumberAvailableMachines());
waitDelay("Init", 0.0, 0);
}
/**
* Init method starts with 0 as the parameter and aligns the indexes for the
* number available machines to the indexes of totalNumberMachines.Fires the
* necessary index property changes. Calls the queue array for the element
* at index i and clears that element. It then sets the values of the
* delayInQueue and timeAtStation array elements back to NaN. It then
* schedules another Init event as long as the i argument is less than the
* totalNumberOfMachines length minus one to account for the off by one 0
* index.
*
* @param i
*/
public void doInit(int i) {
this.numberAvailableMachines[i] = totalNumberMachines[i];
// fireIndexedPropertyChange(i, "numberAvailableMachines", getNumberAvailableMachines(i));
queue.get(i).clear();
// fireIndexedPropertyChange(i, "queue", getQueue(i));
// double[] oldDelayInQueue = getDelayInQueue().clone();
delayInQueue[i] = Double.NaN;
// firePropertyChange("delayInQueue", oldDelayInQueue, getDelayInQueue());
// double[] oldTimeAtStation = getTimeAtStation().clone();
timeAtStation[i] = Double.NaN;
// firePropertyChange("timeAtStation", oldTimeAtStation, getTimeAtStation());
if (i < totalNumberMachines.length - 1) {
waitDelay("Init", 0.0, i + 1);
}
}
/**
* doArrival() method takes in arguments Part Part, and int station.The
* method takes a time stamp on the part, Method then takes the queue at the
* station i and adds the part value to it. Fires changes to the listener
* then schedules the startProcessing event if numberAvailableMachines is
* greater than 0.
*
* @param part
* @param station
*/
public void doArrival(Part part, int station) {
part.stampTime();
SortedSet<Part> oldQueue = getQueue(station);
queue.get(station).add(part);
fireIndexedPropertyChange(station, "queue", oldQueue, getQueue(station));
if (numberAvailableMachines[station] > 0) {
waitDelay("StartProcessing", 0.0, station);
}
}
/**
* doStartProcessing method takes the part at station and removes it from
* the queue, The number of available machines at station are reduced by
* one. the delay in queue array value at station is set to the part elapsed
* time. The part delay in queue is then incremented
*
* @param station
*/
public void doStartProcessing(int station) {
SortedSet<Part> oldQueue = queue.get(station);
Part part = oldQueue.first();
queue.get(station).remove(part);
//fireIndexedPropertyChange(station, "queue", oldQueue, getQueue(station));
int[] oldNumberAvailableMachines = getNumberAvailableMachines().clone();
numberAvailableMachines[station]--;
fireIndexedPropertyChange(station, "numberAvailableMachines", oldNumberAvailableMachines[station], getNumberAvailableMachines()[station]);
double[] oldDelayInQueue = getDelayInQueue();
delayInQueue[station] = part.getElapsedTime();
fireIndexedPropertyChange(station, "delayInQueue", oldDelayInQueue[station], delayInQueue[station]);
part.incrementDelayInQueue(delayInQueue[station]);
waitDelay("EndProcessing", getProcessingTimeGenerator()[station].generate(), part, station);
}
/**
* doEndProcessing() method takes in arguments for part and i. Takes
* numberAvailableMachines at element i and increases it by one. Also
* assigns timeAtStation to the elapsed time variable of the current part.
* Finally determines the path for scheduling based on the preferred
* conditions.
*/
public void doEndProcessing(Part part, int station) {
int[] oldNumberAvailableMachines = getNumberAvailableMachines().clone();
numberAvailableMachines[station]++;
fireIndexedPropertyChange(station, "numberAvailableMachines", oldNumberAvailableMachines[station], getNumberAvailableMachines()[station]);
double[] oldTimeAtStation = getTimeAtStation().clone();
timeAtStation[station] = part.getElapsedTime();
fireIndexedPropertyChange(station, "timeAtStation", oldTimeAtStation[station], getTimeAtStation(station));
if (station < totalNumberMachines.length - 1) {
waitDelay("Arrival", 0.0, part, station + 1);
}
if (station == totalNumberMachines.length - 1) {
waitDelay("PartComplete", 0.0, part);
}
if (!queue.get(station).isEmpty()) {
waitDelay("StartProcessing", 0.0, station);
}
}
/**
* doPartComplete brings in argument part and assigns the value of
* totalTimeInSystem to the parts getAge() value. It also assigns the
* totalDelayInQueue variable to the part's totalDelay(). Increments the
* number of completed parts by one.
*/
public void doPartComplete(Part part) {
double oldTotalTimeInSystem = totalTimeInSystem;
totalTimeInSystem = part.getAge();
firePropertyChange("totalTimeInSystem", oldTotalTimeInSystem, getTotalTimeInSystem());
double oldTotalDelayInQueue = totalDelayInQueue;
totalDelayInQueue = part.getTotalDelayInQueue();
firePropertyChange("totalDelayInQueue", oldTotalDelayInQueue, getTotalDelayInQueue());
}
/**
* @return the totalNumberMachines
*/
public int[] getTotalNumberMachines() {
return totalNumberMachines.clone();
}
/**
* @param station
* @return the totalNumberMachines @ station
*/
public int getTotalNumberMachines(int station) {
return totalNumberMachines[station];
}
/**
* @return the processingTimeGenerator
*/
public RandomVariate[] getProcessingTimeGenerator() {
return processingTimeGenerator.clone();
}
/**
* @return the processingTimeGenerator @ station
*/
public RandomVariate getProcessingTimeGenerator(int station) {
return processingTimeGenerator[station];
}
/**
* @return the numberAvailableMachines
*/
public int[] getNumberAvailableMachines() {
return numberAvailableMachines.clone();
}
/**
* @param station
* @return the numberAvailableMachines @ station
*/
public int getNumberAvailableMachines(int station) {
return numberAvailableMachines[station];
}
/**
* @param station
* @return the queue @ station
*/
public SortedSet<Part> getQueue(int station) {
return new TreeSet<>(queue.get(station));
}
/**
* @return the queue
*/
public List<SortedSet<Part>> getQueue() {
List<SortedSet<Part>> queueListCopy = new ArrayList<>();
for (int station = 0; station < queue.size(); ++station) {
queueListCopy.add(getQueue(station));
}
return queueListCopy;
}
/**
* @return the delayInQueue
*/
public double[] getDelayInQueue() {
return delayInQueue.clone();
}
/**
* @param station
* @return the delayInQueue @ station
*/
public double getDelayInQueue(int station) {
return delayInQueue[station];
}
/**
* @return the timeAtStation
*/
public double[] getTimeAtStation() {
return timeAtStation.clone();
}
/**
* @param station
* @return the timeAtStation @ station
*/
public double getTimeAtStation(int station) {
return timeAtStation[station];
}
/**
* @return the totalDelayInQueue
*/
public double getTotalDelayInQueue() {
return totalDelayInQueue;
}
/**
* @return the totalTimeInSystem
*/
public double getTotalTimeInSystem() {
return totalTimeInSystem;
}
/**
* sets TotalNumberMachines variable
*
* @param totalNumberMachines
*/
public void setTotalNumberMachines(int[] totalNumberMachines) {
this.totalNumberMachines = totalNumberMachines;
}
/**
* sets processingTimeGenerator variable
*
* @param processingTimeGenerator
*/
public void setProcessingTimeGenerator(RandomVariate[] processingTimeGenerator) {
this.processingTimeGenerator = processingTimeGenerator;
}
/**
* @return the numberComplete
*/
public int getNumberComplete() {
return numberComplete;
}
}
package mv3302;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import simkit.stat.SimpleStatsTally;
/**
*
* @author dansl
*/
public class TransientStats implements PropertyChangeListener {
private final String state;
protected List<SimpleStatsTally> data;
protected int nextObs;
public TransientStats(String state) {
this.state = state;
data = new ArrayList<>();
nextObs = 0;
}
public void reset() {
nextObs = 0;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!evt.getPropertyName().equals(state)) {
return;
}
if (nextObs >= getRawData().size()) {
data.add(new SimpleStatsTally("Data " + nextObs));
}
if (evt.getNewValue() instanceof Number) {
data.get(nextObs).newObservation(((Number)evt.getNewValue()).doubleValue());
}
nextObs += 1;
}
/**
* @return the data
*/
public List<SimpleStatsTally> getRawData() {
return new ArrayList<>(data);
}
}
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package mv3302;
import static java.lang.Double.NaN;
import java.util.SortedSet;
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 {
protected SortedSet<Ship> queue;
protected SortedSet<Ship> berths;
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();
delayInQueue = NaN;
timeInSystem = NaN;
}
/**
* Clears the queue and the berths, sets the delay and time in system to
* NaN.
*/
public void doRun() {
queue.clear();
berths.clear();
delayInQueue = NaN;
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();
queue.add(ship);
firePropertyChange("queue", oldQueue, getQueue());
if (berths.size() == 1) {
waitDelay("SwitchTo1Crane", 0.0);
}
if (berths.isEmpty()) {
waitDelay("StartUnload2Cranes", 0.0);
}
}
/**
* 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();
interrupt("EndUnload2Cranes");
waitDelay("StartUnload1Crane", 0.0);
waitDelay("EndUnload1Crane", ship.getRemainingUnloadingTime(), ship);
}
/**
* 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);
firePropertyChange("queue", oldQueue, getQueue());
double oldDelayInQueue = getDelayInQueue();
delayInQueue = ship.getElapsedTime();
firePropertyChange("delayInQueue", oldDelayInQueue, getDelayInQueue());
ship.stampTime();
SortedSet<Ship> oldBerths = getBerths();
berths.add(ship);
firePropertyChange("berths", oldBerths, getBerths());
waitDelay("EndUnload1Crane", ship.getRemainingUnloadingTime(), ship);
}
/**
* 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);
firePropertyChange("queue", oldQueue, getQueue());
double oldDelayInQueue = getDelayInQueue();
delayInQueue = ship.getElapsedTime();
firePropertyChange("delayInQueue", oldDelayInQueue, getDelayInQueue());
ship.stampTime();
SortedSet<Ship> oldBerths = getBerths();
berths.add(ship);
firePropertyChange("berths", oldBerths, getBerths());
waitDelay("EndUnload2Cranes", ship.getRemainingUnloadingTime() / 2);
}
/**
* 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()) {
waitDelay("StartUnload1Crane", 0.0);
}
if (queue.isEmpty()) {
waitDelay("SwitchTo2Cranes", 0.0);
}
}
/**
* 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);
firePropertyChange("berths", oldBerths, getBerths());
double oldTimeInSystem = getTimeInSystem();
timeInSystem = ship.getAge();
firePropertyChange("timeInSystem", oldTimeInSystem, getTimeInSystem());
}
/**
* 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);
interrupt("EndUnload1Crane", ship);
}
/**
* @return the queue
*/
public SortedSet<Ship> getQueue() {
return queue;
}
/**
* @return the berths
*/
public SortedSet<Ship> getBerths() {
return berths;
}
/**
* @return the delayInQueue
*/
public double getDelayInQueue() {
double delayInQueueCopy = delayInQueue;
return delayInQueueCopy;
}
/**
* @return the timeInSystem
*/
public double getTimeInSystem() {
double timeInSystemCopy = timeInSystem;
return timeInSystemCopy;
}
}