From 4fd2a488b7a8b4158e7a610cc3cf92efbe4a6ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 13 Jun 2025 08:39:49 +0200 Subject: [PATCH] Floor star rating to 2 decimal places rather than rounding Rounding semi-regularly confuses users who aim for star rating pass / FC medals and then feel they have been cheated out of a medal because they passed an "X-star beatmap", but the actual star rating of the beatmap is slightly under X. The latest instance of this can be found at https://osu.ppy.sh/community/forums/topics/2091333?n=2. The relevant beatmap there is https://osu.ppy.sh/beatmapsets/2162554#osu/4746232, whose raw star rating is 6.9976070253117344. The other direction would be to fix the star rating medals instead, but I think this is more reasonable given we already do similar things to accuracy displays. --- osu.Game.Tests/NonVisual/FormatUtilsTest.cs | 13 +++++++++++++ osu.Game/Utils/FormatUtils.cs | 11 ++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/NonVisual/FormatUtilsTest.cs b/osu.Game.Tests/NonVisual/FormatUtilsTest.cs index a12658bd8b..0fcf754cf6 100644 --- a/osu.Game.Tests/NonVisual/FormatUtilsTest.cs +++ b/osu.Game.Tests/NonVisual/FormatUtilsTest.cs @@ -21,5 +21,18 @@ namespace osu.Game.Tests.NonVisual { Assert.AreEqual(expectedOutput, input.FormatAccuracy().ToString()); } + + [TestCase(3, "3.00")] + [TestCase(3.3, "3.30")] + [TestCase(3.55, "3.55")] + [TestCase(3.553, "3.55")] + [TestCase(3.557, "3.55")] + [TestCase(3.9999, "3.99")] + [TestCase(3.999999, "3.99")] + [TestCase(4, "4.00")] + public void TestStarRatingFormatting(double input, string expectedOutput) + { + Assert.AreEqual(expectedOutput, input.FormatStarRating().ToString()); + } } } diff --git a/osu.Game/Utils/FormatUtils.cs b/osu.Game/Utils/FormatUtils.cs index f7250c6833..fa7d6595e9 100644 --- a/osu.Game/Utils/FormatUtils.cs +++ b/osu.Game/Utils/FormatUtils.cs @@ -36,7 +36,16 @@ namespace osu.Game.Utils /// Formats the supplied star rating in a consistent, simplified way. /// /// The star rating to be formatted. - public static LocalisableString FormatStarRating(this double starRating) => starRating.ToLocalisableString("0.00"); + public static LocalisableString FormatStarRating(this double starRating) + { + // for the sake of display purposes, we don't want to show a user a "rounded up" star rating to the next whole number. + // 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"); + } /// /// Finds the number of digits after the decimal.