1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-27 06:29:54 +08:00

Adjust implementation of star rating filtering in song select to new star rating flooring behaviour

Required for things to not be broken after the previous change.
This commit is contained in:
Bartłomiej Dach
2025-06-13 08:58:01 +02:00
Unverified
parent 4fd2a488b7
commit eda489b911
5 changed files with 41 additions and 21 deletions
@@ -85,16 +85,6 @@ namespace osu.Game.Tests.NonVisual.Filtering
Assert.That(filterCriteria.SearchTerms[0].MatchMode, Is.EqualTo(FilterCriteria.MatchMode.IsolatedPhrase));
}
/*
* The following tests have been written a bit strangely (they don't check exact
* bound equality with what the filter says).
* This is to account for floating-point arithmetic issues.
* For example, specifying a bpm<140 filter would previously match beatmaps with BPM
* of 139.99999, which would be displayed in the UI as 140.
* Due to this the tests check the last tick inside the range and the first tick
* outside of the range.
*/
[TestCase("star")]
[TestCase("stars")]
public void TestApplyStarQueries(string variant)
@@ -105,11 +95,31 @@ namespace osu.Game.Tests.NonVisual.Filtering
Assert.AreEqual("easy", filterCriteria.SearchText.Trim());
Assert.AreEqual(1, filterCriteria.SearchTerms.Length);
Assert.IsNotNull(filterCriteria.StarDifficulty.Max);
Assert.Greater(filterCriteria.StarDifficulty.Max, 3.99d);
Assert.Less(filterCriteria.StarDifficulty.Max, 4.00d);
Assert.AreEqual(filterCriteria.StarDifficulty.Max, 4.00d);
Assert.IsNull(filterCriteria.StarDifficulty.Min);
}
[Test]
public void TestStarQueriesInclusive()
{
const string query = $"stars>=6";
var filterCriteria = new FilterCriteria();
FilterQueryParser.ApplyQueries(filterCriteria, query);
Assert.AreEqual(filterCriteria.StarDifficulty.Min, 6.00d);
Assert.True(filterCriteria.StarDifficulty.IsLowerInclusive);
Assert.IsNull(filterCriteria.StarDifficulty.Max);
}
/*
* The following tests have been written a bit strangely (they don't check exact
* bound equality with what the filter says).
* This is to account for floating-point arithmetic issues.
* For example, specifying a bpm<140 filter would previously match beatmaps with BPM
* of 139.99999, which would be displayed in the UI as 140.
* Due to this the tests check the last tick inside the range and the first tick
* outside of the range.
*/
[Test]
public void TestApplyApproachRateQueries()
{
@@ -5,6 +5,7 @@ using System;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Screens.Select.Filter;
using osu.Game.Utils;
namespace osu.Game.Screens.Select.Carousel
{
@@ -59,7 +60,7 @@ namespace osu.Game.Screens.Select.Carousel
if (!match) return false;
match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(BeatmapInfo.StarRating);
match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(BeatmapInfo.StarRating.FloorToDecimalDigits(2));
match &= !criteria.ApproachRate.HasFilter || criteria.ApproachRate.IsInRange(BeatmapInfo.Difficulty.ApproachRate);
match &= !criteria.DrainRate.HasFilter || criteria.DrainRate.IsInRange(BeatmapInfo.Difficulty.DrainRate);
match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(BeatmapInfo.Difficulty.CircleSize);
+7 -1
View File
@@ -41,7 +41,7 @@ namespace osu.Game.Screens.Select
case "star":
case "stars":
case "sr":
return TryUpdateCriteriaRange(ref criteria.StarDifficulty, op, value, 0.01d / 2);
return TryUpdateCriteriaRange(ref criteria.StarDifficulty, op, value, 0);
case "ar":
return TryUpdateCriteriaRange(ref criteria.ApproachRate, op, value);
@@ -309,6 +309,8 @@ namespace osu.Game.Screens.Select
case Operator.Equal:
range.Min = value - tolerance;
range.Max = value + tolerance;
if (tolerance == 0)
range.IsLowerInclusive = range.IsUpperInclusive = true;
break;
case Operator.Greater:
@@ -317,6 +319,8 @@ namespace osu.Game.Screens.Select
case Operator.GreaterOrEqual:
range.Min = value - tolerance;
if (tolerance == 0)
range.IsLowerInclusive = true;
break;
case Operator.Less:
@@ -325,6 +329,8 @@ namespace osu.Game.Screens.Select
case Operator.LessOrEqual:
range.Max = value + tolerance;
if (tolerance == 0)
range.IsUpperInclusive = true;
break;
}
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Carousel;
using osu.Game.Screens.Select;
using osu.Game.Utils;
namespace osu.Game.Screens.SelectV2
{
@@ -81,7 +82,7 @@ namespace osu.Game.Screens.SelectV2
if (!match) return false;
match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(beatmap.StarRating);
match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(beatmap.StarRating.FloorToDecimalDigits(2));
match &= !criteria.ApproachRate.HasFilter || criteria.ApproachRate.IsInRange(beatmap.Difficulty.ApproachRate);
match &= !criteria.DrainRate.HasFilter || criteria.DrainRate.IsInRange(beatmap.Difficulty.DrainRate);
match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(beatmap.Difficulty.CircleSize);
+8 -6
View File
@@ -10,6 +10,12 @@ namespace osu.Game.Utils
{
public static class FormatUtils
{
public static double FloorToDecimalDigits(this double value, uint digits)
{
double base10 = Math.Pow(10, digits);
return Math.Floor(value * base10) / base10;
}
/// <summary>
/// Turns the provided accuracy into a percentage with 2 decimal places.
/// </summary>
@@ -21,9 +27,7 @@ namespace osu.Game.Utils
// ie. a score which gets 89.99999% shouldn't ever show as 90%.
// the reasoning for this is that cutoffs for grade increases are at whole numbers and displaying the required
// percentile with a non-matching grade is confusing.
accuracy = Math.Floor(accuracy * 10000) / 10000;
return accuracy.ToLocalisableString("0.00%");
return accuracy.FloorToDecimalDigits(4).ToLocalisableString("0.00%");
}
/// <summary>
@@ -42,9 +46,7 @@ namespace osu.Game.Utils
// i.e. a beatmap which has a star rating of 6.9999* should never show as 7.00*.
// this matters for star rating medals which use hard cutoffs at whole numbers,
// which then confuses users when they beat a 6.9999* beatmap but don't get the 7-star medal.
starRating = Math.Floor(starRating * 100) / 100;
return starRating.ToLocalisableString("0.00");
return starRating.FloorToDecimalDigits(2).ToLocalisableString("0.00");
}
/// <summary>