/// <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 ItemSet(string title = "") { this.SetKey = null; this.MatchCount = 0; this.title = title; this.description = ""; this.type = Type.Custom; this.map = Map.any; this.mode = Mode.any; this.priority = false; this.sortrank = 0; this.blocks = null; }
public static ItemSet generate(PurchaseSetKey setKey, ChampionPurchaseCalculator stats) { //Lookup the champion var championKey = StaticDataStore.Champions.Keys[setKey.ChampionId]; var championInfo = StaticDataStore.Champions.Champions[championKey]; // Create the set and key it ItemSet itemSet = new ItemSet(); itemSet.SetKey = setKey; itemSet.MatchCount = stats.MatchCount; //Come up with an item set title itemSet.title = championInfo.Name + " " + ItemSetNaming.ToolName; //Add a nice description of how this was generated itemSet.description = "Pro item set generated using " + stats.MatchCount.ToString() + " challenger/master matches."; //Fill out a bunch of other stuff that is the same for this tool itemSet.type = type; itemSet.map = map; itemSet.mode = mode; itemSet.priority = priority; itemSet.sortrank = sortRank < 0 ? 0 : sortRank; // Block info var blockData = new[] { new { Name = "Starting Items", Stage = GameStage.Start }, new { Name = "Early Items", Stage = GameStage.Early }, new { Name = "Midgame Items", Stage = GameStage.Mid }, new { Name = "Lategame Items", Stage = GameStage.Late } }; // Create blocks and filter to non-empty blocks var blocks = blockData .Where(blockInfo => stats.Purchases.ContainsKey(blockInfo.Stage)) .Select(blockInfo => new ItemSet.Block(blockInfo.Name) { items = stats.Purchases[blockInfo.Stage].Select(entry => new ItemSet.Item(entry.ItemId.ToString()) { count = 1, percentage = entry.Percentage }).ToList() }) .Where(block => block.items.Count > 0).ToList(); // Combine adjacent items blocks.ForEach(block => { for (int i = 0; i < block.items.Count - 1; ++i) { if (block.items[i].id == block.items[i + 1].id) { // Remove when adjacent, and keep the lower percentage block.items[i].count = block.items[i].count + 1; block.items.RemoveAt(i+1); --i; } } }); // Add blocks to item set itemSet.blocks = blocks; return itemSet; }
public static ItemSet generate(PurchaseSetKey setKey, ChampionPurchaseCalculator stats) { //Lookup the champion var championKey = StaticDataStore.Champions.Keys[setKey.ChampionId]; var championInfo = StaticDataStore.Champions.Champions[championKey]; // Create the set and key it ItemSet itemSet = new ItemSet(); itemSet.SetKey = setKey; itemSet.MatchCount = stats.MatchCount; //Come up with an item set title itemSet.title = championInfo.Name + " " + ItemSetNaming.ToolName; //Add a nice description of how this was generated itemSet.description = "Pro item set generated using " + stats.MatchCount.ToString() + " challenger/master matches."; //Fill out a bunch of other stuff that is the same for this tool itemSet.type = type; itemSet.map = map; itemSet.mode = mode; itemSet.priority = priority; itemSet.sortrank = sortRank < 0 ? 0 : sortRank; // Block info var blockData = new[] { new { Name = "Starting Items", Stage = GameStage.Start }, new { Name = "Early Items", Stage = GameStage.Early }, new { Name = "Midgame Items", Stage = GameStage.Mid }, new { Name = "Lategame Items", Stage = GameStage.Late } }; // Create blocks and filter to non-empty blocks var blocks = blockData .Where(blockInfo => stats.Purchases.ContainsKey(blockInfo.Stage)) .Select(blockInfo => new ItemSet.Block(blockInfo.Name) { items = stats.Purchases[blockInfo.Stage].Select(entry => new ItemSet.Item(entry.ItemId.ToString()) { count = 1, percentage = entry.Percentage }).ToList() }) .Where(block => block.items.Count > 0).ToList(); // Combine adjacent items blocks.ForEach(block => { for (int i = 0; i < block.items.Count - 1; ++i) { if (block.items[i].id == block.items[i + 1].id) { // Remove when adjacent, and keep the lower percentage block.items[i].count = block.items[i].count + 1; block.items.RemoveAt(i + 1); --i; } } }); // Add blocks to item set itemSet.blocks = blocks; return(itemSet); }
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)); } }