Files @ 6a6817b17a06
Branch filter:

Location: ATITD-Tools/Desert-Paint-Codex/Services/ReagentService.cs - annotation

Jason Maltzen
Simulator view updates: new warning when the recipe is below minimum concentration. Add the missing reactions to the warning about missing reactions. Show the current saved recipe for a color, and allow replacing/saving the current simulated recipe as the recipe for that color.
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
6919080271d5
6919080271d5
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
40eaee10ae56
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
6919080271d5
40eaee10ae56
40eaee10ae56
using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
using DesertPaintCodex.Models;
using DesertPaintCodex.Util;

namespace DesertPaintCodex.Services
{
    internal static class ReagentService
    {
        private static readonly Regex _ppReagentRegex        = new(@"(?<name>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+)\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal))\s*\|\s*(?<max>\d+).*");
        private static readonly Regex _ppCatalystRegex       = new(@"(?<name>(\w*\s)*\w+\w+)\s*\|\s*catalyst\s*\|\s*(?<cost>\d+)\s*\|\s*(?<enabled>[YN])\s*\|\s*(?<bulk>(bulk|normal)).*");
        private static readonly Regex _internalReagentRegex  = new(@"(?<name>(\w*\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*(?<red>\d+),\s*(?<green>\d+),\s*(?<blue>\d+).*");
        private static readonly Regex _internalCatalystRegex = new(@"(?<name>(\w+\s)*\w+)\s*\|\s*(?<ppname>\w+)\s*\|\s*catalyst.*");
        private static readonly Regex _renameHeader          = new(@"#\s*(?<header>\w*)");
        private static readonly Regex _renameRegex           = new(@"(?<oldName>(\w+\s)*\w+)\s*\|\s*(?<newName>(\w+\s)*\w+)");

        private static readonly Dictionary<string, Reagent> _reagents   = new();
        private static readonly Dictionary<string, string>  _ppToInternalName = new(); // pp name to our name
        private static readonly Dictionary<string, string> _ppRenames = new();
        private static readonly Dictionary<string, string> _internalRenames = new();
        
        private static bool _initialized = false;

        public static List<string> Names { get; } = new();


        private static void Initialize()
        {
            if (_initialized) return;

            string? reagentsPath = FileUtils.FindApplicationResourceFile("ingredients.txt");
            Debug.Assert(reagentsPath != null);

            Load(reagentsPath);

            string? renamesPath = FileUtils.FindApplicationResourceFile("renames.txt");

            if (renamesPath != null)
            {
                LoadAliases(renamesPath);
            }

            _initialized = true;
        }
        
        // Loads reagent name/colors
        private static void Load(string file)
        {
            _reagents.Clear();
            _ppToInternalName.Clear();
            Names.Clear();

            int index = 0;

            using StreamReader reader = new(file);
            string? line;
            while ((line = reader.ReadLine()) != null)
            {
                Match match = _internalReagentRegex.Match(line);
                if (match.Success)
                {
                    string name   = match.Groups["name"].Value;
                    string ppname = match.Groups["ppname"].Value;
                    Debug.WriteLine("Adding reagent[" + name + "] from line: [" + line + "]");
                    _reagents.Add(name,
                        new Reagent(name, ppname,
                            byte.Parse(match.Groups["red"].Value),
                            byte.Parse(match.Groups["green"].Value),
                            byte.Parse(match.Groups["blue"].Value),
                            index++));
                    // nameStore.AppendValues(name);
                    Names.Add(name);
                    _ppToInternalName.Add(ppname, name);
                }
                else
                {
                    match = _internalCatalystRegex.Match(line);
                    
                    if (!match.Success) continue;
                    
                    string name   = match.Groups["name"].Value;
                    string ppname = match.Groups["ppname"].Value;
                    _reagents.Add(name, new Reagent(ppname, ppname, index++));
                    // nameStore.AppendValues(name);
                    Names.Add(name);
                    _ppToInternalName.Add(ppname, name);
                }
            }
        }

        private static void LoadAliases(string file)
        {
            _ppRenames.Clear();
            _internalRenames.Clear();

            Dictionary<string, string>? renameDict = null;
            
            using StreamReader reader = new(file);
            string? line;
            while ((line = reader.ReadLine()) != null)
            {
                Match match = _renameHeader.Match(line);
                if (match.Success)
                {
                    string header = match.Groups["header"].Value;
                    renameDict = header switch
                    {
                        "PracticalPaint" => _ppRenames,
                        "Internal"       => _internalRenames,
                        _                => renameDict
                    };
                }

                if (renameDict == null) continue;
                
                match = _renameRegex.Match(line);
                
                if (!match.Success) continue;
                
                string oldName = match.Groups["oldName"].Value;
                string newName = match.Groups["newName"].Value;
                renameDict.Add(oldName, newName);
            }
        }

        public static void LoadProfileReagents(string file)
        {
            Initialize();
            
            using StreamReader reader = new(file);
            string? line;
            while ((line = reader.ReadLine()) != null)
            {
                Match match = _ppReagentRegex.Match(line);
                if (match.Success)
                {
                    string ppname = match.Groups["name"].Value;
                    if (_ppRenames.TryGetValue(ppname, out string? rename))
                    {
                        ppname = rename; // Apply rename.
                    }
                    
                    if (_ppToInternalName.TryGetValue(ppname, out string? name))
                    {
                        Reagent reagent = GetReagent(name);
                        if (reagent.IsCatalyst) continue;
                        reagent.Enabled   = match.Groups["enabled"].Value.Equals("Y");
                        reagent.Cost      = uint.Parse(match.Groups["cost"].Value);
                        reagent.RecipeMax = uint.Parse(match.Groups["max"].Value);
                    }
                }
                else
                {
                    match = _ppCatalystRegex.Match(line);
                    
                    if (!match.Success) continue;
                    
                    string ppname = match.Groups["name"].Value;
                    if (_ppRenames.TryGetValue(ppname, out string? rename))
                    {
                        ppname = rename; // Apply rename.
                    }
                    
                    if (_ppToInternalName.TryGetValue(ppname, out string? name))
                    {
                        Reagent reagent = GetReagent(name);
                        
                        if (reagent is not {IsCatalyst: true}) continue;
                        
                        reagent.Enabled = match.Groups["enabled"].Value.Equals("Y");
                        reagent.Cost    = uint.Parse(match.Groups["cost"].Value);
                    }
                }
            }
        }

        public static void SaveProfileReagents(string file)
        {
            Initialize();
            
            using StreamWriter writer = new(file);
            writer.WriteLine("// Ingredients are in the form:");
            writer.WriteLine("// Name | RGB values | cost | enabled (Y/N) | bulk/normal | max items per paint (1-20)");
            writer.WriteLine("//");
            writer.WriteLine("// It is recommended to only change the cost value");
            writer.WriteLine("// It is not recommended to set many of the ingredients above 10 per paint");

            List<Reagent> sortedReagents = new(_reagents.Count);
            sortedReagents.AddRange(_reagents.Values);
            sortedReagents.Sort((x, y) =>
                ((x.IsCatalyst && !y.IsCatalyst) ?
                    1 : ((y.IsCatalyst && !x.IsCatalyst) ?
                        -1 : string.Compare(x.PracticalPaintName, y.PracticalPaintName, StringComparison.InvariantCulture))));
            
            foreach (Reagent reagent in sortedReagents)
            {
                if (!reagent.IsCatalyst)
                {
                    writer.WriteLine("{0,-10} | {1,3}, {2,3}, {3,3} | {4,7} | {5} | {6} | {7}",
                        reagent.PracticalPaintName,
                        reagent.Color?.Red, reagent.Color?.Blue, reagent.Color?.Green,
                        reagent.Cost,
                        reagent.Enabled ? "Y" : "N",
                        reagent.RecipeMax >= 10 ? "  bulk" : "normal",
                        reagent.RecipeMax);
                }
                else
                {
                    writer.WriteLine("{0,-10} | catalyst | {1,7} | {2} | normal | 1",
                        reagent.PracticalPaintName,
                        reagent.Cost,
                        reagent.Enabled ? "Y" : "N");
                }
            }
        }


        public static void InitializeReactions(ReactionSet reactions)
        {
            Initialize();
            foreach (KeyValuePair<string, Reagent> pair1 in _reagents)
            {
                foreach (KeyValuePair<string, Reagent> pair2 in _reagents)
                {
                    if (pair1.Key != pair2.Key)
                    {
                        reactions.Set(pair1.Value, pair2.Value, null);
                    }
                }
            }
        }

        public static Reagent GetReagent(string reagentName)
        {
            Initialize();

            Reagent? returnVal = GetReagentByInternalName(reagentName);

            if (returnVal != null) return returnVal;

            returnVal = GetReagentByPPName(reagentName);

            if (returnVal != null) return returnVal;
            
            string? rename = null;
            if (_internalRenames.TryGetValue(reagentName, out rename))
            {
                returnVal = GetReagentByInternalName(rename);
                if (returnVal != null) return returnVal;
            }

            if (_ppRenames.TryGetValue(reagentName, out rename))
            {
                returnVal = GetReagentByPPName(rename);
                if (returnVal != null) return returnVal;
            }
            
            Debug.Assert(returnVal != null);

            return returnVal;
        }

        private static Reagent? GetReagentByInternalName(string internalName)
        {
            return _reagents.TryGetValue(internalName, out Reagent? returnVal) ? returnVal : null;
        }

        private static Reagent? GetReagentByPPName(string ppName)
        {
            if (!_ppToInternalName.TryGetValue(ppName, out string? otherName)) return null;
            
            return _reagents.TryGetValue(otherName, out Reagent? returnVal) ? returnVal : null;
        }
    }
}