1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gscg.gameactors;
15
16 import java.io.IOException;
17 import java.io.ObjectOutputStream;
18 import java.io.Serializable;
19 import java.net.URL;
20 import java.rmi.RemoteException;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Properties;
25 import java.util.Set;
26
27 import javax.vecmath.Point3d;
28
29 import nl.tudelft.simulation.actor.messagehandlers.HandleAllMessages;
30 import nl.tudelft.simulation.actor.messagehandlers.MessageHandlerInterface;
31 import nl.tudelft.simulation.dsol.experiment.TimeUnit;
32 import nl.tudelft.simulation.dsol.experiment.TimeUnitInterface;
33 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
34 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
35 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
36 import nl.tudelft.simulation.dsol.statistics.charts.XYChart;
37 import nl.tudelft.simulation.event.Event;
38 import nl.tudelft.simulation.event.EventInterface;
39 import nl.tudelft.simulation.event.EventType;
40 import nl.tudelft.simulation.jstats.distributions.DistConstant;
41 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
42 import nl.tudelft.simulation.jstats.streams.StreamInterface;
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.Bill;
51 import nl.tudelft.simulation.supplychain.content.Content;
52 import nl.tudelft.simulation.supplychain.content.InternalDemand;
53 import nl.tudelft.simulation.supplychain.content.Order;
54 import nl.tudelft.simulation.supplychain.content.OrderBasedOnQuote;
55 import nl.tudelft.simulation.supplychain.content.OrderConfirmation;
56 import nl.tudelft.simulation.supplychain.content.Payment;
57 import nl.tudelft.simulation.supplychain.content.Quote;
58 import nl.tudelft.simulation.supplychain.content.RequestForQuote;
59 import nl.tudelft.simulation.supplychain.product.Product;
60 import nl.tudelft.simulation.supplychain.roles.Role;
61 import nl.tudelft.simulation.supplychain.stock.StockInterface;
62 import nl.tudelft.simulation.supplychain.stock.StockUpdateData;
63 import nl.tudelft.simulation.supplychain.transport.TransportMode;
64
65 import org.gscg.common.gui.exceptions.ReceivedUnknownEventException;
66 import org.gscg.common.interactionlayer.AnnounceInterface;
67 import org.gscg.common.interactionlayer.timecontrol.GlobalRowOrColumnNumber;
68 import org.gscg.experiment.HandlerParser;
69 import org.gscg.game.GameGlobalData;
70 import org.gscg.singleuser.handlers.InteractiveOrderHandlerStock;
71 import org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface;
72 import org.gscg.singleuser.interactionlayer.business.statistics.CustomerStatistics;
73 import org.gscg.singleuser.interactionlayer.dataobjects.DateIntData;
74 import org.gscg.singleuser.interactionlayer.dataobjects.content.BillData;
75 import org.gscg.singleuser.interactionlayer.dataobjects.content.QuoteData;
76 import org.gscg.singleuser.interactionlayer.dataobjects.content.RFQData;
77 import org.gscg.singleuser.interactionlayer.dataobjects.content.RFQDataSuppliers;
78 import org.gscg.singleuser.interactionlayer.dataobjects.content.SentOrderConfirmationData;
79 import org.gscg.singleuser.interactionlayer.dataobjects.content.SentQuoteData;
80 import org.jdom.Element;
81
82 /***
83 * The GameDistributorInteractive extends a GameDistributor from the
84 * supplychain-game project and provides additional interactive functionalities.
85 * <br>
86 * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
87 * Delft, the Netherlands. All rights reserved.
88 *
89 * See for project information <a href="http://www.simulation.tudelft.nl/">
90 * www.simulation.tudelft.nl </a>.
91 *
92 * The source code and binary code of this software is proprietary information
93 * of Delft University of Technology.
94 *
95 * @author <a
96 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
97 * Verbraeck </a>
98 * @version $Revision: 1.2 $ $Date: 2005/08/09 15:43:40 $
99 * @since 1.0.0 <br>
100 */
101
102 public class GameDistributorInteractive extends GameDistributor implements
103 GameActorInteractiveInterface, AnnounceInterface
104 {
105 /*** the map with distributors after deserialization */
106 private static Set distributors = new HashSet();
107
108 /***
109 * @return returns the set with distributors of which the interactivity mode
110 * has changed after deseriliazation due to changes in the
111 * distributor.properties file
112 */
113 public static Set getChangedDistributors()
114 {
115 return GameDistributorInteractive.distributors;
116 }
117
118 /*** the serial version uid */
119 private static final long serialVersionUID = 13L;
120
121 /*** a client has sent an RFQ which forms the basis for a quote */
122 public static final EventType RFQ_SENT_BY_CLIENT_EVENT = new EventType(
123 "RFQ_SENT_BY_CLIENT_EVENT");
124
125 /*** a client has selected a quote which forms the basis for an order */
126 public static final EventType SELECTED_QUOTE_EVENT = new EventType(
127 "SELECTED_QUOTE_EVENT");
128
129 /*** a client has selected a bill to pay */
130 public static final EventType PAY_BILL_EVENT = new EventType(
131 "PAY_BILL_EVENT");
132
133 /*** a client has selected an rfq and sent a quote */
134 public static final EventType QUOTE_SENT_BY_CLIENT_EVENT = new EventType(
135 "QUOTE_SENT_BY_CLIENT_EVENT");
136
137 /*** a client has deleted an rfq */
138 public static final EventType RFQ_DELETED_BY_CLIENT_EVENT = new EventType(
139 "RFQ_DELETED_BY_CLIENT_EVENT");
140
141 /*** a client has confirmed an order */
142 public static final EventType ORDER_CONFIRMATION_SENT_BY_CLIENT_EVENT = new EventType(
143 "ORDER_CONFIRMATION_SENT_BY_CLIENT_EVENT");
144
145 /*** events fired by client */
146 private EventType[] eventsSentByClientArray = {
147 GameDistributorInteractive.ORDER_CONFIRMATION_SENT_BY_CLIENT_EVENT,
148 GameDistributorInteractive.RFQ_SENT_BY_CLIENT_EVENT,
149 GameDistributorInteractive.SELECTED_QUOTE_EVENT,
150 GameDistributorInteractive.PAY_BILL_EVENT,
151 GameDistributorInteractive.QUOTE_SENT_BY_CLIENT_EVENT,
152 GameDistributorInteractive.RFQ_DELETED_BY_CLIENT_EVENT};
153
154 /*** the SingleUserInteractionLayerInterface */
155 private SingleUserInteractionLayerInterface singleUserInteractionLayer;
156
157 /***
158 * constructs a new GameDistributorInteractive; used when dragging and
159 * dropping an actor
160 *
161 * @param name the name
162 * @param simulator the simulator
163 * @param position the position
164 * @param bank the bank
165 */
166 public GameDistributorInteractive(final String name,
167 final DEVSSimulatorInterface simulator, final Point3d position,
168 final Bank bank)
169 {
170 super(name, simulator, position, bank);
171 }
172
173 /***
174 * constructs a new GameDistributorInteractive
175 *
176 * @param globalSupplyChainData the global supply chain data
177 * @param name the name
178 * @param simulator the simulator
179 * @param position the position
180 * @param roles the roles to implement
181 * @param bank the bank
182 * @param initialBankAccount the initial bank account
183 * @param product the product
184 * @param amount the amount
185 * @param manufacturer the manufacturer
186 */
187 public GameDistributorInteractive(
188 final GameGlobalData globalSupplyChainData, final String name,
189 final DEVSSimulatorInterface simulator, final Point3d position,
190 final Role[] roles, final Bank bank,
191 final double initialBankAccount, final Product[] product,
192 final Double[] amount, final Trader[] manufacturer)
193 {
194 super(name, simulator, position, roles, bank, initialBankAccount,
195 product, amount, manufacturer, globalSupplyChainData);
196 }
197
198 /***
199 * constructs a new GameDistributorInteractive
200 *
201 * @param globalSupplyChainData the global supply chain data
202 * @param name the name
203 * @param simulator the simulator
204 * @param position the position
205 * @param roles the roles to implement
206 * @param bank the bank
207 * @param product the product
208 * @param amount the amount
209 * @param manufacturer the manufacturer
210 */
211 public GameDistributorInteractive(
212 final GameGlobalData globalSupplyChainData, final String name,
213 final DEVSSimulatorInterface simulator, final Point3d position,
214 final Role[] roles, final Bank bank, final Product[] product,
215 final Double[] amount, final Trader[] manufacturer)
216 {
217 super(name, simulator, position, roles, bank, product, amount,
218 manufacturer, globalSupplyChainData);
219 }
220
221 /***
222 * @see org.gscg.gameactors.GameDistributor#init()
223 */
224 protected void init()
225 {
226
227
228
229
230 Properties properties = new Properties();
231 try
232 {
233 properties.load(URLResource
234 .getResourceAsStream("/distributor.properties"));
235 } catch (Exception exception)
236 {
237 exception.printStackTrace();
238 }
239 if (properties.getProperty(this.name) != null)
240 {
241 String result = properties.getProperty(this.name);
242 if (result.equalsIgnoreCase("false"))
243 {
244 super.humanControlled = false;
245 Logger.info(this, "init", "GameDistributorInteractive: "
246 + this.name + " set to computer-controlled mode");
247 this.addComputerControlledContentHandlers();
248 } else if (result.equalsIgnoreCase("true"))
249 {
250 try
251 {
252 if (this.simulator.getReplication().getRunControl()
253 .getWarmupPeriod() > 0.0)
254 {
255
256
257
258
259
260 this.simulator.addListener(this,
261 SimulatorInterface.WARMUP_EVENT);
262 super.humanControlled = false;
263 super.warmingUp = true;
264 Logger
265 .info(
266 this,
267 "init",
268 "GameDistributorInteractive: "
269 + this.name
270 + " set to computer-controlled mode due to the presence of a warm-up period.");
271 this.addComputerControlledContentHandlers();
272 } else
273 {
274 super.humanControlled = true;
275 Logger.info(this, "init",
276 "GameDistributorInteractive: " + this.name
277 + " set to interactive mode");
278 this.addInteractiveContentHandlers();
279 }
280 } catch (RemoteException remoteException)
281 {
282 Logger.severe(this, "init", remoteException);
283 }
284 }
285 } else
286 {
287
288 Logger.severe(this, "init",
289 "GameDistributorInteractive: no key found for " + this.name
290 + " in properties: ." + properties);
291 }
292
293
294
295
296 try
297 {
298 if (this.simulator instanceof AnimatorInterface)
299 {
300 XYChart bankChart = new XYChart(this.simulator, "BankAccount "
301 + this.name);
302 bankChart.add("bank account", this.bankAccount,
303 BankAccount.BANK_ACCOUNT_CHANGED_EVENT);
304 }
305 } catch (RemoteException remoteException)
306 {
307 Logger.severe(this, "init", remoteException);
308 }
309 }
310
311 /***
312 * @see org.gscg.gameactors.GameDistributor#addDevices()
313 */
314 protected void addDevices()
315 {
316 try
317 {
318 StreamInterface stream = this.simulator.getReplication().getStream(
319 "default");
320 double hour = TimeUnit.convert(1.0, TimeUnitInterface.HOUR,
321 this.simulator);
322 DistContinuous hourDist = new DistConstant(stream, hour);
323
324 FaxDevice fax = new FaxDevice("GameDistributorFax", this.simulator);
325 addSendingDevice(fax);
326 MessageHandlerInterface secretary = new HandleAllMessages(this);
327 addReceivingDevice(fax, secretary, hourDist);
328 } catch (RemoteException remoteException)
329 {
330 Logger.severe(this, "addDevices", remoteException);
331 }
332 }
333
334 /***
335 * @see org.gscg.common.interactionlayer.AnnounceInterface#announce(nl.tudelft.simulation.event.EventType,
336 * boolean)
337 */
338 public void announce(final EventType eventType, final boolean announce)
339 {
340 if (eventType.equals(StockInterface.STOCK_CHANGE_EVENT))
341 {
342 List products = super.getProductsOnStock();
343 for (int i = 0; i < products.size(); i++)
344 {
345 Product product = (Product) products.get(i);
346 this.stock.getActualAmount(product);
347 StockUpdateData data = new StockUpdateData(product.getName(),
348 this.stock.getActualAmount(product), this.stock
349 .getClaimedAmount(product), this.stock
350 .getOrderedAmount(product));
351 try
352 {
353 this.singleUserInteractionLayer.notifyAnnounced(new Event(
354 StockInterface.STOCK_CHANGE_EVENT, this, data));
355 } catch (RemoteException remoteException)
356 {
357 Logger.severe(this, "announce", remoteException);
358 }
359 }
360 return;
361 }
362 new ReceivedUnknownEventException(this, "announce", eventType);
363 }
364
365 /***
366 * @see nl.tudelft.simulation.event.EventListenerInterface#notify(nl.tudelft.simulation.event.EventInterface)
367 */
368 public void notify(final EventInterface event)
369 {
370 if (event.getType().equals(GlobalRowOrColumnNumber.UPDATE_CURRENT_DAY))
371 {
372
373 this.sendStockUpdateEvent();
374 this.bankAccount.sendBalanceUpdateEvent();
375 return;
376 }
377 if (event.getType().equals(
378 GameDistributorInteractive.RFQ_SENT_BY_CLIENT_EVENT))
379 {
380
381 RFQDataSuppliers submitRFQData = (RFQDataSuppliers) event
382 .getContent();
383 Product product = this.globalSupplyChainData
384 .getProduct(submitRFQData.getProductName());
385 double earliestDeliveryDate = DateIntData.makeSimulationDate(
386 submitRFQData.getEarliestDelivery(), this.simulator);
387
388 double latestDeliveryDate = DateIntData.makeSimulationDate(
389 submitRFQData.getLatestDelivery(), this.simulator);
390
391
392 try
393 {
394 if (earliestDeliveryDate > this.simulator.getSimulatorTime())
395 {
396 InternalDemand internalDemand = new InternalDemand(this,
397 product, submitRFQData.getAmount(),
398 earliestDeliveryDate, latestDeliveryDate);
399 String[] suppliers = submitRFQData.getSuppliers();
400 handleContent(internalDemand);
401
402 for (int i = 0; i < suppliers.length; i++)
403 {
404 SupplyChainActor supplier = this.globalSupplyChainData
405 .getSupplyChainActor(suppliers[i]);
406 RequestForQuote rfq = new RequestForQuote(this,
407 supplier, internalDemand, product,
408 submitRFQData.getAmount());
409 this.sendContent(rfq, 0.0);
410 }
411 } else
412 {
413 Logger
414 .info(
415 this,
416 "notify",
417 "GameDistributorInteractive did not send RFQ since the earliest delivery date has already been passed in the game.");
418 }
419 } catch (RemoteException remoteException)
420 {
421 Logger.severe(this, "notify", remoteException);
422 }
423 return;
424 }
425 if (event.getType().equals(
426 GameDistributorInteractive.SELECTED_QUOTE_EVENT))
427 {
428 QuoteData data = (QuoteData) event.getContent();
429
430
431 SupplyChainActor sender = this.globalSupplyChainData
432 .getSupplyChainActor(data.getSenderName());
433 try
434 {
435 double proposedDeliveryDate = DateIntData.makeSimulationDate(
436 data.getProposedDelivery(), this.simulator);
437
438 List quotes = super.getGameContentStore().getContentList(
439 data.getRfqData().getInternalDemandIdentifier(),
440 Quote.class, false);
441 OrderBasedOnQuote order = null;
442 for (int i = 0; i < quotes.size(); i++)
443 {
444 Quote quote = (Quote) quotes.get(i);
445 if (quote.getSender().getName().equalsIgnoreCase(
446 sender.getName()))
447 {
448 order = new OrderBasedOnQuote(quote.getReceiver(),
449 quote.getSender(), data.getRfqData()
450 .getInternalDemandIdentifier(),
451 proposedDeliveryDate, quote);
452 break;
453 }
454 }
455
456
457
458
459 if (order != null)
460 {
461 super.interactiveQuoteHandler.addAnsweredQuote(order
462 .getQuote());
463 }
464
465 this.sendContent(order, 0.0);
466
467
468 for (int i = 0; i < quotes.size(); i++)
469 {
470 super.getGameContentStore().removeContent(
471 (Content) quotes.get(i), false);
472 }
473 } catch (Exception exception)
474 {
475 Logger.severe(this, "notify", exception);
476 }
477 return;
478 }
479 if (event.getType().equals(GameDistributorInteractive.PAY_BILL_EVENT))
480 {
481 BillData data = (BillData) event.getContent();
482 Bill bill = (Bill) super.getGameContentStore().getContentList(
483 data.getInternalDemandID(), Bill.class, false).get(0);
484 if (bill == null)
485 {
486 Logger.severe(this, "notify PAY_BILL_EVENT",
487 "bill not found in ContentStore");
488 } else
489 {
490
491 this.pay(bill);
492
493
494 Payment payment = new Payment(bill.getReceiver(), bill
495 .getSender(), bill.getInternalDemandID(), bill, bill
496 .getPrice());
497 this.sendContent(payment, 0.0);
498 }
499 return;
500 }
501 if (event.getType().equals(
502 GameDistributorInteractive.QUOTE_SENT_BY_CLIENT_EVENT))
503 {
504 SentQuoteData data = (SentQuoteData) event.getContent();
505 try
506 {
507 SupplyChainActor sender = this.globalSupplyChainData
508 .getSupplyChainActor(data.getSenderName());
509 SupplyChainActor receiver = this.globalSupplyChainData
510 .getSupplyChainActor(data.getReceiverName());
511
512
513 List rfqs = super.getGameContentStore().getContentList(
514 data.getRfqData().getInternalDemandIdentifier(),
515 RequestForQuote.class, false);
516 RequestForQuote rfq = null;
517 for (int i = 0; i < rfqs.size(); i++)
518 {
519 RequestForQuote result = (RequestForQuote) rfqs.get(i);
520 if (result.getReceiver().getName().equalsIgnoreCase(
521 sender.getName()))
522 {
523 rfq = result;
524 break;
525 }
526 }
527
528 double proposedDeliveryDate = DateIntData.makeSimulationDate(
529 data.getProposedDelivery(), this.simulator);
530
531 if (proposedDeliveryDate > this.simulator.getSimulatorTime())
532 {
533 double price = data.getPrice();
534
535 double weight = rfq.getAmount()
536 * rfq.getProduct().getAverageUnitWeight();
537
538
539 double transportCosts = TransportMode.PLANE.transportCosts(
540 super.latLonDistanceCalculator.getDistance(rfq
541 .getSender(), rfq.getReceiver()), weight);
542
543
544 price += transportCosts;
545
546 Quote quote = new Quote(sender, receiver, data.getRfqData()
547 .getInternalDemandIdentifier(), rfq, rfq
548 .getProduct(), data.getAmount(), price,
549 proposedDeliveryDate, TransportMode.PLANE);
550 this.sendContent(quote, 0.0);
551 } else
552 {
553 Logger
554 .info(
555 this,
556 "notify",
557 "GameDistributorInteractive did not send Quote since the proposed delivery date has already been passed in the game. The accompanying rfq has been deleted.");
558
559
560 super.getGameContentStore().removeContent(rfq, false);
561 }
562 } catch (Exception exception)
563 {
564 Logger.severe(this, "notify", exception);
565 }
566 return;
567 }
568 if (event.getType().equals(
569 GameDistributorInteractive.RFQ_DELETED_BY_CLIENT_EVENT))
570 {
571 RFQData data = (RFQData) event.getContent();
572 try
573 {
574 SupplyChainActor receiver = this.globalSupplyChainData
575 .getSupplyChainActor(data.getReceiverName());
576
577
578 List rfqs = super.getGameContentStore().getContentList(
579 data.getInternalDemandIdentifier(),
580 RequestForQuote.class, false);
581 RequestForQuote rfq = null;
582 for (int i = 0; i < rfqs.size(); i++)
583 {
584 RequestForQuote result = (RequestForQuote) rfqs.get(i);
585 if (result.getReceiver().getName().equalsIgnoreCase(
586 receiver.getName()))
587 {
588 rfq = result;
589 break;
590 }
591 }
592
593
594 super.getGameContentStore().removeContent(rfq, false);
595 } catch (Exception exception)
596 {
597 Logger.severe(this, "notify", exception);
598 }
599 return;
600
601 }
602 if (event
603 .getType()
604 .equals(
605 GameDistributorInteractive.ORDER_CONFIRMATION_SENT_BY_CLIENT_EVENT))
606 {
607 SentOrderConfirmationData data = (SentOrderConfirmationData) event
608 .getContent();
609 try
610 {
611 SupplyChainActor sender = this.globalSupplyChainData
612 .getSupplyChainActor(data.getSenderName());
613 SupplyChainActor receiver = this.globalSupplyChainData
614 .getSupplyChainActor(data.getReceiverName());
615 Order order = (Order) super.getGameContentStore()
616 .getContentList(
617 data.getOrderData().getInternalDemandID(),
618 Order.class, false).get(0);
619 if (order == null)
620 {
621 Logger.severe(this,
622 "notify ORDER_CONFIRMATION_SENT_BY_CLIENT_EVENT",
623 "order not found in ContentStore");
624 } else
625 {
626 OrderConfirmation confirmation = new OrderConfirmation(
627 sender, receiver, data.getOrderData()
628 .getInternalDemandID(), order, data
629 .getConfirmationStatus());
630
631 this.sendContent(confirmation, 0.0);
632 InteractiveOrderHandlerStock handler = new InteractiveOrderHandlerStock(
633 this, super.stock);
634 handler.handleOrder(order);
635
636
637 super.customerStatistics.handleContent(confirmation);
638 }
639 return;
640 } catch (Exception exception)
641 {
642 Logger.severe(this, "notify", exception);
643 }
644 return;
645 }
646 if (event.getType().equals(SimulatorInterface.WARMUP_EVENT))
647 {
648 super.humanControlled = true;
649 super.warmingUp = false;
650 Logger
651 .info(
652 this,
653 "init",
654 "GameDistributorInteractive: "
655 + this.name
656 + " set to interactive mode since the warm-up period has been finished");
657 this.addInteractiveContentHandlers();
658 return;
659 }
660 new ReceivedUnknownEventException(this, "notify", event.getType());
661 }
662
663 /***
664 * pays the bill
665 *
666 * @param bill the bill to pay
667 */
668 public void pay(final Bill bill)
669 {
670 this.bankAccount.withdrawFromBalance(bill.getPrice());
671 }
672
673 /***
674 * @see nl.tudelft.simulation.content.HandlerInterface#handleContent(java.io.Serializable)
675 */
676 public boolean handleContent(final Serializable content)
677 {
678 try
679 {
680 if (super.humanControlled)
681 {
682 if (content instanceof Quote)
683 {
684
685 if (super.interactiveQuoteHandler.handleContent(content))
686 {
687
688 super.getContentStore().addContent((Content) content,
689 false);
690 }
691 return true;
692 }
693 }
694 return super.handleContent(content);
695 } catch (Exception exception)
696 {
697 Logger.severe(this, "handleContent", exception);
698 return false;
699 }
700 }
701
702 /***
703 * @see nl.tudelft.simulation.supplychain.actor.SupplyChainActor#sendContent(nl.tudelft.simulation.supplychain.content.Content,
704 * double)
705 */
706 public void sendContent(final Content content,
707 final double administrativeDelay)
708 {
709 super.sendContent(content, administrativeDelay);
710 }
711
712 /***
713 * @see org.gscg.gameactors.GameActorInteractiveInterface#getSingleUserInteractionLayer()
714 */
715 public SingleUserInteractionLayerInterface getSingleUserInteractionLayer()
716 {
717 return this.singleUserInteractionLayer;
718 }
719
720 /***
721 * @see org.gscg.gameactors.GameActorInteractiveInterface#setSingleUserInteractionLayer(org.gscg.singleuser.interactionlayer.SingleUserInteractionLayerInterface)
722 */
723 public void setSingleUserInteractionLayer(
724 final SingleUserInteractionLayerInterface singleUserInteractionLayer)
725 {
726 this.singleUserInteractionLayer = singleUserInteractionLayer;
727 getGameContentStore().setSingleUserInteractionlayer(
728 this.singleUserInteractionLayer);
729
730 try
731 {
732 for (int i = 0; i < this.eventsSentByClientArray.length; i++)
733 {
734 this.singleUserInteractionLayer.addListener(this,
735 this.eventsSentByClientArray[i], false);
736
737 this.singleUserInteractionLayer
738 .addEventTypeSentByClient(this.eventsSentByClientArray[i]);
739
740 }
741
742
743
744 singleUserInteractionLayer.addEventTypeToAnnounceList(
745 StockInterface.STOCK_CHANGE_EVENT, this);
746
747
748
749
750
751
752 this.singleUserInteractionLayer.addListener(this,
753 GlobalRowOrColumnNumber.UPDATE_CURRENT_DAY);
754 } catch (RemoteException remoteException)
755 {
756 Logger.severe(this, "<init>", remoteException);
757 }
758
759
760
761
762 this.customerStatistics = new CustomerStatistics(this.simulator,
763 this.singleUserInteractionLayer);
764 }
765
766 /***
767 * adds computer-controlled interactive content handlers
768 */
769 public void addComputerControlledContentHandlers()
770 {
771 super.addComputerControlledContentHandlers();
772 }
773
774 /***
775 * adds interactive content handlers
776 */
777 public void addInteractiveContentHandlers()
778 {
779
780 this.removeAllContentHandlers();
781
782
783 URL url = URLResource.getResource("/" + this.name + "_interactive.xml");
784 if (url == null)
785 {
786 url = URLResource
787 .getResource("/distributor_interactive_default_handler.xml");
788 }
789 Logger
790 .info(
791 this,
792 "addInteractiveContentHandlers",
793 "Using: "
794 + url.toExternalForm()
795 + " as the file containing the configuration for the handlers.");
796 try
797 {
798
799 Element rootElement = GameDistributor.builder.build(url)
800 .getRootElement();
801 HandlerParser.parseAndAddHandler(this, rootElement);
802 } catch (Exception exception)
803 {
804 Logger.severe(this, "addInteractiveContentHandlers", exception);
805 }
806 }
807
808
809 /***
810 * Method sendStockUpdateEvent fires an update for all the products
811 * available in the stock
812 */
813 private void sendStockUpdateEvent()
814 {
815 for (Iterator i = this.stock.iterator(); i.hasNext();)
816 {
817 this.stock.sendStockUpdateEvent((Product) i.next());
818 }
819 }
820
821 /***
822 * writes a serializable method to stream
823 *
824 * @param out the outputstream
825 * @throws IOException on IOException
826 */
827 private synchronized void writeObject(final ObjectOutputStream out)
828 throws IOException
829 {
830 out.defaultWriteObject();
831 }
832
833 /***
834 * reads a serializable method from stream
835 *
836 * @param in the inputstream
837 */
838 private synchronized void readObject(final java.io.ObjectInputStream in)
839 {
840 try
841 {
842 in.defaultReadObject();
843
844
845
846
847 Properties properties = new Properties();
848 try
849 {
850 properties.load(URLResource
851 .getResourceAsStream("/distributor.properties"));
852 } catch (Exception exception)
853 {
854 exception.printStackTrace();
855 }
856 if (properties.getProperty(this.name) != null)
857 {
858 String result = properties.getProperty(this.name);
859 if (result.equalsIgnoreCase("false"))
860 {
861
862
863
864
865
866 if (super.humanControlled)
867 {
868 GameDistributorInteractive.distributors.add(this);
869 super.humanControlled = false;
870 System.out
871 .println("GameDistributorInteractive: "
872 + this.name
873 + ": mode has been changed to computer-controlled mode");
874 }
875 } else if (result.equalsIgnoreCase("true"))
876 {
877
878
879
880
881
882
883 if (!super.humanControlled && !super.warmingUp)
884 {
885 System.out
886 .println("GameDistributorInteractive: Deserializing: "
887 + this + " warm-up finished");
888 GameDistributorInteractive.distributors.add(this);
889 super.humanControlled = true;
890 System.out
891 .println("GameDistributorInteractive: "
892 + this.name
893 + ": mode has been changed to interactive mode");
894 } else if (!super.humanControlled)
895 {
896 System.out.println("Deserializing: " + this
897 + " however warm-up not finished yet");
898 }
899 }
900 } else
901 {
902
903 System.out
904 .println("GameDistributorInteractive: no key found for "
905 + this.name + " in properties.");
906 }
907 } catch (IOException exception)
908 {
909 Logger.severe(this, "readObject", exception);
910 } catch (ClassNotFoundException exception)
911 {
912 Logger.severe(this, "readObject", exception);
913 }
914 }
915 }