Move score calculation to ScoreManager

This commit is contained in:
smoogipoo
2021-08-30 19:33:09 +09:00
parent b217dd1a65
commit d03950fb37

View File

@ -34,6 +34,7 @@ namespace osu.Game.Scoring
protected override string ImportFromStablePath => Path.Combine("Data", "r"); protected override string ImportFromStablePath => Path.Combine("Data", "r");
private readonly Bindable<ScoringMode> scoringMode = new Bindable<ScoringMode>();
private readonly RulesetStore rulesets; private readonly RulesetStore rulesets;
private readonly Func<BeatmapManager> beatmaps; private readonly Func<BeatmapManager> beatmaps;
@ -51,6 +52,8 @@ namespace osu.Game.Scoring
this.beatmaps = beatmaps; this.beatmaps = beatmaps;
this.difficulties = difficulties; this.difficulties = difficulties;
this.configManager = configManager; this.configManager = configManager;
configManager?.BindWith(OsuSetting.ScoreDisplayMode, scoringMode);
} }
protected override ScoreInfo CreateModel(ArchiveReader archive) protected override ScoreInfo CreateModel(ArchiveReader archive)
@ -113,7 +116,7 @@ namespace osu.Game.Scoring
/// <returns>The bindable containing the total score.</returns> /// <returns>The bindable containing the total score.</returns>
public Bindable<long> GetBindableTotalScore(ScoreInfo score) public Bindable<long> GetBindableTotalScore(ScoreInfo score)
{ {
var bindable = new TotalScoreBindable(score, difficulties); var bindable = new TotalScoreBindable(score, this);
configManager?.BindWith(OsuSetting.ScoreDisplayMode, bindable.ScoringMode); configManager?.BindWith(OsuSetting.ScoreDisplayMode, bindable.ScoringMode);
return bindable; return bindable;
} }
@ -128,42 +131,12 @@ namespace osu.Game.Scoring
/// <returns>The bindable containing the formatted total score string.</returns> /// <returns>The bindable containing the formatted total score string.</returns>
public Bindable<string> GetBindableTotalScoreString(ScoreInfo score) => new TotalScoreStringBindable(GetBindableTotalScore(score)); public Bindable<string> GetBindableTotalScoreString(ScoreInfo score) => new TotalScoreStringBindable(GetBindableTotalScore(score));
/// <summary> public long GetTotalScore(ScoreInfo score) => GetTotalScoreAsync(score).Result;
/// Provides the total score of a <see cref="ScoreInfo"/>. Responds to changes in the currently-selected <see cref="ScoringMode"/>.
/// </summary> public async Task<long> GetTotalScoreAsync(ScoreInfo score, CancellationToken cancellationToken = default)
private class TotalScoreBindable : Bindable<long>
{ {
public readonly Bindable<ScoringMode> ScoringMode = new Bindable<ScoringMode>();
private readonly ScoreInfo score;
private readonly Func<BeatmapDifficultyCache> difficulties;
/// <summary>
/// Creates a new <see cref="TotalScoreBindable"/>.
/// </summary>
/// <param name="score">The <see cref="ScoreInfo"/> to provide the total score of.</param>
/// <param name="difficulties">A function to retrieve the <see cref="BeatmapDifficultyCache"/>.</param>
public TotalScoreBindable(ScoreInfo score, Func<BeatmapDifficultyCache> difficulties)
{
this.score = score;
this.difficulties = difficulties;
ScoringMode.BindValueChanged(onScoringModeChanged, true);
}
private IBindable<StarDifficulty?> difficultyBindable;
private CancellationTokenSource difficultyCancellationSource;
private void onScoringModeChanged(ValueChangedEvent<ScoringMode> mode)
{
difficultyCancellationSource?.Cancel();
difficultyCancellationSource = null;
if (score.Beatmap == null) if (score.Beatmap == null)
{ return score.TotalScore;
Value = score.TotalScore;
return;
}
int beatmapMaxCombo; int beatmapMaxCombo;
double accuracy = score.Accuracy; double accuracy = score.Accuracy;
@ -183,27 +156,20 @@ namespace osu.Game.Scoring
// This score is guaranteed to be an osu!stable score. // This score is guaranteed to be an osu!stable score.
// The combo must be determined through either the beatmap's max combo value or the difficulty calculator, as lazer's scoring has changed and the score statistics cannot be used. // The combo must be determined through either the beatmap's max combo value or the difficulty calculator, as lazer's scoring has changed and the score statistics cannot be used.
if (score.Beatmap.MaxCombo == null) if (score.Beatmap.MaxCombo != null)
beatmapMaxCombo = score.Beatmap.MaxCombo.Value;
else
{ {
if (score.Beatmap.ID == 0 || difficulties == null) if (score.Beatmap.ID == 0 || difficulties == null)
{ {
// We don't have enough information (max combo) to compute the score, so use the provided score. // We don't have enough information (max combo) to compute the score, so use the provided score.
Value = score.TotalScore; return score.TotalScore;
return;
} }
// We can compute the max combo locally after the async beatmap difficulty computation. // We can compute the max combo locally after the async beatmap difficulty computation.
difficultyBindable = difficulties().GetBindableDifficulty(score.Beatmap, score.Ruleset, score.Mods, (difficultyCancellationSource = new CancellationTokenSource()).Token); var difficulty = await difficulties().GetDifficultyAsync(score.Beatmap, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false);
difficultyBindable.BindValueChanged(d => beatmapMaxCombo = difficulty.MaxCombo;
{
if (d.NewValue is StarDifficulty diff)
updateScore(diff.MaxCombo, accuracy);
}, true);
return;
} }
beatmapMaxCombo = score.Beatmap.MaxCombo.Value;
} }
else else
{ {
@ -212,23 +178,47 @@ namespace osu.Game.Scoring
beatmapMaxCombo = Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetValueOrDefault(r)).Sum(); beatmapMaxCombo = Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetValueOrDefault(r)).Sum();
} }
updateScore(beatmapMaxCombo, accuracy);
}
private void updateScore(int beatmapMaxCombo, double accuracy)
{
if (beatmapMaxCombo == 0) if (beatmapMaxCombo == 0)
{ return 0;
Value = 0;
return;
}
var ruleset = score.Ruleset.CreateInstance(); var ruleset = score.Ruleset.CreateInstance();
var scoreProcessor = ruleset.CreateScoreProcessor(); var scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = score.Mods; scoreProcessor.Mods.Value = score.Mods;
Value = (long)Math.Round(scoreProcessor.GetScore(ScoringMode.Value, beatmapMaxCombo, accuracy, (double)score.MaxCombo / beatmapMaxCombo, score.Statistics)); return (long)Math.Round(scoreProcessor.GetScore(scoringMode.Value, beatmapMaxCombo, accuracy, (double)score.MaxCombo / beatmapMaxCombo, score.Statistics));
}
/// <summary>
/// Provides the total score of a <see cref="ScoreInfo"/>. Responds to changes in the currently-selected <see cref="ScoringMode"/>.
/// </summary>
private class TotalScoreBindable : Bindable<long>
{
public readonly Bindable<ScoringMode> ScoringMode = new Bindable<ScoringMode>();
private readonly ScoreInfo score;
private readonly ScoreManager scoreManager;
/// <summary>
/// Creates a new <see cref="TotalScoreBindable"/>.
/// </summary>
/// <param name="score">The <see cref="ScoreInfo"/> to provide the total score of.</param>
/// <param name="scoreManager">The <see cref="ScoreManager"/>.</param>
public TotalScoreBindable(ScoreInfo score, ScoreManager scoreManager)
{
this.score = score;
this.scoreManager = scoreManager;
ScoringMode.BindValueChanged(onScoringModeChanged, true);
}
private CancellationTokenSource difficultyCancellationSource;
private void onScoringModeChanged(ValueChangedEvent<ScoringMode> mode)
{
difficultyCancellationSource?.Cancel();
difficultyCancellationSource = new CancellationTokenSource();
scoreManager.GetTotalScoreAsync(score, difficultyCancellationSource.Token).ContinueWith(s => Value = s.Result, TaskContinuationOptions.OnlyOnRanToCompletion);
} }
} }