001    package market;
002    
003    import java.awt.Rectangle;
004    import java.io.IOException;
005    import java.util.ArrayList;
006    import java.util.Calendar;
007    import java.util.Iterator;
008    import java.util.List;
009    
010    import javax.swing.JFrame;
011    
012    import log.Log;
013    import market.event.MarketEventListener;
014    import market.resource.IconSetter;
015    import market.statistics.CCompleteStats;
016    import market.statistics.CCustomerStats;
017    import market.statistics.CISalesStats;
018    import market.statistics.CSalesStats;
019    import market.statistics.Statistics;
020    import sale.Action;
021    import sale.MenuSheet;
022    import sale.MenuSheetItem;
023    import sale.SaleProcess;
024    import sale.SalesPoint;
025    import sale.Shop;
026    import sale.StepTimer;
027    import sale.Time;
028    import data.Catalog;
029    import data.CountingStock;
030    import data.IntegerValue;
031    import data.Value;
032    import data.ooimpl.CatalogImpl;
033    import data.ooimpl.StoringStockImpl;
034    
035    /**
036     * The Shop of this sale-application.
037     */
038    public class SMarket extends Shop {
039    
040        public static final String CAT_ARTICLECATALOG = "Produktkatalog";
041        public static final String CAT_OPENPURCHASE = "Erwartete Lieferungen";
042        public static final String CAT_CUSTOMER = "Kunden";
043        public static final String CAT_COMPLETE_SALESSTATS = "Komplette Statistik";
044        public static final String STK_OFFER = "Angebot";
045        public static final String STK_TILLQUEUE = "Kunden-Warteschlange";
046        public static final String STK_WAREHOUSEQUEUE = "Auftrags-Warteschlange";
047        public static final String MARKET_CLOSES_SHORT = "ACHTUNG: Der Markt schließt jetzt.";
048        public static final String MARKET_CLOSES_LONG = "Der Markt schließt gleich. Beehren sie uns doch " +
049                "morgen wieder.";
050        public static final String MARKET_CLOSES_NOT = "Der Markt hat doch noch eine Weile geöffnet.";
051        public static final String MARKET_CLOSED = "Der Markt hat geschlossen.";
052        public static final String MARKET_OPENED = "Der Markt hat geöffnet.";
053        private static final String SHOP_CAPTION = "Großmarkt Sohn & Sohn";
054    
055        private MenuSheetItem msiNewCustomer;
056        private MenuSheetItem msiCustomer;
057        private MenuSheetItem msiSeller;
058        private MenuSheetItem msiWorker;
059        private MenuSheetItem msiManager;
060        private Calendar dateOfOpening;
061    
062    
063        /**
064         * The {@link Options options}, which affect the computation of the discount and the
065         * dismissal compensation.
066         */
067        private Options options = new Options();
068    
069        /**
070         * The listeners listening to market events.
071         */
072        private MarketEventListener[] evl = new MarketEventListener [0];
073    
074        /**
075         * Indicates if market ist open, soon to close, or closed.
076         */
077        private int open;
078    
079        /**
080         * Indicates if the market's time has advanced.
081         * This variable is set to true when the day changes. As soon as the market opens,
082         * timeAdvanced will be false.<br>
083         * That makes it possible to distinguish between the two possibilities
084         * <ol><li>time has advanced and market can be opened</li>
085         * <li>market has just closed and day has not been changed yet</li></ol>
086         */
087        private boolean timeAdvanced;
088    
089        /**
090         * Catalog which contains all {@link CIArticle CIArticles}
091         */
092        private CatalogImpl c_articleCatalog;
093    
094        /**
095         * Stock which contains all {@link CIArticle CIArticles} currently available
096         */
097        private CSOffer cs_offer;
098    
099        /**
100         * Catalog which contains all orders placed by the manager that have not yet arrived.
101         */
102        private COpenPurchaseOrders c_openPurchaseOrders;
103    
104        /**
105         * Catalog that stores all customers' names.
106         * This catalog is needed for the customer stock ({@link #ss_tillQueue till queue}).
107         */
108        private CatalogImpl c_customer;
109    
110        /**
111         * Catalog that stores sales statistics for the current day. This Catalog is used to make sure that
112         * sales don't show up in the statistics unless the day-end closing has been completed.
113         */
114        private CSalesStats c_dailyStats;
115    
116        /**
117         * Catalog that stores sales statistics (amount of sold articles, revenue from sold articles...)
118         * for one month.
119         */
120        private CSalesStats c_monthlyStats;
121    
122        /**
123         * Catalog that stores {@link CSalesStats sales statistics} of all passed months.
124         */
125        private CCompleteStats c_completeStats;
126    
127        /**
128         * Catalog that stores the statistics of all market's customers. Those statistics are
129         * time independend, that means, it is not split up into months.
130         */
131        private CCustomerStats c_customerStats;
132    
133        /**
134         * The global queue of customers' orders waiting for warehouse-worker-processing.
135         */
136        private StoringStockImpl ss_warehouseQueue;
137    
138        /**
139         * The global queue of customers waiting at the till.
140         */
141        private StoringStockImpl ss_tillQueue;
142    
143        /**
144         * The money of the market.
145         */
146        private IntegerValue iv_account;
147    
148    
149    //####################### SalesPoint methods ################################################################
150    
151        /**
152         * Creates an SMarket, initiates global Catalogs, Stocks and other settings.
153         */
154        public SMarket(Time time){
155            super();
156            setTheShop(this);
157            setTimer(new StepTimer(time));
158            setShopFrameBounds(new Rectangle(50,50,400,300));
159            setShopFrameTitle(SHOP_CAPTION + "  -  " + getTime());
160            IconSetter.setIcon(getShopFrame());
161            open = 2; timeAdvanced = true; //shop starts in the morning
162            c_articleCatalog = new CArticleCatalog(CAT_ARTICLECATALOG);
163            addCatalog(c_articleCatalog);
164            cs_offer = new CSOffer(STK_OFFER, c_articleCatalog);
165            addStock(cs_offer);
166            c_customer = new CatalogImpl(CAT_CUSTOMER);
167            addCatalog(c_customer);
168            ss_tillQueue = new SSListenable(STK_TILLQUEUE, c_customer);
169            addStock(ss_tillQueue);
170            ss_warehouseQueue = new SSListenable(STK_WAREHOUSEQUEUE, c_customer);
171            addStock(ss_warehouseQueue);
172            iv_account = new IntegerValue(0);
173            //clone, otherwise dateOfOpening would change with current time
174            dateOfOpening = (Calendar)getTime().clone();
175        }
176    
177        /**
178         * Returns the JFrame of the Shop window. The difference to the {@link Shop Shop's} getShopFrame()
179         * method is, that this one is public, as the Shop's window is needed by a dialog.
180         * @see JDDShowMessage#showMessageDialog(String, String)
181         *
182         * @return the Shop's frame.
183         */
184        public JFrame getShopFrame() {
185            return super.getShopFrame();
186        }
187    
188        /**
189         * Starts the Shop and initializes statistics items.
190         */
191        public void start() {
192            c_openPurchaseOrders = new COpenPurchaseOrders(CAT_OPENPURCHASE);
193            addCatalog(c_openPurchaseOrders);
194            c_monthlyStats = new CSalesStats(getYear(), getMonth());
195            c_monthlyStats.initPriceHistory();
196            addCatalog(c_monthlyStats);
197            c_dailyStats = new CSalesStats(getYear(), getMonth());
198            c_customerStats = new CCustomerStats();
199            c_completeStats = new CCompleteStats(CAT_COMPLETE_SALESSTATS);
200            addCatalog(c_completeStats);
201            super.start();
202            try {
203                Log.setGlobalLogFile("marketlog.txt", true, false);
204            }
205            catch (IOException e) {
206                System.err.println("Cannot set log file");
207            }
208            setOpen(0);
209        }
210    
211        /**
212         * Closes the SMarket.
213         */
214        public void quit() {
215            if (shutdown (false)) {
216                System.exit(0);
217            }
218        }
219    
220        /**
221         * Sets the icon when market is loaded from persistence file.
222         */
223        public void resume() {
224            super.resume();
225            IconSetter.setIcon(getShopFrame());
226        }
227    
228        /**
229         * Creates the MenuSheet of the SMarket
230         *
231         * @return the MenuSheet of the SMarket
232         */
233        public MenuSheet createShopMenuSheet(){
234            MenuSheet msMenuBar = new MenuSheet("Menubar");
235            MenuSheet msShop = (MenuSheet)super.createShopMenuSheet().getTaggedItem(Shop.SHOP_MENU_TAG, false);
236            MenuSheet msLogOn = new MenuSheet("Anmeldung");
237            MenuSheet msSimulation = new MenuSheet("Simulation");
238            msiNewCustomer = new MenuSheetItem("Kundenregistrierung", SProcessCustomerEditProfile.create());
239            msiCustomer = new MenuSheetItem("Kunde", SProcessLogOn.createLogOnProcess(UMUserBase.CUSTOMER));
240            msiSeller = new MenuSheetItem("Kasse", SProcessLogOn.createLogOnProcess(UMUserBase.SELLER));
241            msiWorker = new MenuSheetItem("Lager", SProcessLogOn.createLogOnProcess(UMUserBase.WAREHOUSE_WORKER));
242            msiManager = new MenuSheetItem("Manager", SProcessLogOn.createLogOnProcess(UMUserBase.MANAGER));
243            MenuSheetItem msiAdvanceTime = new MenuSheetItem("Zu Wunschdatum vor", new Action() {
244                    public void doAction(SaleProcess p, SalesPoint sp) {
245                        if (isOpen()) {
246                            JDDShowMessage.showMessageDialog(
247                                    "Die Zeit kann erst weitergeschaltet werden,\nwenn der Markt " +
248                                    "geschlossen ist.\n\n (Manager -> System -> Öffnen/Schließen)", "Fehler");
249                        } else {
250                            SMarket.getTheShop().addSalesPoint(new SPTime());
251                        }
252            }});
253            msLogOn.add(msiNewCustomer);
254            msLogOn.add(msiCustomer);
255            msLogOn.add(msiSeller);
256            msLogOn.add(msiWorker);
257            msLogOn.add(msiManager);
258            msSimulation.add(msiAdvanceTime);
259            msMenuBar.add(msShop);
260            msMenuBar.add(msLogOn);
261            msMenuBar.add(msSimulation);
262            return msMenuBar;
263        }
264    
265        /**
266         * Adds a {@link SalesPoint} to the market attaches a {@link MarketEventListener} to it.
267         *
268         * @param sp the SalesPoint to be added.
269         */
270        public void addSalesPoint(SalesPoint sp) {
271            super.addSalesPoint(sp);
272            if (sp instanceof SPListenable) SMarket.addEventListener((SPListenable)sp);
273            if (sp instanceof SPCustomer) SMarket.addEventListener((SPCustomer)sp);
274        }
275    
276        /**
277         * Removes a {@link SalesPoint} to the market detachses its {@link MarketEventListener}.
278         *
279         * @param sp the SalesPoint to be removed.
280         */
281        public void removeSalesPoint(SalesPoint sp) {
282            super.removeSalesPoint(sp);
283            if (sp instanceof SPListenable) SMarket.removeEventListener((SPListenable)sp);
284            if (sp instanceof SPCustomer) SMarket.removeEventListener((SPCustomer)sp);
285        }
286    
287    
288    
289    //##################### Our methods #########################################################################
290    
291    ////////////////////////////////////////////////////////////////////////////////////////////////////////
292    // Account (getting and setting)
293    ////////////////////////////////////////////////////////////////////////////////////////////////////////
294    
295        /**
296         * Adds a Value to the markets account.
297         *
298         * @param money the Value that will be added.
299         */
300        public static void addToAccount(Value money) {
301            ((SMarket)Shop.getTheShop()).iv_account.addAccumulating(money);
302        }
303    
304        /**
305         * Subtracts a Value from the markets account.
306         *
307         * @param money the Value that will be substracted.
308         */
309        public static void subtractFromAccount(Value money) {
310            ((SMarket)Shop.getTheShop()).iv_account.subtractAccumulating(money);
311        }
312    
313        /**
314         * @return the account of the market as Value.
315         */
316        public static Value getAccount(){
317            return ((SMarket)Shop.getTheShop()).iv_account;
318        }
319    
320        public static Options getOptions() {
321            return getTheMarket().options;
322        }
323    
324    
325    ////////////////////////////////////////////////////////////////////////////////
326    // Shortcuts
327    ////////////////////////////////////////////////////////////////////////////////
328    
329        /**
330         * @return the singleton instance of SMarket.
331         */
332        public static SMarket getTheMarket() {
333            return (SMarket)getTheShop();
334        }
335    
336        /**
337         * Shortcut for catalog with all articles.
338         */
339        public static CArticleCatalog getArticleCatalog() {
340          return (CArticleCatalog)getTheShop().getCatalog(CAT_ARTICLECATALOG);
341        }
342    
343        /**
344         * Shortcut to the market's current stock.
345         */
346        public static CSOffer getOffer() {
347          return (CSOffer)getTheShop().getStock(STK_OFFER);
348        }
349    
350        /**
351         * Shortcut to the catalog that holds the market's purchases which have not yet arrived.
352         */
353        public static COpenPurchaseOrders getOpenPurchaseOrder() {
354            return (COpenPurchaseOrders)getTheShop().getCatalog(CAT_OPENPURCHASE);
355        }
356    
357        /**
358         * Shortcut to the catalog that holds all customers of the market.
359         * This catalog is needed as a base for till- and warehouse-queue.
360         */
361        public static Catalog getCustomers(){
362            return Shop.getTheShop().getCatalog(SMarket.CAT_CUSTOMER);
363        }
364    
365        /**
366         * Shortcut for the queue of customers who want to pay.
367         */
368        public static SSListenable getTillQueue(){
369            return (SSListenable)Shop.getTheShop().getStock(SMarket.STK_TILLQUEUE);
370        }
371    
372        /**
373         * Shortcut for the queue of orders waiting at the warehouse.
374         */
375        public static SSListenable getWarehouseQueue(){
376            return (SSListenable)Shop.getTheShop().getStock(SMarket.STK_WAREHOUSEQUEUE);
377        }
378    
379        /**
380         * Shortcut to the catalog that holds the current day's statistics.
381         */
382        public static CSalesStats getDailySalesStats() {
383            return (CSalesStats)(getTheMarket()).c_dailyStats;
384        }
385    
386        /**
387         * Shortcut to the catalog that holds the current month's statistics.
388         */
389        public static CSalesStats getMonthlySalesStats() {
390            return (CSalesStats)(getTheMarket()).c_monthlyStats;
391        }
392    
393        /**
394         * Shortcut to the statistics catalog
395         */
396        public static CCompleteStats getCompleteSalesStats() {
397            return (CCompleteStats)getTheShop().getCatalog(CAT_COMPLETE_SALESSTATS);
398        }
399    
400        /**
401         * Shortcut to the customer stats catalog
402         */
403        public static CCustomerStats getCustomerStats() {
404            return getTheMarket().c_customerStats;
405        }
406    
407    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
408    // Misc.
409    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
410    
411        /**
412         * Returns Categories of all available Articles.
413         * This method is used by dropdown filters for initialization.
414         */
415        public static Object[] getArticleCategories(){
416            List l = new ArrayList();
417            l.add("Alles");
418            Iterator it = getArticleCatalog().iterator(null, false);
419            CIArticle art = null;
420            String category = null;
421            while (it.hasNext()) {
422                art = (CIArticle)it.next();
423                category = art.getCategory();
424                if (!l.contains(category)) {
425                    l.add(category);
426                }
427            }
428            return l.toArray();
429        }
430    
431        /**
432         * Sets the market's state.
433         *
434         * @param i <ul>
435         *             <li>0: The market is open, customers can buy</li>
436         *             <li>1: The market is about to close, customers cannot login nor start new
437         *                      purchases, even if they are already logged in.</li>
438         *             <li>2: The market is closed, only the manager can log in</li>
439         *          </ul>
440         */
441        public void setOpen(int i) {
442            open = i;
443            if (i == 0) {
444                timeAdvanced = false;
445                msiNewCustomer.setEnabled(true);
446                msiCustomer.setEnabled(true);
447                msiSeller.setEnabled(true);
448                msiWorker.setEnabled(true);
449            }
450            if (i == 1) {
451                fireMarketClosing();
452                msiNewCustomer.setEnabled(false);
453                msiCustomer.setEnabled(false);
454            }
455            if (i == 2) {
456                fireMarketClosed();
457                addDailyStatsToMonthlyStats();
458                msiNewCustomer.setEnabled(false);
459                msiCustomer.setEnabled(false);
460                msiSeller.setEnabled(false);
461                msiWorker.setEnabled(false);
462            }
463        }
464    
465        /**
466         * @return whether the market is currently open or not.
467         */
468         public static boolean isOpen() {
469            return getTheMarket().open == 0 || getTheMarket().open == 1;
470         }
471    
472         /**
473          * @return whether the manager has announced the market's closing or not.
474          */
475         public static boolean isToBeClosed() {
476            return getTheMarket().open == 1;
477         }
478    
479         /**
480          * @return whether the time has advanced or not.
481          * @see #timeAdvanced
482          */
483         public static boolean hasTimeAdvanced() {
484            return getTheMarket().timeAdvanced;
485         }
486    
487    
488    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
489    // Time
490    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
491    
492         /**
493          * Convenience method
494          *
495          * @return the current date.
496          */
497        public static Calendar getTime() {
498            return (Calendar)getTheMarket().getTimer().getTime();
499        }
500    
501        /**
502         * @return the date that the market has started its business.
503         */
504        public static Calendar getDateOfOpening() {
505            return getTheMarket().dateOfOpening;
506        }
507    
508        /**
509         * Convencience method.
510         *
511         * @return the current year.
512         */
513        public static int getYear() {
514            return getTime().get(Calendar.YEAR);
515        }
516    
517        /**
518         * Convenience method.
519         *
520         * @return the current month.
521         */
522        public static int getMonth() {
523            return getTime().get(Calendar.MONTH);
524        }
525    
526        /**
527         * Sets the market's time to a new date.
528         *
529         * @param newTime the new date to be set.
530         */
531        public static void setTime(Calendar newTime) {
532            int diff = Conversions.dayDifference(getTime(), newTime);
533            getTheShop().getTimer().setTime(newTime);
534            getTheMarket().computeEventsOnDayChanges(diff);
535        }
536    
537        /**
538         * Advances the market's time by 1 day.
539         */
540        public static void setNextDay() {
541            getTheShop().getTimer().goAhead();
542            getTheMarket().computeEventsOnDayChanges(1);
543        }
544    
545        /**
546         * Does things that need to be done when the time advances.
547         * The Shop's title is set to the new date, the waiting time for new orders is decreased,
548         * if new orders arrived they are added to the current offer.
549         * If not only the day but also the month changed, the statistics and the market's account
550         * are updated.
551         *
552         * @param daysAdvanced The number of days the time advanced.
553         */
554        private void computeEventsOnDayChanges(int daysAdvanced) {
555            setShopFrameTitle(SHOP_CAPTION + "  -  " + getTime());
556            timeAdvanced = true;
557            //when open purchase orders arrive, add them to market's stock, otherwise just decrease the
558            //numbers of days to wait
559            CountingStock arrivedOrders = getOpenPurchaseOrder().subtractPassedDays(daysAdvanced);
560            if(arrivedOrders.size(null)>0){
561                getOffer().addStock(arrivedOrders, null, false);
562                getWarehouseQueue().fireWakeUpOrders();
563            }
564            if (hasMonthChanged(daysAdvanced)) {//if month changed
565                getMonthlySalesStats().setWages(
566                        UMUserBase.getGlobalBase().getCurrentWages()); //save current wages to statistics
567                getCompleteSalesStats().add(getMonthlySalesStats(), null); //update statistics catalogs
568                int currentMiscCosts = c_monthlyStats.getCosts();
569                considerJumpedOverMonths();
570                c_monthlyStats = new CSalesStats(getYear(), getMonth());
571                c_monthlyStats.setCosts(currentMiscCosts);
572                c_monthlyStats.initPriceHistory();
573                subtractFromAccount(new IntegerValue(monthlyCosts()));      //update account
574            }
575            fireTimeAdvanced();
576        }
577    
578        /**
579         * This method checks if the month changed due to the progress of time.
580         *
581         * @param daysAdvanced The number of days the time advanced.
582         * @return true, if the month changed
583         */
584        private boolean hasMonthChanged(int daysAdvanced) {
585            int dayOfMonth = getTime().get(Calendar.DAY_OF_MONTH);
586            return daysAdvanced >= dayOfMonth;
587        }
588    
589        /**
590         * Adds an empty statistics entry to the statistics for every month that has been jumped over.
591         * Besides, the monthly costs of the market are subtracted from the account.
592         */
593        private void considerJumpedOverMonths() {
594            int currentMiscCosts = c_monthlyStats.getCosts();
595            CCompleteStats ccs = getCompleteSalesStats();
596            int m = Statistics.getLastArticleStatisticsMonth() + 1; //set not to last month, but to its successor
597            int y = Statistics.getLastArticleStatisticsYear();
598            if (m == 12) {
599                m = 0;
600                y++;
601            }
602            int mNow = getMonth();
603            int yNow = getYear();
604            while (m != mNow || y != yNow) {
605                CSalesStats css = new CSalesStats(y, m);
606                css.setCosts(currentMiscCosts);
607                css.initPriceHistory();
608                css.setWages(UMUserBase.getGlobalBase().getCurrentWages());
609                ccs.add(css, null);
610                subtractFromAccount(new IntegerValue(monthlyCosts()));      //update account
611                m++;
612                if (m == 12) {
613                    m = 0;
614                    y++;
615                }
616            }
617        }
618    
619        /**
620         * Adds today's statistic entries to the monthly stats.
621         * This covers the sales statistics of every single article and the current day's total revenue.
622         */
623        private void addDailyStatsToMonthlyStats() {
624            Iterator it = c_dailyStats.iterator(null, false);
625            while (it.hasNext()) {
626                CISalesStats dailyCiss = (CISalesStats)it.next();
627                c_monthlyStats.get(dailyCiss.getArticleID()).addAmount(dailyCiss.getAmount());
628                c_monthlyStats.get(dailyCiss.getArticleID()).addRevenue(dailyCiss.getRevenue());
629            }
630            c_monthlyStats.addRevenue(c_dailyStats.getRevenue());
631            c_dailyStats = new CSalesStats(getYear(), getMonth());
632        }
633    
634        /**
635         * Convenience method that returns the total costs per month.
636         * This covers both the whole wages and the miscellaneous costs that were set in the options.
637         */
638        private int monthlyCosts() {
639            return UMUserBase.getGlobalBase().getCurrentWages() + c_monthlyStats.getCosts();
640        }
641    
642    
643    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
644    // Event handling
645    /////////////////////////////////////////////////////////////////////////////////////////////////////////////
646    
647        /**
648         * Adds a new EventListener to the market.
649         */
650        public static void addEventListener(MarketEventListener e) {
651            MarketEventListener[] evl = (getTheMarket()).evl;
652            int len = evl.length;
653            boolean exists = false;
654            for (int i = 0; i < len; i++) {
655                exists = exists || (evl[i] == e);
656            }
657            if (!exists) {
658                MarketEventListener[] temp = new MarketEventListener[len+1];
659                System.arraycopy(evl, 0, temp, 0, len);
660                temp[len] = e;
661                evl = temp;
662            }
663            (getTheMarket()).evl = evl;
664        }
665    
666        /**
667         * Removes an EventListener from the market.
668         */
669        public static void removeEventListener(MarketEventListener e) {
670            MarketEventListener[] evl = (getTheMarket()).evl;
671            for (int i = 0; i < evl.length; i++) {
672                if (evl[i] == e) {
673                    MarketEventListener[] temp = new MarketEventListener[evl.length-1];
674                    if (i > 0) System.arraycopy(evl,0,temp,0,i);
675                    if (i < evl.length-1) System.arraycopy(evl,i+1,temp,i,evl.length-1-i);
676                    evl = temp;
677                    break;
678                }
679            }
680            (getTheMarket()).evl = evl;
681        }
682    
683    
684        /**
685         * Fires an event to all listeners: The market is about to close. (Which means, the manager pressed
686         * his "Closing-Time" button.)
687         */
688        public static void fireMarketClosing()  {
689            MarketEventListener[] evl = (getTheMarket()).evl;
690            for (int i = 0; i < evl.length; i++) {
691                if (evl[i] != null) evl[i].notifyOnMarketClosing();
692            }
693        }
694    
695        /**
696         * Fires an event to all listeners: The market isn't about to close anymore. (Which means, the manager
697         * canceled closing time.)
698         */
699        public static void fireMarketNotClosing()  {
700            MarketEventListener[] evl = (getTheMarket()).evl;
701            for (int i = 0; i < evl.length; i++) {
702                if (evl[i] != null) evl[i].notifyOnMarketNotClosing();
703            }
704        }
705    
706        /**
707         * Fires an event to all listeners: The market has just closed.
708         */
709        public static void fireMarketClosed()  {
710            MarketEventListener[] evl = (getTheMarket()).evl;
711            for (int i = 0; i < evl.length; i++) {
712                if (evl[i] != null) evl[i].marketClosed();
713            }
714        }
715    
716        /**
717         * Fires an event to all listeners: The market has just opened.
718         */
719        public static void fireMarketOpened()  {
720            MarketEventListener[] evl = (getTheMarket()).evl;
721            for (int i = 0; i < evl.length; i++) {
722                if (evl[i] != null) evl[i].marketOpened();
723            }
724        }
725    
726        /**
727         * Fires an event to all listeners: The time has advanced..
728         */
729        public static void fireTimeAdvanced()  {
730            MarketEventListener[] evl = (getTheMarket()).evl;
731            for (int i = 0; i < evl.length; i++) {
732                if (evl[i] != null) evl[i].timeAdvanced();
733            }
734        }
735    
736        /**
737         * Fires an event to all listeners: The number of workers or orders to process has changed.
738         */
739        public static void fireUpdateWorkerScreen(){
740             MarketEventListener[] evl = (getTheMarket()).evl;
741            for (int i = 0; i < evl.length; i++) {
742                if (evl[i] != null) evl[i].workerInformationChanged();
743            }
744        }
745    }