public Trade(Transportation transport, Route route, Load load, TradingPost source, TradingPost destination, List<Modifier> modifiers) { Destination = destination; Load = load; Route = route; Transport = transport; Modifiers = modifiers; BaseDuration = TimeSpan.FromSeconds(route.Duration.TotalSeconds / Transport.SpeedFactor); BaseCost = load.Slots.Sum(i => i.Key.Price * i.Value); BaseProfit = BaseGold = BaseMerchantRating = load.CalculateProfit(destination); BaseExperience = load.CalculateExperience(destination); Cost = BaseCost; Profit = (int)(BaseProfit * (1 + modifiers.Sum(m => m.ProfitBonus))); Gold = (int)(BaseGold * (1 + modifiers.Sum(m => m.GoldBonus))); MerchantRating = (int)(BaseMerchantRating * (1 + modifiers.Sum(m => m.MerchantRatingBonus))); Experience = (int)(BaseExperience * (1 + modifiers.Sum(m => m.ExpBonus))); Duration = TimeSpan.FromSeconds(route.Duration.TotalSeconds / (Transport.SpeedFactor + modifiers.Sum(m => m.SpeedBonus))); Gold = Math.Max(0, Gold); MerchantRating = Math.Max(0, MerchantRating); Experience = Math.Max(0, Experience); AddedCost = Cost - BaseCost; AddedProfit = Profit - BaseProfit; AddedGold = Gold - BaseGold; AddedMerchantRating = MerchantRating - BaseMerchantRating; AddedExperience = Experience - BaseExperience; AddedDuration = Duration - BaseDuration; ProfitPerSecond = Profit / Duration.TotalSeconds; if (source.NoProfits.Contains(destination.Id)) Flags |= TradeFlags.NoProfit; if (route.Path.Select(w => w.Target.Region).Any(r => r.ChokePoint)) Flags |= TradeFlags.ChokePoint; ModifierNames = string.Join(", ", Modifiers.Select(m => m.Name)); }
public Load Copy() { var newLoad = new Load(SlotCapacity, WeightCapacity); foreach (var kvp in _slots) newLoad._slots.Add(kvp.Key, kvp.Value); return newLoad; }
private void GetLoads(ConcurrentBag<Load> loads, TradingPost post, Load currentLoad, long currentDucts) { if (currentLoad.RemainingSlots == 0) return; var candidates = post.Items.Where(i => i.Status == ItemStatus.Available && !currentLoad.Slots.ContainsKey(i)).ToList(); Parallel.ForEach(candidates, i => FillLoadWithItem(loads, post, currentLoad, currentDucts, i)); }
private void FillLoadWithItem(ConcurrentBag<Load> loads, TradingPost post, Load currentLoad, long currentDucats, Item item) { var canAdd = (int)(currentDucats / item.Price); var added = AddItemToLoad(loads, post, currentLoad, currentDucats, item, canAdd); var excess = added % item.QuantityPerSlot; if (added < item.QuantityPerSlot || excess == 0) return; AddItemToLoad(loads, post, currentLoad, currentDucats, item, added - excess); }
private int AddItemToLoad(ConcurrentBag<Load> loads, TradingPost post, Load currentLoad, long currentDucats, Item item, int requested) { var loadCopy = currentLoad.Copy(); var added = loadCopy.AddItem(item, Math.Min(item.Stock, requested)); if (added != 0) { loads.Add(loadCopy); GetLoads(loads, post, loadCopy, currentDucats - item.Price * added); } return added; }
public ConcurrentBag<Trade> CalculateTrades(TradingPost post) { var newTrades = new ConcurrentBag<Trade>(); var s = new System.Diagnostics.Stopwatch(); s.Start(); var mods = GetModifierCombinations(Modifiers); var cmMod = new Modifier(-1, "Commerce Mastery", 0, 0, 0, CmRank.Bonus, CmRank.Bonus, CmRank.Bonus, CmRank.Bonus, new List<int>(), new List<int>()); foreach (var m in mods) m.Add(cmMod); mods.Add(new List<Modifier> { cmMod }); Parallel.ForEach(Transports.Where(t => t.Enabled), t => { var allowedMods = mods.Where(combination => !combination.Any(m => m.TransportationBlacklist.Contains(t.Id)) ); Parallel.ForEach(allowedMods, m => { var baseLoad = new Load(t.Slots + m.Sum(i => i.ExtraSlots), t.Weight + m.Sum(i => i.ExtraWeight)); var loads = new ConcurrentBag<Load>(); GetLoads(loads, post, baseLoad, Ducats); foreach (var load in loads) foreach (var dst in Posts.Where(p => p != post)) { newTrades.Add(new Trade(t, Route(post.Waypoint, dst.Waypoint), load, post, dst, m)); } }); }); s.Stop(); System.Diagnostics.Debug.WriteLine("Calculated {0} possible trades ({1} items, {2} destinations, {3} means of transport, {4} modifier combinations) in {5}", newTrades.Count, post.Items.Count(i => i.Status == ItemStatus.Available), Posts.Count - 1, Transports.Count(t => t.Enabled), mods.Count, s.Elapsed); return newTrades; }