1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gscg.singleuser.handlers;
15
16 import java.io.Serializable;
17 import java.util.HashMap;
18 import java.util.Map;
19
20 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
21 import nl.tudelft.simulation.logger.Logger;
22 import nl.tudelft.simulation.supplychain.actor.Trader;
23 import nl.tudelft.simulation.supplychain.content.Quote;
24 import nl.tudelft.simulation.supplychain.content.RequestForQuote;
25 import nl.tudelft.simulation.supplychain.handlers.SupplyChainHandler;
26 import nl.tudelft.simulation.supplychain.product.Product;
27 import nl.tudelft.simulation.supplychain.transport.TransportMode;
28
29 import org.gscg.common.geo.CalculateLatLonDistance;
30 import org.gscg.experiment.DistTriangularGetters;
31
32 /***
33 * The RequestForQuotehandler implements the business logic for a supplier who
34 * receives a RequestForQuote. The most simple version answers yes if the
35 * product is on stock or ordered, and bases the price on the average costs of
36 * the items on stock, after adding a fixed, but changeable, profit margin. The
37 * answer is no if the product is not on stock, nor ordered. <br>
38 * <p>
39 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
40 * Delft, the Netherlands. All rights reserved.
41 *
42 * See for project information <a href="http://www.simulation.tudelft.nl/">
43 * www.simulation.tudelft.nl </a>.
44 *
45 * The source code and binary code of this software is proprietary information
46 * of Delft University of Technology.
47 *
48 * @version 1.0 Mar 4, 2004 <br>
49 * @author <a
50 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
51 * Verbraeck </a>
52 */
53 public class PCShopRequestForQuoteHandler extends SupplyChainHandler
54 {
55 /*** the serial version uid */
56 private static final long serialVersionUID = 11L;
57
58 /*** the reaction time of the handler in simulation time units */
59 private DistContinuous handlingTimeDistribution = null;
60
61 /*** the distribution to use for the price */
62 private Map priceDistributions = null;
63
64 /*** the distribution to use for the delay */
65 private DistContinuous delayDistribution = null;
66
67 /*** the lat lon distance calculator to use */
68 private CalculateLatLonDistance latLonDistanceCalculator = null;
69
70 /***
71 * Construct a new RFQ handler.
72 *
73 * @param owner a trader in this case as only traders handle RFQs
74 * @param handlingTimeDistribution the distribution for the handling time
75 * @param products the products to link to the price distributions
76 * @param priceDistributions the price distributions
77 * @param delayDistribution the distribution for the delay
78 */
79 public PCShopRequestForQuoteHandler(final Trader owner,
80 final DistContinuous handlingTimeDistribution,
81 final Product[] products,
82 final DistTriangularGetters[] priceDistributions,
83 final DistContinuous delayDistribution)
84 {
85 super(owner);
86 this.handlingTimeDistribution = handlingTimeDistribution;
87 this.priceDistributions = new HashMap();
88 for (int i = 0; i < products.length; i++)
89 {
90 this.priceDistributions.put(products[i], priceDistributions[i]);
91 }
92 this.delayDistribution = delayDistribution;
93 this.latLonDistanceCalculator = new CalculateLatLonDistance();
94 }
95
96 /***
97 * @see nl.tudelft.simulation.content.HandlerInterface#handleContent(java.io.Serializable)
98 */
99 public synchronized boolean handleContent(final Serializable content)
100 {
101 RequestForQuote rfq = (RequestForQuote) checkContent(content);
102 if (!isValidContent(rfq))
103 {
104 return false;
105 }
106 Product product = rfq.getProduct();
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 double price = Math.round(rfq.getAmount()
122 * ((1 + ((DistTriangularGetters) this.priceDistributions
123 .get(product)).draw() / 100) * product
124 .getUnitMarketPrice()) * 0.7);
125
126 double weight = rfq.getAmount()
127 * rfq.getProduct().getAverageUnitWeight();
128
129
130 double transportCosts = TransportMode.PLANE.transportCosts(
131 this.latLonDistanceCalculator.getDistance(rfq.getSender(), rfq
132 .getReceiver()), weight);
133
134
135 price += transportCosts;
136
137
138 double handlingDelay = this.handlingTimeDistribution.draw();
139
140
141 double date = Math.max(this.owner.getSimulatorTime(), rfq
142 .getEarliestDeliveryDate()
143 + this.delayDistribution.draw() + handlingDelay);
144
145
146 Quote quote = new Quote(this.owner, rfq.getSender(), rfq
147 .getInternalDemandID(), rfq, product, rfq.getAmount(), price,
148 date, TransportMode.PLANE);
149 super.owner.sendContent(quote, handlingDelay);
150 return true;
151 }
152
153 /***
154 * @see nl.tudelft.simulation.supplychain.handlers.SupplyChainHandler#checkContentClass(java.io.Serializable)
155 */
156 protected boolean checkContentClass(final Serializable content)
157 {
158 return (content instanceof RequestForQuote);
159 }
160
161 /***
162 * Method changePrice changes the price distribution of a PCManufacturer
163 *
164 * @param product the product to change the distribution for
165 * @param up if true, price will increase, if false, the price will decrease
166 * @param percentage the percentage to change the price with
167 */
168 public synchronized void changePrice(final Product product,
169 final boolean up, final double percentage)
170 {
171 DistTriangularGetters distribution = (DistTriangularGetters) this.priceDistributions
172 .get(product);
173 DistTriangularGetters newDistribution = null;
174 if (distribution != null)
175 {
176 if (up)
177 {
178 double newB = distribution.getB() * (1 + (percentage / 100));
179
180
181 newDistribution = new DistTriangularGetters(distribution
182 .getStream(), newB
183 - (distribution.getB() - distribution.getA()), newB,
184 newB + (distribution.getC() - distribution.getB()));
185 } else
186 {
187 newDistribution = new DistTriangularGetters(distribution
188 .getStream(), distribution.getA()
189 * (1 - (percentage / 100)), distribution.getB()
190 * (1 - (percentage / 100)), distribution.getC()
191 * (1 - (percentage / 100)));
192 }
193
194 this.priceDistributions.put(product, newDistribution);
195 } else
196 {
197 Logger.severe(this, "changePrice",
198 "Could not find distribution for product: "
199 + product.getName());
200 }
201 }
202 }