mirror of https://github.com/ppy/osu
Update `OptionalSet` implementation to intersect across multiple filters rather than union
This commit is contained in:
parent
c24eb066dc
commit
e52d51cd0a
|
@ -114,17 +114,18 @@ public string SearchText
|
||||||
|
|
||||||
public IRulesetFilterCriteria? RulesetCriteria { get; set; }
|
public IRulesetFilterCriteria? RulesetCriteria { get; set; }
|
||||||
|
|
||||||
public struct OptionalSet<T> : IEquatable<OptionalSet<T>>
|
public readonly struct OptionalSet<T> : IEquatable<OptionalSet<T>>
|
||||||
where T : struct
|
where T : struct, Enum
|
||||||
{
|
{
|
||||||
public bool HasFilter => Values.Count > 0;
|
public bool HasFilter => true;
|
||||||
|
|
||||||
public bool IsInRange(T value) => Values.Contains(value);
|
public bool IsInRange(T value) => Values.Contains(value);
|
||||||
|
|
||||||
public HashSet<T> Values = new HashSet<T>();
|
public HashSet<T> Values { get; }
|
||||||
|
|
||||||
public OptionalSet()
|
public OptionalSet()
|
||||||
{
|
{
|
||||||
|
Values = Enum.GetValues<T>().ToHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(OptionalSet<T> other) => Values.SetEquals(other.Values);
|
public bool Equals(OptionalSet<T> other) => Values.SetEquals(other.Values);
|
||||||
|
|
|
@ -69,7 +69,7 @@ private static bool tryParseKeywordCriteria(FilterCriteria criteria, string key,
|
||||||
return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt);
|
return TryUpdateCriteriaRange(ref criteria.BeatDivisor, op, value, tryParseInt);
|
||||||
|
|
||||||
case "status":
|
case "status":
|
||||||
return TryUpdateCriteriaSet(ref criteria.OnlineStatus, op, value, tryParseEnum);
|
return TryUpdateCriteriaSet(ref criteria.OnlineStatus, op, value);
|
||||||
|
|
||||||
case "creator":
|
case "creator":
|
||||||
case "author":
|
case "author":
|
||||||
|
@ -302,54 +302,70 @@ public static bool TryUpdateCriteriaRange<T>(ref FilterCriteria.OptionalRange<T>
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to parse a keyword filter of type <typeparamref name="T"/>,
|
/// Attempts to parse a keyword filter of type <typeparamref name="T"/>,
|
||||||
/// from the specified <paramref name="op"/> and <paramref name="val"/>.
|
/// from the specified <paramref name="op"/> and <paramref name="filterValue"/>.
|
||||||
/// If <paramref name="val"/> can be parsed into <typeparamref name="T"/> using <paramref name="parseFunction"/>, the function returns <c>true</c>
|
/// If <paramref name="filterValue"/> can be parsed successfully, the function returns <c>true</c>
|
||||||
/// and the resulting range constraint is stored into the <paramref name="range"/>'s expected values.
|
/// and the resulting range constraint is stored into the <paramref name="range"/>'s expected values.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="range">The <see cref="FilterCriteria.OptionalSet{T}"/> to store the parsed data into, if successful.</param>
|
/// <param name="range">The <see cref="FilterCriteria.OptionalSet{T}"/> to store the parsed data into, if successful.</param>
|
||||||
/// <param name="op">The operator for the keyword filter.</param>
|
/// <param name="op">The operator for the keyword filter.</param>
|
||||||
/// <param name="val">The value of the keyword filter.</param>
|
/// <param name="filterValue">The value of the keyword filter.</param>
|
||||||
/// <param name="parseFunction">Function used to determine if <paramref name="val"/> can be converted to type <typeparamref name="T"/>.</param>
|
public static bool TryUpdateCriteriaSet<T>(ref FilterCriteria.OptionalSet<T> range, Operator op, string filterValue)
|
||||||
public static bool TryUpdateCriteriaSet<T>(ref FilterCriteria.OptionalSet<T> range, Operator op, string val, TryParseFunction<T> parseFunction)
|
|
||||||
where T : struct, Enum
|
|
||||||
=> parseFunction.Invoke(val, out var converted) && tryUpdateCriteriaSet(ref range, op, converted);
|
|
||||||
|
|
||||||
private static bool tryUpdateCriteriaSet<T>(ref FilterCriteria.OptionalSet<T> range, Operator op, T pivotValue)
|
|
||||||
where T : struct, Enum
|
where T : struct, Enum
|
||||||
{
|
{
|
||||||
var allDefinedValues = Enum.GetValues<T>();
|
var matchingValues = new HashSet<T>();
|
||||||
|
|
||||||
foreach (var val in allDefinedValues)
|
if (op == Operator.Equal && filterValue.Contains(','))
|
||||||
{
|
{
|
||||||
int compareResult = Comparer<T>.Default.Compare(val, pivotValue);
|
string[] splitValues = filterValue.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
|
||||||
switch (op)
|
foreach (string splitValue in splitValues)
|
||||||
{
|
{
|
||||||
case Operator.Less:
|
if (!tryParseEnum<T>(splitValue, out var parsedValue))
|
||||||
if (compareResult < 0) range.Values.Add(val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Operator.LessOrEqual:
|
|
||||||
if (compareResult <= 0) range.Values.Add(val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Operator.Equal:
|
|
||||||
if (compareResult == 0) range.Values.Add(val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Operator.GreaterOrEqual:
|
|
||||||
if (compareResult >= 0) range.Values.Add(val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Operator.Greater:
|
|
||||||
if (compareResult > 0) range.Values.Add(val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
matchingValues.Add(parsedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!tryParseEnum<T>(filterValue, out var pivotValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var allDefinedValues = Enum.GetValues<T>();
|
||||||
|
|
||||||
|
foreach (var val in allDefinedValues)
|
||||||
|
{
|
||||||
|
int compareResult = Comparer<T>.Default.Compare(val, pivotValue);
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case Operator.Less:
|
||||||
|
if (compareResult < 0) matchingValues.Add(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Operator.LessOrEqual:
|
||||||
|
if (compareResult <= 0) matchingValues.Add(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Operator.Equal:
|
||||||
|
if (compareResult == 0) matchingValues.Add(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Operator.GreaterOrEqual:
|
||||||
|
if (compareResult >= 0) matchingValues.Add(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Operator.Greater:
|
||||||
|
if (compareResult > 0) matchingValues.Add(val);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
range.Values.IntersectWith(matchingValues);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue