package nl.tudelft.simulation.examples.dsol.terminal; import java.io.Serializable; import org.djutils.event.EventInterface; import org.djutils.event.EventListenerInterface; import org.djutils.event.EventType; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.model.AbstractDSOLModel; import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException; import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterInteger; import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap; import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface; import nl.tudelft.simulation.jstats.distributions.DistExponential; import nl.tudelft.simulation.jstats.distributions.DistTriangular; import nl.tudelft.simulation.jstats.streams.StreamInterface; /** * A simple model of a container terminal.
* (c) copyright 2018 Delft University of Technology , the Netherlands.
* See for project information www.simulation.tudelft.nl
* License of use: General Public License (GPL) , no warranty
* @author Alexander Verbraeck */ public class Terminal extends AbstractDSOLModel.TimeDouble implements EventListenerInterface { /** The default serial version UID for serializable classes. */ private static final long serialVersionUID = 1L; /** the ship-full event. */ public static final EventType READY_EVENT = new EventType("READY_EVENT"); /** QCs. */ private int numQC = 5; /** AGVs. */ private int numAGV = 25; /** replication nr. */ private final int rep; /** debug info or not. */ public static final boolean DEBUG = false; /** the ship for pub/sub when ready. */ private Ship ship; /** * constructor for the Container Terminal. * @param simulator DEVSSimulatorInterface.TimeDouble; the simulator * @param rep int; the replication number * @throws InputParameterException on input parameter error */ public Terminal(final DEVSSimulatorInterface.TimeDouble simulator, final int rep) throws InputParameterException { super(simulator); this.rep = rep; this.inputParameterMap.add(new InputParameterInteger("numQC", "Number of QCs", "Number of Quay Cranes (QCs)", 10, 1.0)); this.inputParameterMap.add( new InputParameterInteger("numAGV", "Number of AGVs", "Number of Automated Quided Vehicles (AGVs)", 20, 2.0)); } /** {@inheritDoc} */ @Override public final void constructModel() throws SimRuntimeException { StreamInterface defaultStream = this.simulator.getReplication().getStream("default"); try { InputParameterMap parameters = this.simulator.getReplication().getTreatment().getInputParameterMap(); this.numQC = (Integer) parameters.get("numQC").getCalculatedValue(); this.numAGV = (Integer) parameters.get("numAGV").getCalculatedValue(); } catch (InputParameterException ipe) { throw new SimRuntimeException(ipe); } int numCont = 3000; QC qc = new QC(this.simulator, "QC", this.numQC, new DistExponential(defaultStream, 60. / 30.)); AGV agv = new AGV(this.simulator, "AGV", this.numAGV, new DistTriangular(defaultStream, 7, 9, 14)); this.ship = new Ship(numCont); this.ship.addListener(this, Ship.SHIP_FULL_EVENT); for (int c = 0; c < numCont; c++) { new Container(this.simulator, c, qc, agv, this.ship); } } /** * @return the ship for pub/sub */ public Ship getShip() { return this.ship; } /** {@inheritDoc} */ @Override public void notify(final EventInterface event) { if (event.getType().equals(Ship.SHIP_FULL_EVENT)) { try { this.simulator.stop(); double ready = this.simulator.getSimulatorTime() / 60.0; double delayHours = Math.max(0.0, Math.ceil(ready) - 20.0); if (DEBUG) { System.out.println("Delay = " + delayHours); } double costs = Math.max(20.0, Math.ceil(ready)) * (300.0 * this.numQC + 12.0 * this.numAGV) + 2500.0 * delayHours; if (DEBUG) { System.out.println("Costs = " + costs); } int nrCont = (Integer) event.getContent(); fireEvent(Terminal.READY_EVENT, new Output(this.numQC, this.numAGV, this.rep, delayHours, costs, ready, nrCont)); } catch (SimRuntimeException exception) { getSimulator().getLogger().always().error(exception); } } } /** {@inheritDoc} */ @Override public Serializable getSourceId() { return "Terminal"; } /** */ public static class Output implements Serializable { /** */ private static final long serialVersionUID = 1L; /** QCs. */ private final int numQC; /** AGVs. */ private final int numAGV; /** replication nr. */ private final int rep; /** delay. */ private final double delayHours; /** costs. */ private final double costs; /** time when ready in hrs. */ private final double ready; /** nr containers handled. */ private final int nrCont; /** * /** * @param numQC int; qc * @param numAGV int; agv * @param rep int; replication nr * @param delayHours double; delay in hours * @param costs double; costs in Euros * @param ready double; time when ready in hrs * @param nrCont int; nr containers handled */ public Output(final int numQC, final int numAGV, final int rep, final double delayHours, final double costs, final double ready, final int nrCont) { super(); this.numQC = numQC; this.numAGV = numAGV; this.rep = rep; this.delayHours = delayHours; this.costs = costs; this.ready = ready; this.nrCont = nrCont; } /** * @return numQC */ public final int getNumQC() { return this.numQC; } /** * @return numAGV */ public final int getNumAGV() { return this.numAGV; } /** * @return rep */ public final int getRep() { return this.rep; } /** * @return delayHours */ public final double getDelayHours() { return this.delayHours; } /** * @return costs */ public final double getCosts() { return this.costs; } /** * @return ready */ public final double getReady() { return this.ready; } /** * @return nrCont */ public final int getNrCont() { return this.nrCont; } } }