001package com.fs.starfarer.api.impl.campaign.events;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.Collections;
006import java.util.HashSet;
007import java.util.List;
008import java.util.Map;
009import java.util.Random;
010import java.util.Set;
011
012import org.apache.log4j.Logger;
013
014import com.fs.starfarer.api.Global;
015import com.fs.starfarer.api.campaign.CampaignClockAPI;
016import com.fs.starfarer.api.campaign.CampaignFleetAPI;
017import com.fs.starfarer.api.campaign.LocationAPI;
018import com.fs.starfarer.api.campaign.SectorEntityToken;
019import com.fs.starfarer.api.campaign.StarSystemAPI;
020import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
021import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
022import com.fs.starfarer.api.campaign.econ.MarketAPI;
023import com.fs.starfarer.api.campaign.events.CampaignEventTarget;
024import com.fs.starfarer.api.campaign.events.CampaignEventPlugin.PriceUpdatePlugin.PriceType;
025import com.fs.starfarer.api.impl.campaign.ids.Commodities;
026import com.fs.starfarer.api.impl.campaign.ids.Tags;
027import com.fs.starfarer.api.util.IntervalUtil;
028import com.fs.starfarer.api.util.SaveableIterator;
029import com.fs.starfarer.api.util.TimeoutTracker;
030import com.fs.starfarer.api.util.WeightedRandomPicker;
031
032public class TradeInfoUpdateEvent extends BaseEventPlugin {
033        
034        public static final float TIMEOUT = 30f;
035        
036        public static Logger log = Global.getLogger(TradeInfoUpdateEvent.class);
037        
038        private IntervalUtil remoteTracker;
039        private IntervalUtil localTracker;
040        private TimeoutTracker<String> sinceLastLocalReport = new TimeoutTracker<String>();
041        private TimeoutTracker<String> sinceLastRemoteReport = new TimeoutTracker<String>();
042        
043        private List<PriceUpdatePlugin> updatesForNextReport = new ArrayList<PriceUpdatePlugin>();
044        private SectorEntityToken commRelayForNextReport = null;
045        
046        public void init(String type, CampaignEventTarget eventTarget) {
047                super.init(type, eventTarget);
048                remoteTracker = new IntervalUtil(0.5f, 1.5f);
049                localTracker = new IntervalUtil(0.5f, 1.5f);
050        }
051        
052        public void startEvent() {
053                super.startEvent();
054        }
055        
056        public void advance(float amount) {
057                //if (true) return;
058                
059                if (!isEventStarted()) return;
060                if (isDone()) return;
061                
062                float days = Global.getSector().getClock().convertToDays(amount);
063                
064                sinceLastLocalReport.advance(days);
065                sinceLastRemoteReport.advance(days);
066                
067                localTracker.advance(days);
068                if (localTracker.intervalElapsed()) {
069                        checkLocalPrices();
070                }
071                
072                remoteTracker.advance(days);
073                if (remoteTracker.intervalElapsed()) {
074                        checkRemotePrices();
075                }
076        }
077
078
079        //private SaveableIterator<SectorEntityToken> relayIter = null;
080        private SaveableIterator<StarSystemAPI> starSystemIter = null;
081
082        private CampaignEventTarget tempTarget;
083
084        private void checkRemotePrices() {
085                
086                if (starSystemIter == null || !starSystemIter.hasNext()) {
087//                      List<SectorEntityToken> relays = Global.getSector().getIntel().getCommSnifferLocations();
088//                      if (Global.getSettings().isDevMode()) {
089//                              relays = Global.getSector().getEntitiesWithTag(Tags.COMM_RELAY);
090//                      }
091//                      relayIter = new SaveableIterator<SectorEntityToken>(relays);
092                        List<StarSystemAPI> systems = new ArrayList<StarSystemAPI>(Global.getSector().getStarSystems());
093                        Collections.shuffle(systems);
094                        starSystemIter = new SaveableIterator<StarSystemAPI>(systems);
095                        
096                        float size = systems.size();
097                        float interval = 1.5f * TIMEOUT / size;
098                        remoteTracker.setInterval(interval * 0.75f,  interval * 1.25f);
099                }
100                if(!starSystemIter.hasNext()) return;
101
102                
103                final StarSystemAPI system = starSystemIter.next();
104                //if (Global.getSector().getCurrentLocation() == system) return;
105                
106                
107                List<SectorEntityToken> relays = system.getEntitiesWithTag(Tags.COMM_RELAY);
108                List<SectorEntityToken> withIntel = Global.getSector().getIntel().getCommSnifferLocations();
109                
110                SectorEntityToken relay = null;
111                for (SectorEntityToken curr : relays) {
112                        if (withIntel.contains(curr)) {
113                                relay = curr;
114                                break;
115                        }
116                }
117                
118                boolean hasIntel = relay != null;
119                if (relay == null && relays.size() > 0) {
120                        relay = relays.get(new Random().nextInt(relays.size()));
121                }
122
123                if (relay == null) return;
124                
125                String id = relay.getContainingLocation().getId();
126                if (sinceLastRemoteReport.contains(id)) return;
127                
128                
129                List<PriceUpdate> list = getPriceUpdatesFor(system);
130                if (!list.isEmpty()) {
131                        
132                        commRelayForNextReport = relay;
133                        if (hasIntel) {
134                                pickUpdatesFrom(system, list, PickMode.REMOTE_WITH_INTEL);
135                                if (!updatesForNextReport.isEmpty()) {
136                                        sinceLastRemoteReport.set(id, TIMEOUT);
137//                                      Global.getSector().reportEventStage(this, "prices_sniffer", relay, MessagePriority.SECTOR, new BaseOnMessageDeliveryScript() {
138//                                              public void beforeDelivery(CommMessageAPI message) {
139//                                                      if (system != Global.getSector().getPlayerFleet().getContainingLocation()) {
140//                                                              message.setShowInCampaignList(false);
141//                                                      }
142//                                              }
143//                                      });
144                                }
145                        } else {
146                                pickUpdatesFrom(system, list, PickMode.REMOTE);
147                                if (!updatesForNextReport.isEmpty()) {
148                                        sinceLastRemoteReport.set(id, TIMEOUT);
149//                                      Global.getSector().reportEventStage(this, "prices_remote", relay, MessagePriority.SECTOR, new BaseOnMessageDeliveryScript() {
150//                                              public void beforeDelivery(CommMessageAPI message) {
151//                                                      if (system != Global.getSector().getPlayerFleet().getContainingLocation()) {
152//                                                              message.setShowInCampaignList(false);
153//                                                      }
154//                                              }
155//                                      });
156                                }
157                        }
158                }
159        }
160
161
162        private void checkLocalPrices() {
163                //if (Global.getSector().isInNewGameAdvance()) return;
164                
165                CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
166                if (playerFleet.isInHyperspace() || playerFleet.getContainingLocation() == null) return;
167                String id = playerFleet.getContainingLocation().getId();
168                if (sinceLastLocalReport.contains(id)) return;
169                
170                List<PriceUpdate> list = getPriceUpdatesFor(playerFleet.getContainingLocation());
171                
172                if (!list.isEmpty()) {
173                        pickUpdatesFrom(playerFleet.getContainingLocation(), list, PickMode.LOCAL);
174                        if (!updatesForNextReport.isEmpty()) {
175                                sinceLastLocalReport.set(id, TIMEOUT);
176                                //Global.getSector().reportEventStage(this, "prices_local", playerFleet, MessagePriority.SECTOR);
177                        }
178                }
179        }
180        
181        private static enum PickMode {
182                LOCAL,
183                REMOTE,
184                REMOTE_WITH_INTEL,
185        }
186        
187        private void pickUpdatesFrom(LocationAPI system, List<PriceUpdate> updates, PickMode mode) {
188                
189                float numMarkets = 0;
190                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
191                        if (market.getContainingLocation() != system) continue;
192                        //numMarkets += market.getSize();
193                        numMarkets++;
194                        
195                }
196                int max = 0;
197                switch (mode) {
198                case LOCAL:
199                        //max = (int) Math.max(2, numMarkets - 2);
200                        max = (int) Math.max(2, numMarkets) + 1;
201                        break;
202                case REMOTE:
203                        max = (int) Math.max(1, numMarkets - 2);
204                        break;
205                case REMOTE_WITH_INTEL:
206                        max = (int) Math.max(1, numMarkets);
207                        break;
208                }
209                
210                if (max > 5) max = 5;
211                if (max < 1) max = 1;
212                
213                
214                log.info("");
215                log.info("");
216                log.info("Picking " + max + " updates");
217                
218                WeightedRandomPicker<PriceUpdate> picker = new WeightedRandomPicker<PriceUpdate>();
219                List<PriceUpdatePlugin> known = getPlayerKnownUpdates();
220                for (PriceUpdate pu : updates) {
221                        float weight = getWeightFor(pu, known);
222                        if (weight <= 0) continue;
223                        
224                        log.info(pu.getCommodity().getCommodity().getName() + "(" + pu.getCommodity().getMarket().getName() + "): weight " + weight); 
225                        picker.add(pu, weight);
226                }
227                
228                log.info("");
229                updatesForNextReport.clear();
230                for (int i = 0; i < max; i++) {
231                        PriceUpdate update = picker.pick();
232                        if (update != null) {
233                                log.info("Picked " + update.getCommodity().getCommodity().getName() + "(" + update.getCommodity().getMarket().getName() + ")");
234                                updatesForNextReport.add(update);
235                                picker.remove(update);
236                        }
237                }
238        }
239        
240        
241        private void pickAllRelevantFromMarket(MarketAPI market, List<PriceUpdate> updates) {
242                log.info("Picking market updates");
243                
244                updatesForNextReport.clear();
245                List<PriceUpdatePlugin> known = getPlayerKnownUpdates();
246                for (PriceUpdate update : updates) {
247//                      System.out.println("Checking for local update: " + update.getCommodity().getCommodity().getName());
248//                      if (!update.isSignificant()) continue;
249//                      float weight = getWeightFor(update, known);
250//                      log.info(update.getCommodity().getCommodity().getName() + ": weight " + (int) weight);
251                        //if (update.getType() != PriceType.NORMAL || weight > 100) {
252                        if (shouldUpdateLocally(update, known)) {
253                                log.info("Adding " + update.getCommodity().getCommodity().getName() + "(" + update.getCommodity().getMarket().getName() + ")");
254                                updatesForNextReport.add(update);
255                        }
256                }
257        }
258        
259        
260        private List<PriceUpdate> getPriceUpdatesFor(LocationAPI system) {
261                List<PriceUpdate> updates = new ArrayList<PriceUpdate>();
262                for (MarketAPI market : Global.getSector().getEconomy().getMarketsCopy()) {
263                        if (market.getContainingLocation() != system) continue;
264                        updates.addAll(getUpdatesFor(market));
265                }
266                return updates;
267        }
268        
269        private List<PriceUpdate> getUpdatesFor(MarketAPI market) {
270                List<PriceUpdate> updates = new ArrayList<PriceUpdate>();
271                if (!market.isInEconomy()) {
272                        return updates;
273                }
274                for (CommodityOnMarketAPI com : market.getAllCommodities()) {
275                        if (com.isNonEcon()) continue;
276                        if (com.isPersonnel()) continue;
277                        float volumeFactor = com.getStockpile() + com.getDemand().getDemandValue();
278                        if (volumeFactor < 50) continue;
279                        PriceUpdate update = new PriceUpdate(com);
280                        if (update.isSignificant()) {
281                                updates.add(update);
282                        }
283                }
284                return updates;
285        }
286        
287        private float getWeightFor(PriceUpdatePlugin update, List<PriceUpdatePlugin> known) {
288                CommodityOnMarketAPI com = update.getCommodity();
289                MarketAPI market = update.getMarket();
290                
291//              if (market.getId().contains("achaman") && com.getId().equals("food")) {
292//                      System.out.println("dfsdfefw2");
293//              }
294//              if (com.getId().equals("food")) {
295//                      System.out.println("dfsdfefw2");
296//              }
297                
298                float volumeFactor = com.getStockpile() + com.getDemand().getDemandValue();
299                if (volumeFactor == 0) return 0f;
300                
301                volumeFactor = (float) Math.sqrt(volumeFactor);
302                
303                //volumeFactor *= com.getCommodity().getBasePrice();
304                
305                //volumeFactor *= (float) market.getSize();
306                
307                if (update.getType() == PriceType.NORMAL) {
308                        //volumeFactor = (float) Math.sqrt(volumeFactor);
309                        volumeFactor *= 0.25f;
310                }
311                
312                float numCheap = 0;
313                float numExpensive = 0;
314                float numNormal = 0;
315                
316                
317                CampaignClockAPI clock = Global.getSector().getClock();
318                float daysSinceLastSame = Float.MAX_VALUE;
319                
320                int numSeenSkipped = 0;
321                Set<CommodityOnMarketAPI> seen = new HashSet<CommodityOnMarketAPI>();
322                for (PriceUpdatePlugin curr : known) {
323                        CommodityOnMarketAPI currCom = curr.getCommodity();
324                        if (currCom == null) continue;
325                        if (seen.contains(currCom)) {
326                                numSeenSkipped++;
327                                continue;
328                        }
329                        seen.add(currCom);
330                        if (!currCom.getId().equals(com.getId())) continue;
331                        
332                        if (currCom == com) {
333                                float priceDiff = Math.abs(curr.getDemandPrice() + curr.getSupplyPrice() - update.getDemandPrice() - update.getSupplyPrice());
334                                if (priceDiff < 0.2f * (curr.getDemandPrice() + curr.getSupplyPrice())) {
335                                        daysSinceLastSame = clock.getElapsedDaysSince(curr.getTimestamp());
336                                }
337                        }
338                        //clock.getElapsedDaysSince(-55661070348000L)
339                        switch (curr.getType()) {
340                        case CHEAP:
341                                numCheap++;
342                                break;
343                        case EXPENSIVE:
344                                numExpensive++;
345                                break;
346                        case NORMAL:
347                                numNormal++;
348                                break;
349                        }
350                }
351                
352                if (daysSinceLastSame < 30) return 0f;
353                
354                if (update.getType() == PriceType.NORMAL) {
355                        if (numExpensive + numCheap == 0) {
356                                return 0f;
357                        }
358                        if (numCheap == 0 && update.getAvailable() <= 10) {
359                                return 0f;
360                        }
361                        if (numExpensive == 0 && update.getDemand() <= 10) {
362                                return 0f;
363                        }
364                }
365                
366                float total = numCheap + numExpensive + numNormal;
367                
368                float weightMult = 1f;
369                if (total <= 0) total = 1f;
370                switch (update.getType()) {
371                case CHEAP:
372                        weightMult = 1f + 3f * Math.max(0, numNormal + numExpensive - numCheap) / total;
373                        break;
374                case EXPENSIVE:
375                        weightMult = 1f + 3f * Math.max(0, numNormal + numCheap - numExpensive) / total;
376                        
377                        if (!com.isFuel() && !com.isPersonnel() && !com.getId().equals(Commodities.SUPPLIES)) {
378                                CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
379                                float f = playerFleet.getCargo().getQuantity(CargoItemType.RESOURCES, com.getId()) / Math.max(playerFleet.getCargo().getMaxCapacity(), 1);
380                                weightMult *= (1f + 2f * f);
381                        }
382                        
383                        break;
384                case NORMAL:
385                        weightMult = 1f + 1f * Math.max(0, numCheap + numExpensive - numNormal) / total;
386                        break;
387                }
388                
389                return volumeFactor * weightMult;
390        }
391        
392        
393        
394        private boolean shouldUpdateLocally(PriceUpdate update, List<PriceUpdatePlugin> known) {
395//              if (update.getCommodity().getId().equals(Commodities.LOBSTER)) {
396//                      System.out.println("wfwefweew");
397//              }
398                if (!update.isSignificant()) return false;
399                
400                CommodityOnMarketAPI com = update.getCommodity();
401                MarketAPI market = com.getMarket();
402                StarSystemAPI system = market.getStarSystem();
403                
404//              float numCheap = 0;
405//              float numExpensive = 0;
406//              float numNormal = 0;
407//              float numLocalNormal = 0;
408                
409                CampaignClockAPI clock = Global.getSector().getClock();
410                float daysSinceLastSame = Float.MAX_VALUE;
411                
412                int numSeenSkipped = 0;
413                Set<CommodityOnMarketAPI> seen = new HashSet<CommodityOnMarketAPI>();
414                PriceUpdatePlugin mostRecent = null;
415                for (PriceUpdatePlugin curr : known) {
416                        CommodityOnMarketAPI currCom = curr.getCommodity();
417                        if (currCom == null) continue;
418                        if (seen.contains(currCom)) {
419                                numSeenSkipped++;
420                                continue;
421                        }
422                        seen.add(currCom);
423                        if (!currCom.getId().equals(com.getId())) continue;
424                        
425                        if (currCom == com) {
426                                mostRecent = curr;
427                                float priceDiff = Math.abs(curr.getDemandPrice() + curr.getSupplyPrice() - update.getDemandPrice() - update.getSupplyPrice());
428                                if (priceDiff < 0.2f * (curr.getDemandPrice() + curr.getSupplyPrice())) {
429                                        daysSinceLastSame = clock.getElapsedDaysSince(curr.getTimestamp());
430                                }
431                                break;
432                        }
433                        //clock.getElapsedDaysSince(-55661070348000L)
434//                      switch (curr.getType()) {
435//                      case CHEAP:
436//                              numCheap++;
437//                              break;
438//                      case EXPENSIVE:
439//                              numExpensive++;
440//                              break;
441//                      case NORMAL:
442//                              numNormal++;
443//                              if (system != null && system == curr.getMarket().getStarSystem()) {
444//                                      numLocalNormal++;
445//                              }
446//                              break;
447//                      }
448                }
449                
450                if (daysSinceLastSame < 5) return false;
451                
452                //boolean canSell = (int) Misc.getRounded(update.getAvailable()) >= 5;
453                
454                if (update.getType() != PriceType.NORMAL) {
455                        return true;
456                }
457                
458                //if (mostRecent != null && mostRecent.getType() != PriceType.NORMAL && update.getType() == PriceType.NORMAL) {
459                if (mostRecent != null) {
460//                      if (mostRecent.getType() != PriceType.NORMAL && update.getType() == PriceType.NORMAL) {
461//                              update.get
462//                      }
463                        return true;
464                }
465                
466                return false;
467                
468//              CommodityStatTracker stats = SharedData.getData().getActivityTracker().getCommodityTracker();
469//              CommodityStats cs = stats.getStats(update.getCommodity().getId());
470//              
471//              float numMarkets = Global.getSector().getEconomy().getMarketsCopy().size();
472//              if (numMarkets < 1) return false; // ??? no markets
473//              
474//              if (com.getAverageStockpileAfterDemand() > cs.getTotalStockpiles() * 4f / numMarkets) {
475//                      return true;
476//              }
477//              if (com.getDemand().getDemandValue() > cs.getTotalDemand() * 1f / numMarkets) {
478//                      return true;
479//              }
480                
481//              if (update.getType() == PriceType.NORMAL) {
482//                      if (numExpensive + numCheap == 0) return false;
483//                      if (numExpensive > 0 && (numCheap > 0 || numLocalNormal > 0)) return false;
484//              }
485//              
486//              return true;
487        }
488        
489        
490        /**
491         * Some of the updates may be contradictory, but since this is used for computing
492         * weights when picking which updates to send, it's probably good enough.
493         * @return
494         */
495        private List<PriceUpdatePlugin> getPlayerKnownUpdates() {
496                
497                CampaignClockAPI clock = Global.getSector().getClock();
498                
499                List<PriceUpdatePlugin> updates = new ArrayList<PriceUpdatePlugin>();
500//              for (CommMessageAPI message : Global.getSector().getIntel().getMessagesCopy()) {
501//                      if (clock.getElapsedDaysSince(message.getTimeSent()) > 30) continue;
502//                      if (!message.hasTag(Tags.REPORT_PRICES)) continue;
503//                      
504//                      List<PriceUpdatePlugin> list = message.getPriceUpdates();
505//                      if (list == null || list.isEmpty()) continue;
506//                      
507////                    if (message.getMarket() != null && message.getMarket().getId().contains("skathi")) {
508////                            System.out.println("e23edfsdf");
509////                    }
510//                      for (PriceUpdatePlugin curr : list) {
511//                              updates.add(curr);
512//                      }
513//              }
514//              
515//              Collections.sort(updates, new Comparator<PriceUpdatePlugin>() {
516//                      public int compare(PriceUpdatePlugin o1, PriceUpdatePlugin o2) {
517//                              long result = (o2.getTimestamp() - o1.getTimestamp());
518//                              if (result > 0)
519//                                      return 1;
520//                              if (result < 0)
521//                                      return -1;
522//                              return 0;
523//                      }
524//              });
525                
526                
527                return updates;
528        }
529        
530        
531        @Override
532        public void reportPlayerOpenedMarket(MarketAPI market) {
533                getLocalUpdates(market);
534        }
535
536        @Override
537        public void reportPlayerClosedMarket(MarketAPI market) {
538                //market.removeCondition(Conditions.EVENT_TRADE_DISRUPTION);
539                //market.getCommodityData(Commodities.HEAVY_MACHINERY).getPlayerPriceMod().modifyMult("sdfsdfsd", 0.1f);
540                getLocalUpdates(market);
541        }
542        
543        protected void getLocalUpdates(MarketAPI market) {
544//              float days = SharedData.getData().getPlayerActivityTracker().getDaysSinceLastVisitTo(market);
545//              if (days < 3) return;
546                
547                CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
548//              if (playerFleet.isInHyperspace()) return;
549                
550                List<PriceUpdate> list = getUpdatesFor(market);
551                tempTarget = new CampaignEventTarget(market);
552                this.market = market;
553                if (!list.isEmpty()) {
554                        pickAllRelevantFromMarket(market, list);
555                        if (!updatesForNextReport.isEmpty()) {
556                                //Global.getSector().reportEventStage(this, "prices_market", playerFleet, MessagePriority.DELIVER_IMMEDIATELY);
557                        }
558                }
559                tempTarget = null;
560                this.market = null;
561        }
562        
563
564
565        @Override
566        public List<PriceUpdatePlugin> getPriceUpdates() {
567                return updatesForNextReport;
568        }
569        
570        @Override
571        public List<String> getRelatedCommodities() {
572                return super.getRelatedCommodities();
573        }
574        
575
576        public Map<String, String> getTokenReplacements() {
577                Map<String, String> map = super.getTokenReplacements();
578//              CampaignFleetAPI playerFleet = Global.getSector().getPlayerFleet();
579//              if (playerFleet.isInHyperspace()) {
580//                      map.put("$fromSystem", "hyperspace");
581//              } else {
582//                      map.put("$fromSystem", ((StarSystemAPI)playerFleet.getContainingLocation()).getBaseName());
583//              }
584                
585                if (commRelayForNextReport != null) {
586                        map.put("$relayName", commRelayForNextReport.getName());
587                        if (commRelayForNextReport.isInHyperspace()) {
588                                map.put("$fromSystem", "hyperspace");
589                        } else {
590                                map.put("$fromSystem", ((StarSystemAPI)commRelayForNextReport.getContainingLocation()).getBaseName());
591                        }
592                }
593                
594                List<PriceUpdatePlugin> updates = getPriceUpdates();
595                if (updates != null && !updates.isEmpty()) {
596                        String priceList = "Price information updated for: ";
597                        for (PriceUpdatePlugin update : updates) {
598                                CommodityOnMarketAPI com = update.getCommodity();
599                                priceList += com.getCommodity().getName()  + " (" + com.getMarket().getName() + "), ";
600                        }
601                        priceList = priceList.substring(0, priceList.length() - 2);
602                        priceList += ".";
603                        map.put("$priceList", priceList);
604                }
605                return map;
606        }
607
608        @Override
609        public String[] getHighlights(String stageId) {
610//              List<String> result = new ArrayList<String>();
611//              addTokensToList(result, "$neededFood");
612//              return result.toArray(new String[0]);
613                return null;
614        }
615        
616        @Override
617        public Color[] getHighlightColors(String stageId) {
618                return super.getHighlightColors(stageId);
619        }
620        
621        @Override
622        public CampaignEventTarget getEventTarget() {
623                if (tempTarget != null) return tempTarget;
624                return super.getEventTarget();
625        }
626
627        public boolean isDone() {
628                return false;
629        }
630        
631        
632        @Override
633        public String getEventName() {
634                return "Trade info update"; // not used anywhere
635        }
636
637        @Override
638        public CampaignEventCategory getEventCategory() {
639                return CampaignEventCategory.DO_NOT_SHOW_IN_MESSAGE_FILTER;
640        }
641        
642        public boolean showAllMessagesIfOngoing() {
643                return false;
644        }
645}
646
647
648
649
650
651
652
653
654
655