public static string AddPriceModifierText(ThingDef thingDef)
        {
            if (CapitalismUtils.ShouldIgnoreTrade())
            {
                return(string.Empty);
            }

            var modifier = GetPriceModifierIfExists(thingDef);

            if (modifier.HasValue)
            {
                return("\n  x " + modifier.Value.ToString("F2") + " (supply/demand)");
            }
            return(string.Empty);
        }
        private void RegisterTemporaryTrader(Pawn pawn, string name, List <Thing> goods, int forgetTraderAfter)
        {
            if (temporaryTraders.Any(t => t?.pawn == pawn && t?.name == name))
            {
                return;
            }

            temporaryTraders.Add(new TemporaryTrader
            {
                expiresAtTick = Find.TickManager.TicksGame + forgetTraderAfter,
                pawn          = pawn,
                name          = name,
                goods         = goods
            });
            CapitalismUtils.LogAndMessage("Registering temporary trader " + temporaryTraders.Last().ToString());
        }
        public void RegisterTrade(Faction faction, ITrader trader, ThingDef thingDef, int count)
        {
            var timeToForget = trader is Settlement
                ? Capitalism.Settings.RememberSettlementMaxTime
                : trader is Pawn || trader is Caravan
                    ? Capitalism.Settings.RememberCaravanTime
                    : Capitalism.Settings.RememberOrbitalTradersTime;

            registeredTrades.Add(new ThingTrade()
            {
                expiresAtTick = Find.TickManager.TicksGame + timeToForget,
                count         = count,
                thingDef      = CapitalismUtils.GroupCertainThingDefs(thingDef),
                settlement    = trader as Settlement,
                faction       = faction
            });
            priceModifiers = null;
        }
        private void ExpireOldData(IEnumerable <IExpirable> expirableData)
        {
            var expired = expirableData
                          .Where(t => t.HasExpired)
                          .ToList();

            foreach (var t in expired)
            {
                CapitalismUtils.LogAndMessage("Forgetting " + t.ToString());
            }
            if (expired.Any())
            {
                priceModifiers = null;
            }

            expirableData = expirableData
                            .Where(t => !t.HasExpired)
                            .ToList();
        }
        public Dictionary <ThingDef, float> GeneratePriceModifiers()
        {
            ExpireOldData(registeredTrades);
            ExpireOldData(temporaryTraders);


            var totalInCirculation = new Dictionary <ThingDef, int>();
            var totalTraded        = new Dictionary <ThingDef, int>();

            foreach (var settlement in Find.WorldObjects.Settlements)
            {
                var inStock = settlement.trader.StockListForReading;
                foreach (var t in inStock)
                {
                    var def = CapitalismUtils.GroupCertainThingDefs(t.def);
                    if (!totalInCirculation.ContainsKey(def))
                    {
                        totalInCirculation[def] = 0;
                    }
                    totalInCirculation[def] += t.stackCount;
                }
            }

            foreach (var trader in temporaryTraders)
            {
                foreach (var t in trader.goods)
                {
                    var def = CapitalismUtils.GroupCertainThingDefs(t.def);
                    if (!totalInCirculation.ContainsKey(def))
                    {
                        totalInCirculation[def] = 0;
                    }
                    totalInCirculation[def] += t.stackCount;
                }
            }

            foreach (var t in registeredTrades)
            {
                if (!totalTraded.ContainsKey(t.thingDef))
                {
                    totalTraded[t.thingDef] = 0;
                }
                totalTraded[t.thingDef] += t.count;
            }

            var priceModifiers = new Dictionary <ThingDef, float>();

            foreach (var pair in totalInCirculation)
            {
                if (totalTraded.ContainsKey(pair.Key))
                {
                    var inCirculation              = pair.Value;
                    var boughtByPlayer             = totalTraded[pair.Key];
                    var inCirculationWithoutPlayer = inCirculation + boughtByPlayer;
                    var initialModifier            = (float)Math.Sqrt(inCirculationWithoutPlayer / (float)inCirculation);
                    var multipliedModifier         = 1 + (initialModifier - 1) * Capitalism.Settings.EffectMultiplier;
                    var maxModifier = Capitalism.Settings.MaxSupplyDemandChangePercent / 100f;
                    priceModifiers[pair.Key] = Math.Min(Math.Max(multipliedModifier, 1 / maxModifier), maxModifier);
                }
            }

            CapitalismUtils.LogAndMessage("New price modifiers: " + string.Join(", ", priceModifiers.Select(kv => kv.Key.label + ":" + kv.Value.ToString("F"))));

            return(priceModifiers);
        }