Create.java
package nl.tudelft.simulation.dsol.formalisms.flow;
import org.djutils.event.EventType;
import org.djutils.exceptions.Throw;
import org.djutils.metadata.MetaData;
import org.djutils.metadata.ObjectDescriptor;
import nl.tudelft.simulation.dsol.SimRuntimeException;
import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEvent;
import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEventInterface;
import nl.tudelft.simulation.dsol.simtime.SimTime;
import nl.tudelft.simulation.dsol.simtime.dist.DistContinuousSimulationTime;
import nl.tudelft.simulation.dsol.simulators.DevsSimulatorInterface;
import nl.tudelft.simulation.jstats.distributions.DistDiscrete;
import nl.tudelft.simulation.jstats.distributions.DistDiscreteConstant;
/**
* The Create flow object generates entities with a certain inter-arrival time. The class is abstract because the modeller has
* to provide the generateEntity method that generates an entity with the correct id and attributes.
* <p>
* Copyright (c) 2002-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
* project is distributed under a three-clause BSD-style license, which can be found at
* <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">
* https://https://simulation.tudelft.nl/dsol/docs/latest/license.html</a>.
* </p>
* @author <a href="https://www.linkedin.com/in/peterhmjacobs">Peter Jacobs </a>
* @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
* @param <T> the time type
*/
public abstract class Create<T extends Number & Comparable<T>> extends FlowObject<T>
{
/** */
public static final long serialVersionUID = 20140805L;
/** CREATE_EVENT is fired on creation. */
public static final EventType CREATE_EVENT = new EventType(new MetaData("CREATE_EVENT", "Created entities)",
new ObjectDescriptor("numberCreated", "number of entities created", Integer.class)));
/** the inter-arrival time distribution. */
private DistContinuousSimulationTime<T> interval;
/** the start time distribution for the generator. */
private final DistContinuousSimulationTime<T> startTime;
/** the distribution of the number of objects generated at each generation event. */
private final DistDiscrete batchSize;
/** the maximum number of creation events. */
private long maxNumberCreationEvents = Long.MAX_VALUE;
/** the maximum number of generated entities. */
private long maxNumberGeneratedEntities = Long.MAX_VALUE;
/** the end time for the generator; when null, there is no end time. */
private T endTime = null;
/** the number of creation events; note: not the number of generated entities. */
private long numberCreationEvents = 0;
/** the number of generated entities. */
private long numberGeneratedEntities = 0;
/** the next construction event. */
private SimEventInterface<T> nextEvent = null;
/**
* Construct a new generator for objects in a simulation. Constructed objects are sent to the 'destination' of the Create
* flow object when a destination has been indicated with the setDestination method.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param interval DistContinuousSimulationTime<T>; the start time distribution for the generator
* @param startTime DistContinuousSimulationTime<T>; the inter-arrival time distribution
* @param batchSize DistDiscrete; the distribution of the number of objects generated at each generation event
*/
public Create(final String id, final DevsSimulatorInterface<T> simulator, final DistContinuousSimulationTime<T> interval,
final DistContinuousSimulationTime<T> startTime, final DistDiscrete batchSize)
{
super(id, simulator);
Throw.whenNull(startTime, "startTime cannot be null");
Throw.whenNull(interval, "interval cannot be null");
Throw.whenNull(batchSize, "batchSize cannot be null");
this.startTime = startTime;
this.interval = interval;
this.batchSize = batchSize;
this.nextEvent = getSimulator().scheduleEventAbs(this.startTime.draw(), this, "generate", null);
}
/**
* Construct a new generator for objects in a simulation. Constructed objects are sent to the 'destination' of the Create
* flow object when a destination has been indicated with the setDestination method.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param interval DistContinuousSimulationTime<T>; the start time distribution for the generator
* @param startTime DistContinuousSimulationTime<T>; the inter-arrival time distribution
* @param batchSize int; the number of objects generated at each generation event
*/
public Create(final String id, final DevsSimulatorInterface<T> simulator, final DistContinuousSimulationTime<T> interval,
final DistContinuousSimulationTime<T> startTime, final int batchSize)
{
this(id, simulator, interval, startTime, new DistDiscreteConstant(simulator.getModel().getDefaultStream(), batchSize));
}
/**
* Construct a new generator for objects in a simulation. Constructed objects are sent to the 'destination' of the Create
* flow object when a destination has been indicated with the setDestination method. This constructor has a maximum number
* of entities generated, which results in stopping the generator when the maximum number of entities has been reached.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param interval DistContinuousSimulationTime<T>; the start time distribution for the generator
* @param startTime DistContinuousSimulationTime<T>; the inter-arrival time distribution
*/
public Create(final String id, final DevsSimulatorInterface<T> simulator, final DistContinuousSimulationTime<T> interval,
final DistContinuousSimulationTime<T> startTime)
{
this(id, simulator, interval, startTime, 1);
}
/**
* Construct a new generator for objects in a simulation, but without the interval (to be set later, e.g., by the generator
* classes with a schedule). Constructed objects are sent to the 'destination' of the Create flow object when a
* destination has been indicated with the setDestination method. This constructor has a maximum number of entities
* generated, which results in stopping the generator when the maximum number of entities has been reached.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param batchSize DistDiscrete; the number of objects generated at each generation event
*/
protected Create(final String id, final DevsSimulatorInterface<T> simulator, final DistDiscrete batchSize)
{
super(id, simulator);
Throw.whenNull(batchSize, "batchSize cannot be null");
this.startTime = null;
this.batchSize = batchSize;
this.nextEvent = getSimulator().scheduleEventNow(this, "generate", null);
}
/**
* Construct a new generator for objects in a simulation, but without the interval (to be set later, e.g., by the generator
* classes with a schedule). Constructed objects are sent to the 'destination' of the Create flow object when a
* destination has been indicated with the setDestination method. This constructor has a maximum number of entities
* generated, which results in stopping the generator when the maximum number of entities has been reached.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param batchSize int; the number of objects generated at each generation event
*/
protected Create(final String id, final DevsSimulatorInterface<T> simulator, final int batchSize)
{
this(id, simulator, new DistDiscreteConstant(simulator.getModel().getDefaultStream(), batchSize));
}
/**
* Construct a new generator for objects in a simulation. Constructed objects are sent to the 'destination' of the Create
* flow object when a destination has been indicated with the setDestination method. This constructor has a maximum number
* of entities generated, which results in stopping the generator when the maximum number of entities has been reached.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param interval DistContinuousSimulationTime<T>; the start time distribution for the generator
* @param batchSize int; the number of objects generated at each generation event
*/
public Create(final String id, final DevsSimulatorInterface<T> simulator, final DistContinuousSimulationTime<T> interval,
final int batchSize)
{
this(id, simulator, batchSize);
Throw.whenNull(interval, "interval cannot be null");
this.interval = interval;
}
/**
* Construct a new generator for objects in a simulation. Constructed objects are sent to the 'destination' of the Create
* flow object when a destination has been indicated with the setDestination method. This constructor has a maximum number
* of entities generated, which results in stopping the generator when the maximum number of entities has been reached.
* @param id String; the id of the FlowObject
* @param simulator DevsSimulatorInterface<T>; is the on which the construction of the objects must be scheduled.
* @param interval DistContinuousSimulationTime<T>; the start time distribution for the generator
*/
public Create(final String id, final DevsSimulatorInterface<T> simulator, final DistContinuousSimulationTime<T> interval)
{
this(id, simulator, interval, 1);
}
/**
* Generate a new entity.
*/
protected synchronized void generate()
{
if (this.numberCreationEvents > this.maxNumberCreationEvents)
{
return;
}
this.numberCreationEvents++;
for (int i = 0; i < this.batchSize.draw(); i++)
{
Entity<T> entity = generateEntity();
this.fireTimedEvent(Create.CREATE_EVENT, 1, getSimulator().getSimulatorTime());
this.releaseEntity(entity);
this.numberGeneratedEntities++;
if (this.numberGeneratedEntities > this.maxNumberGeneratedEntities)
{
return;
}
}
this.nextEvent =
new SimEvent<T>(SimTime.plus(getSimulator().getSimulatorTime(), this.interval.draw()), this, "generate", null);
if (this.endTime != null && (this.nextEvent.getAbsoluteExecutionTime().doubleValue() > this.endTime.doubleValue()))
{
return;
}
getSimulator().scheduleEvent(this.nextEvent);
}
/**
* Generate a new entity. To be specified for the specific Generator.
* @return Entity<T>; the generated entity
*/
protected abstract Entity<T> generateEntity();
/** {@inheritDoc} */
@Override
public void receiveEntity(final Entity<T> entity)
{
throw new SimRuntimeException("Generator should not receive any entities");
}
/**
* Return the batch size distribution.
* @return DistDiscrete; the batch size distribution
*/
public DistDiscrete getBatchSize()
{
return this.batchSize;
}
/**
* Return the interarrival distribution.
* @return DistContinuousSimulationTime<T>; the interarrival distribution
*/
public DistContinuousSimulationTime<T> getInterval()
{
return this.interval;
}
/**
* Set a new interarrival distribution. This is used by, e.g., the GenerateSchedule classes that changes the arrival rate at
* set intervals.
* @param interval DistContinuousSimulationTime<T>; the new interarrival distribution
*/
public void setInterval(final DistContinuousSimulationTime<T> interval)
{
Throw.whenNull(interval, "interval cannot be null");
this.interval = interval;
if (this.nextEvent != null)
{
getSimulator().cancelEvent(this.nextEvent);
this.nextEvent = new SimEvent<T>(SimTime.plus(getSimulator().getSimulatorTime(), this.interval.draw()), this,
"generate", null);
if (this.endTime != null && (this.nextEvent.getAbsoluteExecutionTime().doubleValue() > this.endTime.doubleValue()))
{
return;
}
getSimulator().scheduleEvent(this.nextEvent);
}
}
/**
* Return the maximum number of entities to be created.
* @return long the maxNumber
*/
public long getMaxNumber()
{
return this.maxNumberCreationEvents;
}
/**
* sets the maximum number of entities to be created.
* @param maxNumber long; is the maxNumber
*/
public void setMaxNumber(final long maxNumber)
{
this.maxNumberCreationEvents = maxNumber;
}
/**
* returns the startTime of the generator.
* @return DistContinuous
*/
public DistContinuousSimulationTime<T> getStartTime()
{
return this.startTime;
}
/**
* @return maxNumberCreationEvents
*/
public long getMaxNumberCreationEvents()
{
return this.maxNumberCreationEvents;
}
/**
* @param maxNumberCreationEvents set maxNumberCreationEvents
*/
public void setMaxNumberCreationEvents(final long maxNumberCreationEvents)
{
this.maxNumberCreationEvents = maxNumberCreationEvents;
}
/**
* @return maxNumberGeneratedEntities
*/
public long getMaxNumberGeneratedEntities()
{
return this.maxNumberGeneratedEntities;
}
/**
* @param maxNumberGeneratedEntities set maxNumberGeneratedEntities
*/
public void setMaxNumberGeneratedEntities(final long maxNumberGeneratedEntities)
{
this.maxNumberGeneratedEntities = maxNumberGeneratedEntities;
}
/**
* @return endTime
*/
public T getEndTime()
{
return this.endTime;
}
/**
* @param endTime set endTime
*/
public void setEndTime(final T endTime)
{
this.endTime = endTime;
}
/**
* @return numberCreationEvents
*/
public long getNumberCreationEvents()
{
return this.numberCreationEvents;
}
/**
* @return numberGeneratedEntities
*/
public long getNumberGeneratedEntities()
{
return this.numberGeneratedEntities;
}
/**
* @return nextEvent
*/
public SimEventInterface<T> getNextEvent()
{
return this.nextEvent;
}
}