Files
SabreTools/SabreTools.DatTools/Setter.cs

465 lines
16 KiB
C#
Raw Normal View History

2021-02-01 14:07:50 -08:00
using System.Collections.Generic;
2024-03-05 17:17:40 -05:00
using System.Linq;
using SabreTools.Core.Filter;
2021-02-01 14:07:50 -08:00
using SabreTools.Core.Tools;
using SabreTools.DatFiles;
2021-02-01 14:07:50 -08:00
using SabreTools.DatItems;
2021-02-02 10:23:43 -08:00
using SabreTools.DatItems.Formats;
2024-10-24 00:36:44 -04:00
using SabreTools.IO.Logging;
2021-02-01 14:07:50 -08:00
2024-10-30 11:26:56 -04:00
namespace SabreTools.DatTools
2021-02-01 14:07:50 -08:00
{
/// <summary>
/// Set fields on DatItems
/// </summary>
public class Setter
{
#region Fields
/// <summary>
/// Mappings to set DatHeader fields
/// </summary>
2024-03-05 17:17:40 -05:00
public Dictionary<string, string> HeaderFieldMappings { get; } = [];
2021-02-01 14:07:50 -08:00
/// <summary>
/// Mappings to set Machine fields
/// </summary>
2024-03-05 17:17:40 -05:00
public Dictionary<string, string> MachineFieldMappings { get; } = [];
2021-02-01 14:07:50 -08:00
/// <summary>
/// Mappings to set DatItem fields
/// </summary>
2024-10-24 03:16:45 -04:00
public Dictionary<FilterKey, string> ItemFieldMappings { get; } = [];
2021-02-01 14:07:50 -08:00
#endregion
2023-03-26 21:47:17 -04:00
2021-02-01 14:07:50 -08:00
#region Logging
/// <summary>
/// Logging object
/// </summary>
2025-01-08 16:59:44 -05:00
private readonly Logger _logger = new();
2021-02-01 14:07:50 -08:00
#endregion
#region Population
2024-03-05 17:17:40 -05:00
/// <summary>
/// Populate the setters using a field name and a value
/// </summary>
/// <param name="field">Field name</param>
/// <param name="value">Field value</param>
2024-10-24 03:16:45 -04:00
public void PopulateSetters(FilterKey field, string value)
2024-03-05 17:17:40 -05:00
=> PopulateSettersFromList([field], [value]);
2021-02-01 14:07:50 -08:00
/// <summary>
/// Populate the setters using a set of field names
/// </summary>
/// <param name="fields">List of field names</param>
2024-03-05 17:17:40 -05:00
/// <param name="values">List of field values</param>
2024-10-24 03:16:45 -04:00
public void PopulateSettersFromList(List<FilterKey> fields, List<string> values)
2021-02-01 14:07:50 -08:00
{
// If the list is null or empty, just return
2024-03-05 17:17:40 -05:00
if (values == null || values.Count == 0)
2021-02-01 14:07:50 -08:00
return;
2024-03-05 17:17:40 -05:00
var watch = new InternalStopwatch("Populating setters from list");
2021-02-01 14:07:50 -08:00
// Now we loop through and get values for everything
2024-03-05 17:17:40 -05:00
for (int i = 0; i < fields.Count; i++)
2021-02-01 14:07:50 -08:00
{
2024-10-24 03:16:45 -04:00
FilterKey field = fields[i];
2024-03-05 17:17:40 -05:00
string value = values[i];
2021-02-01 14:07:50 -08:00
2024-03-05 17:17:40 -05:00
if (!SetSetter(field, value))
2025-01-08 16:59:44 -05:00
_logger.Warning($"The value {value} did not match any known field names. Please check the wiki for more details on supported field names.");
2024-03-05 17:17:40 -05:00
}
2021-02-01 14:07:50 -08:00
2024-03-05 17:17:40 -05:00
watch.Stop();
}
2024-03-05 17:33:02 -05:00
/// <summary>
/// Populate the setters using a set of field names
/// </summary>
/// <param name="mappings">Dictionary of mappings</param>
2024-10-24 03:16:45 -04:00
public void PopulateSettersFromDictionary(Dictionary<FilterKey, string>? mappings)
2024-03-05 17:33:02 -05:00
{
// If the dictionary is null or empty, just return
if (mappings == null || mappings.Count == 0)
return;
var watch = new InternalStopwatch("Populating setters from dictionary");
// Now we loop through and get values for everything
foreach (var mapping in mappings)
{
2024-10-24 03:16:45 -04:00
FilterKey field = mapping.Key;
2024-03-05 17:33:02 -05:00
string value = mapping.Value;
if (!SetSetter(field, value))
2025-01-08 16:59:44 -05:00
_logger.Warning($"The value {value} did not match any known field names. Please check the wiki for more details on supported field names.");
2024-03-05 17:33:02 -05:00
}
watch.Stop();
}
2024-03-05 17:17:40 -05:00
/// <summary>
/// Set remover from a value
/// </summary>
2024-10-24 03:16:45 -04:00
/// <param name="key">Key for the remover to be set</param>
private bool SetSetter(FilterKey key, string value)
2024-03-05 17:17:40 -05:00
{
2024-10-24 04:01:45 -04:00
switch (key.ItemName)
2024-03-05 17:17:40 -05:00
{
case Models.Metadata.MetadataFile.HeaderKey:
2024-10-24 04:01:45 -04:00
HeaderFieldMappings[key.FieldName] = value;
2024-03-05 17:17:40 -05:00
return true;
case Models.Metadata.MetadataFile.MachineKey:
2024-10-24 04:01:45 -04:00
MachineFieldMappings[key.FieldName] = value;
2024-03-05 17:17:40 -05:00
return true;
default:
2024-10-24 03:16:45 -04:00
ItemFieldMappings[key] = value;
2024-03-05 17:17:40 -05:00
return true;
2021-02-01 14:07:50 -08:00
}
}
#endregion
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="datHeader">DatHeader to set fields on</param>
public void SetFields(DatHeader datHeader)
{
2024-03-05 17:17:40 -05:00
// If we have an invalid input, return
2025-01-10 22:03:50 -05:00
if (HeaderFieldMappings.Count == 0)
2021-02-01 14:07:50 -08:00
return;
2024-03-06 00:33:45 -05:00
foreach (var kvp in HeaderFieldMappings)
2024-03-05 17:17:40 -05:00
{
2024-03-06 00:33:45 -05:00
datHeader.SetField(kvp.Key, kvp.Value);
2024-03-05 17:17:40 -05:00
}
}
2021-02-01 14:07:50 -08:00
2024-03-05 17:17:40 -05:00
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="machine">Machine to set fields on</param>
public void SetFields(Machine? machine)
{
// If we have an invalid input, return
if (machine == null || MachineFieldMappings.Count == 0)
2024-03-05 17:17:40 -05:00
return;
2021-02-01 14:07:50 -08:00
2024-03-05 17:17:40 -05:00
foreach (var kvp in MachineFieldMappings)
{
machine.SetField(kvp.Key, kvp.Value);
}
2021-02-01 14:07:50 -08:00
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="datItem">DatItem to set fields on</param>
public void SetFields(DatItem datItem)
{
2024-03-05 20:07:38 -05:00
// If we have an invalid input, return
2024-03-05 17:17:40 -05:00
if (datItem == null)
2021-02-01 14:07:50 -08:00
return;
#region Common
2021-02-01 14:07:50 -08:00
2024-03-05 17:17:40 -05:00
// Handle Machine fields
2025-05-02 16:46:20 -04:00
if (MachineFieldMappings.Count > 0 && datItem.GetMachine() != null)
SetFields(datItem.GetMachine()!);
2024-03-05 17:17:40 -05:00
// If there are no field names, return
if (ItemFieldMappings == null || ItemFieldMappings.Count == 0)
2024-03-05 17:17:40 -05:00
return;
// If there are no field names for this type or generic, return
2024-03-11 16:26:28 -04:00
string? itemType = datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>().AsStringValue();
2024-10-24 03:16:45 -04:00
if (itemType == null || (!ItemFieldMappings.Keys.Any(kvp => kvp.ItemName == itemType) && !ItemFieldMappings.Keys.Any(kvp => kvp.ItemName == "item")))
2024-03-05 17:17:40 -05:00
return;
// Get the combined list of fields to remove
var fieldMappings = new Dictionary<string, string>();
2024-10-24 03:16:45 -04:00
foreach (var mapping in ItemFieldMappings.Where(kvp => kvp.Key.ItemName == "item").ToDictionary(kvp => kvp.Key.FieldName, kvp => kvp.Value))
2024-03-05 17:17:40 -05:00
{
fieldMappings[mapping.Key] = mapping.Value;
}
2024-10-24 03:16:45 -04:00
foreach (var mapping in ItemFieldMappings.Where(kvp => kvp.Key.ItemName == itemType).ToDictionary(kvp => kvp.Key.FieldName, kvp => kvp.Value))
2024-03-05 17:17:40 -05:00
{
fieldMappings[mapping.Key] = mapping.Value;
}
// If the field specifically contains Name, set it separately
if (fieldMappings.Keys.Contains(Models.Metadata.Rom.NameKey))
2024-03-10 20:39:54 -04:00
{
2024-03-05 17:17:40 -05:00
datItem.SetName(fieldMappings[Models.Metadata.Rom.NameKey]);
2024-03-10 20:39:54 -04:00
fieldMappings.Remove(Models.Metadata.Rom.NameKey);
}
2021-02-01 14:07:50 -08:00
#endregion
#region Item-Specific
2024-03-05 02:20:12 -05:00
// Handle unnested sets first
2024-03-05 17:17:40 -05:00
foreach (var kvp in fieldMappings)
2024-03-05 02:20:12 -05:00
{
datItem.SetField(kvp.Key, kvp.Value);
}
2024-03-05 17:17:40 -05:00
2024-03-05 02:20:12 -05:00
// Handle nested sets
switch (datItem)
{
2025-02-24 09:54:06 -05:00
case Adjuster adjuster: SetNestedFields(adjuster); break;
case Configuration condition: SetNestedFields(condition); break;
case ConfSetting confSetting: SetNestedFields(confSetting); break;
case Device device: SetNestedFields(device); break;
case DipSwitch dipSwitch: SetNestedFields(dipSwitch); break;
case DipValue dipValue: SetNestedFields(dipValue); break;
case Disk disk: SetNestedFields(disk); break;
case Input input: SetNestedFields(input); break;
case Part part: SetNestedFields(part); break;
case Port port: SetNestedFields(port); break;
case Rom rom: SetNestedFields(rom); break;
case Slot slot: SetNestedFields(slot); break;
}
2021-02-01 14:07:50 -08:00
#endregion
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="adjuster">Adjuster to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Adjuster adjuster)
2021-02-01 14:07:50 -08:00
{
// Field.DatItem_Conditions does not apply here
if (adjuster.ConditionsSpecified)
{
2024-03-08 21:12:13 -05:00
foreach (Condition subCondition in adjuster.GetFieldValue<Condition[]?>(Models.Metadata.Adjuster.ConditionKey)!)
2021-02-01 14:07:50 -08:00
{
2024-03-05 02:20:12 -05:00
SetFields(subCondition);
2021-02-01 14:07:50 -08:00
}
}
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="configuration">Configuration to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Configuration configuration)
2021-02-01 14:07:50 -08:00
{
if (configuration.ConditionsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (Condition subCondition in configuration.GetFieldValue<Condition[]?>(Models.Metadata.Configuration.ConditionKey)!)
2021-02-01 14:07:50 -08:00
{
2024-03-05 02:20:12 -05:00
SetFields(subCondition);
2021-02-01 14:07:50 -08:00
}
}
if (configuration.LocationsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (ConfLocation subLocation in configuration.GetFieldValue<ConfLocation[]?>(Models.Metadata.Configuration.ConfLocationKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subLocation);
}
}
if (configuration.SettingsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (ConfSetting subSetting in configuration.GetFieldValue<ConfSetting[]?>(Models.Metadata.Configuration.ConfSettingKey)!)
2021-02-01 14:07:50 -08:00
{
2024-03-05 02:20:12 -05:00
SetFields(subSetting as DatItem);
2021-02-01 14:07:50 -08:00
}
}
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="confSetting">ConfSetting to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(ConfSetting confSetting)
{
if (confSetting.ConditionsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (Condition subCondition in confSetting.GetFieldValue<Condition[]?>(Models.Metadata.ConfSetting.ConditionKey)!)
{
2024-03-05 02:20:12 -05:00
SetFields(subCondition);
}
}
}
2021-02-01 14:07:50 -08:00
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="device">Device to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Device device)
2021-02-01 14:07:50 -08:00
{
if (device.ExtensionsSpecified)
2021-02-01 14:07:50 -08:00
{
2024-03-09 21:34:26 -05:00
foreach (Extension subExtension in device.GetFieldValue<Extension[]?>(Models.Metadata.Device.ExtensionKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subExtension);
2021-02-01 14:07:50 -08:00
}
}
if (device.InstancesSpecified)
2021-02-01 14:07:50 -08:00
{
2024-03-09 21:34:26 -05:00
foreach (Instance subInstance in device.GetFieldValue<Instance[]?>(Models.Metadata.Device.InstanceKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subInstance);
2021-02-01 14:07:50 -08:00
}
}
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="dipSwitch">DipSwitch to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(DipSwitch dipSwitch)
2021-02-01 14:07:50 -08:00
{
if (dipSwitch.ConditionsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (Condition subCondition in dipSwitch.GetFieldValue<Condition[]?>(Models.Metadata.DipSwitch.ConditionKey)!)
2021-02-01 14:07:50 -08:00
{
2024-03-05 02:20:12 -05:00
SetFields(subCondition);
2021-02-01 14:07:50 -08:00
}
}
if (dipSwitch.LocationsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (DipLocation subLocation in dipSwitch.GetFieldValue<DipLocation[]?>(Models.Metadata.DipSwitch.DipLocationKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subLocation);
}
}
if (dipSwitch.ValuesSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (DipValue subValue in dipSwitch.GetFieldValue<DipValue[]?>(Models.Metadata.DipSwitch.DipValueKey)!)
2021-02-01 14:07:50 -08:00
{
2024-03-05 02:20:12 -05:00
SetFields(subValue as DatItem);
2021-02-01 14:07:50 -08:00
}
}
2024-03-09 21:34:26 -05:00
if (!dipSwitch.PartSpecified)
2024-03-10 16:49:07 -04:00
dipSwitch.SetFieldValue<Part?>(DipSwitch.PartKey, new Part());
2024-03-09 21:34:26 -05:00
2024-03-10 16:49:07 -04:00
SetFields((dipSwitch.GetFieldValue<Part?>(DipSwitch.PartKey) as DatItem)!);
2021-02-01 14:07:50 -08:00
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="dipValue">DipValue to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(DipValue dipValue)
{
if (dipValue.ConditionsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (Condition subCondition in dipValue.GetFieldValue<Condition[]?>(Models.Metadata.DipValue.ConditionKey)!)
{
2024-03-05 02:20:12 -05:00
SetFields(subCondition);
}
}
}
2021-02-01 14:07:50 -08:00
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="disk">Disk to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Disk disk)
2021-02-01 14:07:50 -08:00
{
2024-03-09 21:34:26 -05:00
if (!disk.DiskAreaSpecified)
2024-03-10 16:49:07 -04:00
disk.SetFieldValue<DiskArea?>(Disk.DiskAreaKey, new DiskArea());
2024-03-09 21:34:26 -05:00
2024-03-10 16:49:07 -04:00
SetFields(disk.GetFieldValue<DiskArea?>(Disk.DiskAreaKey)! as DatItem);
2024-03-09 21:34:26 -05:00
if (!disk.PartSpecified)
2024-03-10 16:49:07 -04:00
disk.SetFieldValue<Part?>(Disk.PartKey, new Part());
2021-02-01 14:07:50 -08:00
2024-03-10 16:49:07 -04:00
SetFields(disk.GetFieldValue<Part?>(Disk.PartKey)! as DatItem);
2021-02-01 14:07:50 -08:00
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="input">Input to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Input input)
2021-02-01 14:07:50 -08:00
{
if (input.ControlsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (Control subControl in input.GetFieldValue<Control[]?>(Models.Metadata.Input.ControlKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subControl);
}
}
}
2024-03-05 02:20:12 -05:00
/// <summary>s
2021-02-01 14:07:50 -08:00
/// Set fields with given values
/// </summary>
/// <param name="part">Part to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Part part)
2021-02-01 14:07:50 -08:00
{
if (part.FeaturesSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (PartFeature subPartFeature in part.GetFieldValue<PartFeature[]?>(Models.Metadata.Part.FeatureKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subPartFeature);
}
}
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="port">Port to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Port port)
2021-02-01 14:07:50 -08:00
{
if (port.AnalogsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (Analog subAnalog in port.GetFieldValue<Analog[]?>(Models.Metadata.Port.AnalogKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subAnalog);
}
}
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="rom">Rom to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Rom rom)
2021-02-01 14:07:50 -08:00
{
2024-03-09 21:34:26 -05:00
if (!rom.DataAreaSpecified)
2024-03-10 16:49:07 -04:00
rom.SetFieldValue<DataArea?>(Rom.DataAreaKey, new DataArea());
2024-03-09 21:34:26 -05:00
2024-03-10 16:49:07 -04:00
SetFields(rom.GetFieldValue<DataArea?>(Rom.DataAreaKey)! as DatItem);
2024-03-09 21:34:26 -05:00
if (!rom.PartSpecified)
2024-03-10 16:49:07 -04:00
rom.SetFieldValue<Part?>(Rom.PartKey, new Part());
2021-02-01 14:07:50 -08:00
2024-03-10 16:49:07 -04:00
SetFields(rom.GetFieldValue<Part?>(Rom.PartKey)! as DatItem);
2021-02-01 14:07:50 -08:00
}
/// <summary>
/// Set fields with given values
/// </summary>
/// <param name="slot">Slot to remove replace fields in</param>
2025-02-24 09:54:06 -05:00
private void SetNestedFields(Slot slot)
2021-02-01 14:07:50 -08:00
{
if (slot.SlotOptionsSpecified)
{
2024-03-09 21:34:26 -05:00
foreach (SlotOption subSlotOption in slot.GetFieldValue<SlotOption[]?>(Models.Metadata.Slot.SlotOptionKey)!)
2021-02-01 14:07:50 -08:00
{
SetFields(subSlotOption);
}
}
}
}
}