public static PurchaseSet Combine(PurchaseSet a, PurchaseSet b) { PurchaseSet set = new PurchaseSet(null); PurchaseSet.Combine(a.ItemPurchases, b.ItemPurchases, ref set.ItemPurchases); return(set); }
/// <summary> /// Track purchases for this champion. /// </summary> public void Process(ChampionMatchItemPurchases matchPurchases) { // Create or get the purchase set for this match PurchaseSetKey key = new PurchaseSetKey(matchPurchases); PurchaseSet set = PurchaseSets.GetOrAdd(key, k => new PurchaseSet(k)); set.Process(matchPurchases); }
public PurchaseSet Combine(PurchaseSet other) { return(PurchaseSet.Combine(this, other)); }
public ChampionPurchaseCalculator(PurchaseSet set) { Key = set.Key; MatchCount = set.MatchCount; // Create stats var stats = PurchaseStats.Create(set.AllItemPurchases, set.MatchCount); // Compute initial determinations based on game stage and settings percentages var statsList = stats.SelectMany(kvp => kvp.Value.Select(nkvp => nkvp.Value)); var purchaseDeterminations = statsList.Select(purchaseStats => new IncludeDetermination() { Stats = purchaseStats, GameStage = SetBuilderSettings.GetGameStage(purchaseStats), Include = false }).ToDictionary( determination => new ItemPurchaseTrackerData.ItemPurchaseKey(determination.Stats) ); // Filter initial include list by percentage purchaseDeterminations.Values .Where(determination => determination.Stats.Percentage >= SetBuilderSettings.ItemMinimumPurchasePercentage[determination.GameStage]) .ToList() .ForEach(determination => determination.Include = true); // Compute build path includes DetermineBuildPathIncludes(purchaseDeterminations); // Generate stage-based include list Purchases = purchaseDeterminations.Values .Where(determination => determination.Include) .GroupBy(determination => determination.GameStage) .ToDictionary( g => g.Key, g => g.Select(d => d.Stats).OrderBy(s => s.AveragePurchaseTimeSeconds).ToList() ); // If early items contain items that build into a mid-game item, migrate the mid-game item to early game if (Purchases.ContainsKey(GameStage.Early) && Purchases.ContainsKey(GameStage.Mid)) { // Check if a full build path exists in the early stage already bool hasFullEarlyPath = Purchases[GameStage.Early].Any(p => p.FinalBuildItemPercentage.Any(finalItem => Purchases[GameStage.Early].Any(i => finalItem.Key.ItemId == i.ItemId))); if (!hasFullEarlyPath) { // Find the first early game item that builds into something in mid-game var earlyItem = Purchases[GameStage.Early].FirstOrDefault(p => p.FinalBuildItemPercentage.Any(finalItem => Purchases[GameStage.Mid].Any(i => finalItem.Key.ItemId == i.ItemId))); if (earlyItem != null) { // Find the mid-game item to move var midItemIndex = Purchases[GameStage.Mid].FindIndex(i => earlyItem.FinalBuildItemPercentage.Any(kvp => kvp.Key.ItemId == i.ItemId)); var midItem = Purchases[GameStage.Mid][midItemIndex]; // Move the mid-game item Purchases[GameStage.Early].Add(midItem); Purchases[GameStage.Mid].RemoveAt(midItemIndex); } } } // If start items add up to less than 475, try to absorb first early item if (Purchases.ContainsKey(GameStage.Start) && Purchases.ContainsKey(GameStage.Early)) { int startCost = Purchases[GameStage.Start].Sum(d => StaticDataStore.Items.Items[d.ItemId].Gold.TotalPrice); if (startCost < 475) { ItemPurchaseStats d = Purchases[GameStage.Early].FirstOrDefault(); if (StaticDataStore.Items.Items[d.ItemId].Gold.TotalPrice + startCost <= 475) { // Move item Purchases[GameStage.Start].Add(d); Purchases[GameStage.Early].RemoveAt(0); } } } // Move consumables to end of each section foreach (GameStage stage in Purchases.Keys) { // Remove all consumables, sort by cost, then add to end of list var purchaseList = Purchases[stage]; var consumables = purchaseList.Where(d => StaticDataStore.Items.Items[d.ItemId].Consumed).ToList(); purchaseList.RemoveAll(d => consumables.Contains(d)); consumables.Sort((a, b) => { int cmp = StaticDataStore.Items.Items[a.ItemId].Gold.TotalPrice.CompareTo( StaticDataStore.Items.Items[b.ItemId].Gold.TotalPrice); if (cmp != 0) { return(cmp); } return(a.ItemId.CompareTo(b.ItemId)); } ); purchaseList.AddRange(consumables); } // Remove components in mid/late game var removeComponentsStages = new[] { GameStage.Late, GameStage.Mid }; IEnumerable <ItemStatic> componentItems = Enumerable.Empty <ItemStatic>(); foreach (GameStage stage in removeComponentsStages) { if (!Purchases.ContainsKey(stage)) { continue; } var allComponents = Purchases[stage] .Select(p => StaticDataStore.Items.Items[p.ItemId]) .Where(i => i.Into == null || i.Into.Count == 0) .SelectMany(i => i.AllComponents()) .Where(i => i.Tags == null || (!i.Tags.Contains("Boots") && !i.Tags.Contains("Trinket"))) .Distinct(); componentItems = componentItems.Concat(allComponents).Distinct().ToList(); // Remove any component items Purchases[stage].RemoveAll(i => componentItems.Any(c => c.Id == i.ItemId)); } }