1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gscg.gameactors;
15
16 import java.net.URL;
17 import java.rmi.RemoteException;
18 import java.util.Iterator;
19 import java.util.Set;
20
21 import javax.media.j3d.Bounds;
22 import javax.vecmath.Point2d;
23 import javax.vecmath.Point3d;
24
25 import nl.tudelft.simulation.actor.messagehandlers.HandleAllMessages;
26 import nl.tudelft.simulation.actor.messagehandlers.MessageHandlerInterface;
27 import nl.tudelft.simulation.content.HandlerInterface;
28 import nl.tudelft.simulation.dsol.experiment.TimeUnit;
29 import nl.tudelft.simulation.dsol.experiment.TimeUnitInterface;
30 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
31 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
32 import nl.tudelft.simulation.jstats.distributions.DistConstant;
33 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
34 import nl.tudelft.simulation.jstats.distributions.DistExponential;
35 import nl.tudelft.simulation.jstats.streams.Java2Random;
36 import nl.tudelft.simulation.jstats.streams.StreamInterface;
37 import nl.tudelft.simulation.language.d3.BoundingBox;
38 import nl.tudelft.simulation.language.d3.DirectedPoint;
39 import nl.tudelft.simulation.language.io.URLResource;
40 import nl.tudelft.simulation.logger.Logger;
41 import nl.tudelft.simulation.messaging.devices.reference.FaxDevice;
42 import nl.tudelft.simulation.supplychain.actor.SupplyChainActor;
43 import nl.tudelft.simulation.supplychain.banking.Bank;
44 import nl.tudelft.simulation.supplychain.banking.BankAccount;
45 import nl.tudelft.simulation.supplychain.content.InternalDemand;
46 import nl.tudelft.simulation.supplychain.content.LeanContentStore;
47 import nl.tudelft.simulation.supplychain.demand.Demand;
48 import nl.tudelft.simulation.supplychain.handlers.InternalDemandHandlerRFQ;
49 import nl.tudelft.simulation.supplychain.product.Product;
50 import nl.tudelft.simulation.supplychain.reference.Customer;
51 import nl.tudelft.simulation.supplychain.reference.Retailer;
52 import nl.tudelft.simulation.supplychain.roles.BuyingRole;
53 import nl.tudelft.simulation.supplychain.roles.DemandGenerationRole;
54
55 import org.gscg.common.GameActorInterface;
56 import org.gscg.common.geo.CalculateLatLonDistance;
57 import org.gscg.experiment.DistTriangularDiscrete;
58 import org.gscg.experiment.HandlerParser;
59 import org.gscg.gameleader.animation2D.GisActorAnimation;
60 import org.jdom.Element;
61 import org.jdom.input.SAXBuilder;
62
63 /***
64 * The GameMarket extends a Customer from the supplychain project and provides
65 * additional game-specific functionalities. <br>
66 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
67 * Delft, the Netherlands. All rights reserved.
68 *
69 * See for project information <a href="http://www.simulation.tudelft.nl/">
70 * www.simulation.tudelft.nl </a>.
71 *
72 * The source code and binary code of this software is proprietary information
73 * of Delft University of Technology.
74 *
75 * @author <a
76 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
77 * Verbraeck </a>
78 * @version $Revision: 1.1 $ $Date: 2005/08/03 08:52:50 $
79 * @since 1.0.0 <br>
80 */
81
82 public class GameMarket extends Customer implements GameActorInterface
83 {
84 /*** builder the xerces parser with validation turned on */
85 private static SAXBuilder builder = new SAXBuilder(
86 "org.apache.xerces.parsers.SAXParser", true);
87
88 static
89 {
90
91 GameMarket.builder.setFeature("http://xml.org/sax/features/validation",
92 true);
93 GameMarket.builder.setFeature(
94 "http://apache.org/xml/features/validation/schema", true);
95
96
97 String xsd = URLResource.getResource("/handler.xsd").toExternalForm();
98 GameMarket.builder
99 .setProperty(
100 "http://apache.org/xml/properties/schema/external-schemaLocation",
101 "http://www.simulation.tudelft.nl/dsol " + xsd);
102 }
103
104 /*** the serial version uid */
105 private static final long serialVersionUID = 12L;
106
107 /*** the stream to use */
108 private transient static StreamInterface defaultStream = new Java2Random();
109
110 /*** the product that PCMarket wants to buy */
111 private Product[] product;
112
113 /*** the fixed retailer where PCMarket buys */
114 private Retailer[] retailer;
115
116 /*** the location on the small map */
117 private DirectedPoint smallMapLocation = new DirectedPoint();
118
119 /*** the demand generators */
120 private Demand[] demand = null;
121
122 /*** the animation used for serialization */
123 private GisActorAnimation animation = null;
124
125 /*** true for debug mode */
126 private boolean debug = false;
127
128 /***
129 * constructs a new GameMarket; used when dragging and dropping an actor
130 *
131 * @param name the name
132 * @param simulator the simulator
133 * @param position the position
134 * @param bank the bank
135 */
136 public GameMarket(final String name,
137 final DEVSSimulatorInterface simulator, final Point3d position,
138 final Bank bank)
139 {
140 super(name, simulator, position, bank, 0.0);
141 this.initAnimation();
142 }
143
144 /***
145 * constructs a new GameMarket
146 *
147 * @param name the name
148 * @param simulator the simulator
149 * @param position the position
150 * @param bank the bank
151 * @param initialBankAccount the initial bank account
152 * @param product the product
153 * @param demand the demand generators for the products
154 * @param retailer the retailer
155 * @throws RemoteException thrown in case of a network exception
156 */
157 public GameMarket(final String name,
158 final DEVSSimulatorInterface simulator, final Point3d position,
159 final Bank bank, final double initialBankAccount,
160 final Product[] product, final Demand[] demand,
161 final Retailer[] retailer) throws RemoteException
162 {
163 super(name, simulator, position, bank, initialBankAccount);
164 super.setContentStore(new LeanContentStore(this, simulator));
165 this.product = (Product[]) product.clone();
166 this.demand = demand;
167 this.retailer = retailer;
168 this.init();
169
170
171 if (this.animation == null)
172 {
173 this.initAnimation();
174 }
175 }
176
177 /***
178 * @throws RemoteException thrown in case of a network error
179 */
180 public void init() throws RemoteException
181 {
182 double hour = TimeUnit.convert(1.0, TimeUnitInterface.HOUR,
183 this.simulator);
184 DistContinuous hourDist = new DistConstant(GameMarket.defaultStream,
185 hour);
186 double minute = TimeUnit.convert(1.0, TimeUnitInterface.MINUTE,
187 super.simulator);
188
189
190 FaxDevice fax = new FaxDevice("Fax-" + this.name, this.simulator);
191 super.addSendingDevice(fax);
192 MessageHandlerInterface secretary = new HandleAllMessages(this);
193 super.addReceivingDevice(fax, secretary, hourDist);
194
195
196
197 BuyingRole buyingRole = new BuyingRole(this, super.simulator,
198 super.bankAccount);
199 super.setBuyingRole(buyingRole);
200
201
202
203 DemandGenerationRole dgRole = new DemandGenerationRole(this,
204 super.simulator, new DistExponential(GameMarket.defaultStream,
205 2.0 * minute));
206
207 for (int i = 0; i < this.demand.length; i++)
208 {
209 dgRole.addDemandGenerator(this.demand[i].getProduct(),
210 this.demand[i]);
211 }
212 super.setDemandGenerationRole(dgRole);
213
214
215 URL url = URLResource.getResource("/" + this.name
216 + "_computer_controlled.xml");
217 if (url == null)
218 {
219 url = URLResource.getResource("/market_default_handler.xml");
220 }
221 Logger
222 .info(
223 this,
224 "init",
225 "Using: "
226 + url.toExternalForm()
227 + " as the file containing the configuration for the handlers.");
228 try
229 {
230
231 Element rootElement = GameDistributor.builder.build(url)
232 .getRootElement();
233 HandlerParser.parseAndAddHandler(this, rootElement);
234 } catch (Exception exception)
235 {
236 Logger.severe(this, "init", exception);
237 }
238
239 if (this.contentHandlers.containsKey(InternalDemand.class))
240 {
241 Set resolvedhandlers = (Set) this.contentHandlers
242 .get(InternalDemand.class);
243
244 for (Iterator it = resolvedhandlers.iterator(); it.hasNext();)
245 {
246 HandlerInterface handler = (HandlerInterface) it.next();
247 if (handler instanceof InternalDemandHandlerRFQ)
248 {
249 for (int i = 0; i < this.product.length; i++)
250 {
251 for (int ii = 0; ii < this.retailer.length; ii++)
252 {
253 ((InternalDemandHandlerRFQ) handler).addSupplier(
254 this.product[i], this.retailer[ii]);
255 }
256 }
257 }
258 }
259 }
260
261
262
263
264 if (this.simulator instanceof AnimatorInterface)
265 {
266 nl.tudelft.simulation.dsol.statistics.charts.XYChart bankChart = new nl.tudelft.simulation.dsol.statistics.charts.XYChart(
267 this.simulator, "BankAccount " + this.name);
268 bankChart.add("bank account", this.bankAccount,
269 BankAccount.BANK_ACCOUNT_CHANGED_EVENT);
270 }
271 }
272
273 /***
274 * Initializes the animation.
275 */
276 private void initAnimation()
277 {
278
279 this.animation = new GisActorAnimation(
280 this,
281 this.simulator,
282 GameMarket.class
283 .getResource("/nl/tudelft/simulation/supplychain/images/Market.gif"));
284 }
285
286 /***
287 * @see nl.tudelft.simulation.dsol.animation.LocatableInterface#getBounds()
288 */
289 public Bounds getBounds()
290 {
291
292 return new BoundingBox(1.0, 1.0, 0.0);
293 }
294
295 /***
296 * @return Returns the smallMapLocation.
297 */
298 public DirectedPoint getSmallMapLocation()
299 {
300 return this.smallMapLocation;
301 }
302
303 /***
304 * @param smallMapLocation The smallMapLocation to set.
305 */
306 public void setSmallMapLocation(final DirectedPoint smallMapLocation)
307 {
308 this.smallMapLocation = smallMapLocation;
309 }
310
311 /***
312 * @see nl.tudelft.simulation.actor.ActorInterface#getName()
313 */
314 public String getName()
315 {
316 return this.name;
317 }
318
319 /***
320 * @return Returns the animation
321 */
322 protected GisActorAnimation getAnimation()
323 {
324 return this.animation;
325 }
326
327 /***
328 * @see nl.tudelft.simulation.supplychain.actor.SupplyChainActor#calculateDistance(nl.tudelft.simulation.supplychain.actor.SupplyChainActor)
329 */
330 public double calculateDistance(final SupplyChainActor actor)
331 {
332 return new CalculateLatLonDistance().getDistance(new Point2d(
333 this.location.x, this.location.y), new Point2d(actor
334 .getLocation().x, actor.getLocation().y));
335 }
336
337 /***
338 * Method changeDemand changes the demand of a PCMarket for the specified
339 * product.
340 *
341 * @param product the product to change the demand for
342 * @param up if true, demand will increase, if false, the demand will
343 * decrease
344 * @param percentage the percentage to change the demand with
345 */
346 public void changeDemand(final Product product, final boolean up,
347 final double percentage)
348 {
349 Demand demand = super.getDemandGenerationRole().getDemandGenerator(
350 product);
351 if (demand != null)
352 {
353 DistContinuous amount = demand.getAmount();
354 if (amount instanceof org.gscg.experiment.DistTriangularDiscrete)
355 {
356 DistTriangularDiscrete oldAmount = (DistTriangularDiscrete) amount;
357 DistTriangularDiscrete newAmount = null;
358
359 if (up)
360 {
361 double newB = oldAmount.getB() * (1 + (percentage / 100));
362
363
364 newAmount = new DistTriangularDiscrete(oldAmount
365 .getStream(), newB
366 - (oldAmount.getB() - oldAmount.getA()), newB, newB
367 + (oldAmount.getC() - oldAmount.getB()));
368 if (this.debug)
369 {
370 System.out.println("DEBUG -- PCMarket: "
371 + oldAmount.getA() + " _ " + newAmount.getA());
372 System.out.println("DEBUG -- PCMarket: "
373 + oldAmount.getB() + " _ " + newAmount.getB());
374 System.out.println("DEBUG -- PCMarket: "
375 + oldAmount.getC() + " _ " + newAmount.getC());
376 }
377 } else
378 {
379 newAmount = new DistTriangularDiscrete(oldAmount
380 .getStream(), oldAmount.getA()
381 * (1 - (percentage / 100)), oldAmount.getB()
382 * (1 - (percentage / 100)), oldAmount.getC()
383 * (1 - (percentage / 100)));
384 }
385
386 Demand newDemand = new Demand(product, demand.getInterval(),
387 newAmount, demand.getEarliestDeliveryDate(), demand
388 .getLatestDeliveryDate());
389
390 super.getDemandGenerationRole().removeDemandGenerator(product);
391
392
393 super.getDemandGenerationRole().addDemandGenerator(
394 newDemand.getProduct(), newDemand);
395 }
396 } else
397 {
398 Logger.severe(this, "changeDemand",
399 "Could not find demand for product: " + product.getName());
400 }
401 }
402 }