From 8a2e840a835927fdc23e9638defac7aa2baaa96e Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 3 Sep 2020 00:48:07 -0700 Subject: [PATCH] Promote SharedFeature --- SabreTools.Library/DatFiles/ItemDictionary.cs | 12 + SabreTools.Library/DatFiles/Json.cs | 3 + SabreTools.Library/DatFiles/SabreDat.cs | 9 + SabreTools.Library/DatFiles/SoftwareList.cs | 33 ++- SabreTools.Library/DatItems/Auxiliary.cs | 21 -- SabreTools.Library/DatItems/DatItem.cs | 5 +- SabreTools.Library/DatItems/Enums.cs | 9 +- SabreTools.Library/DatItems/Machine.cs | 61 ----- SabreTools.Library/DatItems/SharedFeature.cs | 243 ++++++++++++++++++ SabreTools.Library/Filtering/Filter.cs | 38 +-- SabreTools.Library/Tools/Converters.cs | 29 +-- 11 files changed, 311 insertions(+), 152 deletions(-) create mode 100644 SabreTools.Library/DatItems/SharedFeature.cs diff --git a/SabreTools.Library/DatFiles/ItemDictionary.cs b/SabreTools.Library/DatFiles/ItemDictionary.cs index 0da179d9..7fa54108 100644 --- a/SabreTools.Library/DatFiles/ItemDictionary.cs +++ b/SabreTools.Library/DatFiles/ItemDictionary.cs @@ -209,6 +209,12 @@ namespace SabreTools.Library.DatFiles [JsonIgnore] public long SampleCount { get; private set; } = 0; + /// + /// Number of SharedFeature items + /// + [JsonIgnore] + public long SharedFeatureCount { get; private set; } = 0; + /// /// Number of Slot items /// @@ -650,6 +656,9 @@ namespace SabreTools.Library.DatFiles case ItemType.Sample: SampleCount++; break; + case ItemType.SharedFeature: + SharedFeatureCount++; + break; case ItemType.Slot: SlotCount++; break; @@ -830,6 +839,9 @@ namespace SabreTools.Library.DatFiles case ItemType.Sample: SampleCount--; break; + case ItemType.SharedFeature: + SharedFeatureCount--; + break; case ItemType.Slot: SlotCount--; break; diff --git a/SabreTools.Library/DatFiles/Json.cs b/SabreTools.Library/DatFiles/Json.cs index 67653989..e00c074f 100644 --- a/SabreTools.Library/DatFiles/Json.cs +++ b/SabreTools.Library/DatFiles/Json.cs @@ -292,6 +292,9 @@ namespace SabreTools.Library.DatFiles case ItemType.Setting: datItem = datItemObj.ToObject(); break; + case ItemType.SharedFeature: + datItem = datItemObj.ToObject(); + break; case ItemType.Slot: datItem = datItemObj.ToObject(); break; diff --git a/SabreTools.Library/DatFiles/SabreDat.cs b/SabreTools.Library/DatFiles/SabreDat.cs index aa5b281a..3bca42e1 100644 --- a/SabreTools.Library/DatFiles/SabreDat.cs +++ b/SabreTools.Library/DatFiles/SabreDat.cs @@ -1602,6 +1602,15 @@ namespace SabreTools.Library.DatFiles xtw.WriteEndElement(); break; + case ItemType.SharedFeature: + var sharedFeature = datItem as SharedFeature; + xtw.WriteStartElement("file"); + xtw.WriteAttributeString("type", "sharedfeat"); + xtw.WriteRequiredAttributeString("name", sharedFeature.Name); + xtw.WriteRequiredAttributeString("value", sharedFeature.Value); + xtw.WriteEndElement(); + break; + case ItemType.Slot: var slot = datItem as Slot; xtw.WriteStartElement("file"); diff --git a/SabreTools.Library/DatFiles/SoftwareList.cs b/SabreTools.Library/DatFiles/SoftwareList.cs index b7205504..ad5099af 100644 --- a/SabreTools.Library/DatFiles/SoftwareList.cs +++ b/SabreTools.Library/DatFiles/SoftwareList.cs @@ -180,17 +180,17 @@ namespace SabreTools.Library.DatFiles break; case "sharedfeat": - var sharedFeature = new SharedFeature + ParseAddHelper(new SharedFeature { Name = reader.GetAttribute("name"), Value = reader.GetAttribute("value"), - }; - // Ensure the list exists - if (machine.SharedFeatures == null) - machine.SharedFeatures = new List(); - - machine.SharedFeatures.Add(sharedFeature); + Source = new Source + { + Index = indexId, + Name = filename, + }, + }); reader.Read(); break; @@ -703,17 +703,6 @@ namespace SabreTools.Library.DatFiles xtw.WriteOptionalElementString("publisher", datItem.Machine.Publisher); xtw.WriteOptionalElementString("category", datItem.Machine.Category); - if (datItem.Machine.SharedFeatures != null && datItem.Machine.SharedFeatures.Count > 0) - { - foreach (SharedFeature kvp in datItem.Machine.SharedFeatures) - { - xtw.WriteStartElement("sharedfeat"); - xtw.WriteRequiredAttributeString("name", kvp.Name); - xtw.WriteRequiredAttributeString("value", kvp.Value); - xtw.WriteEndElement(); - } - } - xtw.Flush(); } catch (Exception ex) @@ -861,6 +850,14 @@ namespace SabreTools.Library.DatFiles // End dataarea xtw.WriteEndElement(); break; + + case ItemType.SharedFeature: + var sharedFeature = datItem as SharedFeature; + xtw.WriteStartElement("sharedfeat"); + xtw.WriteRequiredAttributeString("name", sharedFeature.Name); + xtw.WriteRequiredAttributeString("value", sharedFeature.Value); + xtw.WriteEndElement(); + break; } // End part diff --git a/SabreTools.Library/DatItems/Auxiliary.cs b/SabreTools.Library/DatItems/Auxiliary.cs index da3611ef..445b6d49 100644 --- a/SabreTools.Library/DatItems/Auxiliary.cs +++ b/SabreTools.Library/DatItems/Auxiliary.cs @@ -13,27 +13,6 @@ using SabreTools.Library.Tools; /// namespace SabreTools.Library.DatItems { - #region Machine - - #region SoftwareList - - /// - /// Represents one SoftwareList shared feature object - /// - [JsonObject("sharedfeat")] - public class SharedFeature - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("value")] - public string Value { get; set; } - } - - #endregion - - #endregion // Machine - #region DatItem #region OpenMSX diff --git a/SabreTools.Library/DatItems/DatItem.cs b/SabreTools.Library/DatItems/DatItem.cs index 6537ab8c..409b77fd 100644 --- a/SabreTools.Library/DatItems/DatItem.cs +++ b/SabreTools.Library/DatItems/DatItem.cs @@ -349,7 +349,6 @@ namespace SabreTools.Library.DatItems // SoftwareList Field.Machine_Supported, - Field.Machine_SharedFeatures, }; #endregion @@ -538,6 +537,9 @@ namespace SabreTools.Library.DatItems case ItemType.Setting: return new Setting(); + case ItemType.SharedFeature: + return new SharedFeature(); + case ItemType.Slot: return new Slot(); @@ -581,6 +583,7 @@ namespace SabreTools.Library.DatItems ItemType.Release => new Release(), ItemType.Rom => new Rom(), ItemType.Sample => new Sample(), + ItemType.SharedFeature => new SharedFeature(), ItemType.Slot => new Slot(), ItemType.SlotOption => new SlotOption(), ItemType.SoftwareList => new SoftwareList(), diff --git a/SabreTools.Library/DatItems/Enums.cs b/SabreTools.Library/DatItems/Enums.cs index 6403bcf2..a309c05a 100644 --- a/SabreTools.Library/DatItems/Enums.cs +++ b/SabreTools.Library/DatItems/Enums.cs @@ -221,11 +221,6 @@ namespace SabreTools.Library.DatItems Machine_Supported, - // SharedFeatures - Machine_SharedFeatures, // TODO: Fix usage of SharedFeatures - Machine_SharedFeature_Name, - Machine_SharedFeature_Value, - #endregion #endregion // Machine @@ -425,6 +420,9 @@ namespace SabreTools.Library.DatItems // Release DatItem_Language, + // SharedFeature + DatItem_SharedFeatureValue, + // Slot.SlotOptions DatItem_SlotOptions, DatItem_SlotOption_Name, @@ -498,6 +496,7 @@ namespace SabreTools.Library.DatItems Release, Sample, Setting, + SharedFeature, Slot, SlotOption, SoftwareList, diff --git a/SabreTools.Library/DatItems/Machine.cs b/SabreTools.Library/DatItems/Machine.cs index 6becc6cf..2aba8150 100644 --- a/SabreTools.Library/DatItems/Machine.cs +++ b/SabreTools.Library/DatItems/Machine.cs @@ -259,12 +259,6 @@ namespace SabreTools.Library.DatItems [JsonProperty("supported", DefaultValueHandling = DefaultValueHandling.Ignore)] public Supported Supported { get; set; } = Supported.NULL; - /// - /// List of shared feature items - /// - [JsonProperty("sharedfeat", DefaultValueHandling = DefaultValueHandling.Ignore)] - public List SharedFeatures { get; set; } = null; - #endregion #endregion @@ -515,7 +509,6 @@ namespace SabreTools.Library.DatItems #region SoftwareList Supported = this.Supported, - SharedFeatures = this.SharedFeatures, #endregion }; @@ -782,54 +775,6 @@ namespace SabreTools.Library.DatItems if (filter.Machine_Supported.MatchesNegative(Supported.NULL, Supported) == true) return false; - #region SharedFeatures - - // Machine_SharedFeatures - if (filter.Machine_SharedFeatures.MatchesNeutral(null, SharedFeatures?.Any() ?? false) == false) - return false; - - // Machine_SharedFeature_Name - if (SharedFeatures?.Any() == true) - { - bool anyPositive = false; - bool anyNegative = false; - - foreach (var sharedFeature in SharedFeatures) - { - if (filter.Machine_SharedFeature_Name.MatchesPositiveSet(sharedFeature?.Name) != false) - anyPositive = true; - if (filter.Machine_SharedFeature_Name.MatchesNegativeSet(sharedFeature?.Name) == true) - anyNegative = true; - } - - if (!anyPositive) - return false; - if (anyNegative) - return false; - } - - // Machine_SharedFeature_Value - if (SharedFeatures?.Any() == true) - { - bool anyPositive = false; - bool anyNegative = false; - - foreach (var sharedFeature in SharedFeatures) - { - if (filter.Machine_SharedFeature_Value.MatchesPositiveSet(sharedFeature?.Value) != false) - anyPositive = true; - if (filter.Machine_SharedFeature_Value.MatchesNegativeSet(sharedFeature?.Value) == true) - anyNegative = true; - } - - if (!anyPositive) - return false; - if (anyNegative) - return false; - } - - #endregion - #endregion // SoftwareList return true; @@ -973,9 +918,6 @@ namespace SabreTools.Library.DatItems if (fields.Contains(Field.Machine_Supported)) Supported = Supported.NULL; - if (fields.Contains(Field.Machine_SharedFeatures)) - SharedFeatures = null; - #endregion } @@ -1126,9 +1068,6 @@ namespace SabreTools.Library.DatItems if (fields.Contains(Field.Machine_Supported)) Supported = machine.Supported; - if (fields.Contains(Field.Machine_SharedFeatures)) - SharedFeatures = machine.SharedFeatures; - #endregion } diff --git a/SabreTools.Library/DatItems/SharedFeature.cs b/SabreTools.Library/DatItems/SharedFeature.cs new file mode 100644 index 00000000..62ba583c --- /dev/null +++ b/SabreTools.Library/DatItems/SharedFeature.cs @@ -0,0 +1,243 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using SabreTools.Library.Filtering; +using Newtonsoft.Json; +using SabreTools.Library.Tools; + +namespace SabreTools.Library.DatItems +{ + /// + /// Represents one shared feature object + /// + [JsonObject("sharedfeat")] + public class SharedFeature : DatItem + { + #region Fields + + /// + /// Name of the item + /// + [JsonProperty("name")] + public string Name { get; set; } + + /// + /// SharedFeature value + /// + [JsonProperty("value")] + public string SharedFeatureValue { get; set; } + + #endregion + + #region Accessors + + /// + /// Gets the name to use for a DatItem + /// + /// Name if available, null otherwise + public override string GetName() + { + return Name; + } + + /// + /// Set fields with given values + /// + /// Mappings dictionary + public override void SetFields(Dictionary mappings) + { + // Set base fields + base.SetFields(mappings); + + // Handle SharedFeature-specific fields + if (mappings.Keys.Contains(Field.DatItem_Name)) + Name = mappings[Field.DatItem_Name]; + + if (mappings.Keys.Contains(Field.DatItem_SharedFeatureValue)) + SharedFeatureValue = mappings[Field.DatItem_SharedFeatureValue]; + } + + #endregion + + #region Constructors + + /// + /// Create a default, empty SharedFeature object + /// + public SharedFeature() + { + Name = string.Empty; + ItemType = ItemType.SharedFeature; + } + + #endregion + + #region Cloning Methods + + public override object Clone() + { + return new SharedFeature() + { + Name = this.Name, + ItemType = this.ItemType, + DupeType = this.DupeType, + + AltName = this.AltName, + AltTitle = this.AltTitle, + + Original = this.Original, + OpenMSXSubType = this.OpenMSXSubType, + OpenMSXType = this.OpenMSXType, + Remark = this.Remark, + Boot = this.Boot, + + Part = this.Part, + Features = this.Features, + AreaName = this.AreaName, + AreaSize = this.AreaSize, + AreaWidth = this.AreaWidth, + AreaEndianness = this.AreaEndianness, + Value = this.Value, + LoadFlag = this.LoadFlag, + + Machine = this.Machine.Clone() as Machine, + Source = this.Source.Clone() as Source, + Remove = this.Remove, + + SharedFeatureValue = this.SharedFeatureValue, + }; + } + + #endregion + + #region Comparision Methods + + public override bool Equals(DatItem other) + { + // If we don't have a sample, return false + if (ItemType != other.ItemType) + return false; + + // Otherwise, treat it as a SharedFeature + SharedFeature newOther = other as SharedFeature; + + // If the archive information matches + return (Name == newOther.Name && SharedFeatureValue == newOther.SharedFeatureValue); + } + + #endregion + + #region Filtering + + /// + /// Clean a DatItem according to the cleaner + /// + /// Cleaner to implement + public override void Clean(Cleaner cleaner) + { + // Clean common items first + base.Clean(cleaner); + + // If we're stripping unicode characters, strip item name + if (cleaner?.RemoveUnicode == true) + Name = Sanitizer.RemoveUnicodeCharacters(Name); + + // If we are in NTFS trim mode, trim the game name + if (cleaner?.Trim == true) + { + // Windows max name length is 260 + int usableLength = 260 - Machine.Name.Length - (cleaner.Root?.Length ?? 0); + if (Name.Length > usableLength) + { + string ext = Path.GetExtension(Name); + Name = Name.Substring(0, usableLength - ext.Length); + Name += ext; + } + } + } + + /// + /// Check to see if a DatItem passes the filter + /// + /// Filter to check against + /// True if the item passed the filter, false otherwise + public override bool PassesFilter(Filter filter) + { + // Check common fields first + if (!base.PassesFilter(filter)) + return false; + + // Filter on item name + if (filter.DatItem_Name.MatchesPositiveSet(Name) == false) + return false; + if (filter.DatItem_Name.MatchesNegativeSet(Name) == true) + return false; + + // Filter on info value + if (filter.DatItem_SharedFeatureValue.MatchesPositiveSet(SharedFeatureValue) == false) + return false; + if (filter.DatItem_SharedFeatureValue.MatchesNegativeSet(SharedFeatureValue) == true) + return false; + + return true; + } + + /// + /// Remove fields from the DatItem + /// + /// List of Fields to remove + public override void RemoveFields(List fields) + { + // Remove common fields first + base.RemoveFields(fields); + + // Remove the fields + if (fields.Contains(Field.DatItem_Name)) + Name = null; + + if (fields.Contains(Field.DatItem_SharedFeatureValue)) + SharedFeatureValue = null; + } + + /// + /// Set internal names to match One Rom Per Game (ORPG) logic + /// + public override void SetOneRomPerGame() + { + string[] splitname = Name.Split('.'); + Machine.Name += $"/{string.Join(".", splitname.Take(splitname.Length > 1 ? splitname.Length - 1 : 1))}"; + Name = Path.GetFileName(Name); + } + + #endregion + + #region Sorting and Merging + + /// + /// Replace fields from another item + /// + /// DatItem to pull new information from + /// List of Fields representing what should be updated + public override void ReplaceFields(DatItem item, List fields) + { + // Replace common fields first + base.ReplaceFields(item, fields); + + // If we don't have a SharedFeature to replace from, ignore specific fields + if (item.ItemType != ItemType.SharedFeature) + return; + + // Cast for easier access + SharedFeature newItem = item as SharedFeature; + + // Replace the fields + if (fields.Contains(Field.DatItem_Name)) + Name = newItem.Name; + + if (fields.Contains(Field.DatItem_SharedFeatureValue)) + SharedFeatureValue = newItem.SharedFeatureValue; + } + + #endregion + } +} diff --git a/SabreTools.Library/Filtering/Filter.cs b/SabreTools.Library/Filtering/Filter.cs index 2c8db4a4..8ee3af89 100644 --- a/SabreTools.Library/Filtering/Filter.cs +++ b/SabreTools.Library/Filtering/Filter.cs @@ -86,11 +86,6 @@ namespace SabreTools.Library.Filtering public FilterItem Machine_Supported { get; private set; } = new FilterItem() { Positive = Supported.NULL, Negative = Supported.NULL }; - // SharedFeatures - public FilterItem Machine_SharedFeatures { get; private set; } = new FilterItem() { Neutral = null }; - public FilterItem Machine_SharedFeature_Name { get; private set; } = new FilterItem(); - public FilterItem Machine_SharedFeature_Value { get; private set; } = new FilterItem(); - #endregion #endregion // Machine Filters @@ -290,6 +285,9 @@ namespace SabreTools.Library.Filtering // Release public FilterItem DatItem_Language { get; private set; } = new FilterItem(); + // SharedFeature + public FilterItem DatItem_SharedFeatureValue { get; private set; } = new FilterItem(); + // Slots.SlotOptions public FilterItem DatItem_SlotOptions { get; private set; } = new FilterItem() { Neutral = null }; public FilterItem DatItem_SlotOption_Name { get; private set; } = new FilterItem(); @@ -651,28 +649,6 @@ namespace SabreTools.Library.Filtering Machine_Supported.Positive |= value.AsSupported(); break; - // SharedFeatures - case Field.Machine_SharedFeatures: - if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase)) - Machine_SharedFeatures.Neutral = false; - else - Machine_SharedFeatures.Neutral = true; - break; - - case Field.Machine_SharedFeature_Name: - if (negate) - Machine_SharedFeature_Name.NegativeSet.Add(value); - else - Machine_SharedFeature_Name.PositiveSet.Add(value); - break; - - case Field.Machine_SharedFeature_Value: - if (negate) - Machine_SharedFeature_Value.NegativeSet.Add(value); - else - Machine_SharedFeature_Value.PositiveSet.Add(value); - break; - #endregion #endregion // Machine Filters @@ -1627,6 +1603,14 @@ namespace SabreTools.Library.Filtering DatItem_Language.PositiveSet.Add(value); break; + // SharedFeature + case Field.DatItem_SharedFeatureValue: + if (negate) + DatItem_SharedFeatureValue.NegativeSet.Add(value); + else + DatItem_SharedFeatureValue.PositiveSet.Add(value); + break; + // Slots.SlotOptions case Field.DatItem_SlotOptions: if (negate || value.Equals("false", StringComparison.OrdinalIgnoreCase)) diff --git a/SabreTools.Library/Tools/Converters.cs b/SabreTools.Library/Tools/Converters.cs index 21b09fe7..4e2b5c3d 100644 --- a/SabreTools.Library/Tools/Converters.cs +++ b/SabreTools.Library/Tools/Converters.cs @@ -644,15 +644,6 @@ namespace SabreTools.Library.Tools case "supported": return Field.Machine_Supported; - case "sharedfeatures": - return Field.Machine_SharedFeatures; - - case "sharedfeature_name": - return Field.Machine_SharedFeature_Name; - - case "sharedfeature_value": - return Field.Machine_SharedFeature_Value; - #endregion } } @@ -1106,6 +1097,10 @@ namespace SabreTools.Library.Tools case "language": return Field.DatItem_Language; + // SharedFeature + case "sharedfeaturevalue": + return Field.DatItem_SharedFeatureValue; + // Slot case "slotoptions": return Field.DatItem_SlotOptions; @@ -1325,16 +1320,6 @@ namespace SabreTools.Library.Tools case "supported": return Field.Machine_Supported; - case "sharedfeat": - case "shared feat": - case "shared-feat": - case "sharedfeature": - case "shared feature": - case "shared-feature": - case "sharedfeatures": - case "shared features": - case "shared-features": - return Field.Machine_SharedFeatures; #endregion @@ -1687,6 +1672,8 @@ namespace SabreTools.Library.Tools return ItemType.Sample; case "setting": return ItemType.Setting; + case "sharedfeat": + return ItemType.SharedFeature; case "slot": return ItemType.Slot; case "slotoption": @@ -1729,6 +1716,7 @@ namespace SabreTools.Library.Tools "rom" => ItemType.Rom, "sample" => ItemType.Sample, "setting" => ItemType.Setting, + "sharedfeat" => ItemType.SharedFeature, "slot" => ItemType.Slot, "slotoption" => ItemType.SlotOption, "softwarelist" => ItemType.SoftwareList, @@ -2331,6 +2319,8 @@ namespace SabreTools.Library.Tools return "sample"; case ItemType.Setting: return "setting"; + case ItemType.SharedFeature: + return "sharedfeat"; case ItemType.Slot: return "slot"; case ItemType.SlotOption: @@ -2373,6 +2363,7 @@ namespace SabreTools.Library.Tools ItemType.Rom => "rom", ItemType.Sample => "sample", ItemType.Setting => "setting", + ItemType.SharedFeature => "sharedfeat", ItemType.Slot => "slot", ItemType.SlotOption => "slotoption", ItemType.SoftwareList => "softwarelist",