diff --git a/SabreTools.Core/Filter/Enums.cs b/SabreTools.Core/Filter/Enums.cs new file mode 100644 index 00000000..7e893737 --- /dev/null +++ b/SabreTools.Core/Filter/Enums.cs @@ -0,0 +1,41 @@ +namespace SabreTools.Core.Filter +{ + /// + /// Determines how a filter group should be applied + /// + public enum GroupType + { + /// + /// Default value, does nothing + /// + NONE, + + /// + /// All must pass for the group to pass + /// + AND, + + /// + /// Any must pass for the group to pass + /// + OR, + } + + /// + /// Determines what operation is being done + /// + public enum Operation + { + /// + /// Default value, does nothing + /// + NONE, + + Equals, + NotEquals, + GreaterThan, + GreaterThanOrEqual, + LessThan, + LessThanOrEqual, + } +} \ No newline at end of file diff --git a/SabreTools.Core/Filter/FilterGroup.cs b/SabreTools.Core/Filter/FilterGroup.cs new file mode 100644 index 00000000..fa36765d --- /dev/null +++ b/SabreTools.Core/Filter/FilterGroup.cs @@ -0,0 +1,136 @@ +using System.Collections.Generic; +using SabreTools.Models.Metadata; + +namespace SabreTools.Core.Filter +{ + /// + /// Represents a set of filters and groups + /// + public class FilterGroup + { + /// + /// All standalone filters in the group + /// + public readonly List Subfilters = []; + + /// + /// All filter groups contained in the group + /// + public readonly List Subgroups = []; + + /// + /// How to apply the group filters + /// + public readonly GroupType GroupType; + + public FilterGroup(GroupType groupType) + { + GroupType = groupType; + } + + public FilterGroup(FilterObject[] filters, GroupType groupType) + { + Subfilters.AddRange(filters); + GroupType = groupType; + } + + public FilterGroup(FilterGroup[] groups, GroupType groupType) + { + Subgroups.AddRange(groups); + GroupType = groupType; + } + + public FilterGroup(FilterObject[] filters, FilterGroup[] groups, GroupType groupType) + { + Subfilters.AddRange(filters); + Subgroups.AddRange(groups); + GroupType = groupType; + } + + #region Matching + + /// + /// Determine if a DictionaryBase object matches the group + /// + public bool Matches(DictionaryBase dictionaryBase) + { + return GroupType switch + { + GroupType.AND => MatchesAnd(dictionaryBase), + GroupType.OR => MatchesOr(dictionaryBase), + _ => false, + }; + } + + /// + /// Determines if a value matches all filters + /// + private bool MatchesAnd(DictionaryBase dictionaryBase) + { + // Run standalone filters + foreach (var filter in Subfilters) + { + // One failed match fails the group + if (!filter.Matches(dictionaryBase)) + return false; + } + + // Run filter subgroups + foreach (var group in Subgroups) + { + // One failed match fails the group + if (!group.Matches(dictionaryBase)) + return false; + } + + return true; + } + + /// + /// Determines if a value matches any filters + /// + private bool MatchesOr(DictionaryBase dictionaryBase) + { + // Run standalone filters + foreach (var filter in Subfilters) + { + // One successful match passes the group + if (filter.Matches(dictionaryBase)) + return true; + } + + // Run filter subgroups + foreach (var group in Subgroups) + { + // One successful match passes the group + if (group.Matches(dictionaryBase)) + return true; + } + + return false; + } + + #endregion + + #region Helpers + + /// + /// Derive a group type from the input string, if possible + /// + private static GroupType GetGroupType(string? groupType) + { + return groupType?.ToLowerInvariant() switch + { + "&" => GroupType.AND, + "&&" => GroupType.AND, + + "|" => GroupType.OR, + "||" => GroupType.OR, + + _ => GroupType.NONE, + }; + } + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Core/Filter/FilterKey.cs b/SabreTools.Core/Filter/FilterKey.cs index e7321ee5..f7e1eefe 100644 --- a/SabreTools.Core/Filter/FilterKey.cs +++ b/SabreTools.Core/Filter/FilterKey.cs @@ -210,6 +210,5 @@ namespace SabreTools.Core.Filter string? constantMatch = Array.Find(constants, c => string.Equals(c, localFieldName, StringComparison.OrdinalIgnoreCase)); return constantMatch; } - } } \ No newline at end of file diff --git a/SabreTools.Core/Filter/Operation.cs b/SabreTools.Core/Filter/Operation.cs deleted file mode 100644 index 2de1cd82..00000000 --- a/SabreTools.Core/Filter/Operation.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace SabreTools.Core.Filter -{ - /// - /// Determines what operation is being done - /// - public enum Operation - { - /// - /// Default value, does nothing - /// - NONE, - - Equals, - NotEquals, - GreaterThan, - GreaterThanOrEqual, - LessThan, - LessThanOrEqual, - } -} \ No newline at end of file