1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 04:52:57 +08:00

Generalized tryUpdateLastPlayedRange to tryUpdateDateRange and Added tests

This commit is contained in:
Elvendir 2023-03-19 18:43:17 +01:00
parent 216a88e18d
commit 6dead81d21
2 changed files with 152 additions and 37 deletions

View File

@ -316,5 +316,87 @@ namespace osu.Game.Tests.NonVisual.Filtering
return false;
}
}
//Date criteria testing
private static readonly object[] correct_date_query_examples =
{
new object[] { "600" },
new object[] { "120:120" },
new object[] { "48:0:0" },
new object[] { "0.5s" },
new object[] { "120m" },
new object[] { "48h120s" },
new object[] { "10y24M" },
new object[] { "10y60d120s" },
new object[] { "0.1y0.1M2d" },
new object[] { "0.99y0.99M2d" }
};
[Test]
[TestCaseSource(nameof(correct_date_query_examples))]
public void TestValidDateQueries(string dateQuery)
{
string query = $"played={dateQuery} time";
var filterCriteria = new FilterCriteria();
FilterQueryParser.ApplyQueries(filterCriteria, query);
Assert.AreEqual(true, filterCriteria.LastPlayed.HasFilter);
}
private static readonly object[] incorrect_date_query_examples =
{
new object[] { "7m27" },
new object[] { "7m7m7m" },
new object[] { "5s6m" },
new object[] { "7d7y" },
new object[] { ":0" },
new object[] { "0:3:" },
new object[] { "\"three days\"" }
};
[Test]
[TestCaseSource(nameof(incorrect_date_query_examples))]
public void TestInvalidDateQueries(string dateQuery)
{
string query = $"played={dateQuery} time";
var filterCriteria = new FilterCriteria();
FilterQueryParser.ApplyQueries(filterCriteria, query);
Assert.AreEqual(false, filterCriteria.LastPlayed.HasFilter);
}
private static readonly object[] list_operators =
{
new object[] { "=", false, false, true, true },
new object[] { ":", false, false, true, true },
new object[] { "<", false, true, false, false },
new object[] { "<=", false, true, true, false },
new object[] { "<:", false, true, true, false },
new object[] { ">", true, false, false, false },
new object[] { ">=", true, false, false, true },
new object[] { ">:", true, false, false, true }
};
[Test]
[TestCaseSource(nameof(list_operators))]
public void TestComparisonDateQueries(string ope, bool minIsNull, bool maxIsNull, bool isLowerInclusive, bool isUpperInclusive)
{
string query = $"played{ope}50";
var filterCriteria = new FilterCriteria();
FilterQueryParser.ApplyQueries(filterCriteria, query);
Assert.AreEqual(isLowerInclusive, filterCriteria.LastPlayed.IsLowerInclusive);
Assert.AreEqual(isUpperInclusive, filterCriteria.LastPlayed.IsUpperInclusive);
Assert.AreEqual(maxIsNull, filterCriteria.LastPlayed.Max == null);
Assert.AreEqual(minIsNull, filterCriteria.LastPlayed.Min == null);
}
[Test]
public void TestOutofrangeDateQuery()
{
const string query = "played=10000y";
var filterCriteria = new FilterCriteria();
FilterQueryParser.ApplyQueries(filterCriteria, query);
Assert.AreEqual(true, filterCriteria.LastPlayed.HasFilter);
Assert.AreEqual(DateTimeOffset.MinValue.AddMilliseconds(1), filterCriteria.LastPlayed.Min);
}
}
}

View File

@ -63,7 +63,7 @@ namespace osu.Game.Screens.Select
case "played":
case "lastplayed":
return tryUpdateLastPlayedRange(criteria, op, value);
return tryUpdateDateRange(ref criteria.LastPlayed, op, value);
case "divisor":
return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt);
@ -374,59 +374,92 @@ namespace osu.Game.Screens.Select
return tryUpdateCriteriaRange(ref criteria.Length, op, totalLength, minScale / 2.0);
}
private static bool tryUpdateLastPlayedRange(FilterCriteria criteria, Operator op, string val)
private static bool tryUpdateDateRange(ref FilterCriteria.OptionalRange<DateTimeOffset> dateRange, Operator op, string val)
{
List<string> parts = new List<string>();
GroupCollection? match = null;
match ??= tryMatchRegex(val, @"^((?<hours>\d+):)?(?<minutes>\d+):(?<seconds>\d+)$");
match ??= tryMatchRegex(val, @"^((?<days>\d+(\.\d+)?)d)?((?<hours>\d+(\.\d+)?)h)?((?<minutes>\d+(\.\d+)?)m)?((?<seconds>\d+(\.\d+)?)s)?$");
match ??= tryMatchRegex(val, @"^((?<years>\d+(\.\d+)?)y)?((?<months>\d+(\.\d+)?)M)?((?<days>\d+(\.\d+)?)d)?((?<hours>\d+(\.\d+)?)h)?((?<minutes>\d+(\.\d+)?)m)?((?<seconds>\d+(\.\d+)?)s)?$");
match ??= tryMatchRegex(val, @"^(?<seconds>\d+(\.\d+)?)$");
if (match == null)
return false;
if (match["seconds"].Success)
parts.Add(match["seconds"].Value + "s");
if (match["minutes"].Success)
parts.Add(match["minutes"].Value + "m");
if (match["hours"].Success)
parts.Add(match["hours"].Value + "h");
if (match["days"].Success)
parts.Add(match["days"].Value + "d");
DateTimeOffset dateTimeOffset = DateTimeOffset.Now;
double totalLength = 0;
int minScale = 86400000;
for (int i = 0; i < parts.Count; i++)
try
{
string part = parts[i];
string partNoUnit = part.TrimEnd('m', 's', 'h', 'd');
if (!tryParseDoubleWithPoint(partNoUnit, out double length))
return false;
List<string> keys = new List<string> { "seconds", "minutes", "hours", "days", "months", "years" };
if (i != parts.Count - 1 && length >= 60)
return false;
if (i != 0 && partNoUnit.Contains('.'))
return false;
foreach (string key in keys)
{
if (match[key].Success)
{
if (!tryParseDoubleWithPoint(match[key].Value, out double length))
return false;
int scale = getLengthScale(part);
totalLength += length * scale;
minScale = Math.Min(minScale, scale);
switch (key)
{
case "seconds":
dateTimeOffset = dateTimeOffset.AddSeconds(-length);
break;
case "minutes":
dateTimeOffset = dateTimeOffset.AddMinutes(-length);
break;
case "hours":
dateTimeOffset = dateTimeOffset.AddHours(-length);
break;
case "days":
dateTimeOffset = dateTimeOffset.AddDays(-length);
break;
case "months":
dateTimeOffset = dateTimeOffset.AddMonths(-(int)Math.Round(length));
break;
case "years":
dateTimeOffset = dateTimeOffset.AddYears(-(int)Math.Round(length));
break;
}
}
}
}
// If DateTime to compare is out-scope put it to Min
catch (Exception)
{
dateTimeOffset = DateTimeOffset.MinValue;
dateTimeOffset = dateTimeOffset.AddMilliseconds(1);
}
totalLength += minScale / 2;
return tryUpdateCriteriaRange(ref dateRange, invert(op), dateTimeOffset);
}
// Limits the date to ~2000 years compared to now
// Might want to do it differently before 4000 A.C.
double limit = 86400000;
limit *= 365 * 2000;
totalLength = Math.Min(totalLength, limit);
// Function to reverse an Operator
private static Operator invert(Operator ope)
{
switch (ope)
{
default:
return Operator.Equal;
DateTimeOffset dateTimeOffset = DateTimeOffset.Now;
return tryUpdateCriteriaRange(ref criteria.LastPlayed, op, dateTimeOffset.AddMilliseconds(-totalLength));
case Operator.Equal:
return Operator.Equal;
case Operator.Greater:
return Operator.Less;
case Operator.GreaterOrEqual:
return Operator.LessOrEqual;
case Operator.Less:
return Operator.Greater;
case Operator.LessOrEqual:
return Operator.GreaterOrEqual;
}
}
}
}