001package com.fs.starfarer.api.impl.campaign.fleets;
002
003import java.util.ArrayList;
004import java.util.LinkedHashMap;
005import java.util.LinkedHashSet;
006import java.util.List;
007import java.util.Map;
008import java.util.Random;
009import java.util.Set;
010
011import com.fs.starfarer.api.Global;
012import com.fs.starfarer.api.campaign.CampaignFleetAPI;
013import com.fs.starfarer.api.campaign.CargoAPI;
014import com.fs.starfarer.api.campaign.FactionAPI;
015import com.fs.starfarer.api.campaign.FleetInflater;
016import com.fs.starfarer.api.campaign.econ.MarketAPI;
017import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
018import com.fs.starfarer.api.characters.MutableCharacterStatsAPI;
019import com.fs.starfarer.api.combat.MutableShipStatsAPI;
020import com.fs.starfarer.api.combat.ShipAPI;
021import com.fs.starfarer.api.combat.ShipVariantAPI;
022import com.fs.starfarer.api.combat.WeaponAPI;
023import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
024import com.fs.starfarer.api.fleet.FleetMemberAPI;
025import com.fs.starfarer.api.impl.campaign.DModManager;
026import com.fs.starfarer.api.impl.campaign.ids.MemFlags;
027import com.fs.starfarer.api.impl.campaign.ids.Tags;
028import com.fs.starfarer.api.loading.FighterWingSpecAPI;
029import com.fs.starfarer.api.loading.VariantSource;
030import com.fs.starfarer.api.loading.WeaponSlotAPI;
031import com.fs.starfarer.api.loading.WeaponSpecAPI;
032import com.fs.starfarer.api.plugins.AutofitPlugin.AutofitPluginDelegate;
033import com.fs.starfarer.api.plugins.AutofitPlugin.AvailableFighter;
034import com.fs.starfarer.api.plugins.AutofitPlugin.AvailableWeapon;
035import com.fs.starfarer.api.plugins.impl.CoreAutofitPlugin;
036import com.fs.starfarer.api.util.ListMap;
037import com.fs.starfarer.api.util.Misc;
038import com.fs.starfarer.api.util.WeightedRandomPicker;
039
040public class DefaultFleetInflater implements FleetInflater, AutofitPluginDelegate {
041
042        public static float GOAL_VARIANT_PROBABILITY = 0.5f;
043        
044        
045        public static class SortedWeapons {
046                protected Map<Integer, WeaponsForTier> tierMap = new LinkedHashMap<Integer, WeaponsForTier>();
047
048                public WeaponsForTier getWeapons(int tier) {
049                        WeaponsForTier data = tierMap.get(tier);
050                        if (data == null) {
051                                data = new WeaponsForTier();
052                                tierMap.put(tier, data);
053                        }
054                        return data;
055                }
056        }
057        
058        public static class WeaponsForTier {
059//              protected Map<String, List<AvailableWeapon>> catMap = new LinkedHashMap<String, List<AvailableWeapon>>();
060//
061//              public List<AvailableWeapon> getWeapons(String cat) {
062//                      List<AvailableWeapon> list = catMap.get(cat);
063//                      if (list == null) {
064//                              list = new ArrayList<AvailableWeapon>();
065//                              catMap.put(cat, list);
066//                      }
067//                      return list;
068//              }
069                protected Map<String, WeaponsForSize> catMap = new LinkedHashMap<String, WeaponsForSize>();
070                
071                public WeaponsForSize getWeapons(String cat) {
072                        WeaponsForSize size = catMap.get(cat);
073                        if (size == null) {
074                                size = new WeaponsForSize();
075                                catMap.put(cat, size);
076                        }
077                        return size;
078                }
079        }
080        
081        public static class WeaponsForSize {
082                protected Map<WeaponSize, List<AvailableWeapon>> sizeMap = new LinkedHashMap<WeaponAPI.WeaponSize, List<AvailableWeapon>>();
083                public List<AvailableWeapon> getWeapons(WeaponSize size) {
084                        List<AvailableWeapon> list = sizeMap.get(size);
085                        if (list == null) {
086                                list = new ArrayList<AvailableWeapon>();
087                                sizeMap.put(size, list);
088                        }
089                        return list;
090                }
091        }
092        
093        public static class AvailableFighterImpl implements AvailableFighter {
094                protected FighterWingSpecAPI spec;
095                protected int quantity = 0;
096                
097                public AvailableFighterImpl(FighterWingSpecAPI spec, int quantity) {
098                        this.spec = spec;
099                        this.quantity = quantity;
100                }
101
102                public AvailableFighterImpl(String wingId, int quantity) {
103                        spec = Global.getSettings().getFighterWingSpec(wingId);
104                        this.quantity = quantity;
105                }
106                
107                public String getId() {
108                        return spec.getId();
109                }
110                public float getPrice() {
111                        return 0;
112                }
113                public int getQuantity() {
114                        return quantity;
115                }
116                public CargoAPI getSource() {
117                        return null;
118                }
119                public SubmarketAPI getSubmarket() {
120                        return null;
121                }
122                public FighterWingSpecAPI getWingSpec() {
123                        return spec;
124                }
125                public void setQuantity(int quantity) {
126                        this.quantity = quantity;       
127                }
128        }
129        
130        public static class AvailableWeaponImpl implements AvailableWeapon {
131                protected WeaponSpecAPI spec;
132                protected int quantity = 0;
133                public AvailableWeaponImpl(WeaponSpecAPI spec, int quantity) {
134                        this.spec = spec;
135                        this.quantity = quantity;
136                }
137                
138                public String getId() {
139                        return spec.getWeaponId();
140                }
141                public float getPrice() {
142                        return 0;
143                }
144                public int getQuantity() {
145                        return quantity;
146                }
147                public CargoAPI getSource() {
148                        return null;
149                }
150                public SubmarketAPI getSubmarket() {
151                        return null;
152                }
153                public WeaponSpecAPI getSpec() {
154                        return spec;
155                }
156                public void setQuantity(int quantity) {
157                        this.quantity = quantity;       
158                }
159                
160                protected MutableShipStatsAPI savedCostStats = null;
161                protected float cachedOPCost = -1;
162                public float getOPCost(MutableCharacterStatsAPI stats, MutableShipStatsAPI shipStats) {
163                        if (savedCostStats == shipStats && cachedOPCost >= 0) return cachedOPCost;
164                        
165                        cachedOPCost = spec.getOrdnancePointCost(stats, shipStats);
166                        savedCostStats = shipStats;
167                        return cachedOPCost;
168                }
169        }
170        
171//      protected float quality = 1f;
172//      protected Long seed = null;
173//      protected Long timestamp = null;
174//      protected Boolean persistent = null;
175//      protected ShipPickMode mode = null;
176        
177        protected DefaultFleetInflaterParams p;
178        
179        protected transient FleetMemberAPI currMember = null;
180        protected transient ShipVariantAPI currVariant = null;
181        protected transient List<AvailableFighter> fighters;
182        protected transient List<AvailableWeapon> weapons;
183        protected transient List<String> hullmods;
184        protected transient CampaignFleetAPI fleet;
185        protected transient FactionAPI faction;
186        
187
188        public DefaultFleetInflater(DefaultFleetInflaterParams p) {
189                //this(p.quality, p.seed, p.persistent, p.mode, p.timestamp);
190                this.p = p;
191        }
192//      public DefaultFleetInflater(float quality, Long seed, Boolean persistent, ShipPickMode mode, Long timestamp) {
193//              this.quality = quality;
194//              this.seed = seed;
195//              this.persistent = persistent;
196//              this.mode = mode;
197//              this.timestamp = timestamp;
198//      }
199        
200        
201        public static float getTierProbability(int tier, float quality) {
202                //if (true) return 1f;
203                
204//              if (tier == 1) return 0.5f + quality;
205//              if (tier == 2) return 0.25f + quality * 0.5f;
206//              if (tier == 3) return 0.125f + quality * 0.25f;
207                
208                //if (tier != 0) return 0f;
209                
210//              if (tier == 1) return Math.min(0.9f, 0.5f + quality);
211//              if (tier == 2) return Math.min(0.9f, 0.25f + quality * 0.5f);
212//              if (tier == 3) return Math.min(0.9f, 0.125f + quality * 0.25f);
213                
214                // since whether to upgrade or not is now randomized, higher probability of
215                // better tier weapons being available (as they may still not end up being used)
216                if (tier == 1) return Math.min(0.9f, 0.75f + quality);
217                if (tier == 2) return Math.min(0.9f, 0.5f + quality * 0.5f);
218                if (tier == 3) return Math.min(0.9f, 0.25f + quality * 0.25f);
219                
220                return 1f;
221        }
222        
223
224        public void inflate(CampaignFleetAPI fleet) {
225                Random random = new Random();
226                //p.seed = null;
227                if (p.seed != null) random = new Random(p.seed);
228                
229                //p.quality = 2f;
230                
231                //random = new Random();
232
233                
234                Random dmodRandom = new Random();
235                if (p.seed != null) dmodRandom = Misc.getRandom(p.seed, 5);
236                
237                CoreAutofitPlugin auto = new CoreAutofitPlugin(fleet.getCommander());
238                auto.setRandom(random);
239
240                boolean upgrade = random.nextFloat() < Math.min(0.1f + p.quality * 0.5f, 0.5f);
241                auto.setChecked(CoreAutofitPlugin.UPGRADE, upgrade);
242                
243                //auto.setChecked(CoreAutofitPlugin.RANDOMIZE, true);
244                //auto.getOptions().get(4).checked = true; // upgrade
245                
246                this.fleet = fleet;
247                this.faction = fleet.getFaction();
248                if (p.factionId != null) {
249                        this.faction = Global.getSector().getFaction(p.factionId);
250                }
251                
252                //this.faction = Global.getSector().getFaction(Factions.HEGEMONY);
253                
254                hullmods = new ArrayList<String>(faction.getKnownHullMods());
255                
256//              fighters = new ArrayList<AvailableFighter>();
257//              for (String wingId : faction.getKnownFighters()) {
258//                      fighters.add(new AvailableFighterImpl(wingId, 1000));
259//              }
260                
261                SortedWeapons nonPriorityWeapons = new SortedWeapons();
262                SortedWeapons priorityWeapons = new SortedWeapons();
263                
264                
265                Set<String> weaponCategories = new LinkedHashSet<String>();
266                for (String weaponId : faction.getKnownWeapons()) {
267                        if (!faction.isWeaponKnownAt(weaponId, p.timestamp)) continue;
268                        
269                        WeaponSpecAPI spec = Global.getSettings().getWeaponSpec(weaponId);
270                        //if (mode == ShipPickMode.IMPORTED && !spec.hasTag(Items.TAG_BASE_BP)) continue;
271                        
272                        if (spec == null) {
273                                throw new RuntimeException("Weapon with spec id [" + weaponId + "] not found");
274                        }
275                        
276                        int tier = spec.getTier();
277                        String cat = spec.getAutofitCategory();
278                        
279                        if (isPriority(spec)) {
280                                List<AvailableWeapon> list = priorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(spec.getSize());
281                                list.add(new AvailableWeaponImpl(spec, 1000));
282                        } else {
283                                List<AvailableWeapon> list = nonPriorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(spec.getSize());
284                                list.add(new AvailableWeaponImpl(spec, 1000));
285                        }
286                        weaponCategories.add(cat);
287                }
288                
289                ListMap<AvailableFighter> nonPriorityFighters = new ListMap<AvailableFighter>(); 
290                ListMap<AvailableFighter> priorityFighters = new ListMap<AvailableFighter>(); 
291                Set<String> fighterCategories = new LinkedHashSet<String>();
292                for (String wingId : faction.getKnownFighters()) {
293                        if (!faction.isFighterKnownAt(wingId, p.timestamp)) continue;
294                        
295                        FighterWingSpecAPI spec = Global.getSettings().getFighterWingSpec(wingId);
296                        if (spec == null) {
297                                throw new RuntimeException("Fighter wing with spec id [" + wingId + "] not found");
298                        }
299                        
300                        //if (mode == ShipPickMode.IMPORTED && !spec.hasTag(Items.TAG_BASE_BP)) continue;
301                        //int tier = spec.getTier();
302                        String cat = spec.getAutofitCategory();
303//                      if (cat == null) {
304//                              System.out.println("wfewfwe");
305//                      }
306                        if (isPriority(spec)) {
307                                priorityFighters.add(cat, new AvailableFighterImpl(spec, 1000));
308                        } else {
309                                nonPriorityFighters.add(cat, new AvailableFighterImpl(spec, 1000));
310                        }
311                        fighterCategories.add(cat);
312                }
313                
314                
315                //float averageDmods = (1f - quality) / Global.getSettings().getFloat("qualityPerDMod");
316                float averageDmods = getAverageDmodsForQuality(p.quality);
317                
318                //System.out.println("Quality: " + quality + ", Average: " + averageDmods);
319                
320                boolean forceAutofit = fleet.getMemoryWithoutUpdate().getBoolean(MemFlags.MEMORY_KEY_FORCE_AUTOFIT_ON_NO_AUTOFIT_SHIPS);
321                int memberIndex = 0;
322                for (FleetMemberAPI member : fleet.getFleetData().getMembersListCopy()) {
323                        
324                        if (!forceAutofit && member.getHullSpec().hasTag(Tags.TAG_NO_AUTOFIT)) {
325                                continue;
326                        }
327                        if (!forceAutofit && member.getVariant() != null && member.getVariant().hasTag(Tags.TAG_NO_AUTOFIT)) {
328                                continue;
329                        }
330                        
331                        if (!faction.isPlayerFaction()) {
332                                if (!forceAutofit && member.getHullSpec().hasTag(Tags.TAG_NO_AUTOFIT_UNLESS_PLAYER)) {
333                                        continue;
334                                }
335                                if (!forceAutofit && member.getVariant() != null && member.getVariant().hasTag(Tags.TAG_NO_AUTOFIT_UNLESS_PLAYER)) {
336                                        continue;
337                                }
338                        }
339                        
340                        // need this so that when reinflating a fleet that lost members, the members reinflate consistently
341                        if (p.seed != null) {
342                                int extra = member.getShipName().hashCode();
343                                random = new Random(p.seed * extra);
344                                auto.setRandom(random);
345                                dmodRandom = Misc.getRandom(p.seed * extra, 5);
346                        }
347
348                        List<WeaponSize> sizes = new ArrayList<WeaponAPI.WeaponSize>();
349                        sizes.add(WeaponSize.SMALL);
350                        sizes.add(WeaponSize.MEDIUM);
351                        sizes.add(WeaponSize.LARGE);
352                        
353                        weapons = new ArrayList<AvailableWeapon>();
354                        for (String cat : weaponCategories) {
355                                for (WeaponSize size : sizes) {
356                                        boolean foundSome = false;
357                                        for (int tier = 0; tier < 4; tier++) {
358                                                float p = getTierProbability(tier, this.p.quality);
359                                                if (this.p.allWeapons != null && this.p.allWeapons) {
360                                                        p = 1f;
361                                                }
362                                                
363                                                List<AvailableWeapon> priority = priorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(size);
364                                                List<AvailableWeapon> nonPriority = nonPriorityWeapons.getWeapons(tier).getWeapons(cat).getWeapons(size);
365                                                
366                                                if (!foundSome) {
367                                                        p = 1f;
368                                                }
369                                                
370                                                boolean tierAvailable = random.nextFloat() < p;
371                                                if (!tierAvailable && foundSome) continue;
372                                                //if (random.nextFloat() >= p) continue;
373                                                
374                                                int num = 2;
375                                                switch (size) {
376                                                case LARGE: num = 2; break;
377                                                case MEDIUM: num = 2; break;
378                                                case SMALL: num = 2; break;
379                                                }
380//                                              if (!tierAvailable) {
381//                                                      num = 1;
382//                                              }
383                                                
384                                                if (this.p.allWeapons != null && this.p.allWeapons) {
385                                                        num = 500;
386                                                }
387                                                
388                                                Set<Integer> picks = makePicks(num, priority.size(), random);
389                                                for (Integer index : picks) {
390                                                        AvailableWeapon w = priority.get(index);
391                                                        weapons.add(w);
392                                                        foundSome = true;
393                                                }
394                                                
395                                                num -= picks.size();
396                                                if (num > 0) {
397                                                        picks = makePicks(num, nonPriority.size(), random);
398                                                        for (Integer index : picks) {
399                                                                AvailableWeapon w = nonPriority.get(index);
400                                                                weapons.add(w);
401                                                                foundSome = true;
402                                                        }
403                                                }
404                                        }
405                                }
406                        }
407                        
408                        fighters = new ArrayList<AvailableFighter>();
409                        for (String cat : fighterCategories) {
410                                List<AvailableFighter> priority = priorityFighters.get(cat);
411
412                                boolean madePriorityPicks = false;
413                                if (priority != null) {
414                                        int num = random.nextInt(2) + 1;
415                                        if (this.p.allWeapons != null && this.p.allWeapons) {
416                                                num = 100;
417                                        }
418                                        
419                                        Set<Integer> picks = makePicks(num, priority.size(), random);
420                                        for (Integer index : picks) {
421                                                AvailableFighter f = priority.get(index);
422                                                fighters.add(f);
423                                                madePriorityPicks = true;
424                                        }
425                                }
426                                
427                                if (!madePriorityPicks) {
428                                        int num = random.nextInt(2) + 1;
429                                        if (this.p.allWeapons != null && this.p.allWeapons) {
430                                                num = 100;
431                                        }
432                                        
433                                        List<AvailableFighter> nonPriority = nonPriorityFighters.get(cat);
434                                        Set<Integer> picks = makePicks(num, nonPriority.size(), random);
435                                        for (Integer index : picks) {
436                                                AvailableFighter f = nonPriority.get(index);
437                                                fighters.add(f);
438                                        }
439                                }
440                        }
441                        
442//                      if (member.getHullId().equals("grendel")) {
443//                              System.out.println("efwefwef");
444//                      }
445                        ShipVariantAPI target = member.getVariant();
446                        if (target.getOriginalVariant() != null) {
447                                // needed if inflating the same fleet repeatedly to pick up weapon availability changes etc
448                                target = Global.getSettings().getVariant(target.getOriginalVariant());
449                        }
450                        
451                        if (faction.isPlayerFaction()) {
452                                if (random.nextFloat() < GOAL_VARIANT_PROBABILITY) {
453                                        List<ShipVariantAPI> targets = Global.getSector().getAutofitVariants().getTargetVariants(member.getHullId());
454                                        WeightedRandomPicker<ShipVariantAPI> alts = new WeightedRandomPicker<ShipVariantAPI>(random);
455                                        for (ShipVariantAPI curr : targets) {
456                                                if (curr.getHullSpec().getHullId().equals(target.getHullSpec().getHullId())) {
457                                                        alts.add(curr);
458                                                }
459                                        }
460                                        if (!alts.isEmpty()) {
461                                                target = alts.pick();
462                                        }
463                                }
464                        }
465                        
466                        
467                        currVariant = Global.getSettings().createEmptyVariant(fleet.getId() + "_" + memberIndex, target.getHullSpec());
468                        currMember = member;
469                        
470                        if (target.isStockVariant()) {
471                                currVariant.setOriginalVariant(target.getHullVariantId());
472                        }
473                        
474                        float rProb = faction.getDoctrine().getAutofitRandomizeProbability();
475                        if (p.rProb != null) rProb = p.rProb;
476                        boolean randomize = random.nextFloat() < rProb;
477                        if (member.isStation()) randomize = false;
478                        auto.setChecked(CoreAutofitPlugin.RANDOMIZE, randomize);
479                        
480                        memberIndex++;
481                        
482                        int maxSmods = 0;
483                        if (p.averageSMods != null && !member.isCivilian()) {
484                                maxSmods = getMaxSMods(currVariant, p.averageSMods, dmodRandom) - currVariant.getSMods().size();
485                        }
486                        auto.doFit(currVariant, target, maxSmods, this);
487                        currVariant.setSource(VariantSource.REFIT);
488                        member.setVariant(currVariant, false, false);
489                        
490                        //int dmods = (int) Math.round(averageDmods + dmodRandom.nextFloat() * 2f - 1f);
491//                      int dmods = (int) Math.round(averageDmods + dmodRandom.nextFloat() * 3f - 2f);
492//                      if (dmods > 5) dmods = 5;
493//                      int dmodsAlready = DModManager.getNumDMods(currVariant);
494//                      dmods -= dmodsAlready;
495//                      if (dmods > 0) {
496//                              DModManager.setDHull(currVariant);
497//                              DModManager.addDMods(member, true, dmods, dmodRandom);
498//                      }
499                        
500                        if (!currMember.isStation()) {
501                                int addDmods = getNumDModsToAdd(currVariant, averageDmods, dmodRandom);
502                                if (addDmods > 0) {
503                                        DModManager.setDHull(currVariant);
504                                        DModManager.addDMods(member, true, addDmods, dmodRandom);
505                                }
506                        }
507                }
508                
509                
510                fleet.getFleetData().setSyncNeeded();
511                fleet.getFleetData().syncIfNeeded();
512                
513                // handled in the method that calls inflate()
514                //ListenerUtil.reportFleetInflated(fleet, this);
515        }
516        
517        public static int getNumDModsToAdd(ShipVariantAPI variant, float averageDMods, Random random) {
518                int dmods = (int) Math.round(averageDMods + random.nextDouble() * 3f - 2f);
519                if (dmods > 5) dmods = 5;
520                int dmodsAlready = DModManager.getNumDMods(variant);
521                dmods -= dmodsAlready;
522                
523                return Math.max(0, dmods);
524        }
525        
526        public static int getMaxSMods(ShipVariantAPI variant, int averageSMods, Random random) {
527                float f = random.nextFloat();
528                int sMods = averageSMods;
529                if (f < 0.25f) {
530                        sMods = averageSMods - 1;
531                } else if (f < 0.5f) {
532                        sMods = averageSMods + 1;
533                }
534                if (sMods > 3) sMods = 3;
535                if (sMods < 0) sMods = 0;
536                return sMods;
537        }
538        
539        public static float getAverageDmodsForQuality(float quality) {
540                float averageDmods = (1f - quality) / Global.getSettings().getFloat("qualityPerDMod");
541                return averageDmods;
542        }
543
544        
545        public static Set<Integer> makePicks(int num, int max, Random random) {
546                if (num > max) num = max;
547                Set<Integer> result = new LinkedHashSet<Integer>();
548                if (num == 0) return result;
549                
550                if (num == max) {
551                        for (int i = 0; i < max; i++) {
552                                result.add(i);
553                        }
554                        return result;
555                }
556                
557                while (result.size() < num) {
558                        int add = random.nextInt(max);
559                        result.add(add);
560                }
561                
562                return result;
563        }
564        
565        
566        public boolean removeAfterInflating() {
567                return p.persistent == null || !p.persistent;
568        }
569
570        public void setRemoveAfterInflating(boolean removeAfterInflating) {
571                p.persistent = !removeAfterInflating;
572                if (!p.persistent) p.persistent = null;
573        }
574
575        public void clearFighterSlot(int index, ShipVariantAPI variant) {
576                variant.setWingId(index, null);
577                for (AvailableFighter curr : fighters) {
578                        if (curr.getId().equals(curr.getId())) {
579                                curr.setQuantity(curr.getQuantity() + 1);
580                                break;
581                        }
582                }
583        }
584
585        public void clearWeaponSlot(WeaponSlotAPI slot, ShipVariantAPI variant) {
586                variant.clearSlot(slot.getId());
587                for (AvailableWeapon curr : weapons) {
588                        if (curr.getId().equals(curr.getId())) {
589                                curr.setQuantity(curr.getQuantity() + 1);
590                                break;
591                        }
592                }
593        }
594
595        public void fitFighterInSlot(int index, AvailableFighter fighter, ShipVariantAPI variant) {
596                fighter.setQuantity(fighter.getQuantity() - 1);
597                variant.setWingId(index, fighter.getId());
598        }
599
600        public void fitWeaponInSlot(WeaponSlotAPI slot, AvailableWeapon weapon, ShipVariantAPI variant) {
601                weapon.setQuantity(weapon.getQuantity() - 1);
602                variant.addWeapon(slot.getId(), weapon.getId());
603        }
604
605        public List<AvailableFighter> getAvailableFighters() {
606                return fighters;
607        }
608
609        public List<AvailableWeapon> getAvailableWeapons() {
610                return weapons;
611        }
612        
613        public List<String> getAvailableHullmods() {
614                return hullmods;
615        }
616
617        public ShipAPI getShip() {
618                return null;
619        }
620
621        
622//      public void syncUIWithVariant() {
623//              syncUIWithVariant(null);
624//      }
625        public void syncUIWithVariant(ShipVariantAPI variant) {
626                
627        }
628        
629        public boolean isPriority(WeaponSpecAPI weapon) {
630                return faction.isWeaponPriority(weapon.getWeaponId());
631        }
632
633        public boolean isPriority(FighterWingSpecAPI wing) {
634                return faction.isFighterPriority(wing.getId());
635        }
636        
637        public FleetMemberAPI getMember() {
638                return currMember;
639        }
640        
641        
642        public static void main(String[] args) {
643                
644                Random random = new Random();
645        
646                
647                float total = 0f;
648                float num = 1000f;
649                int []counts = new int[10];
650                for (int i = 0; i < num; i++) {
651                        int dmods = 1;
652                        total += dmods;
653                        counts[dmods]++;
654                }
655                
656                System.out.println("Average dmods: " + total / num);
657                for (int i = 0; i <= 5; i++) {
658                        System.out.println(i + ":" + counts[i]);
659                }
660        }
661        public FactionAPI getFaction() {
662                return faction;
663        }
664        public Long getSeed() {
665                return p.seed;
666        }
667        public void setSeed(Long seed) {
668                this.p.seed = seed;
669        }
670        public Boolean getPersistent() {
671                return p.persistent;
672        }
673        public void setPersistent(Boolean persistent) {
674                this.p.persistent = persistent;
675        }
676        public float getQuality() {
677                return p.quality;
678        }
679        public int getAverageNumSMods() {
680                return p.averageSMods == null ? 0 : p.averageSMods;
681        }
682        public void setQuality(float quality) {
683                this.p.quality = quality;
684        }
685        public Long getTimestamp() {
686                return p.timestamp;
687        }
688        public void setTimestamp(Long timestamp) {
689                this.p.timestamp = timestamp;
690        }
691        public Object getParams() {
692                return p;
693        }
694        
695        
696        public boolean canAddRemoveHullmodInPlayerCampaignRefit(String modId) {
697                return true;
698        }
699
700        public boolean isPlayerCampaignRefit() {
701                return false;
702        }
703
704
705        public boolean isAllowSlightRandomization() {
706                return true;
707        }
708
709
710        @Override
711        public MarketAPI getMarket() {
712                return null;
713        }
714
715        @Override
716        public FleetMemberAPI getFleetMember() {
717                return null;
718        }
719}