Changeset - d63ade4d8489
[Not reviewed]
Jason Maltzen - 3 years ago 2021-08-16 07:58:58
jason@hiddenachievement.com
Recipe generation no longer incorrectly skips some recipes when a catalyst is included. This should result in some less expensive receips, and more total recipes tested.
5 files changed with 239 insertions and 28 deletions:
0 comments (0 inline, 0 general)
Models/PaintRecipe.cs
Show inline comments
...
 
@@ -274,2 +274,23 @@ namespace DesertPaintCodex.Models
 

	
 
        public uint Concentration
 
        {
 
            get
 
            {
 
                uint concentration = 0;
 
                foreach (ReagentQuantity ingredient in _recipe)
 
                {
 
                    string reagentName = ingredient.Name;
 
                    if (string.IsNullOrEmpty(reagentName))
 
                    {
 
                        continue;
 
                    }
 

	
 
                    Reagent reagent = ReagentService.GetReagent(reagentName);
 
                    if (reagent.IsCatalyst) continue;
 
                    concentration += ingredient.Quantity;
 
                }
 
                return concentration;
 
            }
 
        }
 

	
 
        public uint GetBulkCost(uint quantity)
Models/RecipeSearchNode.cs
Show inline comments
...
 
@@ -29,2 +29,6 @@ namespace DesertPaintCodex.Models
 

	
 
        public bool ShouldLog { get; private set; }
 

	
 
        public Action<string>? WriteLog = null;
 

	
 
        private uint _maxReagents;
...
 
@@ -73,2 +77,4 @@ namespace DesertPaintCodex.Models
 
            }
 

	
 
            RefreshShouldLog();
 
        }
...
 
@@ -110,2 +116,4 @@ namespace DesertPaintCodex.Models
 
            UsedQuantity = 0;
 

	
 
            RefreshShouldLog();
 
        }
...
 
@@ -134,2 +142,4 @@ namespace DesertPaintCodex.Models
 
            UsedQuantity = 0;
 

	
 
            RefreshShouldLog();
 
        }
...
 
@@ -156,2 +166,10 @@ namespace DesertPaintCodex.Models
 
            UsedQuantity = 0;
 

	
 
            RefreshShouldLog();
 
        }
 

	
 
        private void RefreshShouldLog()
 
        {
 
            ShouldLog = false;
 
            // (ReagentCount == 5) && (GetReagent(0).Name == "Iron") && (GetReagent(1).Name == "Red Sand") && (GetReagent(2).Name == "Sulfur") && (GetReagent(3).Name == "Carrot") && (GetReagent(4).Name == "Copper");
 
        }
...
 
@@ -173,2 +191,3 @@ namespace DesertPaintCodex.Models
 
            --_nextReagentPos;
 
            RefreshShouldLog();
 
        }
...
 
@@ -188,2 +207,3 @@ namespace DesertPaintCodex.Models
 
            }
 
            RefreshShouldLog();
 
        }
...
 
@@ -237,3 +257,7 @@ namespace DesertPaintCodex.Models
 
            UsedQuantity = 0;
 
            uint remainingReagents = ((uint)_nextReagentPos - CatalystCount);
 
            if (ShouldLog)
 
            {
 
                WriteLog?.Invoke($" == initializing {this} @ quantity {CurrentTargetQuantity} with {CatalystCount} catalysts ==");
 
            }
 
            uint remainingReagents = ((uint)_nextReagentPos); // Remaining reagents, including catalysts
 
            uint remainingWeight = CurrentTargetQuantity - CatalystCount;
...
 
@@ -248,2 +272,7 @@ namespace DesertPaintCodex.Models
 
                    ++UsedQuantity;
 
                    // This takes quantity but not weight (concentration)
 
                    if (ShouldLog)
 
                    {
 
                        WriteLog?.Invoke($"    + 1 {reagent.Name} (catalyst)");
 
                    }
 
                }
...
 
@@ -258,2 +287,6 @@ namespace DesertPaintCodex.Models
 
                    //Console.WriteLine("Init reagent {0} weight {1}", reagent.Name, weight);
 
                    if (ShouldLog)
 
                    {
 
                        WriteLog?.Invoke($"    + {weight} {reagent.Name} (remain: weight={remainingWeight} reagents={remainingReagents})");
 
                    }
 
                    remainingWeight -= weight;
...
 
@@ -264,2 +297,3 @@ namespace DesertPaintCodex.Models
 
            }
 
            RefreshShouldLog();
 
        }
...
 
@@ -434,4 +468,21 @@ namespace DesertPaintCodex.Models
 
            }
 
            RefreshShouldLog();
 
            return success;
 
        }        
 
        }
 

	
 
        public override string ToString()
 
        {
 
            if (_nextReagentPos == 0)
 
            {
 
                return "No ingredients";
 
            }
 
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
 
            sb.Append(_costSortedReagents[(int)_reagents[0]].Name);
 
            for (int idx = 1; idx < _nextReagentPos; ++idx)
 
            {
 
                Reagent reagent = _costSortedReagents[(int)_reagents[idx]];
 
                sb.Append($", {reagent.Name}");
 
            }
 
            return sb.ToString();
 
        }
 
    }
Models/Settings.cs
Show inline comments
...
 
@@ -19,4 +19,5 @@ namespace DesertPaintCodex.Models
 
            value = false;
 
            return _settings.TryGetValue(key.ToLower(), out string? valStr)
 
                && bool.TryParse(valStr, out value);
 
            bool found = _settings.TryGetValue(key.ToLower(), out string? valStr);
 
            found = found && bool.TryParse(valStr, out value);
 
            return found;
 

	
Services/RecipeGenerator.cs
Show inline comments
...
 
@@ -95,2 +95,31 @@ namespace DesertPaintCodex.Services
 

	
 
        public void FlushLog()
 
        {
 
            _log?.Flush();
 
        }
 

	
 
        public void CloseLog()
 
        {
 
            _log?.Close();
 
            _log = null;
 
        }
 

	
 
        private void WriteLog(string msg)
 
        {
 
            if (_log == null) return;
 
            lock (_workerLock)
 
            {
 
                _log.WriteLine(msg);
 
            }
 
        }
 

	
 
        private void WriteLog(string msg, params object[] args)
 
        {
 
            if (_log == null) return;
 
            lock(_workerLock)
 
            {
 
                _log.WriteLine(msg, args);
 
            }
 
        }
 

	
 
        private class ReagentCostSort : IComparer<Reagent>
...
 
@@ -167,2 +196,4 @@ namespace DesertPaintCodex.Services
 
            // 2) any previously-generated recipes
 
            WriteLog($"===================== BEGIN RECIPE GENERATION ========================== {DateTime.Now}");
 
            WriteLog("Pre-populating basic recipes.");
 
            int enabledReagentCount = 0;
...
 
@@ -198,2 +229,3 @@ namespace DesertPaintCodex.Services
 
                };
 
                initialNode.WriteLog = WriteLog;
 

	
...
 
@@ -207,2 +239,3 @@ namespace DesertPaintCodex.Services
 
                        RecipeSearchNode searchNode = new RecipeSearchNode(initialNode);
 
                        searchNode.WriteLog = WriteLog;
 
                        _searchQueue.Enqueue(searchNode);
...
 
@@ -218,3 +251,3 @@ namespace DesertPaintCodex.Services
 

	
 
            _log?.WriteLine("Begin recipe generation: MaxConcentration={0} MinReagents={1} MaxReagents={2} FullQuantity={3} FullQuantityDepth={4}", MaxConcentration, MinReagents, MaxReagents, FullQuantity, FullQuantityDepth);
 
            WriteLog("Begin recipe generation: MaxConcentration={0} MinReagents={1} MaxReagents={2} FullQuantity={3} FullQuantityDepth={4}", MaxConcentration, MinReagents, MaxReagents, FullQuantity, FullQuantityDepth);
 

	
...
 
@@ -234,3 +267,3 @@ namespace DesertPaintCodex.Services
 

	
 
            _log?.WriteLine("Resuming recipe generation: pre-threads={0} reagent count={1} search queue={2}", _runningThreads, _costSortedReagents.Count, _searchQueue.Count);
 
            WriteLog("Resuming recipe generation: pre-threads={0} reagent count={1} search queue={2}", _runningThreads, _costSortedReagents.Count, _searchQueue.Count);
 
            _runningThreads = 0; // presumably!
...
 
@@ -244,2 +277,3 @@ namespace DesertPaintCodex.Services
 
            Console.WriteLine("Starting {0} generator threads.", threadCount);
 
            WriteLog($"===== Starting {threadCount} threads.");
 
            for (int i = 0; i < threadCount; ++i)
...
 
@@ -383,2 +417,3 @@ namespace DesertPaintCodex.Services
 
                                };
 
                                node.WriteLog = WriteLog;
 
                                success                = success && node.LoadState(reader);
...
 
@@ -422,6 +457,8 @@ namespace DesertPaintCodex.Services
 
                }
 
                
 
                if (!ok) continue;
 

	
 
                if (!ok) break;
 
                
 
                Debug.Assert(node != null);
 

	
 
                node.WriteLog = WriteLog;
 
                
...
 
@@ -434,2 +471,6 @@ namespace DesertPaintCodex.Services
 
                        --targetQuantity;
 
                        if (node.ShouldLog)
 
                        {
 
                            WriteLog($" == Initializing {node} for quantity {targetQuantity}");
 
                        }
 
                        node.InitForQuantity(targetQuantity);
...
 
@@ -451,2 +492,6 @@ namespace DesertPaintCodex.Services
 
                        ++targetQuantity;
 
                        if (node.ShouldLog)
 
                        {
 
                            WriteLog($" == Initializing {node} for quantity {targetQuantity}");
 
                        }
 
                        node.InitForQuantity(targetQuantity);
...
 
@@ -464,3 +509,3 @@ namespace DesertPaintCodex.Services
 
                }
 
            } while (!_requestCancel && ok);
 
            } while (!_requestCancel);
 

	
...
 
@@ -491,9 +536,21 @@ namespace DesertPaintCodex.Services
 
            {
 
                uint newCost = recipe.Cost;
 
                if (_recipeCosts.TryGetValue(colorName, out var cost))
 
                {
 
                    if (cost <= recipe.Cost) return;
 
                    if (cost < newCost)
 
                    {
 
                        // WriteLog($"Skipping recipe (cost {newCost} > {cost}): {recipe}");
 
                        return;
 
                    }
 
                    PaintRecipe origRecipe = _recipes[colorName];
 
                    if (cost == newCost && recipe.Concentration >= origRecipe.Concentration)
 
                    {
 
                        // Same cost, greater concentration - use the lower concentration recipe
 
                        WriteLog($"Skipping recipe (cost {newCost}, {recipe.Concentration} >= {origRecipe.Concentration}): {recipe}");
 
                        return;
 
                    }
 
                        
 
                    _recipes[colorName].CopyFrom(recipe);
 
                    _recipeCosts[colorName] = recipe.Cost;
 
                    _log?.WriteLine("New recipe (cost {0}): {1}", recipe.Cost, recipe);
 
                    _recipes[colorName].CopyFrom(recipe); // Copy recipe because the one passed in should be const and will get overwritten
 
                    _recipeCosts[colorName] = newCost;
 
                    WriteLog($"Replacing recipe (cost {newCost} < {cost}): {recipe}");
 
                        
...
 
@@ -501,3 +558,3 @@ namespace DesertPaintCodex.Services
 
                        
 
                    NewRecipeEventArgs args = new(colorName, recipe);
 
                    NewRecipeEventArgs args = new(colorName, _recipes[colorName]);
 
                    NewRecipe(this, args);
...
 
@@ -507,8 +564,11 @@ namespace DesertPaintCodex.Services
 
                    // This would be an error!
 
                    _recipeCosts.Add(colorName, recipe.Cost);
 
                    _recipes.Add(colorName, new PaintRecipe(recipe));
 
                        
 
                    _recipeCosts.Add(colorName, newCost);
 
                    PaintRecipe newRecipe = new PaintRecipe(recipe); // Copy recipe because the one passed in should be const and will get overwritten
 
                    _recipes.Add(colorName, newRecipe);
 

	
 
                    WriteLog($"New recipe (cost {newCost}): {recipe}");
 

	
 
                    if (NewRecipe == null) return;
 
                        
 
                    NewRecipeEventArgs args = new(colorName, recipe);
 
                    NewRecipeEventArgs args = new(colorName, newRecipe);
 
                    NewRecipe(this, args);
...
 
@@ -603,2 +663,4 @@ namespace DesertPaintCodex.Services
 

	
 
            string origNodeVal = node.ToString();
 

	
 
            // Try next quantity
...
 
@@ -610,3 +672,7 @@ namespace DesertPaintCodex.Services
 
                if (newQuantity > quantityLimit) continue;
 
                
 

	
 
                if (node.ShouldLog)
 
                {
 
                    WriteLog($" == Initializing {node} for quantity {newQuantity}");
 
                }
 
                node.InitForQuantity(newQuantity);
...
 
@@ -615,2 +681,6 @@ namespace DesertPaintCodex.Services
 
                    //if (log != null) { lock(log) { log.WriteLine("Update quantity to {0}", node.CurrentTargetQuantity); } }
 
                    if (node.ShouldLog)
 
                    {
 
                        WriteLog($"  == {node} quantity {newQuantity}");
 
                    }
 
                    return true;
...
 
@@ -620,2 +690,13 @@ namespace DesertPaintCodex.Services
 
            bool ok = NextReagentSetBreadthFirst(node, node.MinReagents, node.MaxReagents);
 
            if (node.ShouldLog)
 
            {
 
                if (ok)
 
                {
 
                    WriteLog($"==== {origNodeVal} next reagent set: {node} @ {node.CurrentTargetQuantity}");
 
                }
 
                else
 
                {
 
                    WriteLog($"==== done with reagent set: {origNodeVal}");
 
                }
 
            }
 
            return ok;
...
 
@@ -631,2 +712,6 @@ namespace DesertPaintCodex.Services
 
            //Console.WriteLine("Finding new recipe after quantity {0}/{1} used {2}", newQuantity, node.MaxConcentration, node.UsedQuantity);
 
            if (node.ShouldLog)
 
            {
 
                WriteLog($" == Initializing {node} for quantity {node.MinConcentration + node.CatalystCount}");
 
            }
 
            node.InitForQuantity(node.MinConcentration + node.CatalystCount); // reset quantity
...
 
@@ -693,2 +778,3 @@ namespace DesertPaintCodex.Services
 
                } while ((node.CatalystCount >= node.ReagentCount) && (node.ReagentCount >= minReagents)); // make sure to skip all-catalyst combinations
 

	
 
                if (recipeFound)
...
 
@@ -704,3 +790,10 @@ namespace DesertPaintCodex.Services
 

	
 
            if (!recipeFound) return false;
 
            if (!recipeFound)
 
            {
 
                if (node.ShouldLog)
 
                {
 
                    WriteLog($" == no more recipes for {node}");
 
                }
 
                return false;
 
            }
 
            
...
 
@@ -727,2 +820,6 @@ namespace DesertPaintCodex.Services
 
            }
 
            if (node.ShouldLog)
 
            {
 
                WriteLog($"   -> {node.TestRecipe}");
 
            }
 
            AddCheapestRecipe(node.TestRecipe);
...
 
@@ -739,2 +836,6 @@ namespace DesertPaintCodex.Services
 
                //Console.WriteLine("Insufficient remaining weight");
 
                if (node.ShouldLog)
 
                {
 
                    WriteLog($" ***** Not enough remaining weight in recipe {node} at target quantity {node.CurrentTargetQuantity} catalysts {node.CatalystCount} min concentration {MinConcentration}");
 
                }
 
                return false;
...
 
@@ -747,2 +848,3 @@ namespace DesertPaintCodex.Services
 
            int reagentsBelow = 0;
 
            // Start from the end of the current reagent list and work to the front
 
            for (int i = (int)depth-1 ; i >= 0; --i)
...
 
@@ -824,2 +926,12 @@ namespace DesertPaintCodex.Services
 

	
 
        public void ResetQueue()
 
        {
 
            lock (_workerLock)
 
            {
 
                // Don't reset the queue ever while running
 
                if (_running) return;
 
                _searchQueue.Clear();
 
            }
 
        }
 

	
 
        public void Reset()
ViewModels/RecipeGeneratorViewModel.cs
Show inline comments
...
 
@@ -128,4 +128,4 @@ namespace DesertPaintCodex.ViewModels
 
            {
 
                string logDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
 
                _generator.Log = System.IO.Path.Combine(logDir, "dpl_generator.txt");
 
                string logDir = DesertPaintCodex.Util.FileUtils.AppDataPath;
 
                _generator.Log = System.IO.Path.Combine(logDir, "recipe_generator_log.txt");
 
            }
...
 
@@ -155,3 +155,11 @@ namespace DesertPaintCodex.ViewModels
 
            SelectedView = 1;
 
            
 

	
 
            _generator.CloseLog();
 
            SettingsService.Get("Generator.Logging", out bool logGenerator, false);
 
            if (logGenerator)
 
            {
 
                string logDir = DesertPaintCodex.Util.FileUtils.AppDataPath;
 
                _generator.Log = System.IO.Path.Combine(logDir, "recipe_generator_log.txt");
 
            }
 

	
 
            _generator.BeginRecipeGeneration(
...
 
@@ -173,3 +181,5 @@ namespace DesertPaintCodex.ViewModels
 
            _profile.SaveRecipes();
 
            
 
            _generator.ResetQueue();
 
            SaveState();
 

	
 
            CanClear = true;
...
 
@@ -191,3 +201,11 @@ namespace DesertPaintCodex.ViewModels
 
            SelectedView = 1;
 
            
 

	
 
            _generator.CloseLog();
 
            SettingsService.Get("Generator.Logging", out bool logGenerator, false);
 
            if (logGenerator)
 
            {
 
                string logDir = DesertPaintCodex.Util.FileUtils.AppDataPath;
 
                _generator.Log = System.IO.Path.Combine(logDir, "recipe_generator_log.txt");
 
            }
 

	
 
            _generator.ResumeRecipeGeneration();
...
 
@@ -304,6 +322,6 @@ namespace DesertPaintCodex.ViewModels
 
        {
 
            SaveState();
 
            
 
            if (_saving)
 
            {
 
                SaveState();
 

	
 
                _generator.ResumeRecipeGeneration();
...
 
@@ -314,5 +332,13 @@ namespace DesertPaintCodex.ViewModels
 

	
 
            if (IsPaused) return;
 
            _generator.FlushLog();
 

	
 
            if (IsPaused)
 
            {
 
                SaveState();
 
                _generator.CloseLog();
 
                return;
 
            }
 

	
 
            End();
 
            _generator.CloseLog();
 
        }
0 comments (0 inline, 0 general)