From 92556db9cd8bae5df028a295338d8ad1065e2a55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 02:37:35 +0900 Subject: [PATCH 01/11] Add query-based filter modes to song select search field --- osu.Game/Beatmaps/BeatmapManager.cs | 1 + .../Select/Carousel/CarouselBeatmap.cs | 24 +++- osu.Game/Screens/Select/FilterControl.cs | 118 ++++++++++++++++-- osu.Game/Screens/Select/FilterCriteria.cs | 33 ++++- 4 files changed, 163 insertions(+), 13 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b9ed3664ef..02d7b2d98f 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -301,6 +301,7 @@ namespace osu.Game.Beatmaps var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.Ruleset = ruleset; + // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; beatmap.BeatmapInfo.Length = calculateLength(beatmap); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 712ab7b571..60e556a261 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -24,12 +24,26 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); - bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); + bool match = + criteria.Ruleset == null || + Beatmap.RulesetID == criteria.Ruleset.ID || + (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); - foreach (var criteriaTerm in criteria.SearchTerms) - match &= - Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || - Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; + match &= criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty); + match &= criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate); + match &= criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate); + match &= criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize); + match &= criteria.Length.IsInRange(Beatmap.Length); + match &= criteria.BPM.IsInRange(Beatmap.BPM); + + match &= !criteria.BeatDivisor.HasValue || criteria.BeatDivisor == Beatmap.BeatDivisor; + match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; + + if (match) + foreach (var criteriaTerm in criteria.SearchTerms) + match &= + Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || + Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; Filtered.Value = !match; } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index ed74b01fc9..01e7ed9383 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,6 +16,8 @@ using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Graphics.Shapes; using osu.Game.Configuration; using osu.Game.Rulesets; +using System.Text.RegularExpressions; +using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { @@ -33,14 +35,24 @@ namespace osu.Game.Screens.Select private Bindable groupMode; - public FilterCriteria CreateCriteria() => new FilterCriteria + public FilterCriteria CreateCriteria() { - Group = groupMode.Value, - Sort = sortMode.Value, - SearchText = searchTextBox.Text, - AllowConvertedBeatmaps = showConverted.Value, - Ruleset = ruleset.Value - }; + var query = searchTextBox.Text; + + var criteria = new FilterCriteria + { + Group = groupMode.Value, + Sort = sortMode.Value, + AllowConvertedBeatmaps = showConverted.Value, + Ruleset = ruleset.Value + }; + + applyQueries(criteria, ref query); + + criteria.SearchText = query; + + return criteria; + } public Action Exit; @@ -169,5 +181,97 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); + + private static readonly Regex query_syntax_regex = new Regex( + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[:><]+)(?\S*)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private void applyQueries(FilterCriteria criteria, ref string query) + { + foreach (Match match in query_syntax_regex.Matches(query)) + { + var key = match.Groups["key"].Value.ToLower(); + var op = match.Groups["op"].Value; + var value = match.Groups["value"].Value; + + switch (key) + { + case "stars" when double.TryParse(value, out var stars): + updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.5); + break; + + case "ar" when double.TryParse(value, out var ar): + updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.3); + break; + + case "dr" when double.TryParse(value, out var dr): + updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.3); + break; + + case "cs" when double.TryParse(value, out var cs): + updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.3); + break; + + case "bpm" when double.TryParse(value, out var bpm): + updateCriteriaRange(ref criteria.BPM, op, bpm, 0.3); + break; + + case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): + var scale = + value.EndsWith("ms") ? 1 : + value.EndsWith("s") ? 1000 : + value.EndsWith("m") ? 60000 : + value.EndsWith("h") ? 3600000 : 1000; + + updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); + break; + + case "divisor" when op == ":" && int.TryParse(value, out var divisor): + criteria.BeatDivisor = divisor; + break; + + case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): + criteria.OnlineStatus = statusValue; + break; + } + + query = query.Remove(match.Index, match.Length); + } + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double equalityToleration = 0) + { + switch (op) + { + default: + return; + + case ":": + range.IsInclusive = true; + range.Min = value - equalityToleration; + range.Max = value + equalityToleration; + break; + + case ">": + range.IsInclusive = false; + range.Min = value; + break; + + case ">:": + range.IsInclusive = true; + range.Min = value; + break; + + case "<": + range.IsInclusive = false; + range.Max = value; + break; + + case "<:": + range.IsInclusive = true; + range.Max = value; + break; + } + } } } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 140010ff54..84d63c16e0 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; @@ -13,6 +14,17 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; + public OptionalRange StarDifficulty; + public OptionalRange ApproachRate; + public OptionalRange DrainRate; + public OptionalRange CircleSize; + public OptionalRange Length; + public OptionalRange BPM; + + public int? BeatDivisor; + + public BeatmapSetOnlineStatus? OnlineStatus; + public string[] SearchTerms = Array.Empty(); public RulesetInfo Ruleset; @@ -26,8 +38,27 @@ namespace osu.Game.Screens.Select set { searchText = value; - SearchTerms = searchText.Split(',', ' ', '!').Where(s => !string.IsNullOrEmpty(s)).ToArray(); + SearchTerms = searchText.Split(new[] { ',', ' ', '!' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } } + + public struct OptionalRange : IEquatable + { + public bool IsInRange(double value) + { + if (Min.HasValue && (IsInclusive ? value < Min.Value : value <= Min.Value)) + return false; + if (Max.HasValue && (IsInclusive ? value > Max.Value : value >= Max.Value)) + return false; + + return true; + } + + public double? Min; + public double? Max; + public bool IsInclusive; + + public bool Equals(OptionalRange range) => Min == range.Min && Max == range.Max; + } } } From 80f46e02d8578ed0c23db9bb68bd7806f637663c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 15:33:49 +0900 Subject: [PATCH 02/11] Add equals (=) query operator variants --- osu.Game/Screens/Select/FilterControl.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 01e7ed9383..b25e65092e 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -183,7 +183,7 @@ namespace osu.Game.Screens.Select private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); private static readonly Regex query_syntax_regex = new Regex( - @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[:><]+)(?\S*)", + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[=:><]+)(?\S*)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private void applyQueries(FilterCriteria criteria, ref string query) @@ -246,6 +246,7 @@ namespace osu.Game.Screens.Select default: return; + case "=": case ":": range.IsInclusive = true; range.Min = value - equalityToleration; @@ -257,6 +258,7 @@ namespace osu.Game.Screens.Select range.Min = value; break; + case ">=": case ">:": range.IsInclusive = true; range.Min = value; @@ -267,6 +269,7 @@ namespace osu.Game.Screens.Select range.Max = value; break; + case "<=": case "<:": range.IsInclusive = true; range.Max = value; From c1daa187fe2aa68426341c6786b18bbee4c621df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 15:44:14 +0900 Subject: [PATCH 03/11] Reduce default tolerance --- osu.Game/Screens/Select/FilterControl.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b25e65092e..4c91208aec 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -197,23 +197,23 @@ namespace osu.Game.Screens.Select switch (key) { case "stars" when double.TryParse(value, out var stars): - updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.5); + updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; case "ar" when double.TryParse(value, out var ar): - updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.3); + updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; case "dr" when double.TryParse(value, out var dr): - updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.3); + updateCriteriaRange(ref criteria.DrainRate, op, dr); break; case "cs" when double.TryParse(value, out var cs): - updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.3); + updateCriteriaRange(ref criteria.CircleSize, op, cs); break; case "bpm" when double.TryParse(value, out var bpm): - updateCriteriaRange(ref criteria.BPM, op, bpm, 0.3); + updateCriteriaRange(ref criteria.BPM, op, bpm); break; case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double equalityToleration = 0) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { switch (op) { @@ -249,8 +249,8 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - range.Min = value - equalityToleration; - range.Max = value + equalityToleration; + range.Min = value - tolerance; + range.Max = value + tolerance; break; case ">": From 3c21b68b738af2d902341d934f4c34f920b5c5b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 16:51:57 +0900 Subject: [PATCH 04/11] Make OptionalRange generic --- osu.Game/Screens/Select/FilterControl.cs | 27 ++++++++---- osu.Game/Screens/Select/FilterCriteria.cs | 51 ++++++++++++++++------- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 4c91208aec..8fda6c6a97 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -196,19 +196,19 @@ namespace osu.Game.Screens.Select switch (key) { - case "stars" when double.TryParse(value, out var stars): + case "stars" when float.TryParse(value, out var stars): updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; - case "ar" when double.TryParse(value, out var ar): + case "ar" when float.TryParse(value, out var ar): updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; - case "dr" when double.TryParse(value, out var dr): + case "dr" when float.TryParse(value, out var dr): updateCriteriaRange(ref criteria.DrainRate, op, dr); break; - case "cs" when double.TryParse(value, out var cs): + case "cs" when float.TryParse(value, out var cs): updateCriteriaRange(ref criteria.CircleSize, op, cs); break; @@ -239,7 +239,8 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value, double tolerance = 0.05f) + where T : struct, IComparable { switch (op) { @@ -249,8 +250,20 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - range.Min = value - tolerance; - range.Max = value + tolerance; + + switch (value) + { + case float _: + range.Min = (T)(object)((float)(object)value - tolerance); + range.Max = (T)(object)((float)(object)value + tolerance); + break; + + case double _: + range.Min = (T)(object)((double)(object)value - tolerance); + range.Max = (T)(object)((double)(object)value + tolerance); + break; + } + break; case ">": diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 84d63c16e0..4867f27c0b 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -14,12 +14,12 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; - public OptionalRange StarDifficulty; - public OptionalRange ApproachRate; - public OptionalRange DrainRate; - public OptionalRange CircleSize; - public OptionalRange Length; - public OptionalRange BPM; + public OptionalRange StarDifficulty; + public OptionalRange ApproachRate; + public OptionalRange DrainRate; + public OptionalRange CircleSize; + public OptionalRange Length; + public OptionalRange BPM; public int? BeatDivisor; @@ -42,23 +42,44 @@ namespace osu.Game.Screens.Select } } - public struct OptionalRange : IEquatable + public struct OptionalRange : IEquatable> + where T : struct, IComparable { - public bool IsInRange(double value) + public bool IsInRange(T value) { - if (Min.HasValue && (IsInclusive ? value < Min.Value : value <= Min.Value)) - return false; - if (Max.HasValue && (IsInclusive ? value > Max.Value : value >= Max.Value)) - return false; + if (Min.HasValue) + { + int comparison = value.CompareTo(Min.Value); + + if (comparison < 0) + return false; + + if (!IsInclusive && comparison == 0) + return false; + } + + if (Max.HasValue) + { + int comparison = value.CompareTo(Max.Value); + + if (comparison > 0) + return false; + + if (!IsInclusive && comparison == 0) + return false; + } return true; } - public double? Min; - public double? Max; + public T? Min; + public T? Max; public bool IsInclusive; - public bool Equals(OptionalRange range) => Min == range.Min && Max == range.Max; + public bool Equals(OptionalRange other) + => Min.Equals(other.Min) + && Max.Equals(other.Max) + && IsInclusive.Equals(other.IsInclusive); } } } From 0915a94470bd67b3d1cdcabb21bd12c6d3e66373 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 16:53:27 +0900 Subject: [PATCH 05/11] Make BeatDivisor use OptionalRange --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- osu.Game/Screens/Select/FilterCriteria.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 60e556a261..7017310018 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.Length.IsInRange(Beatmap.Length); match &= criteria.BPM.IsInRange(Beatmap.BPM); - match &= !criteria.BeatDivisor.HasValue || criteria.BeatDivisor == Beatmap.BeatDivisor; + match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; if (match) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 8fda6c6a97..829f16d622 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -226,8 +226,8 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); break; - case "divisor" when op == ":" && int.TryParse(value, out var divisor): - criteria.BeatDivisor = divisor; + case "divisor" when int.TryParse(value, out var divisor): + updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 4867f27c0b..4584c63c2e 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -20,8 +20,7 @@ namespace osu.Game.Screens.Select public OptionalRange CircleSize; public OptionalRange Length; public OptionalRange BPM; - - public int? BeatDivisor; + public OptionalRange BeatDivisor; public BeatmapSetOnlineStatus? OnlineStatus; From 167bb9fcc16751087fc687d3424e7ea7cfafa555 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:11:28 +0900 Subject: [PATCH 06/11] Fix ugly casts --- osu.Game/Screens/Select/FilterControl.cs | 46 +++++++++++++++--------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 829f16d622..6ada0e4980 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -239,8 +239,36 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value, double tolerance = 0.05f) - where T : struct, IComparable + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) + { + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + + updateCriteriaRange(ref range, op, value); + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05f) + { + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + + updateCriteriaRange(ref range, op, value); + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) + where T : struct, IComparable { switch (op) { @@ -250,20 +278,6 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - - switch (value) - { - case float _: - range.Min = (T)(object)((float)(object)value - tolerance); - range.Max = (T)(object)((float)(object)value + tolerance); - break; - - case double _: - range.Min = (T)(object)((double)(object)value - tolerance); - range.Max = (T)(object)((double)(object)value + tolerance); - break; - } - break; case ">": From d7831d8f5d6cdced76b9ff070b1d0d55c932818b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:11:43 +0900 Subject: [PATCH 07/11] Use non-generic IComparable interface --- osu.Game/Screens/Select/FilterCriteria.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 4584c63c2e..ff55ef5b12 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -42,13 +43,13 @@ namespace osu.Game.Screens.Select } public struct OptionalRange : IEquatable> - where T : struct, IComparable + where T : struct, IComparable { public bool IsInRange(T value) { - if (Min.HasValue) + if (Min != null) { - int comparison = value.CompareTo(Min.Value); + int comparison = Comparer.Default.Compare(value, Min.Value); if (comparison < 0) return false; @@ -57,9 +58,9 @@ namespace osu.Game.Screens.Select return false; } - if (Max.HasValue) + if (Max != null) { - int comparison = value.CompareTo(Max.Value); + int comparison = Comparer.Default.Compare(value, Max.Value); if (comparison > 0) return false; From 7683f7ff23198fc782135b4959550abe13236c97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:12:07 +0900 Subject: [PATCH 08/11] Make OnlineStatus use OptionalRange --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- osu.Game/Screens/Select/FilterCriteria.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 7017310018..9cc84c8bdd 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.BPM.IsInRange(Beatmap.BPM); match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); - match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; + match &= criteria.OnlineStatus.IsInRange(Beatmap.Status); if (match) foreach (var criteriaTerm in criteria.SearchTerms) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 6ada0e4980..f1c8bb3a4e 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -230,8 +230,8 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; - case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): - criteria.OnlineStatus = statusValue; + case "status" when Enum.TryParse(value, true, out var statusValue): + updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); break; } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index ff55ef5b12..674f64efb4 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -22,8 +22,7 @@ namespace osu.Game.Screens.Select public OptionalRange Length; public OptionalRange BPM; public OptionalRange BeatDivisor; - - public BeatmapSetOnlineStatus? OnlineStatus; + public OptionalRange OnlineStatus; public string[] SearchTerms = Array.Empty(); From e075dd7ea84258862fac010f95e4a56d62d6ea0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:16:34 +0900 Subject: [PATCH 09/11] Fix equals operator not working --- osu.Game/Screens/Select/FilterControl.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index f1c8bb3a4e..cd958a9503 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -241,6 +241,8 @@ namespace osu.Game.Screens.Select private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) { + updateCriteriaRange(ref range, op, value); + switch (op) { case "=": @@ -249,12 +251,12 @@ namespace osu.Game.Screens.Select range.Max = value + tolerance; break; } - - updateCriteriaRange(ref range, op, value); } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05f) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { + updateCriteriaRange(ref range, op, value); + switch (op) { case "=": @@ -263,8 +265,6 @@ namespace osu.Game.Screens.Select range.Max = value + tolerance; break; } - - updateCriteriaRange(ref range, op, value); } private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) @@ -278,6 +278,8 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; + range.Min = value; + range.Max = value; break; case ">": From 96ea507320f6b10a9b902f5c1cc6f2df17a9c07a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:21:22 +0900 Subject: [PATCH 10/11] Reorder comparison for readability --- osu.Game/Screens/Select/FilterCriteria.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 674f64efb4..a3fa1b10ca 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select if (comparison < 0) return false; - if (!IsInclusive && comparison == 0) + if (comparison == 0 && !IsInclusive) return false; } @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select if (comparison > 0) return false; - if (!IsInclusive && comparison == 0) + if (comparison == 0 && !IsInclusive) return false; } From 5120d82ef84cba05df1b775cd1689b1e7d60a562 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:36:42 +0900 Subject: [PATCH 11/11] Fix crash with multiple range criterias --- osu.Game/Screens/Select/FilterControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index cd958a9503..e3c23f7e22 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -235,7 +235,7 @@ namespace osu.Game.Screens.Select break; } - query = query.Remove(match.Index, match.Length); + query = query.Replace(match.ToString(), ""); } }