diff --git a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs index f08bd09cf5..181b740729 100644 --- a/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs +++ b/osu.Game.Tests/NonVisual/Filtering/FilterQueryParserTest.cs @@ -138,6 +138,7 @@ namespace osu.Game.Tests.NonVisual.Filtering new object[] { "65m", TimeSpan.FromMinutes(65), TimeSpan.FromMinutes(1), true }, new object[] { "90s", TimeSpan.FromSeconds(90), TimeSpan.FromSeconds(1), true }, new object[] { "80m20s", TimeSpan.FromSeconds(4820), TimeSpan.FromSeconds(1), true }, + new object[] { "1h20s", TimeSpan.FromSeconds(3620), TimeSpan.FromSeconds(1), true }, new object[] { "7.5m27s", new TimeSpan(), new TimeSpan(), false }, new object[] { "7m27", new TimeSpan(), new TimeSpan(), false }, new object[] { "7m7m7m", new TimeSpan(), new TimeSpan(), false }, diff --git a/osu.Game/Screens/Select/FilterQueryParser.cs b/osu.Game/Screens/Select/FilterQueryParser.cs index b8c85c5ce0..19fb8665d2 100644 --- a/osu.Game/Screens/Select/FilterQueryParser.cs +++ b/osu.Game/Screens/Select/FilterQueryParser.cs @@ -129,6 +129,16 @@ namespace osu.Game.Screens.Select value = Enum.GetNames(typeof(TEnum)).FirstOrDefault(name => name.StartsWith(value, true, CultureInfo.InvariantCulture)); return Enum.TryParse(value, true, out result); } + private static bool tryMatchRegex(string value, string regex, ref GroupCollection result) + { + Match matchs = Regex.Match(value, regex); + if (matchs.Success) + { + result = matchs.Groups; + return true; + } + return false; + } /// /// Attempts to parse a keyword filter with the specified and textual . @@ -314,28 +324,22 @@ namespace osu.Game.Screens.Select private static bool tryUpdateLengthRange(FilterCriteria criteria, Operator op, string val) { List parts = new List(); + GroupCollection groups = null; - if (Regex.IsMatch(val, @"^\d+(:\d+){1,2}$")) // formats like 12:34 + if ( + tryMatchRegex(val, @"^((?\d+):)?(?\d+):(?\d+)$", ref groups) || + tryMatchRegex(val, @"^((?\d+(\.\d+)?)h)?((?\d+(\.\d+)?)m)?((?\d+(\.\d+)?)s)?$", ref groups) || + tryMatchRegex(val, @"^(?\d+(\.\d+)?)$", ref groups) + ) { - List splitted = val.Split(':').ToList(); - while (splitted.Count < 3) - splitted.Insert(0, "0"); - - parts.Add(splitted[2] + 's'); - parts.Add(splitted[1] + 'm'); - parts.Add(splitted[0] + 'h'); + if (groups["seconds"].Success) + parts.Add(groups["seconds"].Value + "s"); + if (groups["minutes"].Success) + parts.Add(groups["minutes"].Value + "m"); + if (groups["hours"].Success) + parts.Add(groups["hours"].Value + "h"); } - else if (Regex.IsMatch(val, @"^(\d+(\.\d+)?[hms]){1,3}$") && "hms".Contains(Regex.Replace(val, @"[\d\.]", ""))) // formats like 1h2m3s - { - string[] splitted = Regex.Split(val, @"(?<=[hms])").Where(x => x.Length > 0).Reverse().ToArray(); - parts.AddRange(splitted); - } - else if (Regex.IsMatch(val, @"^\d+(\.\d+)?$")) // only one number - { - parts.Add(val + 's'); - } - - if (parts.Count == 0) + else return false; double totalLength = 0;