/**
*
*/
package org.opentrafficsim.water.demand;
import java.io.Serializable;
import org.djunits.value.vdouble.scalar.Time;
import org.opentrafficsim.water.role.Company;
import org.opentrafficsim.water.role.ShippingLine;
import org.opentrafficsim.water.statistics.ContainerTransportCO2BreakdownEnum;
import org.opentrafficsim.water.statistics.ContainerTransportCostBreakdownEnum;
import org.opentrafficsim.water.statistics.ContainerTransportFeeBreakdownEnum;
import org.opentrafficsim.water.statistics.ContainerTransportTimeBreakdownEnum;
import org.opentrafficsim.water.statistics.FullEmptyEnum;
import org.opentrafficsim.water.transfer.Terminal;
import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
/**
* A container is exactly 1 TEU. It collects statistics along the way, which are reported to the statistics objects just before
* the container disappears from the model at the inland client or deep sea terminal / empty depot.
*
* Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
*
* Based on software from the IDVV project, which is Copyright (c) 2013 Rijkswaterstaat - Dienst Water, Verkeer en Leefomgeving
* and licensed without restrictions to Delft University of Technology, including the right to sub-license sources and derived
* products to third parties.
*
* $LastChangedDate: 2015-07-24 02:58:59 +0200 (Fri, 24 Jul 2015) $, @version $Revision: 1147 $, by $Author: averbraeck $,
* initial version Nov 6, 2016
* @author Alexander Verbraeck
*/
public class Container implements Serializable
{
/** */
private static final long serialVersionUID = 1L;
/** the simulator. */
private final DEVSSimulatorInterface.TimeDoubleUnit simulator;
/** origin terminal. */
private Terminal terminalFrom;
/** destination terminal. */
private Terminal terminalTo;
/** terminal where the container was stacked last. */
private Terminal terminalLastStacked;
/** empty? */
private boolean empty;
/** shipping line. */
private ShippingLine shippingLine;
/** creation time of container. */
private Time creationTime;
/** time of arrival at last terminal in the stack (for statistics about terminal staying time). */
private Time stackArrivalTime;
/** time when container loaded on ship. */
private Time onShipTime;
/** cost breakdown (based on actual costs) of ALL handling of the container (could be multiple services). */
private float[] transportCosts = new float[ContainerTransportCostBreakdownEnum.values().length];
/** fee breakdown (based on fixed costs for actions) of ALL handling of the container. */
private float[] transportFee = new float[ContainerTransportFeeBreakdownEnum.values().length];
/** co2 breakdown (in si unit) for ALL handling of the container (could be multiple services). */
private float[] transportKgCO2 = new float[ContainerTransportCO2BreakdownEnum.values().length];
/** time breakdown (in si unit) for ALL handling of the container (could be multiple services). */
private float[] transportTime = new float[ContainerTransportTimeBreakdownEnum.values().length];
/**
* @param simulator DEVSSimulatorInterface.TimeDoubleUnit; the simulator
* @param terminalFrom Terminal; origin terminal
* @param terminalTo Terminal; destination terminal
* @param empty boolean; empty or full
* @param shippingLine ShippingLine; shipping line of the container
*/
public Container(final DEVSSimulatorInterface.TimeDoubleUnit simulator, final Terminal terminalFrom,
final Terminal terminalTo, final boolean empty, final ShippingLine shippingLine)
{
super();
this.simulator = simulator;
this.terminalFrom = terminalFrom;
this.terminalLastStacked = terminalFrom;
this.terminalTo = terminalTo;
this.empty = empty;
this.shippingLine = shippingLine;
this.creationTime = this.simulator.getSimulatorTime();
for (int i = 0; i < ContainerTransportCostBreakdownEnum.values().length; i++)
{
this.transportCosts[i] = 0.0f;
}
for (int i = 0; i < ContainerTransportFeeBreakdownEnum.values().length; i++)
{
this.transportFee[i] = 0.0f;
}
for (int i = 0; i < ContainerTransportCO2BreakdownEnum.values().length; i++)
{
this.transportKgCO2[i] = 0.0f;
}
for (int i = 0; i < ContainerTransportTimeBreakdownEnum.values().length; i++)
{
this.transportTime[i] = 0.0f;
}
}
/**
* @param costEnum ContainerTransportCostBreakdownEnum; cost category
* @param cost double; cost to add
*/
public final void addTransportCost(final ContainerTransportCostBreakdownEnum costEnum, final double cost)
{
this.transportCosts[costEnum.ordinal()] += cost;
}
/**
* @param feeEnum ContainerTransportFeeBreakdownEnum; cost category
* @param fee double; the fee to add
*/
public final void addTransportFee(final ContainerTransportFeeBreakdownEnum feeEnum, final double fee)
{
this.transportFee[feeEnum.ordinal()] += fee;
}
/**
* @param co2Enum ContainerTransportCO2BreakdownEnum; CO2 category
* @param kgCO2 double; the amount of CO2 to add
*/
public final void addTransportKgCO2(final ContainerTransportCO2BreakdownEnum co2Enum, final double kgCO2)
{
this.transportKgCO2[co2Enum.ordinal()] += kgCO2;
}
/**
* @param timeEnum ContainerTransportTimeBreakdownEnum; time category
* @param time double; the time in hours to add
*/
public final void addTransportTime(final ContainerTransportTimeBreakdownEnum timeEnum, final double time)
{
this.transportTime[timeEnum.ordinal()] += time;
}
/**
* @param costEnum ContainerTransportCostBreakdownEnum; cost category
* @return costs of this cost breakdown category until now
*/
public final double getTransportCost(final ContainerTransportCostBreakdownEnum costEnum)
{
return this.transportCosts[costEnum.ordinal()];
}
/**
* @param feeEnum ContainerTransportFeeBreakdownEnum; cost category
* @return fee until now of this cost breakdown category until now
*/
public final double getTransportFee(final ContainerTransportFeeBreakdownEnum feeEnum)
{
return this.transportFee[feeEnum.ordinal()];
}
/**
* @param co2Enum ContainerTransportCO2BreakdownEnum; CO2 category
* @return kg CO2 of this CO2 breakdown category until now
*/
public final double getTransportKgCO2(final ContainerTransportCO2BreakdownEnum co2Enum)
{
return this.transportKgCO2[co2Enum.ordinal()];
}
/**
* @param timeEnum ContainerTransportTimeBreakdownEnum; time category
* @return the time in hours
*/
public final double getTransportTime(final ContainerTransportTimeBreakdownEnum timeEnum)
{
return this.transportTime[timeEnum.ordinal()];
}
/**
* @return summed total costs
*/
public final double getSumTransportCost()
{
double sum = 0.0;
for (int i = 0; i < ContainerTransportCostBreakdownEnum.values().length; i++)
{
sum += this.transportCosts[i];
}
return sum;
}
/**
* @return summed total fee
*/
public final double getSumTransportFee()
{
double sum = 0.0;
for (int i = 0; i < ContainerTransportFeeBreakdownEnum.values().length; i++)
{
sum += this.transportFee[i];
}
return sum;
}
/**
* @return summed total kg CO2
*/
public final double getSumTransportKgCO2()
{
double sum = 0.0;
for (int i = 0; i < ContainerTransportCO2BreakdownEnum.values().length; i++)
{
sum += this.transportKgCO2[i];
}
return sum;
}
/**
* @return summed total time
*/
public final double getSumTransportTime()
{
double sum = 0.0;
for (int i = 0; i < ContainerTransportTimeBreakdownEnum.values().length; i++)
{
sum += this.transportTime[i];
}
return sum;
}
/**
* Collect the final statistics when the container arrived at its destination.
*/
@SuppressWarnings("checkstyle:needbraces")
public final void collectTerminalStatisticsAtContainerDestination()
{
// Terminal terminal = this.terminalTo.isRtmTerminal() ? this.terminalFrom : this.terminalTo;
// TODO: add at terminal: totalCosts += terminal.getAnnualFixedCostsTerminalPerTEU();
// TerminalStatistics stats = terminal.getTerminalStatistics();
//
// stats.costPerTEU.get(DirectionEnum.TOTAL).tally(getSumTransportCost());
// stats.feePerTEU.get(DirectionEnum.TOTAL).tally(getSumTransportFee());
// stats.kgCO2PerTEU.get(DirectionEnum.TOTAL).tally(getSumTransportKgCO2());
// stats.transportTime.get(DirectionEnum.TOTAL).tally(getSumTransportTime());
// for (ContainerTransportCostBreakdownEnum ctcb : ContainerTransportCostBreakdownEnum.values())
// stats.addBreakdownCost(DirectionEnum.TOTAL, ctcb, this.getTransportCost(ctcb));
// for (ContainerTransportFeeBreakdownEnum ctfb : ContainerTransportFeeBreakdownEnum.values())
// stats.addBreakdownFee(DirectionEnum.TOTAL, ctfb, this.getTransportFee(ctfb));
// for (ContainerTransportCO2BreakdownEnum ctcb : ContainerTransportCO2BreakdownEnum.values())
// stats.addBreakdownCO2(DirectionEnum.TOTAL, ctcb, this.getTransportKgCO2(ctcb));
// for (ContainerTransportTimeBreakdownEnum cttb : ContainerTransportTimeBreakdownEnum.values())
// stats.addBreakdownTime(DirectionEnum.TOTAL, cttb, this.getTransportTime(cttb));
//
// if (this.terminalTo.isRtmTerminal())
// {
// stats.costPerTEU.get(DirectionEnum.TORTM).tally(getSumTransportCost());
// stats.feePerTEU.get(DirectionEnum.TORTM).tally(getSumTransportFee());
// stats.kgCO2PerTEU.get(DirectionEnum.TORTM).tally(getSumTransportKgCO2());
// stats.transportTime.get(DirectionEnum.TORTM).tally(getSumTransportTime());
// for (ContainerTransportCostBreakdownEnum ctcb : ContainerTransportCostBreakdownEnum.values())
// stats.addBreakdownCost(DirectionEnum.TORTM, ctcb, this.getTransportCost(ctcb));
// for (ContainerTransportFeeBreakdownEnum ctfb : ContainerTransportFeeBreakdownEnum.values())
// stats.addBreakdownFee(DirectionEnum.TORTM, ctfb, this.getTransportFee(ctfb));
// for (ContainerTransportCO2BreakdownEnum ctcb : ContainerTransportCO2BreakdownEnum.values())
// stats.addBreakdownCO2(DirectionEnum.TORTM, ctcb, this.getTransportKgCO2(ctcb));
// for (ContainerTransportTimeBreakdownEnum cttb : ContainerTransportTimeBreakdownEnum.values())
// stats.addBreakdownTime(DirectionEnum.TORTM, cttb, this.getTransportTime(cttb));
// }
//
// else
//
// {
// stats.costPerTEU.get(DirectionEnum.FROMRTM).tally(getSumTransportCost());
// stats.feePerTEU.get(DirectionEnum.FROMRTM).tally(getSumTransportFee());
// stats.kgCO2PerTEU.get(DirectionEnum.FROMRTM).tally(getSumTransportKgCO2());
// stats.transportTime.get(DirectionEnum.FROMRTM).tally(getSumTransportTime());
// for (ContainerTransportCostBreakdownEnum ctcb : ContainerTransportCostBreakdownEnum.values())
// stats.addBreakdownCost(DirectionEnum.FROMRTM, ctcb, this.getTransportCost(ctcb));
// for (ContainerTransportFeeBreakdownEnum ctfb : ContainerTransportFeeBreakdownEnum.values())
// stats.addBreakdownFee(DirectionEnum.FROMRTM, ctfb, this.getTransportFee(ctfb));
// for (ContainerTransportCO2BreakdownEnum ctcb : ContainerTransportCO2BreakdownEnum.values())
// stats.addBreakdownCO2(DirectionEnum.FROMRTM, ctcb, this.getTransportKgCO2(ctcb));
// for (ContainerTransportTimeBreakdownEnum cttb : ContainerTransportTimeBreakdownEnum.values())
// stats.addBreakdownTime(DirectionEnum.FROMRTM, cttb, this.getTransportTime(cttb));
// }
}
/**
* @return the terminalFrom
*/
public final Terminal getTerminalFrom()
{
return this.terminalFrom;
}
/**
* @return the terminalTo
*/
public final Terminal getTerminalTo()
{
return this.terminalTo;
}
/**
* @return the terminalCurrent
*/
public final Terminal getTerminalLastStacked()
{
return this.terminalLastStacked;
}
/**
* @param terminalFrom Terminal; the terminalFrom to set
*/
public final void setTerminalFrom(final Terminal terminalFrom)
{
this.terminalFrom = terminalFrom;
}
/**
* @param terminalTo Terminal; the terminalTo to set
*/
public final void setTerminalTo(final Terminal terminalTo)
{
this.terminalTo = terminalTo;
}
/**
* @param terminalLastStacked Terminal; the terminalCurrent to set
*/
public final void setTerminalLastStacked(final Terminal terminalLastStacked)
{
this.terminalLastStacked = terminalLastStacked;
}
/**
* @return the empty
*/
public final boolean isEmpty()
{
return this.empty;
}
/**
* @return full or empty
*/
public final FullEmptyEnum fullEmpty()
{
if (this.empty)
{
return FullEmptyEnum.EMPTY;
}
return FullEmptyEnum.FULL;
}
/**
* @return the owner
*/
public final Company getOwner()
{
return this.shippingLine;
}
/**
* @return the shippingLine
*/
public final ShippingLine getShippingLine()
{
return this.shippingLine;
}
/** {@inheritDoc} */
@Override
public final String toString()
{
String full = this.empty ? "[EMPTY]" : "[FULL]";
return "Container from " + this.terminalFrom.getName() + " to " + this.terminalTo.getName() + " at "
+ this.terminalLastStacked.getName() + " (owner " + this.shippingLine.getCode() + ") " + full;
}
/**
* @return short info
*/
public final String toShortString()
{
String full = this.empty ? "[E]" : "[F]";
return this.terminalFrom.getName() + "->" + this.terminalTo.getName() + "@" + this.terminalLastStacked.getName() + full;
}
/**
* @return the arrivalTime
*/
public final Time getStackArrivalTime()
{
return this.stackArrivalTime;
}
/**
* set the arrivalTime.
*/
public final void setStackArrivalTime()
{
this.stackArrivalTime = this.simulator.getSimulatorTime();
}
/**
* @return the creationTime
*/
public final Time getCreationTime()
{
return this.creationTime;
}
/**
* @return the onShipTime
*/
public final Time getOnShipTime()
{
return this.onShipTime;
}
/**
* set onShipTime.
*/
public final void setOnShipTime()
{
this.onShipTime = this.simulator.getSimulatorTime();
}
}