View Javadoc
1   package nl.tudelft.simulation.dsol.tutorial.section42;
2   
3   import org.djutils.event.EventType;
4   import org.djutils.event.LocalEventProducer;
5   
6   import nl.tudelft.simulation.dsol.formalisms.eventscheduling.SimEvent;
7   import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
8   import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
9   import nl.tudelft.simulation.dsol.simulators.DevsSimulatorInterface;
10  import nl.tudelft.simulation.dsol.tutorial.section42.policies.OrderingPolicy;
11  import nl.tudelft.simulation.dsol.tutorial.section42.policies.StationaryPolicy;
12  
13  /**
14   * A Retailer.
15   * <p>
16   * Copyright (c) 2002-2024 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
17   * for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
18   * project is distributed under a three-clause BSD-style license, which can be found at
19   * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">
20   * https://https://simulation.tudelft.nl/dsol/docs/latest/license.html</a>.
21   * </p>
22   * @author <a href="https://www.linkedin.com/in/peterhmjacobs">Peter Jacobs </a>
23   */
24  public class Retailer extends LocalEventProducer implements BuyerInterface, SellerInterface
25  {
26      /** */
27      private static final long serialVersionUID = 1L;
28  
29      /** TOTAL_ORDERING_COST_EVENT is fired whenever ordering occurs. */
30      public static final EventType TOTAL_ORDERING_COST_EVENT = new EventType("TOTAL_ORDERING_COST_EVENT");
31  
32      /** INVENTORY_LEVEL_EVENT is fired on changes in inventory. */
33      public static final EventType INVENTORY_LEVEL_EVENT = new EventType("INVENTORY_LEVEL_EVENT");
34  
35      /** BACKLOG_LEVEL is fired on BACKLOG_LEVEL changes. */
36      public static final EventType BACKLOG_LEVEL = new EventType("BACKLOG_LEVEL");
37  
38      /** the actual inventoryLevel. */
39      private long inventory = 60L;
40  
41      /** the ordering backlog. */
42      private long backLog = 0L;
43  
44      /** the simulator on which to schedule. */
45      private DevsSimulatorInterface<Double> simulator = null;
46  
47      /** the warehouse we use. */
48      private SellerInterface warehouse = null;
49  
50      /** the orderingPolicy. */
51      private OrderingPolicy orderingPolicy = null;
52  
53      /** the costs. */
54      private double backlogCosts;
55  
56      /** the costs. */
57      private double holdingCosts;
58  
59      /** the costs. */
60      private double marginalCosts;
61  
62      /** the costs. */
63      private double setupCosts;
64  
65      /**
66       * constructs a new Retailer.
67       * @param simulator DevsSimulatorInterface&lt;Double&gt;; the simulator on which we can schedule
68       * @param warehouse SellerInterface; the warehouse to buy at
69       */
70      public Retailer(final DevsSimulatorInterface<Double> simulator, final SellerInterface warehouse)
71      {
72          super();
73          this.simulator = simulator;
74          this.warehouse = warehouse;
75          this.orderingPolicy = new StationaryPolicy(simulator);
76          try
77          {
78              InputParameterMap parameters = simulator.getModel().getInputParameterMap();
79              this.backlogCosts = (Double) parameters.get("retailer.backlogCosts").getCalculatedValue();
80              this.holdingCosts = (Double) parameters.get("retailer.holdingCosts").getCalculatedValue();
81              this.marginalCosts = (Double) parameters.get("retailer.marginalCosts").getCalculatedValue();
82              this.setupCosts = (Double) parameters.get("retailer.setupCosts").getCalculatedValue();
83          }
84          catch (InputParameterException ipe)
85          {
86              ipe.printStackTrace();
87              System.exit(-1);
88          }
89          this.reviewInventory();
90      }
91  
92      /** {@inheritDoc} */
93      @Override
94      public void receiveProduct(final long amount)
95      {
96          long served = this.backLog - Math.max(0, this.backLog - amount);
97          this.backLog = Math.max(0, this.backLog - amount);
98          this.inventory = this.inventory + Math.max(0, amount - served);
99          this.fireTimedEvent(INVENTORY_LEVEL_EVENT, this.inventory, this.simulator.getSimulatorTime());
100         this.fireTimedEvent(BACKLOG_LEVEL, this.backLog, this.simulator.getSimulatorTime());
101     }
102 
103     /**
104      * reviews the inventoryLevel and possibly orders.
105      */
106     private void reviewInventory()
107     {
108         double costs = this.holdingCosts * this.inventory + this.backlogCosts * this.backLog;
109         long amount = this.orderingPolicy.computeAmountToOrder(this.inventory);
110         if (amount > 0)
111         {
112             costs = costs + this.setupCosts + amount * this.marginalCosts;
113             this.fireTimedEvent(TOTAL_ORDERING_COST_EVENT, costs, this.simulator.getSimulatorTime());
114             this.warehouse.order(this, amount);
115         }
116         try
117         {
118             this.simulator.scheduleEvent(
119                     new SimEvent<Double>(this.simulator.getSimulatorTime() + 1.0, this,"reviewInventory", null));
120         }
121         catch (Exception exception)
122         {
123             this.simulator.getLogger().always().error(exception, "reviewInventory");
124         }
125     }
126 
127     /** {@inheritDoc} */
128     @Override
129     public void order(final BuyerInterface buyer, final long amount)
130     {
131         long actualOrderSize = Math.min(amount, this.inventory);
132         this.inventory = this.inventory - actualOrderSize;
133         if (actualOrderSize < amount)
134         {
135             this.backLog = this.backLog + (amount - actualOrderSize);
136         }
137         this.fireTimedEvent(INVENTORY_LEVEL_EVENT, this.inventory, this.simulator.getSimulatorTime());
138         this.fireTimedEvent(BACKLOG_LEVEL, this.backLog, this.simulator.getSimulatorTime());
139         buyer.receiveProduct(actualOrderSize);
140     }
141 
142 }