Starsector API
Loading...
Searching...
No Matches
PlayerTradeDataForSubmarket.java
Go to the documentation of this file.
1
4package com.fs.starfarer.api.impl.campaign.shared;
5
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.HashMap;
9import java.util.LinkedHashMap;
10import java.util.List;
11import java.util.Map;
12
13import com.fs.starfarer.api.Global;
14import com.fs.starfarer.api.campaign.CargoAPI;
15import com.fs.starfarer.api.campaign.CargoAPI.CargoItemType;
16import com.fs.starfarer.api.campaign.CargoStackAPI;
17import com.fs.starfarer.api.campaign.PlayerMarketTransaction;
18import com.fs.starfarer.api.campaign.PlayerMarketTransaction.ShipSaleInfo;
19import com.fs.starfarer.api.campaign.econ.CommodityOnMarketAPI;
20import com.fs.starfarer.api.campaign.econ.MarketAPI;
21import com.fs.starfarer.api.campaign.econ.SubmarketAPI;
22import com.fs.starfarer.api.combat.MutableStatWithTempMods;
23import com.fs.starfarer.api.impl.campaign.ids.Commodities;
24import com.fs.starfarer.api.impl.campaign.ids.Conditions;
25import com.fs.starfarer.api.impl.campaign.ids.Stats;
26import com.fs.starfarer.api.impl.campaign.submarkets.BaseSubmarketPlugin.ShipSalesData;
27import com.fs.starfarer.api.util.IntervalUtil;
28import com.fs.starfarer.api.util.Misc;
29
31
32 private Map<String, MutableStatWithTempMods> tx = new HashMap<String, MutableStatWithTempMods>();
33
34 private CargoAPI playerBought, playerSold;
35 private float accumulatedPlayerTradeValueForPositive = 0;
36 private float accumulatedPlayerTradeValueForNegative = 0;
37 private float totalPlayerTradeValue = 0;
38
39 private IntervalUtil tracker;
40
41 private Map<String, ShipSalesData> playerBoughtShips = new LinkedHashMap<String, ShipSalesData>();
42 private Map<String, ShipSalesData> playerSoldShips = new LinkedHashMap<String, ShipSalesData>();
43 private MarketAPI market;
44 private SubmarketAPI submarket;
45
46 public PlayerTradeDataForSubmarket(SubmarketAPI submarket) {
47 this.market = submarket.getMarket();
48 this.submarket = submarket;
49
50 playerBought = Global.getFactory().createCargo(true);
51 playerSold = Global.getFactory().createCargo(true);
52
53 tracker = Misc.createEconIntervalTracker();
54 }
55
56 protected Object readResolve() {
57 if (tx == null) {
58 tx = new HashMap<String, MutableStatWithTempMods>();
59 }
60 return this;
61 }
62
63 public static String getTXId(CargoStackAPI stack) {
64 return stack.getType().name() + "_" + stack.getData().toString();
65 }
66
67 public static String getTXId(ShipSalesData data) {
68 return data.getVariantId();
69 }
70
71 public MutableStatWithTempMods getStat(String id) {
72 MutableStatWithTempMods stat = tx.get(id);
73 if (stat == null) {
74 stat = new MutableStatWithTempMods(0);
75 tx.put(id, stat);
76 }
77 return stat;
78 }
79
80 public void advance(float days) {
81 tracker.advance(days);
82 if (tracker.intervalElapsed()) {
83 //float factor = 1f - Misc.getGenericRollingAverageFactor();
84 float factor = 0.5f;
85
86 for (CargoStackAPI stack : playerBought.getStacksCopy()) {
87 stack.setSize(stack.getSize() * factor);
88 if (stack.getSize() < 10) {
89 stack.setSize(0);
90 }
91 }
92 playerBought.removeEmptyStacks();
93 for (CargoStackAPI stack : playerSold.getStacksCopy()) {
94 stack.setSize(stack.getSize() * factor);
95 if (stack.getSize() < 10) {
96 stack.setSize(0);
97 }
98 }
99 playerSold.removeEmptyStacks();
100
101 //System.out.println("Ships: " + (playerBoughtShips.size() + playerSoldShips.size()));
102// if (playerSold.getMothballedShips() != null) {
103// System.out.println("Ships: " + playerSold.getMothballedShips().getNumMembers());
104// }
105
106 List<String> remove = new ArrayList<String>();
107 for (ShipSalesData data : playerBoughtShips.values()) {
108 data.setNumShips(data.getNumShips() * factor);
109 data.setTotalValue(data.getTotalValue() * factor);
110 if (data.getNumShips() < 0.2f) remove.add(data.getVariantId());
111 }
112 for (String vid : remove) {
113 playerBoughtShips.remove(vid);
114 }
115 remove.clear();
116
117 for (ShipSalesData data : playerSoldShips.values()) {
118 data.setNumShips(data.getNumShips() * factor);
119 data.setTotalValue(data.getTotalValue() * factor);
120 if (data.getNumShips() < 0.2f) remove.add(data.getVariantId());
121 }
122 for (String vid : remove) {
123 playerSoldShips.remove(vid);
124 }
125 remove.clear();
126
127
128 accumulatedPlayerTradeValueForPositive *= factor;
129 accumulatedPlayerTradeValueForNegative *= factor;
130 totalPlayerTradeValue *= factor;
131 }
132 }
133
134
135 public void addTransaction(PlayerMarketTransaction transaction) {
136 for (CargoStackAPI stack : transaction.getSold().getStacksCopy()) {
138 }
139 for (CargoStackAPI stack : transaction.getBought().getStacksCopy()) {
141 }
142 for (ShipSaleInfo info : transaction.getShipsBought()) {
144 }
145 for (ShipSaleInfo info : transaction.getShipsSold()) {
147 }
148 }
149
150 private float getTransponderMult() {
151 boolean tOn = Global.getSector().getPlayerFleet().isTransponderOn();
152 float mult = 1f;
153 if (!tOn) {
154 //mult = 0.25f;
155 mult = Global.getSettings().getFloat("transponderOffMarketAwarenessMult");
156 }
157 return mult;
158 }
159
160 public void addToTrackedPlayerBought(ShipSaleInfo info) {
161 String vid = info.getMember().getVariant().getHullSpec().getHullId();
162 ShipSalesData bought = getBoughtShipData(vid);
163 ShipSalesData sold = getSoldShipData(vid);
164
165 float playerImpactMult = Global.getSettings().getFloat("economyPlayerTradeImpactMult");
166
167 float fractionBought = 1f;
168 if (sold.getNumShips() > 0) {
169 fractionBought = Math.max(0, fractionBought - sold.getNumShips());
170 sold.setNumShips(sold.getNumShips() - 1f);
171 sold.setTotalValue(sold.getTotalValue() - (1f - fractionBought) * info.getPrice() * playerImpactMult);
172 if (sold.getNumShips() < 0) sold.setNumShips(0);
173 if (sold.getTotalValue() < 0) sold.setTotalValue(0);
174 }
175
176 if (fractionBought > 0) {
177 accumulatedPlayerTradeValueForPositive += info.getPrice() * playerImpactMult * fractionBought * getTransponderMult();
178 accumulatedPlayerTradeValueForNegative += info.getPrice() * playerImpactMult * fractionBought * getTransponderMult();
179 totalPlayerTradeValue += info.getPrice() * playerImpactMult * fractionBought * getTransponderMult();
180 bought.setNumShips(bought.getNumShips() + 1f * fractionBought);
181 bought.setTotalValue(bought.getTotalValue() + info.getPrice() * playerImpactMult * fractionBought);
182 }
183 }
184
185 public void addToTrackedPlayerSold(ShipSaleInfo info) {
186 String vid = info.getMember().getVariant().getHullSpec().getHullId();
187 ShipSalesData bought = getBoughtShipData(vid);
188 ShipSalesData sold = getSoldShipData(vid);
189
190 float playerImpactMult = Global.getSettings().getFloat("economyPlayerTradeImpactMult");
191
192 float fractionSold = 1f;
193 if (bought.getNumShips() > 0) {
194 fractionSold = Math.max(0, fractionSold - bought.getNumShips());
195 bought.setNumShips(bought.getNumShips() - 1f);
196 bought.setTotalValue(bought.getTotalValue() - (1f - fractionSold) * info.getPrice() * playerImpactMult);
197 if (bought.getNumShips() < 0) bought.setNumShips(0);
198 if (bought.getTotalValue() < 0) bought.setTotalValue(0);
199 }
200
201 if (fractionSold > 0) {
202 accumulatedPlayerTradeValueForPositive += info.getPrice() * playerImpactMult * fractionSold * getTransponderMult();
203 accumulatedPlayerTradeValueForNegative += info.getPrice() * playerImpactMult * fractionSold * getTransponderMult();
204 totalPlayerTradeValue += info.getPrice() * playerImpactMult * fractionSold * getTransponderMult();
205 sold.setNumShips(sold.getNumShips() + 1f * fractionSold);
206 sold.setTotalValue(sold.getTotalValue() + info.getPrice() * playerImpactMult * fractionSold);
207 }
208 }
209
210 public void addToTrackedPlayerBought(CargoStackAPI stack) {
211 float qty = stack.getSize() - playerSold.getQuantity(stack.getType(), stack.getData());
212 float impact = computeImpactOfHavingAlreadyBought(market,
213 stack.getType(), stack.getData(), stack.getBaseValuePerUnit(), qty);
214 accumulatedPlayerTradeValueForPositive += impact * getTransponderMult();
215 accumulatedPlayerTradeValueForNegative += impact * getTransponderMult();
216 totalPlayerTradeValue += impact * getTransponderMult();
217
218 playerBought.addItems(stack.getType(), stack.getData(), stack.getSize());
219 playerSold.removeItems(stack.getType(), stack.getData(), stack.getSize());
220
221 if (qty >= 1 && stack.getType() == CargoItemType.RESOURCES) {
223 float price = computePriceOfHavingAlreadyBought(market,
224 stack.getType(), stack.getData(), stack.getBaseValuePerUnit(), qty);
225 data.reportNetBought((String)stack.getData(), qty, price);
226 }
227 }
228
229 public void addToTrackedPlayerSold(CargoStackAPI stack) {
230 addToTrackedPlayerSold(stack, -1);
231 }
232
233 public void addToTrackedPlayerSold(CargoStackAPI stack, float totalPriceOverride) {
234 float qty = stack.getSize() - playerBought.getQuantity(stack.getType(), stack.getData());
235 float impact = computeImpactOfHavingAlreadySold(market,
236 stack.getType(), stack.getData(), stack.getBaseValuePerUnit(), qty);
237
238 playerSold.addItems(stack.getType(), stack.getData(), stack.getSize());
239 playerBought.removeItems(stack.getType(), stack.getData(), stack.getSize());
240
241 float overrideImpactMult = 1f;
242 if (qty >= 1 && stack.getType() == CargoItemType.RESOURCES) {
244 float price = computePriceOfHavingAlreadySold(market,
245 stack.getType(), stack.getData(), stack.getBaseValuePerUnit(), qty);
246 if (totalPriceOverride > 0) {
247 if (price > 0) {
248 overrideImpactMult = totalPriceOverride / price;
249 }
250 price = totalPriceOverride;
251 }
252
253// String multId = Stats.getPlayerTradeImpactMultId(commodityId);
254// val *= market.getStats().getDynamic().getValue(multId);
255// multId = Stats.getPlayerSellImpactMultId(commodityId);
256// val *= market.getStats().getDynamic().getValue(multId);
257
258 data.reportNetSold((String)stack.getData(), qty, price);
259 }
260
261 accumulatedPlayerTradeValueForPositive += impact * getTransponderMult() * overrideImpactMult;
262 accumulatedPlayerTradeValueForNegative += impact * getTransponderMult() * overrideImpactMult;
263 totalPlayerTradeValue += impact * getTransponderMult() * overrideImpactMult;
264 }
265
266 public static float computeImpactOfHavingAlreadySold(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty) {
267 if (qty < 1) return 0;
268
269 float playerImpactMult = Global.getSettings().getFloat("economyPlayerTradeImpactMult");
270 float illegalImpactMult = Global.getSettings().getFloat("economyPlayerSellIllegalImpactMult");
271 float militaryImpactMult = Global.getSettings().getFloat("economyPlayerSellMilitaryImpactMult");
272
273 if (type == CargoItemType.RESOURCES) {
274 String commodityId = (String) data;
275 CommodityOnMarketAPI com = market.getCommodityData(commodityId);
276 float val = market.getDemandPriceAssumingExistingTransaction(commodityId, qty, -qty * com.getUtilityOnMarket(), true);
277 if (!market.hasCondition(Conditions.FREE_PORT) &&
278 market.isIllegal(commodityId)) {
279 val *= illegalImpactMult;
280 }
281 val *= playerImpactMult;
282
283 String multId = Stats.getPlayerTradeRepImpactMultId(commodityId);
284 val *= market.getStats().getDynamic().getValue(multId);
285 multId = Stats.getPlayerSellRepImpactMultId(commodityId);
286 val *= market.getStats().getDynamic().getValue(multId);
287
288 if (com.getCommodity().hasTag(Commodities.TAG_MILITARY)) {
289 val *= militaryImpactMult;
290 }
291 return val;
292 } else {
293 float val = (float) baseValue * qty * playerImpactMult;
294 return val;
295 }
296 }
297
298 public static float computePriceOfHavingAlreadySold(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty) {
299 if (qty < 1) return 0;
300
301 if (type == CargoItemType.RESOURCES) {
302 String commodityId = (String) data;
303 CommodityOnMarketAPI com = market.getCommodityData(commodityId);
304 float val = market.getDemandPriceAssumingExistingTransaction(commodityId, qty, -qty * com.getUtilityOnMarket(), true);
305 return val;
306 } else {
307 float val = (float) baseValue * qty;
308 return val;
309 }
310 }
311
312 public static float computeImpactOfHavingAlreadyBought(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty) {
313 if (qty < 1) return 0;
314
315 float playerImpactMult = Global.getSettings().getFloat("economyPlayerTradeImpactMult");
316// market.getSupplyPriceAssumingExistingTransaction(commodityId, qty, qty * com.getUtilityOnMarket(), true);
317// market.getSupplyPriceAssumingExistingTransaction(commodityId, qty, 1, true);
318 if (type == CargoItemType.RESOURCES) {
319 String commodityId = (String) data;
320 CommodityOnMarketAPI com = market.getCommodityData(commodityId);
321 float val = market.getSupplyPriceAssumingExistingTransaction(commodityId, qty, qty * com.getUtilityOnMarket(), true);
322 val *= playerImpactMult;
323
324 String multId = Stats.getPlayerTradeRepImpactMultId(commodityId);
325 val *= market.getStats().getDynamic().getValue(multId);
326 multId = Stats.getPlayerBuyRepImpactMultId(commodityId);
327 val *= market.getStats().getDynamic().getValue(multId);
328 return val;
329 } else {
330 float val = (float) baseValue * qty * playerImpactMult;
331 return val;
332 }
333 }
334
335 public static float computePriceOfHavingAlreadyBought(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty) {
336 if (qty < 1) return 0;
337
338 if (type == CargoItemType.RESOURCES) {
339 String commodityId = (String) data;
340 CommodityOnMarketAPI com = market.getCommodityData(commodityId);
341 float val = market.getSupplyPriceAssumingExistingTransaction(commodityId, qty, qty * com.getUtilityOnMarket(), true);
342 return val;
343 } else {
344 float val = (float) baseValue * qty;
345 return val;
346 }
347 }
348
349
351 return totalPlayerTradeValue;
352 }
353
354 public void setTotalPlayerTradeValue(float totalPlayerTradeValue) {
355 this.totalPlayerTradeValue = totalPlayerTradeValue;
356 }
357
358 public CargoAPI getRecentPlayerBought() {
359 return playerBought;
360 }
361
362 public CargoAPI getRecentPlayerSold() {
363 return playerSold;
364 }
365
367 return accumulatedPlayerTradeValueForPositive;
368 }
369
370 public void setAccumulatedPlayerTradeValueForPositive(float accumulatedPlayerTradeValue) {
371 this.accumulatedPlayerTradeValueForPositive = accumulatedPlayerTradeValue;
372 }
373
375 return accumulatedPlayerTradeValueForNegative;
376 }
377
379 float accumulatedPlayerTradeValueForNegative) {
380 this.accumulatedPlayerTradeValueForNegative = accumulatedPlayerTradeValueForNegative;
381 }
382
383 public IntervalUtil getTracker() {
384 return tracker;
385 }
386
387 public Collection<ShipSalesData> getRecentlyPlayerBoughtShips() {
388 return playerBoughtShips.values();
389 }
390
391 public Collection<ShipSalesData> getRecentlyPlayerSoldShips() {
392 return playerSoldShips.values();
393 }
394
395 public MarketAPI getMarket() {
396 return market;
397 }
398
399 public SubmarketAPI getSubmarket() {
400 return submarket;
401 }
402
403
404 protected ShipSalesData getSoldShipData(String vid) {
405 ShipSalesData sold = playerSoldShips.get(vid);
406 if (sold == null) {
407 sold = new ShipSalesData();
408 sold.setVariantId(vid);
409 playerSoldShips.put(vid, sold);
410 }
411 return sold;
412 }
413
414 protected ShipSalesData getBoughtShipData(String vid) {
415 ShipSalesData bought = playerBoughtShips.get(vid);
416 if (bought == null) {
417 bought = new ShipSalesData();
418 bought.setVariantId(vid);
419 playerBoughtShips.put(vid, bought);
420 }
421 return bought;
422 }
423
425// float playerImpactMult = Global.getSettings().getFloat("economyPlayerTradeImpactMult");
426// float illegalImpactMult = Global.getSettings().getFloat("economyPlayerSellIllegalImpactMult");
427
428 float total = 0;
429 for (CargoStackAPI stack : playerBought.getStacksCopy()) {
430 float qty = stack.getSize();
431// if (qty < 1) continue;
432// float val = (float) stack.getBaseValuePerUnit() * qty * playerImpactMult;
433 float val = computeImpactOfHavingAlreadyBought(market,
434 stack.getType(), stack.getData(), stack.getBaseValuePerUnit(), qty);
435 total += val;
436 }
437 for (CargoStackAPI stack : playerSold.getStacksCopy()) {
438 float qty = stack.getSize();
439 if (qty < 1) continue;
440// float val = (float) stack.getBaseValuePerUnit() * qty * playerImpactMult;
441// if (!market.hasCondition(Conditions.FREE_PORT) &&
442// stack.isCommodityStack() && market.isIllegal(stack.getCommodityId())) {
443// val *= illegalImpactMult;
444// }
445 float val = computeImpactOfHavingAlreadySold(market,
446 stack.getType(), stack.getData(), stack.getBaseValuePerUnit(), qty);
447 total += val;
448 }
449 return total;
450 }
451
452 public void setSubmarket(SubmarketAPI submarket) {
453 this.submarket = submarket;
454 }
455
456}
457
458
459
460
461
462
static SettingsAPI getSettings()
Definition Global.java:51
static FactoryAPI getFactory()
Definition Global.java:35
static SectorAPI getSector()
Definition Global.java:59
static float computePriceOfHavingAlreadySold(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty)
static float computePriceOfHavingAlreadyBought(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty)
static float computeImpactOfHavingAlreadySold(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty)
void setAccumulatedPlayerTradeValueForNegative(float accumulatedPlayerTradeValueForNegative)
static float computeImpactOfHavingAlreadyBought(MarketAPI market, CargoItemType type, Object data, float baseValue, float qty)
void reportNetBought(String commodityId, float quantity, float totalPrice)
void reportNetSold(String commodityId, float quantity, float totalPrice)
CargoAPI createCargo(boolean unlimitedStacks)