1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-28 09:37:23 +08:00

Merge pull request #21140 from maromalo/long-standard

Standardise scores to `long` type
This commit is contained in:
Dan Balasescu 2022-11-18 15:26:33 +09:00 committed by GitHub
commit 219d049edf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 36 additions and 35 deletions

View File

@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Tests
AddAssert("player score matching expected bonus score", () => AddAssert("player score matching expected bonus score", () =>
{ {
// multipled by 2 to nullify the score multiplier. (autoplay mod selected) // multipled by 2 to nullify the score multiplier. (autoplay mod selected)
double totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2; long totalScore = ((ScoreExposedPlayer)Player).ScoreProcessor.TotalScore.Value * 2;
return totalScore == (int)(drawableSpinner.Result.RateAdjustedRotation / 360) * new SpinnerTick().CreateJudgement().MaxNumericResult; return totalScore == (int)(drawableSpinner.Result.RateAdjustedRotation / 360) * new SpinnerTick().CreateJudgement().MaxNumericResult;
}); });

View File

@ -35,7 +35,7 @@ namespace osu.Game.Tests.Gameplay
// Apply a miss judgement // Apply a miss judgement
scoreProcessor.ApplyResult(new JudgementResult(new HitObject(), new TestJudgement()) { Type = HitResult.Miss }); scoreProcessor.ApplyResult(new JudgementResult(new HitObject(), new TestJudgement()) { Type = HitResult.Miss });
Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(0.0)); Assert.That(scoreProcessor.TotalScore.Value, Is.EqualTo(0));
} }
[Test] [Test]

View File

@ -22,7 +22,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{ {
private TestGameplayLeaderboard leaderboard; private TestGameplayLeaderboard leaderboard;
private readonly BindableDouble playerScore = new BindableDouble(); private readonly BindableLong playerScore = new BindableLong();
public TestSceneGameplayLeaderboard() public TestSceneGameplayLeaderboard()
{ {
@ -76,8 +76,8 @@ namespace osu.Game.Tests.Visual.Gameplay
createLeaderboard(); createLeaderboard();
addLocalPlayer(); addLocalPlayer();
var player2Score = new BindableDouble(1234567); var player2Score = new BindableLong(1234567);
var player3Score = new BindableDouble(1111111); var player3Score = new BindableLong(1111111);
AddStep("add player 2", () => createLeaderboardScore(player2Score, new APIUser { Username = "Player 2" })); AddStep("add player 2", () => createLeaderboardScore(player2Score, new APIUser { Username = "Player 2" }));
AddStep("add player 3", () => createLeaderboardScore(player3Score, new APIUser { Username = "Player 3" })); AddStep("add player 3", () => createLeaderboardScore(player3Score, new APIUser { Username = "Player 3" }));
@ -161,9 +161,9 @@ namespace osu.Game.Tests.Visual.Gameplay
}); });
} }
private void createRandomScore(APIUser user) => createLeaderboardScore(new BindableDouble(RNG.Next(0, 5_000_000)), user); private void createRandomScore(APIUser user) => createLeaderboardScore(new BindableLong(RNG.Next(0, 5_000_000)), user);
private void createLeaderboardScore(BindableDouble score, APIUser user, bool isTracked = false) private void createLeaderboardScore(BindableLong score, APIUser user, bool isTracked = false)
{ {
var leaderboardScore = leaderboard.Add(user, isTracked); var leaderboardScore = leaderboard.Add(user, isTracked);
leaderboardScore.TotalScore.BindTo(score); leaderboardScore.TotalScore.BindTo(score);

View File

@ -11,7 +11,7 @@ using osu.Game.Graphics.Sprites;
namespace osu.Game.Graphics.UserInterface namespace osu.Game.Graphics.UserInterface
{ {
public abstract class ScoreCounter : RollingCounter<double> public abstract class ScoreCounter : RollingCounter<long>
{ {
protected override double RollingDuration => 1000; protected override double RollingDuration => 1000;
protected override Easing RollingEasing => Easing.Out; protected override Easing RollingEasing => Easing.Out;
@ -36,10 +36,10 @@ namespace osu.Game.Graphics.UserInterface
UpdateDisplay(); UpdateDisplay();
} }
protected override double GetProportionalDuration(double currentValue, double newValue) => protected override double GetProportionalDuration(long currentValue, long newValue) =>
currentValue > newValue ? currentValue - newValue : newValue - currentValue; currentValue > newValue ? currentValue - newValue : newValue - currentValue;
protected override LocalisableString FormatCount(double count) => ((long)count).ToLocalisableString(formatString); protected override LocalisableString FormatCount(long count) => count.ToLocalisableString(formatString);
protected override OsuSpriteText CreateSpriteText() protected override OsuSpriteText CreateSpriteText()
=> base.CreateSpriteText().With(s => s.Font = s.Font.With(fixedWidth: true)); => base.CreateSpriteText().With(s => s.Font = s.Font.With(fixedWidth: true));

View File

@ -31,7 +31,7 @@ namespace osu.Game.Online.API.Requests.Responses
public bool Passed { get; set; } public bool Passed { get; set; }
[JsonProperty("total_score")] [JsonProperty("total_score")]
public int TotalScore { get; set; } public long TotalScore { get; set; }
[JsonProperty("accuracy")] [JsonProperty("accuracy")]
public double Accuracy { get; set; } public double Accuracy { get; set; }
@ -213,7 +213,7 @@ namespace osu.Game.Online.API.Requests.Responses
public static SoloScoreInfo ForSubmission(ScoreInfo score) => new SoloScoreInfo public static SoloScoreInfo ForSubmission(ScoreInfo score) => new SoloScoreInfo
{ {
Rank = score.Rank, Rank = score.Rank,
TotalScore = (int)score.TotalScore, TotalScore = score.TotalScore,
Accuracy = score.Accuracy, Accuracy = score.Accuracy,
PP = score.PP, PP = score.PP,
MaxCombo = score.MaxCombo, MaxCombo = score.MaxCombo,

View File

@ -17,7 +17,7 @@ namespace osu.Game.Online.Rooms
/// The total scores in the playlist item. /// The total scores in the playlist item.
/// </summary> /// </summary>
[JsonProperty("total")] [JsonProperty("total")]
public int? TotalScores { get; set; } public long? TotalScores { get; set; }
/// <summary> /// <summary>
/// The user's score, if any. /// The user's score, if any.

View File

@ -26,7 +26,7 @@ namespace osu.Game.Online.Spectator
/// <summary> /// <summary>
/// The current total score. /// The current total score.
/// </summary> /// </summary>
public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; public readonly BindableLong TotalScore = new BindableLong { MinValue = 0 };
/// <summary> /// <summary>
/// The current accuracy. /// The current accuracy.

View File

@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Difficulty
// calculate total score // calculate total score
ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = perfectPlay.Mods; scoreProcessor.Mods.Value = perfectPlay.Mods;
perfectPlay.TotalScore = (long)scoreProcessor.ComputeScore(ScoringMode.Standardised, perfectPlay); perfectPlay.TotalScore = scoreProcessor.ComputeScore(ScoringMode.Standardised, perfectPlay);
// compute rank achieved // compute rank achieved
// default to SS, then adjust the rank with mods // default to SS, then adjust the rank with mods

View File

@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Scoring
/// <summary> /// <summary>
/// The current total score. /// The current total score.
/// </summary> /// </summary>
public readonly BindableDouble TotalScore = new BindableDouble { MinValue = 0 }; public readonly BindableLong TotalScore = new BindableLong { MinValue = 0 };
/// <summary> /// <summary>
/// The current accuracy. /// The current accuracy.
@ -267,7 +267,7 @@ namespace osu.Game.Rulesets.Scoring
private void updateScore() private void updateScore()
{ {
Accuracy.Value = currentMaximumScoringValues.BaseScore > 0 ? currentScoringValues.BaseScore / currentMaximumScoringValues.BaseScore : 1; Accuracy.Value = currentMaximumScoringValues.BaseScore > 0 ? (double)currentScoringValues.BaseScore / currentMaximumScoringValues.BaseScore : 1;
TotalScore.Value = ComputeScore(Mode.Value, currentScoringValues, maximumScoringValues); TotalScore.Value = ComputeScore(Mode.Value, currentScoringValues, maximumScoringValues);
} }
@ -298,7 +298,7 @@ namespace osu.Game.Rulesets.Scoring
/// <param name="scoreInfo">The <see cref="ScoreInfo"/> to compute the total score of.</param> /// <param name="scoreInfo">The <see cref="ScoreInfo"/> to compute the total score of.</param>
/// <returns>The total score in the given <see cref="ScoringMode"/>.</returns> /// <returns>The total score in the given <see cref="ScoringMode"/>.</returns>
[Pure] [Pure]
public double ComputeScore(ScoringMode mode, ScoreInfo scoreInfo) public long ComputeScore(ScoringMode mode, ScoreInfo scoreInfo)
{ {
if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset))
throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\".");
@ -316,9 +316,9 @@ namespace osu.Game.Rulesets.Scoring
/// <param name="maximum">The maximum scoring values.</param> /// <param name="maximum">The maximum scoring values.</param>
/// <returns>The total score computed from the given scoring values.</returns> /// <returns>The total score computed from the given scoring values.</returns>
[Pure] [Pure]
public double ComputeScore(ScoringMode mode, ScoringValues current, ScoringValues maximum) public long ComputeScore(ScoringMode mode, ScoringValues current, ScoringValues maximum)
{ {
double accuracyRatio = maximum.BaseScore > 0 ? current.BaseScore / maximum.BaseScore : 1; double accuracyRatio = maximum.BaseScore > 0 ? (double)current.BaseScore / maximum.BaseScore : 1;
double comboRatio = maximum.MaxCombo > 0 ? (double)current.MaxCombo / maximum.MaxCombo : 1; double comboRatio = maximum.MaxCombo > 0 ? (double)current.MaxCombo / maximum.MaxCombo : 1;
return ComputeScore(mode, accuracyRatio, comboRatio, current.BonusScore, maximum.CountBasicHitObjects); return ComputeScore(mode, accuracyRatio, comboRatio, current.BonusScore, maximum.CountBasicHitObjects);
} }
@ -333,21 +333,23 @@ namespace osu.Game.Rulesets.Scoring
/// <param name="totalBasicHitObjects">The total number of basic (non-tick and non-bonus) hitobjects in the beatmap.</param> /// <param name="totalBasicHitObjects">The total number of basic (non-tick and non-bonus) hitobjects in the beatmap.</param>
/// <returns>The total score computed from the given scoring component ratios.</returns> /// <returns>The total score computed from the given scoring component ratios.</returns>
[Pure] [Pure]
public double ComputeScore(ScoringMode mode, double accuracyRatio, double comboRatio, double bonusScore, int totalBasicHitObjects) public long ComputeScore(ScoringMode mode, double accuracyRatio, double comboRatio, long bonusScore, int totalBasicHitObjects)
{ {
double accuracyScore = accuracyPortion * accuracyRatio;
double comboScore = comboPortion * comboRatio;
double rawScore = (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
switch (mode) switch (mode)
{ {
default: default:
case ScoringMode.Standardised: case ScoringMode.Standardised:
double accuracyScore = accuracyPortion * accuracyRatio; return (long)Math.Round(rawScore);
double comboScore = comboPortion * comboRatio;
return (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
case ScoringMode.Classic: case ScoringMode.Classic:
// This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring. // This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring.
// The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes. // The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes.
double scaledStandardised = ComputeScore(ScoringMode.Standardised, accuracyRatio, comboRatio, bonusScore, totalBasicHitObjects) / max_score; double scaledRawScore = rawScore / max_score;
return Math.Pow(scaledStandardised * Math.Max(1, totalBasicHitObjects), 2) * ClassicScoreMultiplier; return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, totalBasicHitObjects), 2) * ClassicScoreMultiplier);
} }
} }
@ -417,7 +419,7 @@ namespace osu.Game.Rulesets.Scoring
score.MaximumStatistics[result] = maximumResultCounts.GetValueOrDefault(result); score.MaximumStatistics[result] = maximumResultCounts.GetValueOrDefault(result);
// Populate total score after everything else. // Populate total score after everything else.
score.TotalScore = (long)Math.Round(ComputeScore(ScoringMode.Standardised, score)); score.TotalScore = ComputeScore(ScoringMode.Standardised, score);
} }
/// <summary> /// <summary>

View File

@ -99,7 +99,7 @@ namespace osu.Game.Scoring
var scoreProcessor = ruleset.CreateScoreProcessor(); var scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = score.Mods; scoreProcessor.Mods.Value = score.Mods;
return (long)Math.Round(scoreProcessor.ComputeScore(mode, score)); return scoreProcessor.ComputeScore(mode, score);
} }
/// <summary> /// <summary>

View File

@ -20,13 +20,13 @@ namespace osu.Game.Scoring
/// The sum of all "basic" <see cref="HitObject"/> scoring values. See: <see cref="HitResultExtensions.IsBasic"/> and <see cref="Judgement.ToNumericResult"/>. /// The sum of all "basic" <see cref="HitObject"/> scoring values. See: <see cref="HitResultExtensions.IsBasic"/> and <see cref="Judgement.ToNumericResult"/>.
/// </summary> /// </summary>
[Key(0)] [Key(0)]
public double BaseScore; public long BaseScore;
/// <summary> /// <summary>
/// The sum of all "bonus" <see cref="HitObject"/> scoring values. See: <see cref="HitResultExtensions.IsBonus"/> and <see cref="Judgement.ToNumericResult"/>. /// The sum of all "bonus" <see cref="HitObject"/> scoring values. See: <see cref="HitResultExtensions.IsBonus"/> and <see cref="Judgement.ToNumericResult"/>.
/// </summary> /// </summary>
[Key(1)] [Key(1)]
public double BonusScore; public long BonusScore;
/// <summary> /// <summary>
/// The highest achieved combo. /// The highest achieved combo.

View File

@ -67,7 +67,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
{ {
await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false); await base.PrepareScoreForResultsAsync(score).ConfigureAwait(false);
Score.ScoreInfo.TotalScore = (int)Math.Round(ScoreProcessor.ComputeScore(ScoringMode.Standardised, Score.ScoreInfo)); Score.ScoreInfo.TotalScore = ScoreProcessor.ComputeScore(ScoringMode.Standardised, Score.ScoreInfo);
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -50,7 +50,7 @@ namespace osu.Game.Screens.Play.HUD
private OsuSpriteText positionText, scoreText, accuracyText, comboText, usernameText; private OsuSpriteText positionText, scoreText, accuracyText, comboText, usernameText;
public BindableDouble TotalScore { get; } = new BindableDouble(); public BindableLong TotalScore { get; } = new BindableLong();
public BindableDouble Accuracy { get; } = new BindableDouble(1); public BindableDouble Accuracy { get; } = new BindableDouble(1);
public BindableInt Combo { get; } = new BindableInt(); public BindableInt Combo { get; } = new BindableInt();
public BindableBool HasQuit { get; } = new BindableBool(); public BindableBool HasQuit { get; } = new BindableBool();

View File

@ -9,7 +9,7 @@ namespace osu.Game.Screens.Play.HUD
{ {
public interface ILeaderboardScore public interface ILeaderboardScore
{ {
BindableDouble TotalScore { get; } BindableLong TotalScore { get; }
BindableDouble Accuracy { get; } BindableDouble Accuracy { get; }
BindableInt Combo { get; } BindableInt Combo { get; }

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
@ -184,7 +183,7 @@ namespace osu.Game.Screens.Play.HUD
continue; continue;
if (TeamScores.TryGetValue(u.Team.Value, out var team)) if (TeamScores.TryGetValue(u.Team.Value, out var team))
team.Value += (int)Math.Round(u.ScoreProcessor.TotalScore.Value); team.Value += u.ScoreProcessor.TotalScore.Value;
} }
} }