diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b5170cb..c1e624c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,7 +44,7 @@ jobs: directory: DU-Industry-Tool/bin/Release/ type: 'zip' filename: DU-Industry-Tool-v${{ steps.getversion.outputs.version }}.zip - exclusions: '*.git* /*node_modules/* *.exe.config *.xml *.pdb *.vs* *.user .editorconfig' + exclusions: '*.git* /*node_modules/* *.xml *.pdb *.vs* *.user .editorconfig' - name: Create Github Release if: ${{ (github.ref == 'refs/heads/master') }} # ONLY ON MASTER diff --git a/DU-Industry-Tool/App.config b/DU-Industry-Tool/App.config index 0aec0aa..4ab8fed 100644 --- a/DU-Industry-Tool/App.config +++ b/DU-Industry-Tool/App.config @@ -18,4 +18,7 @@ + + + \ No newline at end of file diff --git a/DU-Industry-Tool/Classes/CalculatorClass.cs b/DU-Industry-Tool/Classes/CalculatorClass.cs index 3fb0a33..082db03 100644 --- a/DU-Industry-Tool/Classes/CalculatorClass.cs +++ b/DU-Industry-Tool/Classes/CalculatorClass.cs @@ -1,13 +1,5 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Windows.Forms; namespace DU_Industry_Tool { @@ -67,17 +59,17 @@ public static void AddSchema(string schemaKey, int qty, double amount) SumSchemClass.Add(schemaKey, new Tuple(qty, amount)); } - public static void Add(SummationType sumType, string ingKey, double quantity) + public static void Add(SummationType sumType, string key, double quantity) { if (!_sums.ContainsKey(sumType)) { _sums.Add(sumType, new SortedDictionary()); } - if (_sums[sumType].ContainsKey(ingKey)) - _sums[sumType][ingKey] += quantity; + if (_sums[sumType].ContainsKey(key)) + _sums[sumType][key] += quantity; else - _sums[sumType].Add(ingKey, quantity); + _sums[sumType].Add(key, quantity); } public static SortedDictionary Get(SummationType sumType) diff --git a/DU-Industry-Tool/Classes/Consts.cs b/DU-Industry-Tool/Classes/Consts.cs new file mode 100644 index 0000000..7e78fd6 --- /dev/null +++ b/DU-Industry-Tool/Classes/Consts.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace DU_Industry_Tool +{ + /// + /// Summary description for Class1 + /// + public static class Consts + { + public static readonly List SizeList = new List { "XS", "S", "M", "L", "XL" }; + public static readonly List TierNames = new List { "", "Basic", "Uncommon", "Advanced", "Rare", "Exotic" }; + + static Consts() + { + // + // TODO: Add constructor logic here + // + } + } +} diff --git a/DU-Industry-Tool/Classes/IndustryManager.cs b/DU-Industry-Tool/Classes/IndustryManager.cs index 2f76edf..238fd45 100644 --- a/DU-Industry-Tool/Classes/IndustryManager.cs +++ b/DU-Industry-Tool/Classes/IndustryManager.cs @@ -13,13 +13,8 @@ namespace DU_Industry_Tool { public class IndustryManager { - private const string CompoundName = "COMPOUNDLIST"; - - private readonly List _sizeList = new List { "XS", "S", "M", "L", "XL" }; - private readonly List _tierNames = new List { "", "Basic", "Uncommon", "Advanced", "Rare", "Exotic" }; - - private readonly SortedDictionary _luaItems; // List of items from du-lua.dev - private readonly SortedDictionary _luaRecipes; // List of recipes from du-lua.dev + private readonly bool SkipProcessing = true; + private readonly string CompoundName = "COMPOUNDLIST"; public readonly SortedDictionary Recipes; // Global list of all our recipes, from the json public List RecipeNames { get; private set; } = new List(); @@ -32,11 +27,17 @@ public class IndustryManager public List Talents { get; } = new List(); public List Groupnames { get; } = new List(370); public StringBuilder CostResults { get; set; } - public SchematicRecipe CompoundRecipe { get; private set; } + // Used products quantity for cost calculations public int ProductQuantity { get; set; } = 1; + + // True, if CompoundRecipe is to be used as calculation target, + // which can contain any amount of items and is created with the + // help of the Production List dialogue public bool ProductionListMode { get; set; } + public SchematicRecipe CompoundRecipe { get; private set; } + // Constructor public IndustryManager(ProgressBar progressBar = null) { CultureInfo.CurrentCulture = new CultureInfo("en-us"); @@ -149,12 +150,12 @@ public IndustryManager(ProgressBar progressBar = null) var timeFactors = batchTimeFactors[tier - 1]; var price = prices[tier - 1]; var btime = batchTimes[tier - 1]; - for (byte size = 0; size < _sizeList.Count; size++) + for (byte size = 0; size < Consts.SizeList.Count; size++) { var schem = new Schematic { - Name = $"Tier {tier} {_sizeList[size]} Element Schematic", - Key = $"T{tier}E{_sizeList[size]}", + Name = $"Tier {tier} {Consts.SizeList[size]} Element Schematic", + Key = $"T{tier}E{Consts.SizeList[size]}", Level = tier, Cost = Math.Round(price, 2), BatchSize = batchSizes[size], @@ -174,7 +175,7 @@ public IndustryManager(ProgressBar progressBar = null) var batchTimesCu = new [] { 750, 5000, 25020, 145020 }; for (var idx = 0; idx <= 3; idx++) // XS - L { - var size = _sizeList[idx]; + var size = Consts.SizeList[idx]; // Construct Support var key = "CS-" + size; Schematics.Add(key, new Schematic() @@ -205,7 +206,7 @@ public IndustryManager(ProgressBar progressBar = null) { var time = batchTimes[i - 2]; var price = prices[i - 2]; - foreach (var size in _sizeList) + foreach (var size in Consts.SizeList) { if (size == "XL") continue; var key = $"T{i}A{size}"; @@ -311,7 +312,7 @@ public IndustryManager(ProgressBar progressBar = null) { try { - _luaItems = JsonConvert.DeserializeObject>( + Utils.LuaItems = JsonConvert.DeserializeObject>( File.ReadAllText("items_api_dump.json")); dmp = true; } @@ -325,7 +326,7 @@ public IndustryManager(ProgressBar progressBar = null) { try { - _luaRecipes = JsonConvert.DeserializeObject>( + Utils.LuaRecipes = JsonConvert.DeserializeObject>( File.ReadAllText("recipes_api_dump.json")); dmpRcp = true; } @@ -344,7 +345,7 @@ public IndustryManager(ProgressBar progressBar = null) // Check against Items from du-lua.dev (optional) if (dmp) { - var dmpItem = _luaItems.FirstOrDefault(x => x.Key == itemId); + var dmpItem = Utils.LuaItems.FirstOrDefault(x => x.Key == itemId); if (dmpItem.Value != null) { // Transfer updateable values and only protocol to debug console @@ -386,7 +387,7 @@ public IndustryManager(ProgressBar progressBar = null) { Debug.WriteLine("NqId NOT FOUND: " + itemId + " Key: " + kvp.Key); itemId = kvp.Value.Id.ToString(); - if (dmp && !_luaItems.ContainsKey(itemId)) + if (dmp && !Utils.LuaItems.ContainsKey(itemId)) { Debug.WriteLine("Id NOT FOUND: " + itemId + " Key: " + kvp.Key); } @@ -397,7 +398,7 @@ public IndustryManager(ProgressBar progressBar = null) // and transfer usable values if (dmpRcp) { - var dmpItem = _luaRecipes.FirstOrDefault(x => + var dmpItem = Utils.LuaRecipes.FirstOrDefault(x => x.Value.Products?.Count > 0 && x.Value.Products[0].Id == kvp.Value.NqId); if (dmpItem.Value != null) @@ -465,10 +466,10 @@ public IndustryManager(ProgressBar progressBar = null) // If item dump exists, do a special honeycomb check for wrong ID's if (dmp && kvp.Key.StartsWith("hc")) { - var luaItem = _luaItems.FirstOrDefault(x => x.Value.Description.StartsWith("Honeycomb") && - !x.Value.DisplayNameWithSize.EndsWith("Schematic Copy") && - x.Value.DisplayNameWithSize.Equals(kvp.Value.Name, - StringComparison.InvariantCultureIgnoreCase)); + var luaItem = Utils.LuaItems.FirstOrDefault(x => x.Value.Description.StartsWith("Honeycomb") && + !x.Value.DisplayNameWithSize.EndsWith("Schematic Copy") && + x.Value.DisplayNameWithSize.Equals(kvp.Value.Name, + StringComparison.InvariantCultureIgnoreCase)); if (!string.IsNullOrEmpty(luaItem.Key) && luaItem.Key != kvp.Value.NqId.ToString()) { if (ulong.TryParse(luaItem.Key, out var uTmp)) @@ -490,9 +491,6 @@ public IndustryManager(ProgressBar progressBar = null) //if (kvp.Value.Nanocraftable) Debug.WriteLine($"{kvp.Value.Name}"); - // Determine the required industry to produce this item - //DetermineIndustryFor(kvp.Value); - if (kvp.Key.StartsWith("Catalyst") || kvp.Value.ParentGroupName == "Ore" || (kvp.Value.ParentGroupName == "Pure" && kvp.Value.Level <= 1)) @@ -581,17 +579,22 @@ public IndustryManager(ProgressBar progressBar = null) } */ - // IF schematic is already assigned, skip further processing - if (!string.IsNullOrEmpty(kvp.Value.SchemaType) && kvp.Value.SchemaPrice > 0) + // Determine the required industry to produce this item + //if (string.IsNullOrEmpty(kvp.Value.Industry)) + //{ + // DetermineIndustryFor(kvp.Value); + //} + + // Skip further processing on some conditions... + if (SkipProcessing || + (!string.IsNullOrEmpty(kvp.Value.SchemaType) && kvp.Value.SchemaPrice > 0) || + kvp.Value.ParentGroupName.EndsWith("parts", StringComparison.InvariantCultureIgnoreCase) || + kvp.Value.Level < 1 || + kvp.Value.Name.StartsWith("catalyst", StringComparison.InvariantCultureIgnoreCase)) { continue; } - // Skip entries without level and Catalysts - if (kvp.Value.Level < 1 || - kvp.Value.Name.StartsWith("catalyst", StringComparison.InvariantCultureIgnoreCase)) - continue; - var idx = ""; var isElement = false; var parentName = kvp.Value.ParentGroupName; @@ -635,7 +638,7 @@ public IndustryManager(ProgressBar progressBar = null) var size = GetElementSize(kvp.Value.Name); idx = "CU-" + size; kvp.Value.SchemaType = idx; - kvp.Value.SchemaPrice = cuPriceList[_sizeList.IndexOf(size)]; + kvp.Value.SchemaPrice = cuPriceList[Consts.SizeList.IndexOf(size)]; continue; } @@ -708,7 +711,7 @@ public IndustryManager(ProgressBar progressBar = null) var size = GetElementSize(kvp.Value.Name); idx = "CS-" + size; kvp.Value.SchemaType = idx; - kvp.Value.SchemaPrice = csPriceList[_sizeList.IndexOf(size)]; + kvp.Value.SchemaPrice = csPriceList[Consts.SizeList.IndexOf(size)]; continue; } @@ -1157,17 +1160,19 @@ public IndustryManager(ProgressBar progressBar = null) // Ammo talents... they have uncommon, advanced of each of xs, s, m, l var typeList = new[] { "Uncommon", "Advanced" }; foreach (var type in typeList) - foreach (var size in _sizeList) { - if (size == "XL") continue; - Talents.Add(new Talent() + foreach (var size in Consts.SizeList) { - Name = type + " Ammo " + size + " Productivity", Addition = 1, Multiplier = 0, - ApplicableRecipes = Recipes.Values - .Where(r => r.ParentGroupName.Contains("Ammo") && r.Level == (type == "Uncommon" ? 2 : 3) && - r.Name.ToLower().EndsWith(" ammo " + size.ToLower())).Select(r => r.Key) - .ToList() - }); + if (size == "XL") continue; + Talents.Add(new Talent() + { + Name = type + " Ammo " + size + " Productivity", Addition = 1, Multiplier = 0, + ApplicableRecipes = Recipes.Values + .Where(r => r.ParentGroupName.Contains("Ammo") && r.Level == (type == "Uncommon" ? 2 : 3) && + r.Name.ToLower().EndsWith(" ammo " + size.ToLower())).Select(r => r.Key) + .ToList() + }); + } } Talents.Sort(TalentComparer); SaveTalents(); @@ -1212,7 +1217,7 @@ private void DetermineIndustryFor(SchematicRecipe recipe) } // elements can be produced by same tier as well as 1 lower tier assemblies: - var indPrefix = recipe.Level > 1 ? _tierNames[recipe.Level-1] : _tierNames[recipe.Level]; + var indPrefix = recipe.Level > 1 ? Consts.TierNames[recipe.Level-1] : Consts.TierNames[recipe.Level]; var indSuffix = ""; var isPart = recipe.ParentGroupName.EndsWith("Parts", StringComparison.InvariantCultureIgnoreCase); @@ -1390,10 +1395,10 @@ private string GetElementSize(string elemName, bool noLowerTier = false) { for (var idx = 0; idx < 5; idx++) { - if (elemName.EndsWith(" " + _sizeList[idx], StringComparison.InvariantCultureIgnoreCase)) + if (elemName.EndsWith(" " + Consts.SizeList[idx], StringComparison.InvariantCultureIgnoreCase)) { // most XL cannot be produced on an L assembler so "idx < 4" condition - return _sizeList[(idx > 0 && idx < 4 && !noLowerTier) ? idx - 1 : idx]; + return Consts.SizeList[(idx > 0 && idx < 4 && !noLowerTier) ? idx - 1 : idx]; } } return ""; @@ -1495,20 +1500,224 @@ public double GetBaseCost(string key) return totalCost; } - // Hold for each Product and Pure the Litres sum to afterwards calculate the needed schematics. - // Example: if in the end we need 380 L of Product "Polycalcite", we need to find out - // the required amount of schematics for each Calcium and Polycalcite - // (with an avatar having all T5 skills). - // Polycalcite: per batch: Input 85.00 L Calcium, Output: 86.25 L - // -> 380/86.25 = 4.40 batches -> rounded up to 5 schematics for the Polycalcite (Chemical). - // Pure Calcium: per batch: Input 55.25 L Limestone, Output: 51.75 L - // So for above 5 batches we need to calculate the number of needed Calcium batches (Refiner): - // -> 5 * 85 L = 425 L total -> 425 L / 51.75 L = 8.21 -> rounded to 9 schematics for the Calcium. - // The refiner requires Tier 2 Pure schematics, the chemical Tier 2 Product schematics. - // -> Refiner 187.50 q * 9 = 1687.50 q - // -> Chemical 562.50 q * 5 = 2812,50 q - // -> SUM for schematics: 4500 quanta - // :grimace: + public void GetTalentsForKey(string key, out double inputMultiplier, out double inputAdder, + out double outputMultiplier, out double outputAdder) + { + inputMultiplier = 1; + inputAdder = 0; + outputMultiplier = 1; + outputAdder = 0; + foreach (var talent in Talents.Where(t => t.ApplicableRecipes.Contains(key))) + { + if (!ApplicableTalents.Contains(talent.Name)) + { + ApplicableTalents.Add(talent.Name); + } + + if (talent.InputTalent) + { + inputMultiplier += + talent.Multiplier * + talent.Value; // Add each talent's multipler and adder so that we get values like 1.15 or 0.85, for pos/neg multipliers + inputAdder += talent.Addition * talent.Value; + } + else + { + outputMultiplier += talent.Multiplier * talent.Value; + outputAdder += talent.Addition * talent.Value; + } + } + } + + private double CalculateItemCost(SortedDictionary itemPrices, string listType = "P", + double quantity = 1, string title = "", bool outputDetails = true) + { + if (itemPrices.Count == 0) return 0; + CostResults.AppendLine(title); + double outSum = 0; + foreach (var item in itemPrices) + { + var key = item.Key; + if (key.StartsWith("T")) + { + key = key.Substring(3); // assume tier at start, e.g. "T2 " + } + var recipe = Recipes.Values.FirstOrDefault(x => x.Name.Equals(key, StringComparison.InvariantCultureIgnoreCase)); + if (recipe == null) + { + Debug.WriteLine("NOT FOUND: " + key); + continue; + } + + var isOre = recipe.ParentGroupName == "Ore"; + var isPart = recipe.ParentGroupName.EndsWith("parts", StringComparison.InvariantCultureIgnoreCase); + var isT1Ore = listType == "U" && isOre && recipe.Level <= 1; + var isPlasma = recipe.ParentGroupName == "Consumables" && recipe.Key.StartsWith("Plasma"); + var orePrice = 0d; + if (listType == "U" && (isPlasma || isOre)) + { + orePrice = Ores.FirstOrDefault(o => o.Name == key)?.Value ?? 0; + } + + var tmp = item.Value * quantity; + var recName = recipe.Name.Substring(0, Math.Min(recipe.Name.Length, 29)); + var output = $"{recName}:".PadRight(30) + $"{tmp:N2}".PadLeft(10) + (isPlasma || isPart ? " " : " L"); + if ((isPlasma || isOre) && orePrice > 0.00d) + { + tmp *= orePrice; + output += " = " + $"{tmp:N2} q".PadLeft(15); + } + + var idx = recipe.SchemaType; + var lvl = recipe.Level < 2 ? 1 : recipe.Level; + if (string.IsNullOrEmpty(idx)) + { + idx = $"T{lvl}{listType}"; + } + + var orePrefix = idx.Substring(0, 2) + " "; + if (isT1Ore || isPlasma || isPart || !Schematics.ContainsKey(idx)) + { + if (outputDetails) + { + CostResults.AppendLine((isPlasma ? "" : orePrefix) + output); + } + continue; + } + + // for every "started" batch we need a schematic (no talents for this in DU yet) + var schem = Schematics[idx]; + var allQuantity = item.Value * quantity; + var cnt = (int)Math.Ceiling(allQuantity / 100); + tmp = schem.Cost * cnt; + Calculator.AddSchema(idx, cnt, tmp); + + if (outputDetails) + { + output += " | " + $"{cnt} sch.".PadLeft(10) + " = " + $"{tmp:N2} q".PadLeft(14); + CostResults.AppendLine(orePrefix + output); + } + outSum += tmp; + } + return outSum; + } + + public List GetOreComponents(string key) + { + // Un-talented only + var products = new List(); + var recipe = Recipes[key]; + + // Skip catalysts entirely tho. + if (Groups.Values.FirstOrDefault(g => g.Id == recipe.GroupId)?.Name == "Catalyst") + return products; + + foreach (var ingredient in recipe.Ingredients) + { + if (Recipes[ingredient.Type].ParentGroupName == "Ore") + { + products.Add(new ProductDetail() + { + Name = ingredient.Name, Quantity = ingredient.Quantity / recipe.Products[0].Quantity, + Type = ingredient.Type + }); + } + else + { + foreach (var result in GetOreComponents(ingredient.Type)) + { + products.Add(new ProductDetail() + { + Name = result.Name, + Quantity = (result.Quantity * ingredient.Quantity) / recipe.Products[0].Quantity, + Type = result.Type + }); + } + } + } + + // Now flatten them into totals + var results = new List(); + foreach (var group in products.GroupBy(p => p.Type)) + { + results.Add(new ProductDetail() + { Name = group.First().Name, Type = group.Key, Quantity = group.Sum(p => p.Quantity) }); + } + + return results; + } + + // This was going to be recursive but those are way too generic. We just want one parent up. + private string GetParentGroupName(Guid id) + { + var group = Groups.Values.FirstOrDefault(g => g.Id == id); + if (group == null) return null; + return group.ParentId != Guid.Empty + ? Groups.Values.FirstOrDefault(g => g.Id == group.ParentId)?.Name ?? "xxx" + : group.Name; + } + + public bool PrepareProductListRecipe() + { + if (ProductionBindingList.Count < 1) return false; + var cmp = new SchematicRecipe + { + Key = CompoundName, + Name = "Production List" + }; + var cnt = 0; + foreach (var prodItem in ProductionBindingList) + { + // Sanity checks + if (string.IsNullOrEmpty(prodItem.Name) || prodItem.Quantity <= 0) + continue; + var rec = Recipes.FirstOrDefault(x => x.Value.Name.Equals(prodItem.Name, StringComparison.InvariantCultureIgnoreCase)); + if (rec.Key == null || rec.Value?.Ingredients?.Any() != true || rec.Value?.Products?.Any() != true) + continue; + + // Accumulate crafting time over all products + cmp.Time += (rec.Value.Time * prodItem.Quantity); + + // Sum up top-level ingredients + foreach (var ing in rec.Value.Ingredients) + { + var tmp = cmp.Ingredients.FirstOrDefault(x => x.Name.Equals(ing.Name, StringComparison.InvariantCultureIgnoreCase)); + if (tmp != null) + { + tmp.Quantity += (ing.Quantity * prodItem.Quantity); + } + else + { + ing.Quantity *= prodItem.Quantity; + cmp.Ingredients.Add(ing); + } + } + + // Process products + foreach (var prd in rec.Value.Products) + { + var tmp = cmp.Products.FirstOrDefault(x => x.Name.Equals(prd.Name, StringComparison.InvariantCultureIgnoreCase)); + if (tmp != null) + { + tmp.Quantity += (prd.Quantity * prodItem.Quantity); + } + else + { + prd.Quantity *= prodItem.Quantity; + cmp.Products.Add(prd); + } + } + cnt++; + } + if (cnt == 0) return false; + CompoundRecipe = cmp; + + // Add compound recipe to main recipe list, check first to remove an existing one + Recipes.Remove(CompoundName); + Recipes[CompoundName] = cmp; + return true; + } + private string _currentRecipe; public double GetTotalCost(string key, double amount = 0, string level = "", int depth = 0, bool silent = false) { @@ -1731,223 +1940,5 @@ public double GetTotalCost(string key, double amount = 0, string level = "", int return costx1; } - public void GetTalentsForKey(string key, out double inputMultiplier, out double inputAdder, - out double outputMultiplier, out double outputAdder) - { - inputMultiplier = 1; - inputAdder = 0; - outputMultiplier = 1; - outputAdder = 0; - foreach (var talent in Talents.Where(t => t.ApplicableRecipes.Contains(key))) - { - if (!ApplicableTalents.Contains(talent.Name)) - { - ApplicableTalents.Add(talent.Name); - } - - if (talent.InputTalent) - { - inputMultiplier += - talent.Multiplier * - talent.Value; // Add each talent's multipler and adder so that we get values like 1.15 or 0.85, for pos/neg multipliers - inputAdder += talent.Addition * talent.Value; - } - else - { - outputMultiplier += talent.Multiplier * talent.Value; - outputAdder += talent.Addition * talent.Value; - } - } - } - - private double CalculateItemCost(SortedDictionary itemPrices, string listType = "P", - double quantity = 1, string title = "", bool outputDetails = true) - { - if (itemPrices.Count == 0) return 0; - CostResults.AppendLine(title); - double outSum = 0; - foreach (var item in itemPrices) - { - var key = item.Key; - if (key.StartsWith("T")) - { - key = key.Substring(3); // assume tier at start, e.g. "T2 " - } - var recipe = Recipes.Values.FirstOrDefault(x => x.Name.Equals(key, StringComparison.InvariantCultureIgnoreCase)); - if (recipe == null) - { - Debug.WriteLine("NOT FOUND: " + key); - continue; - } - - var isOre = recipe.ParentGroupName == "Ore"; - var isPart = recipe.ParentGroupName.EndsWith("parts", StringComparison.InvariantCultureIgnoreCase); - var isT1Ore = listType == "U" && isOre && recipe.Level <= 1; - var isPlasma = recipe.ParentGroupName == "Consumables" && recipe.Key.StartsWith("Plasma"); - var orePrice = 0d; - if (listType == "U" && (isPlasma || isOre)) - { - orePrice = Ores.FirstOrDefault(o => o.Name == key)?.Value ?? 0; - } - - var tmp = item.Value * quantity; - var recName = recipe.Name.Substring(0, Math.Min(recipe.Name.Length, 29)); - var output = $"{recName}:".PadRight(30) + $"{tmp:N2}".PadLeft(10) + (isPlasma || isPart ? " " : " L"); - if ((isPlasma || isOre) && orePrice > 0.00d) - { - tmp *= orePrice; - output += " = " + $"{tmp:N2} q".PadLeft(15); - } - - var idx = recipe.SchemaType; - var lvl = recipe.Level < 2 ? 1 : recipe.Level; - if (string.IsNullOrEmpty(idx)) - { - idx = $"T{lvl}{listType}"; - } - - var orePrefix = idx.Substring(0, 2) + " "; - if (isT1Ore || isPlasma || isPart || !Schematics.ContainsKey(idx)) - { - if (outputDetails) - { - CostResults.AppendLine((isPlasma ? "" : orePrefix) + output); - } - continue; - } - - // for every "started" batch we need a schematic (no talents for this in DU yet) - var schem = Schematics[idx]; - var allQuantity = item.Value * quantity; - var cnt = (int)Math.Ceiling(allQuantity / 100); - tmp = schem.Cost * cnt; - Calculator.AddSchema(idx, cnt, tmp); - - if (outputDetails) - { - output += " | " + $"{cnt} sch.".PadLeft(10) + " = " + $"{tmp:N2} q".PadLeft(14); - CostResults.AppendLine(orePrefix + output); - } - outSum += tmp; - } - return outSum; - } - - public List GetOreComponents(string key) - { - // Un-talented only - var products = new List(); - var recipe = Recipes[key]; - - // Skip catalysts entirely tho. - if (Groups.Values.FirstOrDefault(g => g.Id == recipe.GroupId)?.Name == "Catalyst") - return products; - - foreach (var ingredient in recipe.Ingredients) - { - if (Recipes[ingredient.Type].ParentGroupName == "Ore") - { - products.Add(new ProductDetail() - { - Name = ingredient.Name, Quantity = ingredient.Quantity / recipe.Products[0].Quantity, - Type = ingredient.Type - }); - } - else - { - foreach (var result in GetOreComponents(ingredient.Type)) - { - products.Add(new ProductDetail() - { - Name = result.Name, - Quantity = (result.Quantity * ingredient.Quantity) / recipe.Products[0].Quantity, - Type = result.Type - }); - } - } - } - - // Now flatten them into totals - var results = new List(); - foreach (var group in products.GroupBy(p => p.Type)) - { - results.Add(new ProductDetail() - { Name = group.First().Name, Type = group.Key, Quantity = group.Sum(p => p.Quantity) }); - } - - return results; - } - - // This was going to be recursive but those are way too generic. We just want one parent up. - private string GetParentGroupName(Guid id) - { - var group = Groups.Values.FirstOrDefault(g => g.Id == id); - if (group == null) return null; - return group.ParentId != Guid.Empty - ? Groups.Values.FirstOrDefault(g => g.Id == group.ParentId)?.Name ?? "xxx" - : group.Name; - } - - public bool PrepareProductListRecipe() - { - if (ProductionBindingList.Count < 1) return false; - var cmp = new SchematicRecipe - { - Key = CompoundName, - Name = "Production List" - }; - var cnt = 0; - foreach (var prodItem in ProductionBindingList) - { - // Sanity checks - if (string.IsNullOrEmpty(prodItem.Name) || prodItem.Quantity <= 0) - continue; - var rec = Recipes.FirstOrDefault(x => x.Value.Name.Equals(prodItem.Name, StringComparison.InvariantCultureIgnoreCase)); - if (rec.Key == null || rec.Value?.Ingredients?.Any() != true || rec.Value?.Products?.Any() != true) - continue; - - // Accumulate crafting time over all products - cmp.Time += (rec.Value.Time * prodItem.Quantity); - - // Sum up top-level ingredients - foreach (var ing in rec.Value.Ingredients) - { - var tmp = cmp.Ingredients.FirstOrDefault(x => x.Name.Equals(ing.Name, StringComparison.InvariantCultureIgnoreCase)); - if (tmp != null) - { - tmp.Quantity += (ing.Quantity * prodItem.Quantity); - } - else - { - ing.Quantity *= prodItem.Quantity; - cmp.Ingredients.Add(ing); - } - } - - // Process products - foreach (var prd in rec.Value.Products) - { - var tmp = cmp.Products.FirstOrDefault(x => x.Name.Equals(prd.Name, StringComparison.InvariantCultureIgnoreCase)); - if (tmp != null) - { - tmp.Quantity += (prd.Quantity * prodItem.Quantity); - } - else - { - prd.Quantity *= prodItem.Quantity; - cmp.Products.Add(prd); - } - } - cnt++; - } - if (cnt == 0) return false; - CompoundRecipe = cmp; - - // Add compound recipe to main recipe list, check first to remove an existing one - Recipes.Remove(CompoundName); - Recipes[CompoundName] = cmp; - return true; - } - } } \ No newline at end of file diff --git a/DU-Industry-Tool/Classes/Utils.cs b/DU-Industry-Tool/Classes/Utils.cs new file mode 100644 index 0000000..19a6416 --- /dev/null +++ b/DU-Industry-Tool/Classes/Utils.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; + +namespace DU_Industry_Tool +{ + /// + /// Summary description for Utils + /// + public static class Utils + { + public static SortedDictionary LuaItems; // List of items from du-lua.dev + public static SortedDictionary LuaRecipes; // List of recipes from du-lua.dev + + static Utils() + { + // + } + } +} diff --git a/DU-Industry-Tool/DU-Industry-Tool.csproj b/DU-Industry-Tool/DU-Industry-Tool.csproj index 5ea5590..3b3b905 100644 --- a/DU-Industry-Tool/DU-Industry-Tool.csproj +++ b/DU-Industry-Tool/DU-Industry-Tool.csproj @@ -71,6 +71,8 @@ + + Form diff --git a/DU-Industry-Tool/Forms/MainForm.Designer.cs b/DU-Industry-Tool/Forms/MainForm.Designer.cs index 9da4053..e139b9f 100644 --- a/DU-Industry-Tool/Forms/MainForm.Designer.cs +++ b/DU-Industry-Tool/Forms/MainForm.Designer.cs @@ -63,9 +63,9 @@ private void InitializeComponent() this.kryptonPage1 = new Krypton.Navigator.KryptonPage(); this.searchPanel = new Krypton.Toolkit.KryptonPanel(); this.SearchBox = new Krypton.Toolkit.KryptonComboBox(); - this.SearchButton = new System.Windows.Forms.Button(); - this.QuantityBox = new System.Windows.Forms.ComboBox(); - this.PreviousButton = new System.Windows.Forms.Button(); + this.SearchButton = new Krypton.Toolkit.KryptonButton(); + this.QuantityBox = new Krypton.Toolkit.KryptonComboBox(); + this.PreviousButton = new Krypton.Toolkit.KryptonButton(); this.treeView = new System.Windows.Forms.TreeView(); this.kryptonWorkspaceCell1 = new Krypton.Workspace.KryptonWorkspaceCell(); this.kryptonNavigator1 = new Krypton.Navigator.KryptonNavigator(); @@ -262,36 +262,57 @@ private void InitializeComponent() this.kryptonDockableWorkspace.Location = new System.Drawing.Point(0, 136); this.kryptonDockableWorkspace.MinimumSize = new System.Drawing.Size(300, 400); this.kryptonDockableWorkspace.Name = "kryptonDockableWorkspace"; - this.kryptonDockableWorkspace.PaletteMode = Krypton.Toolkit.PaletteMode.Office2010BlueDarkMode; - // - // - // + this.kryptonDockableWorkspace.PaletteMode = Krypton.Toolkit.PaletteMode.Office2010Blue; this.kryptonDockableWorkspace.Root.Children.AddRange(new System.ComponentModel.Component[] { this.kryptonWorkspaceCell1}); this.kryptonDockableWorkspace.Root.UniqueName = "D51970B3EA2C496AD51970B3EA2C496A"; this.kryptonDockableWorkspace.Root.WorkspaceControl = this.kryptonDockableWorkspace; this.kryptonDockableWorkspace.SeparatorStyle = Krypton.Toolkit.SeparatorStyle.HighProfile; this.kryptonDockableWorkspace.ShowMaximizeButton = false; - this.kryptonDockableWorkspace.Size = new System.Drawing.Size(420, 864); + this.kryptonDockableWorkspace.Size = new System.Drawing.Size(450, 864); this.kryptonDockableWorkspace.SplitterWidth = 8; this.kryptonDockableWorkspace.TabIndex = 0; this.kryptonDockableWorkspace.TabStop = true; this.kryptonDockableWorkspace.WorkspaceCellAdding += new System.EventHandler(this.KryptonDockableWorkspace_WorkspaceCellAdding); // + // kryptonWorkspaceCell1 + // + this.kryptonWorkspaceCell1.AllowPageDrag = false; + this.kryptonWorkspaceCell1.AllowPageReorder = false; + this.kryptonWorkspaceCell1.AllowTabFocus = false; + this.kryptonWorkspaceCell1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.kryptonWorkspaceCell1.Button.ButtonDisplayLogic = Krypton.Navigator.ButtonDisplayLogic.None; + this.kryptonWorkspaceCell1.Button.CloseButtonAction = Krypton.Navigator.CloseButtonAction.None; + this.kryptonWorkspaceCell1.Button.CloseButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; + this.kryptonWorkspaceCell1.Button.ContextButtonAction = Krypton.Navigator.ContextButtonAction.None; + this.kryptonWorkspaceCell1.Button.ContextButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; + this.kryptonWorkspaceCell1.Button.NextButtonAction = Krypton.Navigator.DirectionButtonAction.None; + this.kryptonWorkspaceCell1.Button.NextButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; + this.kryptonWorkspaceCell1.Button.PreviousButtonAction = Krypton.Navigator.DirectionButtonAction.None; + this.kryptonWorkspaceCell1.Button.PreviousButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; + this.kryptonWorkspaceCell1.MaximumSize = new System.Drawing.Size(420, 2000); + this.kryptonWorkspaceCell1.Name = "kryptonWorkspaceCell1"; + this.kryptonWorkspaceCell1.NavigatorMode = Krypton.Navigator.NavigatorMode.BarCheckButtonGroupOutside; + this.kryptonWorkspaceCell1.Pages.AddRange(new Krypton.Navigator.KryptonPage[] { + this.kryptonPage1}); + this.kryptonWorkspaceCell1.SelectedIndex = 0; + this.kryptonWorkspaceCell1.UniqueName = "B46823ED744B4A87B46823ED744B4A87"; + // // kryptonPage1 // this.kryptonPage1.AutoHiddenSlideSize = new System.Drawing.Size(200, 200); - this.kryptonPage1.Controls.Add(this.searchPanel); this.kryptonPage1.Controls.Add(this.treeView); + this.kryptonPage1.Controls.Add(this.searchPanel); + this.kryptonPage1.Dock = DockStyle.Fill; this.kryptonPage1.Flags = 32; this.kryptonPage1.LastVisibleSet = true; this.kryptonPage1.MinimumSize = new System.Drawing.Size(400, 450); this.kryptonPage1.Name = "kryptonPage1"; - this.kryptonPage1.Size = new System.Drawing.Size(418, 831); + this.kryptonPage1.Size = new System.Drawing.Size(450, 831); this.kryptonPage1.Text = "Recipes Explorer"; this.kryptonPage1.TextDescription = ""; this.kryptonPage1.TextTitle = ""; - this.kryptonPage1.ToolTipTitle = "Page ToolTip"; + this.kryptonPage1.ToolTipTitle = ""; this.kryptonPage1.UniqueName = "38D886AD20CD402D38D886AD20CD402D"; // // searchPanel @@ -312,13 +333,14 @@ private void InitializeComponent() this.SearchBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.SearchBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.SearchBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable; - this.SearchBox.DropDownWidth = 200; + this.SearchBox.DropDownWidth = 300; this.SearchBox.IntegralHeight = false; this.SearchBox.Location = new System.Drawing.Point(4, 6); - this.SearchBox.Margin = new System.Windows.Forms.Padding(4, 6, 0, 0); - this.SearchBox.MaxLength = 30; + this.SearchBox.Margin = new System.Windows.Forms.Padding(4, 4, 0, 0); + this.SearchBox.MaxDropDownItems = 20; + this.SearchBox.MaxLength = 40; this.SearchBox.Name = "SearchBox"; - this.SearchBox.Size = new System.Drawing.Size(200, 25); + this.SearchBox.Size = new System.Drawing.Size(200, 24); this.SearchBox.TabIndex = 0; // // SearchButton @@ -330,12 +352,11 @@ private void InitializeComponent() this.SearchButton.Size = new System.Drawing.Size(80, 33); this.SearchButton.TabIndex = 1; this.SearchButton.Text = "Search"; - this.SearchButton.UseVisualStyleBackColor = true; this.SearchButton.Click += new System.EventHandler(this.SearchButton_Click); // // QuantityBox // - this.QuantityBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.QuantityBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown; this.QuantityBox.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.QuantityBox.Items.AddRange(new object[] { "1", @@ -351,61 +372,38 @@ private void InitializeComponent() "1000", "5000", "10000"}); - this.QuantityBox.Location = new System.Drawing.Point(294, 6); + this.QuantityBox.Location = new System.Drawing.Point(294, 4); this.QuantityBox.Margin = new System.Windows.Forms.Padding(4, 6, 0, 0); - this.QuantityBox.MaxDropDownItems = 10; - this.QuantityBox.MaxLength = 4; + this.QuantityBox.MaxDropDownItems = 12; + this.QuantityBox.MaxLength = 6; this.QuantityBox.Name = "QuantityBox"; - this.QuantityBox.Size = new System.Drawing.Size(50, 31); + this.QuantityBox.Size = new System.Drawing.Size(80, 30); this.QuantityBox.TabIndex = 2; // // PreviousButton // this.PreviousButton.AutoSize = true; this.PreviousButton.Enabled = false; - this.PreviousButton.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.PreviousButton.Location = new System.Drawing.Point(347, 3); + this.PreviousButton.Font = new System.Drawing.Font("Segoe UI", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.PreviousButton.Location = new System.Drawing.Point(376, 3); this.PreviousButton.Name = "PreviousButton"; - this.PreviousButton.Size = new System.Drawing.Size(44, 33); + this.PreviousButton.Size = new System.Drawing.Size(40, 33); this.PreviousButton.TabIndex = 3; this.PreviousButton.Text = "<<"; - this.PreviousButton.UseVisualStyleBackColor = true; this.PreviousButton.Click += new System.EventHandler(this.PreviousButton_Click); // // treeView // - this.treeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); + //this.treeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + //| System.Windows.Forms.AnchorStyles.Left) + //| System.Windows.Forms.AnchorStyles.Right))); + this.treeView.Dock = DockStyle.Fill; this.treeView.Location = new System.Drawing.Point(0, 40); this.treeView.MinimumSize = new System.Drawing.Size(400, 400); this.treeView.Name = "treeView"; this.treeView.Size = new System.Drawing.Size(413, 1009); this.treeView.TabIndex = 3; // - // kryptonWorkspaceCell1 - // - this.kryptonWorkspaceCell1.AllowPageDrag = true; - this.kryptonWorkspaceCell1.AllowPageReorder = false; - this.kryptonWorkspaceCell1.AllowTabFocus = false; - this.kryptonWorkspaceCell1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.kryptonWorkspaceCell1.Button.ButtonDisplayLogic = Krypton.Navigator.ButtonDisplayLogic.None; - this.kryptonWorkspaceCell1.Button.CloseButtonAction = Krypton.Navigator.CloseButtonAction.None; - this.kryptonWorkspaceCell1.Button.CloseButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; - this.kryptonWorkspaceCell1.Button.ContextButtonAction = Krypton.Navigator.ContextButtonAction.None; - this.kryptonWorkspaceCell1.Button.ContextButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; - this.kryptonWorkspaceCell1.Button.NextButtonAction = Krypton.Navigator.DirectionButtonAction.None; - this.kryptonWorkspaceCell1.Button.NextButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; - this.kryptonWorkspaceCell1.Button.PreviousButtonAction = Krypton.Navigator.DirectionButtonAction.None; - this.kryptonWorkspaceCell1.Button.PreviousButtonDisplay = Krypton.Navigator.ButtonDisplay.Hide; - this.kryptonWorkspaceCell1.MaximumSize = new System.Drawing.Size(500, 0); - this.kryptonWorkspaceCell1.Name = "kryptonWorkspaceCell1"; - this.kryptonWorkspaceCell1.NavigatorMode = Krypton.Navigator.NavigatorMode.BarCheckButtonGroupOutside; - this.kryptonWorkspaceCell1.Pages.AddRange(new Krypton.Navigator.KryptonPage[] { - this.kryptonPage1}); - this.kryptonWorkspaceCell1.SelectedIndex = 0; - this.kryptonWorkspaceCell1.UniqueName = "B46823ED744B4A87B46823ED744B4A87"; - // // kryptonNavigator1 // this.kryptonNavigator1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -499,9 +497,9 @@ private void InitializeComponent() private System.Windows.Forms.TreeView treeView; private Krypton.Toolkit.KryptonPanel searchPanel; private Krypton.Toolkit.KryptonComboBox SearchBox; - private System.Windows.Forms.Button SearchButton; - private System.Windows.Forms.Button PreviousButton; - private System.Windows.Forms.ComboBox QuantityBox; + private Krypton.Toolkit.KryptonButton SearchButton; + private Krypton.Toolkit.KryptonButton PreviousButton; + private Krypton.Toolkit.KryptonComboBox QuantityBox; private Krypton.Ribbon.KryptonRibbonTab rbnTabTools; private Krypton.Ribbon.KryptonRibbonGroup kryptonRibbonGroup1; private Krypton.Ribbon.KryptonRibbonGroupGallery kryptonRibbonGroupGallery1; diff --git a/DU-Industry-Tool/Program.cs b/DU-Industry-Tool/Program.cs index 1893d54..c2d1417 100644 --- a/DU-Industry-Tool/Program.cs +++ b/DU-Industry-Tool/Program.cs @@ -13,11 +13,12 @@ static class Program [STAThread] static void Main() { - PortableJsonSettingsProvider.SettingsFileName = "DU-Industry-Tool.usersettings.json"; - PortableJsonSettingsProvider.SettingsDirectory = Path.GetDirectoryName(Application.ExecutablePath); - PortableJsonSettingsProvider.ApplyProvider(Properties.Settings.Default); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + //Application.SetHighDpiMode(HighDpiMode.SystemAware); + PortableJsonSettingsProvider.SettingsFileName = "DU-Industry-Tool.usersettings.json"; + PortableSettingsProviderBase.SettingsDirectory = Application.StartupPath; + PortableJsonSettingsProvider.ApplyProvider(Properties.Settings.Default); Application.Run(new MainForm(new IndustryManager())); } } diff --git a/DU-Industry-Tool/Properties/AssemblyInfo.cs b/DU-Industry-Tool/Properties/AssemblyInfo.cs index ccd0118..a5b41ba 100644 --- a/DU-Industry-Tool/Properties/AssemblyInfo.cs +++ b/DU-Industry-Tool/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.8.0.0")] -[assembly: AssemblyFileVersion("0.8.0.0")] +[assembly: AssemblyVersion("0.8.1.0")] +[assembly: AssemblyFileVersion("0.8.1.0")] diff --git a/DU-Industry-Tool/Version.txt b/DU-Industry-Tool/Version.txt index 8adc70f..c18d72b 100644 --- a/DU-Industry-Tool/Version.txt +++ b/DU-Industry-Tool/Version.txt @@ -1 +1 @@ -0.8.0 \ No newline at end of file +0.8.1 \ No newline at end of file diff --git a/DU-Industry-Tool/changelog.md b/DU-Industry-Tool/changelog.md index c4b9e79..234740d 100644 --- a/DU-Industry-Tool/changelog.md +++ b/DU-Industry-Tool/changelog.md @@ -1,5 +1,8 @@ # Changelog +## v0.8.1 +- Fix in DLL version mismatch at startup since 0.8.0 + ## v0.8.0 - New feature: in new "Tools" menu you can find a new "Production List" item: in a special dialogue build a list of craftable recipes to be calculated in one bulk operation. diff --git a/latestchanges.md b/latestchanges.md index 2bec23f..78f68c0 100644 --- a/latestchanges.md +++ b/latestchanges.md @@ -1,5 +1,8 @@ # Latest Changes +## v0.8.1 +- Fix in DLL version mismatch at startup since 0.8.0 + ## v0.8.0 - New feature: in new "Tools" menu you can find a new "Production List" item: in a special dialogue build a list of craftable recipes to be calculated in one bulk operation.