View Javadoc

1   /*
2    * @(#)GameGlobalData.java Jul 10, 2004
3    * 
4    * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
5    * Delft, the Netherlands. All rights reserved.
6    * 
7    * See for project information <a href="http://www.simulation.tudelft.nl/">
8    * www.simulation.tudelft.nl </a>.
9    * 
10   * The source code and binary code of this software is proprietary information
11   * of Delft University of Technology.
12   */
13  
14  package org.gscg.game;
15  
16  import java.io.BufferedWriter;
17  import java.io.FileWriter;
18  import java.io.Serializable;
19  import java.text.DateFormat;
20  import java.util.Calendar;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.TreeMap;
27  
28  import nl.tudelft.simulation.dsol.experiment.TimeUnit;
29  import nl.tudelft.simulation.dsol.experiment.TimeUnitInterface;
30  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
31  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
32  import nl.tudelft.simulation.language.swing.SwingWorker;
33  import nl.tudelft.simulation.logger.Logger;
34  import nl.tudelft.simulation.naming.InitialEventContext;
35  import nl.tudelft.simulation.supplychain.actor.SupplyChainActor;
36  import nl.tudelft.simulation.supplychain.content.Bill;
37  import nl.tudelft.simulation.supplychain.product.Product;
38  
39  import org.gscg.common.GameActorInterface;
40  import org.gscg.common.interactionlayer.location.YellowPage;
41  import org.gscg.gameactors.GameDistributorInteractive;
42  
43  /***
44   * The GameGlobalData contains all the data of the game, e.g. the products and
45   * actors. Furthermore it takes care of providing game-wide statistics. <br>
46   * Copyright (c) 2003-2005 Delft University of Technology, Jaffalaan 5, 2628 BX
47   * Delft, the Netherlands. All rights reserved.
48   * 
49   * See for project information <a href="http://www.simulation.tudelft.nl/">
50   * www.simulation.tudelft.nl </a>.
51   * 
52   * The source code and binary code of this software is proprietary information
53   * of Delft University of Technology.
54   * 
55   * @author <a
56   *         href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
57   *         Verbraeck </a>
58   * @version $Revision: 1.1 $ $Date: 2005/08/03 08:52:49 $
59   * @since 1.0.0 <br>
60   */
61  
62  public class GameGlobalData implements Serializable
63  {
64  	/*** the serial version uid */
65  	private static final long serialVersionUID = 11L;
66  
67  	/*** the name of this object in the context */
68  	public static final String CONTEXT_NAME = "GAME_GLOBAL_DATA";
69  
70  	/*** the map of product names to product objects */
71  	private Map products = new HashMap();
72  
73  	/*** the map of actor names to actor objects */
74  	private Map actors = new HashMap();
75  
76  	/*** the locations and names of the actors */
77  	private YellowPage yellowPage = new YellowPage();
78  
79  	/*** the simulator to use */
80  	private SimulatorInterface simulator = null;
81  
82  	/***
83  	 * constructs a new GlobalSupplyChainData
84  	 * 
85  	 * @param simulator the simulator to use
86  	 */
87  	public GameGlobalData(final SimulatorInterface simulator)
88  	{
89  		super();
90  		// we bind ourselves into the context
91  		try
92  		{
93  			new InitialEventContext().bind(GameGlobalData.CONTEXT_NAME, this);
94  		} catch (Exception exception)
95  		{
96  			Logger.severe(this, "<init>", exception);
97  		}
98  
99  		this.simulator = simulator;
100 
101 		// schedule the tally
102 
103 		/*
104 		 * try { ((DEVSSimulatorInterface) this.simulator).scheduleEvent(1.1,
105 		 * TimeUnitInterface.DAY, this, this, "printTally", new Object[]{}); }
106 		 * catch (Exception exception) { Logger.severe(this, " <init>",
107 		 * exception); }
108 		 */
109 		// schedule output of the balance sheet
110 		try
111 		{
112 			((DEVSSimulatorInterface) this.simulator).scheduleEvent(1.1,
113 					TimeUnitInterface.DAY, this, this, "printBalanceSheet",
114 					new Object[]{});
115 		} catch (Exception exception)
116 		{
117 			Logger.severe(this, " <init>", exception);
118 		}
119 
120 	}
121 
122 	/***
123 	 * @param product the product to add
124 	 */
125 	public void addProduct(final Product product)
126 	{
127 		this.products.put(product.getName(), product);
128 	}
129 
130 	/***
131 	 * @param name the name of the product to get
132 	 * @return returns the Product
133 	 */
134 	public Product getProduct(final String name)
135 	{
136 		return (Product) this.products.get(name);
137 	}
138 
139 	/***
140 	 * @return returns a collection of Products
141 	 */
142 	public Collection getProducts()
143 	{
144 		return this.products.values();
145 	}
146 
147 	/***
148 	 * @param actor the actor to add
149 	 * @param actorType the type of the actor
150 	 * @param interactive indicates whether the actor is human controlled or not
151 	 */
152 	public void addSupplyChainActor(final SupplyChainActor actor,
153 			final String actorType, final boolean interactive)
154 	{
155 		this.actors.put(actor.getName(), actor);
156 		this.yellowPage.addActor((GameActorInterface) actor, actorType,
157 				interactive);
158 	}
159 
160 	/***
161 	 * @param name the name of the actor to get
162 	 * @return returns a SupplyChain actor
163 	 */
164 	public SupplyChainActor getSupplyChainActor(final String name)
165 	{
166 		return (SupplyChainActor) this.actors.get(name);
167 	}
168 
169 	/***
170 	 * @return returns a collection of SupplyChainActors
171 	 */
172 	public Collection getSupplyChainActors()
173 	{
174 		return this.actors.values();
175 	}
176 
177 	/***
178 	 * @return Returns the yellowPage.
179 	 */
180 	public YellowPage getYellowPage()
181 	{
182 		return this.yellowPage;
183 	}
184 
185 	/***
186 	 * Prints a balance sheet to the output stream
187 	 */
188 	protected void printBalanceSheet()
189 	{
190 		SwingWorker worker = new SwingWorker()
191 		{
192 			/***
193 			 * @see nl.tudelft.simulation.language.swing.SwingWorker#construct()
194 			 */
195 			public Object construct()
196 			{
197 				GameGlobalData.this.balanceSheetWorker();
198 				return null;
199 			}
200 		};
201 		worker.start();
202 
203 		try
204 		{
205 			((DEVSSimulatorInterface) this.simulator).scheduleEvent(7.0,
206 					TimeUnitInterface.DAY, this, this, "printBalanceSheet",
207 					new Object[]{});
208 		} catch (Exception exception)
209 		{
210 			Logger.severe(this, "printBalanceSheet", exception);
211 		}
212 	}
213 
214 	/***
215 	 * Prints a tally to the output stream
216 	 */
217 	protected void printTally()
218 	{
219 		SwingWorker worker = new SwingWorker()
220 		{
221 			/***
222 			 * @see nl.tudelft.simulation.language.swing.SwingWorker#construct()
223 			 */
224 			public Object construct()
225 			{
226 				GameGlobalData.this.tallyWorker();
227 				return null;
228 			}
229 		};
230 		worker.start();
231 
232 		try
233 		{
234 			((DEVSSimulatorInterface) this.simulator).scheduleEvent(30.1,
235 					TimeUnitInterface.DAY, this, this, "printTally",
236 					new Object[]{});
237 		} catch (Exception exception)
238 		{
239 			Logger.severe(this, "printTally", exception);
240 		}
241 
242 	}
243 
244 	/***
245 	 * Executed in a swing thread.
246 	 */
247 	private void tallyWorker()
248 	{
249 		try
250 		{
251 			double time = Math.round(TimeUnit.convert(this.simulator
252 					.getSimulatorTime(), this.simulator.getReplication()
253 					.getRunControl().getTreatment().getTimeUnit(),
254 					TimeUnitInterface.DAY));
255 
256 			Calendar calendar = Calendar.getInstance();
257 			calendar.setTimeInMillis(System.currentTimeMillis());
258 			String date = DateFormat.getDateTimeInstance().format(
259 					calendar.getTime());
260 
261 			// replace any :
262 			String[] dates = date.split(":");
263 			date = dates[0] + "_" + dates[1] + "_" + dates[2];
264 
265 			// we pause for a brief moment
266 			// this.simulator.stop();
267 
268 			// we write these objects first since they are used to create a
269 			// context
270 			BufferedWriter out = new BufferedWriter(new FileWriter("_TALLY"
271 					+ " time in days " + time + " wallclock " + date + ".xls"));
272 
273 			// the headers
274 			out.write("Name" + "\t");
275 			out.write("Location" + "\t");
276 			out.write("Bank Account" + "\t");
277 			out.write("Product" + "\t");
278 			out.write("Actual Amount" + "\t");
279 			out.write("Value" + "\t");
280 			out.write("Claimed Amount" + "\t");
281 			out.write("Value" + "\t");
282 			out.write("Ordered Amount" + "\t");
283 			out.write("Value" + "\t");
284 			out.write("" + "\n");
285 
286 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
287 			{
288 				Object actor = this.actors.get(it.next());
289 				double finpos = 0.0;
290 
291 				if (actor instanceof GameDistributorInteractive)
292 				{
293 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
294 					out.write(interactive.getName() + "\t"
295 							+ interactive.getLocationDescription() + "\t" + ""
296 							+ interactive.getBankAccount().getBalance() + "\t");
297 					finpos += interactive.getBankAccount().getBalance();
298 					for (Iterator stockIterator = interactive.getStock()
299 							.iterator(); stockIterator.hasNext();)
300 					{
301 						Product product = (Product) stockIterator.next();
302 						out.write(product.getName() + "\t");
303 						out.write(""
304 								+ interactive.getStock().getActualAmount(
305 										product) + "\t");
306 						double actualValue = interactive.getStock()
307 								.getActualAmount(product)
308 								* product.getUnitMarketPrice();
309 						finpos += actualValue;
310 						out.write("" + actualValue + "\t");
311 						out.write(""
312 								+ interactive.getStock().getClaimedAmount(
313 										product) + "\t");
314 						double claimedValue = interactive.getStock()
315 								.getClaimedAmount(product)
316 								* product.getUnitMarketPrice();
317 						// finpos += claimedValue;
318 						out.write("" + claimedValue + "\t");
319 						out.write(""
320 								+ interactive.getStock().getOrderedAmount(
321 										product) + "\t");
322 						double orderedValue = interactive.getStock()
323 								.getOrderedAmount(product)
324 								* product.getUnitMarketPrice();
325 						finpos -= orderedValue;
326 						out.write("" + orderedValue + "\t");
327 
328 					}
329 					// the financial position
330 					out.write("" + finpos + "\n");
331 				}
332 			}
333 
334 			// close the stream
335 			out.close();
336 
337 		} catch (Exception exception)
338 		{
339 			// TODO make logger dependent
340 			exception.printStackTrace();
341 		}
342 
343 		/*
344 		 * try { this.simulator.start(); } catch (Exception exception) {
345 		 * Logger.severe(this, "printTally", exception); }
346 		 */
347 		Logger.info(this, "printTally", "GlobalSupplyChainData: tally written");
348 	}
349 
350 	/***
351 	 * Executed in a swing thread.
352 	 */
353 	private void balanceSheetWorker()
354 	{
355 		try
356 		{
357 			// the intermediate results
358 			Map assetsPerActor = new TreeMap();
359 			Map liabilitiesPerActor = new TreeMap();
360 			Map equityPerActor = new TreeMap();
361 
362 			double time = Math.round(TimeUnit.convert(this.simulator
363 					.getSimulatorTime(), this.simulator.getReplication()
364 					.getRunControl().getTreatment().getTimeUnit(),
365 					TimeUnitInterface.DAY));
366 
367 			Calendar calendar = Calendar.getInstance();
368 			calendar.setTimeInMillis(System.currentTimeMillis());
369 			String date = DateFormat.getDateTimeInstance().format(
370 					calendar.getTime());
371 
372 			// replace any :
373 			String[] dates = date.split(":");
374 			date = dates[0] + "_" + dates[1] + "_" + dates[2];
375 
376 			// we pause for a brief moment
377 			// this.simulator.stop();
378 
379 			// we write these objects first since they are used to create a
380 			// context
381 			BufferedWriter out = new BufferedWriter(new FileWriter(
382 					"_BALANCESHEET" + " time in days " + time + " wallclock "
383 							+ date + ".xls"));
384 
385 			// the headers
386 			out.write("Balance sheet " + " time in days " + time
387 					+ " wallclock " + date + "\n");
388 			out.write("\n");
389 
390 			// the names of the actors
391 			out.write("Name\t");
392 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
393 			{
394 				Object actor = this.actors.get(it.next());
395 				if (actor instanceof GameDistributorInteractive)
396 				{
397 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
398 					out.write(interactive.getName() + "\t");
399 				}
400 			}
401 			out.write("\n");
402 
403 			// the locations of the actors
404 			out.write("Location\t");
405 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
406 			{
407 				Object actor = this.actors.get(it.next());
408 				if (actor instanceof GameDistributorInteractive)
409 				{
410 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
411 					out.write(interactive.getLocationDescription() + "\t");
412 				}
413 			}
414 			out.write("\n");
415 
416 			// cash
417 			out.write("\nASSETS\nCash & equivalents\t");
418 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
419 			{
420 				Object actor = this.actors.get(it.next());
421 				if (actor instanceof GameDistributorInteractive)
422 				{
423 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
424 					out.write(Math.round(interactive.getBankAccount()
425 							.getBalance())
426 							+ "\t");
427 					assetsPerActor.put(interactive.getName(), new Double(
428 							interactive.getBankAccount().getBalance()));
429 				}
430 			}
431 			out.write("\n");
432 
433 			// accounts receivable
434 			out.write("Accounts receivable\t");
435 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
436 			{
437 				Object actor = this.actors.get(it.next());
438 				if (actor instanceof GameDistributorInteractive)
439 				{
440 					double ar = 0.0;
441 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
442 					for (Iterator stockIterator = interactive.getStock()
443 							.iterator(); stockIterator.hasNext();)
444 					{
445 						Product product = (Product) stockIterator.next();
446 						List billList = interactive.getGameContentStore()
447 								.getAllProductContent(Bill.class, true,
448 										product.getName());
449 						for (Iterator billIterator = billList.iterator(); billIterator
450 								.hasNext();)
451 						{
452 							Bill bill = (Bill) billIterator.next();
453 							if (!bill.isPaid())
454 							{
455 								ar += bill.getPrice();
456 							}
457 						}
458 					}
459 					out.write(Math.round(ar) + "\t");
460 					assetsPerActor.put(interactive.getName(),
461 							new Double(((Double) assetsPerActor.get(interactive
462 									.getName())).doubleValue()
463 									+ ar));
464 				}
465 			}
466 			out.write("\n");
467 
468 			// inventory after depreciation
469 			out.write("Inventory\t");
470 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
471 			{
472 				Object actor = this.actors.get(it.next());
473 				if (actor instanceof GameDistributorInteractive)
474 				{
475 					double inv = 0.0;
476 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
477 					for (Iterator stockIterator = interactive.getStock()
478 							.iterator(); stockIterator.hasNext();)
479 					{
480 						Product product = (Product) stockIterator.next();
481 						inv += interactive.getStock().getActualAmount(product)
482 								* interactive.getStock().getUnitPrice(product);
483 					}
484 					out.write(Math.round(inv) + "\t");
485 					assetsPerActor.put(interactive.getName(),
486 							new Double(((Double) assetsPerActor.get(interactive
487 									.getName())).doubleValue()
488 									+ inv));
489 				}
490 			}
491 			out.write("\n");
492 
493 			// total assets
494 			out.write("TOTAL ASSETS\t");
495 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
496 			{
497 				Object actor = this.actors.get(it.next());
498 				if (actor instanceof GameDistributorInteractive)
499 				{
500 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
501 					double as = ((Double) assetsPerActor.get(interactive
502 							.getName())).doubleValue();
503 					out.write(Math.round(as) + "\t");
504 				}
505 			}
506 			out.write("\n");
507 
508 			// accounts payable
509 			out.write("\nLIABILITIES\nAccounts payable\t");
510 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
511 			{
512 				Object actor = this.actors.get(it.next());
513 				if (actor instanceof GameDistributorInteractive)
514 				{
515 					double ap = 0.0;
516 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
517 					for (Iterator stockIterator = interactive.getStock()
518 							.iterator(); stockIterator.hasNext();)
519 					{
520 						Product product = (Product) stockIterator.next();
521 						List billList = interactive.getGameContentStore()
522 								.getAllProductContent(Bill.class, false,
523 										product.getName());
524 						for (Iterator billIterator = billList.iterator(); billIterator
525 								.hasNext();)
526 						{
527 							Bill bill = (Bill) billIterator.next();
528 							if (!bill.isPaid())
529 							{
530 								ap += bill.getPrice();
531 							}
532 						}
533 					}
534 					out.write(Math.round(ap) + "\t");
535 					liabilitiesPerActor.put(interactive.getName(), new Double(
536 							ap));
537 				}
538 			}
539 			out.write("\n");
540 
541 			// total liabilities
542 			out.write("TOTAL LIABILITIES\t");
543 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
544 			{
545 				Object actor = this.actors.get(it.next());
546 				if (actor instanceof GameDistributorInteractive)
547 				{
548 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
549 					double li = ((Double) liabilitiesPerActor.get(interactive
550 							.getName())).doubleValue();
551 					out.write(Math.round(li) + "\t");
552 				}
553 			}
554 			out.write("\n");
555 
556 			// equity
557 			out.write("\nEQUITY\t");
558 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
559 			{
560 				Object actor = this.actors.get(it.next());
561 				if (actor instanceof GameDistributorInteractive)
562 				{
563 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
564 					double eq = ((Double) assetsPerActor.get(interactive
565 							.getName())).doubleValue()
566 							- ((Double) liabilitiesPerActor.get(interactive
567 									.getName())).doubleValue();
568 					equityPerActor.put(interactive.getName(), new Double(eq));
569 					out.write(Math.round(eq) + "\t");
570 				}
571 			}
572 			out.write("\n");
573 
574 			// close the stream
575 			out.close();
576 
577 			//
578 			// WRITE A TOTAL EQUITY FILE
579 			//
580 
581 			BufferedWriter eqout = new BufferedWriter(new FileWriter(
582 					"_EQUITYSHEET" + " time in days " + time + " wallclock "
583 							+ date + ".xls"));
584 
585 			// the headers
586 			eqout.write("Total balance sheet per player " + " time in days "
587 					+ time + " wallclock " + date + "\n");
588 			eqout.write("\n");
589 
590 			// sort on equity
591 			Map sortedPlayersOnEquity = new TreeMap();
592 			for (Iterator it = this.actors.keySet().iterator(); it.hasNext();)
593 			{
594 				Object actor = this.actors.get(it.next());
595 				if (actor instanceof GameDistributorInteractive)
596 				{
597 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
598 					double eq = ((Double) equityPerActor.get(interactive
599 							.getName())).doubleValue();
600 					String key = "" + Math.round(eq);
601 					while (key.length() < 11)
602 					{
603 						key = "0" + key;
604 					}
605 					key = key + interactive.getName();
606 					sortedPlayersOnEquity.put(key, interactive);
607 				}
608 			}
609 
610 			// the names of the actors
611 			eqout.write("Name\tLocation\tAssets\tLiabilities\tEquity\n");
612 			for (Iterator it = sortedPlayersOnEquity.keySet().iterator(); it
613 					.hasNext();)
614 			{
615 				Object actor = sortedPlayersOnEquity.get(it.next());
616 				if (actor instanceof GameDistributorInteractive)
617 				{
618 					GameDistributorInteractive interactive = (GameDistributorInteractive) actor;
619 					eqout.write(interactive.getName()
620 							+ "\t"
621 							+ interactive.getLocationDescription()
622 							+ "\t"
623 							+ Math.round(((Double) assetsPerActor
624 									.get(interactive.getName())).doubleValue())
625 							+ "\t"
626 							+ Math.round(((Double) liabilitiesPerActor
627 									.get(interactive.getName())).doubleValue())
628 							+ "\t"
629 							+ Math.round(((Double) equityPerActor
630 									.get(interactive.getName())).doubleValue())
631 							+ "\n");
632 				}
633 			}
634 
635 			// close the stream
636 			eqout.close();
637 
638 		} catch (Exception exception)
639 		{
640 			// TODO make logger dependent
641 			exception.printStackTrace();
642 		}
643 
644 		/*
645 		 * try { this.simulator.start(); } catch (Exception exception) {
646 		 * Logger.severe(this, "printTally", exception); }
647 		 */
648 		Logger.info(this, "printbalanceSheet",
649 				"GlobalSupplyChainData: Balance Sheet written");
650 	}
651 }