001package com.fs.starfarer.api.impl.campaign.procgen;
002
003import java.util.ArrayList;
004import java.util.HashSet;
005import java.util.List;
006import java.util.Set;
007
008import org.json.JSONException;
009import org.json.JSONObject;
010
011import com.fs.starfarer.api.util.Misc;
012import com.fs.starfarer.api.util.WeightedRandomPicker;
013
014public class SalvageEntityGenDataSpec {
015        
016        public static enum DiscoverabilityType {
017                DISCOVERABLE,
018                NOT_DISCOVERABLE,
019                ALWAYS_VISIBLE,
020        }
021        
022        public static class DropData implements Cloneable {
023                transient public String group;
024                transient public int chances = -1;
025                transient public int maxChances = -1;
026                transient public int value = -1;
027                transient public float valueMult = 1f;
028                private WeightedRandomPicker<DropGroupRow> custom = null;
029                
030                private String j = null;
031//              public DropData(String group) {
032//                      this.group = group;
033//              }
034                Object readResolve() {
035                        if (j != null) {
036                                try {
037                                        JSONObject json = new JSONObject(j);
038                                        if (json.has("g")) group = json.getString("g");
039                                        if (json.has("c")) {
040                                                chances = json.getInt("c");
041                                        } else {
042                                                chances = -1;
043                                        }
044                                        if (json.has("mC")) {
045                                                maxChances = json.getInt("mC");
046                                        } else {
047                                                maxChances = -1;
048                                        }
049                                        if (json.has("v")) {
050                                                value = json.getInt("v");
051                                        } else {
052                                                value = -1;
053                                        }
054                                        if (json.has("vM")) {
055                                                valueMult = (float) json.getDouble("vM");
056                                        } else {
057                                                valueMult = 1f;
058                                        }
059                                } catch (JSONException e) {
060                                        throw new RuntimeException(e);
061                                }
062                        }
063                        return this;
064                }
065                
066                Object writeReplace() {
067                        try {
068                                JSONObject json = new JSONObject();
069                                if (group != null) json.put("g", group);
070                                if (chances > 0) json.put("c", chances);
071                                if (maxChances > 0) json.put("mC", maxChances);
072                                if (value > 0) json.put("v", value);
073                                if (valueMult != 1) json.put("vM", valueMult);
074                                j = json.toString();
075                        } catch (JSONException e) {
076                                throw new RuntimeException(e);
077                        }
078                        return this;
079                }
080                
081                
082                public void addWeapon(String id, float weight) {
083                        addCustom(DropGroupRow.WEAPON_PREFIX + id, weight);
084                }
085                public void addHullMod(String id, float weight) {
086                        //addCustom(DropGroupRow.MOD_PREFIX + id, weight);
087                        addCustom("item_modspec:" + id, weight);
088                }
089                public void addFighterChip(String id, float weight) {
090                        addCustom(DropGroupRow.FIGHTER_PREFIX + id, weight);
091                }
092                public void addNothing(float weight) {
093                        addCustom(DropGroupRow.NOTHING, weight);
094                }
095                public void addCommodity(String id, float weight) {
096                        addCustom(id, weight);
097                }
098                public void addSpecialItem(String data, float weight) {
099                        addCustom(DropGroupRow.ITEM_PREFIX + data, weight);
100                }
101                public void addCustom(String data, float weight) {
102                        initCustom();
103                        for (int i = 0; i < custom.getItems().size(); i++) {
104                                DropGroupRow row = custom.getItems().get(i);
105                                if (row.getCommodity() != null && row.getCommodity().equals(data)) {
106                                        float w = custom.getWeight(i);
107                                        w += weight;
108                                        custom.setWeight(i, w);
109                                        return;
110                                }
111                        }
112                        DropGroupRow row = new DropGroupRow(data, "custom", weight);
113                        custom.add(row, weight);
114                }
115                
116                public void addRandomWeapons(int tier, float weight) {
117                        addCustom(DropGroupRow.WEAPON_PREFIX, tier, weight, (String []) null);
118                }
119                public void addRandomWeapons(int tier, float weight, String ... tags) {
120                        addCustom(DropGroupRow.WEAPON_PREFIX, tier, weight, tags);
121                }
122                
123                public void addRandomHullmods(int tier, float weight) {
124                        //addCustom(DropGroupRow.MOD_PREFIX, tier, weight, (String []) null);
125                        addCustom("item_modspec:", tier, weight, (String []) null);
126                }
127                public void addRandomHullmods(int tier, float weight, String ... tags) {
128                        //addCustom(DropGroupRow.MOD_PREFIX, tier, weight, tags);
129                        addCustom("item_modspec:", tier, weight, tags);
130                }
131                
132                public void addRandomFighters(int tier, float weight) {
133                        addCustom(DropGroupRow.FIGHTER_PREFIX, tier, weight, (String []) null);
134                }
135                public void addRandomFighters(int tier, float weight, String ... tags) {
136                        addCustom(DropGroupRow.FIGHTER_PREFIX, tier, weight, tags);
137                }
138                
139                private void addCustom(String prefix, int tier, float weight, String ... tags) {
140                        initCustom();
141                        
142                        String data = prefix;
143                        data += "{";
144                        if (tier >= 0) {
145                                data += "tier:" + tier + ",";
146                        }
147                        if (tags != null && tags.length > 0) {
148                                data += "tags:[";
149                                for (String tag : tags) {
150                                        data += tag + ",";
151                                }
152                                data += "]";
153                        }
154                        data += "}";
155                        DropGroupRow row = new DropGroupRow(data, "custom", weight);
156                        custom.add(row, weight);
157                }
158                
159                public void initCustom() {
160                        if (custom == null) {
161                                custom = new WeightedRandomPicker<DropGroupRow>();
162                        }
163                }
164                
165                public void clearCustom() {
166                        custom = null;
167                }
168                
169                public WeightedRandomPicker<DropGroupRow> getCustom() {
170                        return custom;
171                }
172
173                @Override
174                public DropData clone() {
175                        try {
176                                DropData copy = (DropData) super.clone();
177                                
178                                if (custom != null) {
179                                        copy.custom = new WeightedRandomPicker<DropGroupRow>();
180                                        for (int i = 0; i < custom.getItems().size(); i++) {
181                                                copy.custom.add(custom.getItems().get(i), custom.getWeight(i));
182                                        }
183                                }
184                                return copy;
185                        } catch (CloneNotSupportedException e) {
186                                throw new RuntimeException(e);
187                        }
188                }
189        }
190
191//      id,rating,detection_range,xpGain,drop_value,drop_random
192//      derelict_probe,0,2000,500,"basic:2000, extended:500",ai_cores1:1
193//      probDefenders   minStr  maxStr  maxSize
194        // probStation  stationRole
195        private String id;
196        private String nameOverride;
197        private float salvageRating, detectionRange, xpDiscover, xpSalvage, radiusOverride = -1f;
198        private DiscoverabilityType type;
199        private float probDefenders, defQuality, minStr, maxStr, maxDefenderSize, minDefenderSize, probStation;
200        private String stationRole;
201        private String defFaction;
202        
203//      private Map<String, Float> dropValue = new HashMap<String, Float>();
204//      private Map<String, Float> dropRandom = new HashMap<String, Float>();
205        private List<DropData> dropValue = new ArrayList<DropData>();
206        private List<DropData> dropRandom = new ArrayList<DropData>();
207
208        private Set<String> tags = new HashSet<String>();
209        
210        public SalvageEntityGenDataSpec(JSONObject row) throws JSONException {
211                id = row.getString("id");
212                
213                stationRole = row.getString("stationRole");
214                
215                nameOverride = row.optString("name");
216                if (nameOverride != null && nameOverride.isEmpty()) nameOverride = null;
217                
218                salvageRating = (float) row.optDouble("rating", 0);
219                detectionRange = (float) row.optDouble("detection_range", 0);
220                
221                float baseXP = 200 + 1 * (salvageRating * 20f);
222                //baseXP /= 3f;
223                baseXP = Misc.getRounded(baseXP);
224//              if (id.equals("ruins_vast")) {
225//                      System.out.println("wefwefe");
226//              }
227                xpDiscover = (float) row.optDouble("xpDiscover", baseXP);
228                xpSalvage = (float) row.optDouble("xpSalvage", baseXP * 3f);
229                
230                radiusOverride = (float) row.optDouble("radius", -1);
231                
232                defQuality = (float) row.optDouble("defQuality", 1f);
233                
234                probDefenders = (float) row.optDouble("probDefenders", 0);
235                minStr = (float) row.optDouble("minStr", 0);
236                maxStr = (float) row.optDouble("maxStr", 0);
237                maxDefenderSize = (float) row.optDouble("maxSize", 4);
238                minDefenderSize = (float) row.optDouble("minSize", 0);
239                
240                defFaction = row.optString("defFaction", null);
241                if (defFaction != null && defFaction.isEmpty()) defFaction = null;
242                
243                probStation = (float) row.optDouble("probStation", 0);
244                
245                type = Misc.mapToEnum(row, "type", DiscoverabilityType.class, DiscoverabilityType.DISCOVERABLE);
246                
247                if (row.has("drop_value") && !row.getString("drop_value").isEmpty()) {
248                        //readToMap(row.getString("drop_value"), dropValue);
249                        String [] parts = row.getString("drop_value").split(",");
250                        for (String part : parts) {
251                                part = part.trim();
252                                String [] pair = part.split(":");
253                                String key = pair[0].trim();
254                                String value = pair[1].trim();
255                                
256                                DropData data = new DropData();
257                                data.group = key;
258                                data.value = Integer.valueOf(value);
259                                data.chances = -1;
260                                
261                                dropValue.add(data);
262                        }
263                }
264                
265                if (row.has("drop_random") && !row.getString("drop_random").isEmpty()) {
266                        //readToMap(row.getString("drop_random"), dropRandom);
267                        String [] parts = row.getString("drop_random").split(",");
268                        for (String part : parts) {
269                                part = part.trim();
270                                String [] pair = part.split(":");
271                                String key = pair[0].trim();
272                                String value = pair[1].trim();
273                                
274                                DropData data = new DropData();
275                                data.group = key;
276                                
277                                if (value.contains("x")) {
278                                        String [] chancesXValue = value.split("x");
279                                        if (chancesXValue[0].trim().contains("-")) {
280                                                data.chances = Integer.valueOf(chancesXValue[0].trim().split("-")[0]);
281                                                data.maxChances = Integer.valueOf(chancesXValue[0].trim().split("-")[1]);
282                                        } else {
283                                                data.chances = Integer.valueOf(chancesXValue[0].trim());
284                                        }
285                                        data.value = Integer.valueOf(chancesXValue[1].trim()); 
286                                } else {
287                                        data.value = -1;
288                                        
289                                        if (value.contains("-")) {
290                                                data.chances = Integer.valueOf(value.trim().split("-")[0]);
291                                                data.maxChances = Integer.valueOf(value.trim().split("-")[1]);
292                                        } else {
293                                                float c = Float.valueOf(value); 
294                                                data.chances = (int) Math.max(c, 1);
295                                                if (c < 1) data.valueMult = c;
296                                        }
297                                        //data.chances = Integer.valueOf(value);
298                                }
299                                
300                                dropRandom.add(data);
301                        }
302                }
303                
304                String tags = row.optString("tags", null);
305                if (tags != null) {
306                        String [] split = tags.split(",");
307                        for (String tag : split) {
308                                tag = tag.trim();
309                                if (tag.isEmpty()) continue;
310                                addTag(tag);
311                        }
312                }
313        }
314        
315        public String getDefFaction() {
316                return defFaction;
317        }
318
319        public void setDefFaction(String defFaction) {
320                this.defFaction = defFaction;
321        }
322
323
324        public Set<String> getTags() {
325                return tags;
326        }
327        
328        public void addTag(String tag) {
329                tags.add(tag);
330        }
331
332        public boolean hasTag(String tag) {
333                return tags.contains(tag);
334        }
335        
336        public float getRadiusOverride() {
337                return radiusOverride;
338        }
339
340        public void setRadiusOverride(float radiusOverride) {
341                this.radiusOverride = radiusOverride;
342        }
343
344        public String getNameOverride() {
345                return nameOverride;
346        }
347
348        public void setNameOverride(String nameOverride) {
349                this.nameOverride = nameOverride;
350        }
351
352        public String getId() {
353                return id;
354        }
355        public void setId(String id) {
356                this.id = id;
357        }
358        public float getSalvageRating() {
359                return salvageRating;
360        }
361        public void setSalvageRating(float salvageRating) {
362                this.salvageRating = salvageRating;
363        }
364        public float getDetectionRange() {
365                return detectionRange;
366        }
367        public void setDetectionRange(float detectionRange) {
368                this.detectionRange = detectionRange;
369        }
370        public float getXpDiscover() {
371                return xpDiscover;
372        }
373        public void setXpDiscover(float xpDiscover) {
374                this.xpDiscover = xpDiscover;
375        }
376        public float getXpSalvage() {
377                return xpSalvage;
378        }
379        public void setXpSalvage(float xpSalvage) {
380                this.xpSalvage = xpSalvage;
381        }
382
383
384        public List<DropData> getDropValue() {
385                return dropValue;
386        }
387        public List<DropData> getDropRandom() {
388                return dropRandom;
389        }
390        public DiscoverabilityType getType() {
391                return type;
392        }
393        public void setType(DiscoverabilityType type) {
394                this.type = type;
395        }
396        public float getProbDefenders() {
397                return probDefenders;
398        }
399        public void setProbDefenders(float probDefenders) {
400                this.probDefenders = probDefenders;
401        }
402        public float getMinStr() {
403                return minStr;
404        }
405        public void setMinStr(float minStr) {
406                this.minStr = minStr;
407        }
408        public float getMaxStr() {
409                return maxStr;
410        }
411        public void setMaxStr(float maxStr) {
412                this.maxStr = maxStr;
413        }
414        public float getMaxDefenderSize() {
415                return maxDefenderSize;
416        }
417        public void setMaxDefenderSize(float maxSize) {
418                this.maxDefenderSize = maxSize;
419        }
420        
421        public float getMinDefenderSize() {
422                return minDefenderSize;
423        }
424
425        public void setMinDefenderSize(float minDefenderSize) {
426                this.minDefenderSize = minDefenderSize;
427        }
428
429        public float getDefQuality() {
430                return defQuality;
431        }
432
433        public void setDefQuality(float defQuality) {
434                this.defQuality = defQuality;
435        }
436
437        public float getProbStation() {
438                return probStation;
439        }
440
441        public void setProbStation(float probStation) {
442                this.probStation = probStation;
443        }
444
445        public String getStationRole() {
446                return stationRole;
447        }
448
449        public void setStationRole(String stationRole) {
450                this.stationRole = stationRole;
451        }
452
453
454//      public static void readToMap(String input, Map<String, Float> map) {
455//              String [] parts = input.split(",");
456//              for (String part : parts) {
457//                      part = part.trim();
458//                      String [] pair = part.split(":");
459//                      String key = pair[0].trim();
460//                      float value = Float.valueOf(pair[1].trim());
461//                      map.put(key, value);
462//              }
463//      }
464        
465//      public static void verifySpecsExist(Class clazz, List<String> specs, String desc) {
466//              for (String id : specs) {
467//                      Object spec = Global.getSettings().getSpec(clazz, id, true);
468//                      if (spec == null) {
469//                              throw new RuntimeException("Spec of class " + clazz.getName() +
470//                                                                                 " with id [" + id + "] not found while verifying [" + 
471//                                                                                 desc + "]");
472//                      }
473//              }
474//      }
475        
476        
477}