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.Collection;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.media.j3d.Bounds;
27 import javax.vecmath.Point2d;
28 import javax.vecmath.Point3d;
29
30 import nl.tudelft.simulation.actor.messagehandlers.HandleAllMessages;
31 import nl.tudelft.simulation.actor.messagehandlers.MessageHandlerInterface;
32 import nl.tudelft.simulation.content.HandlerInterface;
33 import nl.tudelft.simulation.dsol.experiment.TimeUnit;
34 import nl.tudelft.simulation.dsol.experiment.TimeUnitInterface;
35 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
36 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
37 import nl.tudelft.simulation.dsol.statistics.charts.XYChart;
38 import nl.tudelft.simulation.jstats.distributions.DistConstant;
39 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
40 import nl.tudelft.simulation.jstats.streams.StreamInterface;
41 import nl.tudelft.simulation.language.d3.BoundingBox;
42 import nl.tudelft.simulation.language.d3.DirectedPoint;
43 import nl.tudelft.simulation.language.io.URLResource;
44 import nl.tudelft.simulation.logger.Logger;
45 import nl.tudelft.simulation.messaging.devices.reference.FaxDevice;
46 import nl.tudelft.simulation.supplychain.actor.SupplyChainActor;
47 import nl.tudelft.simulation.supplychain.actor.Trader;
48 import nl.tudelft.simulation.supplychain.banking.Bank;
49 import nl.tudelft.simulation.supplychain.banking.BankAccount;
50 import nl.tudelft.simulation.supplychain.content.InternalDemand;
51 import nl.tudelft.simulation.supplychain.handlers.InternalDemandHandlerRFQ;
52 import nl.tudelft.simulation.supplychain.product.Product;
53 import nl.tudelft.simulation.supplychain.reference.Retailer;
54 import nl.tudelft.simulation.supplychain.roles.Role;
55 import nl.tudelft.simulation.supplychain.stock.Stock;
56
57 import org.gscg.common.GameActorInterface;
58 import org.gscg.common.geo.CalculateLatLonDistance;
59 import org.gscg.experiment.HandlerParser;
60 import org.gscg.game.GameActorContentStore;
61 import org.gscg.game.GameGlobalData;
62 import org.gscg.gameleader.animation2D.GisActorAnimation;
63 import org.gscg.singleuser.handlers.InteractiveQuoteHandler;
64 import org.gscg.singleuser.interactionlayer.business.statistics.CustomerStatistics;
65 import org.gscg.singleuser.interactionlayer.dataobjects.DateIntData;
66 import org.gscg.singleuser.interactionlayer.dataobjects.content.RFQDataSuppliers;
67 import org.jdom.Element;
68 import org.jdom.input.SAXBuilder;
69
70 /***
71 * The GameDistributor extends a Distributor from the supplychain project and
72 * provides additional game-specific functionalities. <br>
73 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
74 * Delft, the Netherlands. All rights reserved.
75 *
76 * See for project information <a href="http://www.simulation.tudelft.nl/">
77 * www.simulation.tudelft.nl </a>.
78 *
79 * The source code and binary code of this software is proprietary information
80 * of Delft University of Technology.
81 *
82 * @author <a
83 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
84 * Verbraeck </a>
85 * @version $Revision: 1.3 $ $Date: 2005/08/09 20:49:45 $
86 * @since 1.0.0 <br>
87 */
88
89 public class GameDistributor extends Retailer implements GameActorInterface,
90 GameInteractiveActorRoleInterface
91 {
92 /*** builder the xerces parser with validation turned on */
93 protected static SAXBuilder builder = new SAXBuilder(
94 "org.apache.xerces.parsers.SAXParser", true);
95
96 static
97 {
98
99 GameDistributor.builder.setFeature(
100 "http://xml.org/sax/features/validation", true);
101 GameDistributor.builder.setFeature(
102 "http://apache.org/xml/features/validation/schema", true);
103
104
105 String xsd = URLResource.getResource("/handler.xsd").toExternalForm();
106 GameDistributor.builder
107 .setProperty(
108 "http://apache.org/xml/properties/schema/external-schemaLocation",
109 "http://www.simulation.tudelft.nl/dsol " + xsd);
110 }
111
112 /*** the serial version uid */
113 private static final long serialVersionUID = 12L;
114
115 /*** debug */
116 private static final boolean DEBUG = false;
117
118 /*** the manufacturers where the GameDistributor buys */
119 protected Trader[] manufacturer;
120
121 /*** the global supply chain game data */
122 protected GameGlobalData globalSupplyChainData = null;
123
124 /*** the customer statistisc for this player */
125 protected CustomerStatistics customerStatistics = null;
126
127 /*** the special interactive quotehander */
128 protected InteractiveQuoteHandler interactiveQuoteHandler = null;
129
130 /*** the lat lon distance calculator to use */
131 protected CalculateLatLonDistance latLonDistanceCalculator = null;
132
133 /*** if true than we use any human intervention */
134 protected boolean humanControlled = false;
135
136 /*** true for warming-up */
137 protected boolean warmingUp = false;
138
139 /*** the location on the small map */
140 private DirectedPoint smallMapLocation = new DirectedPoint();
141
142 /*** the animation used for serialization */
143 private GisActorAnimation animation = null;
144
145 /*** the map with product names and their suppliers */
146 private Map productNameToSuppliers = null;
147
148 /***
149 * constructs a new GameDistributor; used when dragging and dropping an
150 * actor
151 *
152 * @param name the name
153 * @param simulator the simulator
154 * @param position the position
155 * @param bank the bank
156 */
157 public GameDistributor(final String name,
158 final DEVSSimulatorInterface simulator, final Point3d position,
159 final Bank bank)
160 {
161 super(name, simulator, position, new Role[]{}, bank, 0.0);
162 this.initAnimation();
163 }
164
165
166 /***
167 * constructs a new GameDistributor
168 *
169 * @param name the name
170 * @param simulator the simulator
171 * @param position the position
172 * @param roles the roles to implement
173 * @param bank the bank
174 * @param product the product
175 * @param amount the amount
176 * @param manufacturer the manufacturer
177 * @param globalSupplyChainData the global supply chain data
178 */
179 public GameDistributor(final String name,
180 final DEVSSimulatorInterface simulator, final Point3d position,
181 final Role[] roles, final Bank bank, final Product[] product,
182 final Double[] amount, final Trader[] manufacturer,
183 final GameGlobalData globalSupplyChainData)
184 {
185 this(name, simulator, position, roles, bank, 0.0, product, amount,
186 manufacturer, globalSupplyChainData);
187 }
188
189 /***
190 * Constructs a new GameDistributor
191 *
192 * @param name the name
193 * @param simulator the simulator
194 * @param position the position
195 * @param roles the roles to implement
196 * @param bank the bank
197 * @param initialBankAccount the initial bank account
198 * @param product the product
199 * @param amount the amount
200 * @param manufacturer the manufacturer
201 * @param globalSupplyChainData the global supply chain data
202 */
203 public GameDistributor(final String name,
204 final DEVSSimulatorInterface simulator, final Point3d position,
205 final Role[] roles, final Bank bank,
206 final double initialBankAccount, final Product[] product,
207 final Double[] amount, final Trader[] manufacturer,
208 final GameGlobalData globalSupplyChainData)
209 {
210 super(name, simulator, position, roles, bank, initialBankAccount);
211 super.setContentStore(new GameActorContentStore(this, simulator));
212 this.manufacturer = (Trader[]) manufacturer.clone();
213 this.globalSupplyChainData = globalSupplyChainData;
214 this.latLonDistanceCalculator = new CalculateLatLonDistance();
215
216
217
218 this.productNameToSuppliers = new HashMap();
219 for (int i = 0; i < this.manufacturer.length; i++)
220 {
221 Trader trader = this.manufacturer[i];
222 List productsOnStock = trader.getProductsOnStock();
223 for (int ii = 0; ii < productsOnStock.size(); ii++)
224 {
225 Product productOnStock = (Product) productsOnStock.get(ii);
226
227 if (!this.productNameToSuppliers.containsKey(productOnStock
228 .getName()))
229 {
230 this.productNameToSuppliers.put(productOnStock.getName(),
231 new HashSet());
232 }
233 Set set = (Set) this.productNameToSuppliers.get(productOnStock
234 .getName());
235 set.add(trader);
236 this.productNameToSuppliers.put(productOnStock.getName(), set);
237 }
238 }
239
240
241 Stock stock = new Stock(this);
242 for (int i = 0; i < product.length; i++)
243 {
244 stock.addStock(product[i], amount[i].doubleValue(), amount[i]
245 .doubleValue()
246 * product[i].getUnitMarketPrice());
247 }
248 setInitialStock(stock);
249
250
251 this.addDevices();
252
253
254 this.init();
255
256
257 if (this.animation == null)
258 {
259 this.initAnimation();
260 }
261 }
262
263 /***
264 * initializes the content handlers
265 */
266 protected void init()
267 {
268 this.addComputerControlledContentHandlers();
269 try
270 {
271
272
273
274 if (this.simulator instanceof AnimatorInterface)
275 {
276 XYChart bankChart = new XYChart(this.simulator, "BankAccount "
277 + this.name);
278 bankChart.add("bank account", this.bankAccount,
279 BankAccount.BANK_ACCOUNT_CHANGED_EVENT);
280 }
281 } catch (RemoteException remoteException)
282 {
283 Logger.severe(this, "init", remoteException);
284 }
285
286 if (GameDistributor.DEBUG)
287 {
288 System.out.println("GameDistributor: player: " + this.name
289 + " initialized.");
290 }
291 }
292
293 /***
294 * adds computer-controlled interactive content handlers
295 */
296 protected void addComputerControlledContentHandlers()
297 {
298
299 this.removeAllContentHandlers();
300
301
302 URL url = URLResource.getResource("/" + this.name
303 + "_computer_controlled.xml");
304 if (url == null)
305 {
306 url = URLResource.getResource("/distributor_default_handler.xml");
307 }
308 Logger
309 .info(
310 this,
311 "addComputerControlledContentHandlers",
312 "Using: "
313 + url.toExternalForm()
314 + " as the file containing the configuration for the handlers.");
315 try
316 {
317
318 Element rootElement = GameDistributor.builder.build(url)
319 .getRootElement();
320 HandlerParser.parseAndAddHandler(this, rootElement);
321 } catch (Exception exception)
322 {
323 Logger.severe(this, "addComputerControlledContentHandlers",
324 exception);
325 }
326
327
328
329
330 if (this.contentHandlers.containsKey(InternalDemand.class))
331 {
332 Set resolvedHandlers = (Set) this.contentHandlers
333 .get(InternalDemand.class);
334
335 for (Iterator resolvedHandlersIterator = resolvedHandlers
336 .iterator(); resolvedHandlersIterator.hasNext();)
337 {
338 HandlerInterface handler = (HandlerInterface) resolvedHandlersIterator
339 .next();
340
341 if (handler instanceof InternalDemandHandlerRFQ)
342 {
343 Iterator productIterator = this.getStock().iterator();
344 while (productIterator.hasNext())
345 {
346 Product product = (Product) productIterator.next();
347 Set suppliers = (Set) this.getProductNameToSuppliers()
348 .get(product.getName());
349 if (suppliers != null)
350 {
351 for (Iterator supplierIterator = suppliers
352 .iterator(); supplierIterator.hasNext();)
353 {
354 ((InternalDemandHandlerRFQ) handler)
355 .addSupplier(product,
356 (Trader) supplierIterator
357 .next());
358 }
359 } else
360 {
361 Logger.warning(this,
362 "addComputerControlledContentHandlers",
363 "No suppliers found for product: "
364 + product);
365 }
366 }
367 }
368 }
369 }
370 }
371
372 /***
373 * removes all the content handlers
374 */
375 protected void removeAllContentHandlers()
376 {
377 super.contentHandlers.clear();
378 }
379
380 protected void addDevices()
381 {
382 try
383 {
384 StreamInterface stream = this.simulator.getReplication().getStream(
385 "default");
386 double hour = TimeUnit.convert(1.0, TimeUnitInterface.HOUR,
387 this.simulator);
388 DistContinuous hourDist = new DistConstant(stream, hour);
389
390
391
392 FaxDevice fax = new FaxDevice("GameDistributorFax", this.simulator);
393 addSendingDevice(fax);
394 MessageHandlerInterface secretary = new HandleAllMessages(this);
395 addReceivingDevice(fax, secretary, hourDist);
396 } catch (RemoteException remoteException)
397 {
398 Logger.severe(this, "addDevices", remoteException);
399 }
400 }
401
402 /***
403 * Initializes the animation.
404 */
405 private void initAnimation()
406 {
407
408 this.animation = new GisActorAnimation(
409 this,
410 this.simulator,
411 URLResource
412 .getResource("/nl/tudelft/simulation/supplychain/images/Retailer.gif"));
413 }
414
415 /***
416 * @see nl.tudelft.simulation.dsol.animation.LocatableInterface#getBounds()
417 */
418 public Bounds getBounds()
419 {
420 return new BoundingBox(1.0, 1.0, 0.0);
421 }
422
423 /***
424 * Method getContent returns all data objects of type contentClass
425 *
426 * @param contentClass the content class to look for
427 * @param sent indicates whether the content is sent or received
428 * @param productName the name of the product
429 */
430 public void fireAllContentData(final Class contentClass,
431 final boolean sent, final String productName)
432 {
433 getGameContentStore().fireAllProductContentData(contentClass, sent,
434 productName);
435 }
436
437 /***
438 * Method fireAllNumberData.
439 */
440 public void fireAllNumberData()
441 {
442 Collection products = this.globalSupplyChainData.getProducts();
443 Iterator prodIter = products.iterator();
444 while (prodIter.hasNext())
445 {
446 Product product = (Product) prodIter.next();
447 getGameContentStore().fireAllProductNumberData(product.getName());
448 }
449 }
450
451 /***
452 * @param productName the product we want
453 * @return an initialized RFQData object with potential suppliers
454 */
455 public RFQDataSuppliers getInitialRFQData(final String productName)
456 {
457 double day = 0;
458 try
459 {
460 day = TimeUnit.convert(1, TimeUnitInterface.DAY, this.simulator);
461 } catch (Exception exception)
462 {
463 Logger.severe(this, "getInitialRFQData", "TimeUnit.convert failed");
464 }
465
466
467 double earliestDeliveryDate = this.getSimulatorTime() + 14 * day;
468 double defaultAmount = 100;
469 double latestDeliveryDate = earliestDeliveryDate + 7.0 * day;
470
471 String[] supplierNames = new String[0];
472 String[] supplierNickNames = new String[0];
473 Point2d ownLocation = new Point2d(this.getLocation().x, this
474 .getLocation().y);
475 Point2d[] suppliersLocations = new Point2d[0];
476
477 Set suppliers = (Set) this.productNameToSuppliers.get(productName);
478 if (suppliers != null)
479 {
480 supplierNames = new String[suppliers.size()];
481 supplierNickNames = new String[suppliers.size()];
482 suppliersLocations = new Point2d[suppliers.size()];
483
484 int counter = 0;
485 for (Iterator it = suppliers.iterator(); it.hasNext();)
486 {
487 Trader trader = (Trader) it.next();
488 supplierNames[counter] = trader.getName();
489 supplierNickNames[counter] = trader.getLocationDescription();
490 suppliersLocations[counter] = new Point2d(
491 trader.getLocation().x, trader.getLocation().y);
492 counter++;
493 }
494 }
495 return new RFQDataSuppliers(this.name, supplierNames,
496 supplierNickNames, DateIntData.makeDateIntData(
497 earliestDeliveryDate, this.simulator), DateIntData
498 .makeDateIntData(latestDeliveryDate, this.simulator),
499 defaultAmount, productName, ownLocation, suppliersLocations);
500 }
501
502 /***
503 * @return Returns the smallMapLocation.
504 */
505 public DirectedPoint getSmallMapLocation()
506 {
507 return this.smallMapLocation;
508 }
509
510 /***
511 * @param smallMapLocation The smallMapLocation to set.
512 */
513 public void setSmallMapLocation(final DirectedPoint smallMapLocation)
514 {
515 this.smallMapLocation = smallMapLocation;
516 }
517
518 /***
519 * @see org.gscg.gameactors.GameInteractiveActorRoleInterface#getGameContentStore()
520 */
521 public GameActorContentStore getGameContentStore()
522 {
523 return (GameActorContentStore) super.getContentStore();
524 }
525
526 /***
527 * @see nl.tudelft.simulation.actor.ActorInterface#getName()
528 */
529 public String getName()
530 {
531 return this.name;
532 }
533
534 /***
535 * sets the interactive quote handler
536 *
537 * @param interactiveQuoteHandler the interactive quote handler to set
538 */
539 public void setInteractiveQuoteHandler(
540 final InteractiveQuoteHandler interactiveQuoteHandler)
541 {
542 this.interactiveQuoteHandler = interactiveQuoteHandler;
543 }
544
545 /***
546 * @return Returns the animation
547 */
548 protected GisActorAnimation getAnimation()
549 {
550 return this.animation;
551 }
552
553 /***
554 * @see nl.tudelft.simulation.supplychain.actor.SupplyChainActor#calculateDistance(nl.tudelft.simulation.supplychain.actor.SupplyChainActor)
555 */
556 public double calculateDistance(final SupplyChainActor actor)
557 {
558 return new CalculateLatLonDistance().getDistance(new Point2d(
559 this.location.x, this.location.y), new Point2d(actor
560 .getLocation().x, actor.getLocation().y));
561 }
562
563 /***
564 * @return Returns the productNameToSuppliers.
565 */
566 public Map getProductNameToSuppliers()
567 {
568 return this.productNameToSuppliers;
569 }
570
571 /***
572 * @return true if human controlled, false otherwise
573 */
574 public boolean isHumanControlled()
575 {
576 return this.humanControlled;
577 }
578 }