using System; using System.Collections.Generic; using SabreTools.Core; using SabreTools.Core.Tools; using SabreTools.DatFiles; using SabreTools.DatItems; using SabreTools.Logging; namespace SabreTools.Filtering { public class ExtraIni { #region Fields /// /// List of extras to apply /// public List Items { get; set; } = new List(); #endregion #region Logging /// /// Logging object /// private readonly Logger logger; #endregion #region Constructors /// /// Constructor /// public ExtraIni() { logger = new Logger(this); } #endregion #region Population /// /// Populate item using field:file inputs /// /// Field and file combinations public void PopulateFromList(List inputs) { foreach (string input in inputs) { ExtraIniItem item = new ExtraIniItem(); // If we don't even have a possible field and file combination if (!input.Contains(":")) { logger.Warning($"'{input}` is not a valid INI extras string. Valid INI extras strings are of the form 'key:value'. Please refer to README.1ST or the help feature for more details."); return; } string inputTrimmed = input.Trim('"', ' ', '\t'); string fieldString = inputTrimmed.Split(':')[0].ToLowerInvariant().Trim('"', ' ', '\t'); string fileString = inputTrimmed[(fieldString.Length + 1)..].Trim('"', ' ', '\t'); item.DatItemField = fieldString.AsDatItemField(); item.MachineField = fieldString.AsMachineField(); if (item.PopulateFromFile(fileString)) Items.Add(item); } } #endregion #region Running /// /// Apply a set of Extra INIs on the DatFile /// /// Current DatFile object to run operations on /// True if the error that is thrown should be thrown back to the caller, false otherwise /// True if the extras were applied, false on error public bool ApplyExtras(DatFile datFile, bool throwOnError = false) { try { // Bucket by game first datFile.Items.BucketBy(ItemKey.Machine, DedupeType.None); // Create a new set of mappings based on the items var machineMap = new Dictionary>(); var datItemMap = new Dictionary>(); // Loop through each of the extras foreach (ExtraIniItem item in Items) { foreach (var mapping in item.Mappings) { string key = mapping.Key; List machineNames = mapping.Value; // Loop through the machines and add the new mappings foreach (string machine in machineNames) { if (item.MachineField != MachineField.NULL) { if (!machineMap.ContainsKey(machine)) machineMap[machine] = new Dictionary(); machineMap[machine][item.MachineField] = key; } else if (item.DatItemField != DatItemField.NULL) { if (!datItemMap.ContainsKey(machine)) datItemMap[machine] = new Dictionary(); datItemMap[machine][item.DatItemField] = key; } } } } // Now apply the new set of Machine mappings foreach (string key in machineMap.Keys) { // If the key doesn't exist, continue if (!datFile.Items.ContainsKey(key)) continue; List datItems = datFile.Items[key]; Setter setter = new Setter { MachineMappings = machineMap[key] }; foreach (var datItem in datItems) { setter.SetFields(datItem.Machine); } } // Now apply the new set of DatItem mappings foreach (string key in datItemMap.Keys) { // If the key doesn't exist, continue if (!datFile.Items.ContainsKey(key)) continue; List datItems = datFile.Items[key]; Setter setter = new Setter { DatItemMappings = datItemMap[key] }; foreach (var datItem in datItems) { setter.SetFields(datItem); } } } catch (Exception ex) when (!throwOnError) { logger.Error(ex); return false; } return true; } #endregion } }