Changeset - d6859ea7177f
[Not reviewed]
default
0 1 0
Jason Maltzen - 3 years ago 2021-09-10 00:02:16
jason@hiddenachievement.com
Add some sanity checks on min/max concentration and min/max reagents in recipe generation. Also, clear out the search queue when generation has finished so the queue isn't loaded next time. This fixes the start/resume button state when entering the recipe generator after a prior run had finished.
1 file changed with 12 insertions and 0 deletions:
0 comments (0 inline, 0 general)
Services/RecipeGenerator.cs
Show inline comments
...
 
@@ -165,48 +165,54 @@ namespace DesertPaintCodex.Services
 

	
 
        // Generate paint recipes.
 
        // minConcentration - the minimum permitted concentration in a recipe (10 for paint, 50 for ribbons)
 
        // maxConcentration - the maximum concentration for a recipe
 
        // minReagents - the minimum number of ingredients in a recipe
 
        // maxReagents - the maximum number of ingredients allowed in a recipe
 
        // fullQuantityDepth - at this depth of ingredient or below, allow up to fullQuantity of any reagent
 
        // fullQuantity - the maximum amount of any reagent to permit up to the full quantity depth. After that, reagents are limited by the
 
        //                per-reagent value
 
        public void BeginRecipeGeneration(uint minConcentration, uint maxConcentration, uint minReagents, uint maxReagents, uint fullQuantityDepth, uint fullQuantity)
 
        {
 
            if (_running)
 
            {
 
                // Already running - don't start again
 
                return;
 
            }
 

	
 
            MinConcentration = minConcentration;
 
            MaxConcentration = maxConcentration;
 
            MinReagents = minReagents;
 
            MaxReagents = maxReagents;
 
            FullQuantity = fullQuantity;
 
            FullQuantityDepth = fullQuantityDepth;
 

	
 
            // Sanity check
 
            if (MinConcentration < 10) MinConcentration = 10;
 
            if (MaxConcentration < MinConcentration) MaxConcentration = MinConcentration;
 
            if (MinReagents < 1) MinReagents = 1;
 
            if (MaxReagents < MinReagents) MaxReagents = MinReagents;
 

	
 
            // first, sort reagents by cost.
 
            InitSortedReagents();
 

	
 
            _totalReagents = (uint)_costSortedReagents.Count;
 

	
 
            // Pre-populate recipes list with:
 
            // 1) 1-ingredient recipes @ min concentration for all enabled ingredients with a count >= min concentration
 
            // 2) any previously-generated recipes
 
            WriteLog($"===================== BEGIN RECIPE GENERATION ========================== {DateTime.Now}");
 
            WriteLog("Pre-populating basic recipes.");
 
            int enabledReagentCount = 0;
 
            PaintRecipe recipe = new();
 
            foreach (var reagent in _costSortedReagents.Where(reagent => reagent.Enabled))
 
            {
 
                if (!reagent.IsCatalyst && ((reagent.RecipeMax >= minConcentration) || ((FullQuantityDepth > 0) && (FullQuantity >= minConcentration))))
 
                {
 
                    recipe.Clear();
 
                    recipe.AddReagent(reagent.Name, minConcentration);
 
                    AddCheapestRecipe(recipe);
 
                }
 
                ++enabledReagentCount;
 
            }
 
            MaxReagents = (uint)Math.Min(enabledReagentCount, MaxReagents);
 
            MinReagents = Math.Min(MinReagents, MaxReagents);
...
 
@@ -500,48 +506,54 @@ namespace DesertPaintCodex.Services
 
                    while ((ok = IterateBreadthFirst(node)) && !_requestCancel)
 
                    {
 
                        Progress?.Invoke(this, EventArgs.Empty);
 
                    }
 
                }
 
                if (ok)
 
                {
 
                    // stopped because cancel was requested - requeue the node in its current state for resume
 
                    _searchQueue.Enqueue(node);
 
                }
 
            } while (!_requestCancel);
 

	
 
            bool done;
 
            lock(_workerLock)
 
            {
 
                --_runningThreads;
 
                //generatorThreads.Remove(Thread.CurrentThread);
 

	
 
                done = (_runningThreads == 0);
 
            }
 

	
 
            if (!done) return;
 
            
 
            _running       = false;
 
            if (!_requestCancel && !_searchQueue.IsEmpty)
 
            {
 
                Debug.WriteLine($"Recipe generation complete, but search queue isn't empty {_searchQueue.Count}.");
 
                WriteLog($"Recipe generation complete, but search queue isn't empty {_searchQueue.Count}.");
 
                _searchQueue.Clear();
 
            }
 
            _requestCancel = false;
 
            Finished?.Invoke(this, EventArgs.Empty);
 
        }
 

	
 
        // Add the cheapest recipe to the recipe list
 
        // returns the discarded recipe from the pair (or null if no original recipe to replace)
 
        private void AddCheapestRecipe(PaintRecipe recipe)
 
        {
 
            if (!recipe.IsValidForConcentration(MinConcentration)) return;
 
            
 
            string colorName = PaletteService.FindNearest(recipe.ReactedColor);
 
            lock (_workerLock)
 
            {
 
                uint newCost = recipe.Cost;
 
                if (_recipeCosts.TryGetValue(colorName, out var cost))
 
                {
 
                    if (cost < newCost)
 
                    {
 
                        // WriteLog($"Skipping recipe (cost {newCost} > {cost}): {recipe}");
 
                        return;
 
                    }
 
                    PaintRecipe origRecipe = _recipes[colorName];
 
                    if (cost == newCost && recipe.Concentration >= origRecipe.Concentration)
 
                    {
0 comments (0 inline, 0 general)