mirror of
https://github.com/ppy/osu.git
synced 2025-02-28 04:03:06 +08:00
Merge pull request #17359 from frenzibyte/fix-score-panel-max-combo
Improve method of retrieving beatmap maximum combo for results score panels
This commit is contained in:
commit
aea03ca21d
@ -133,7 +133,6 @@ namespace osu.Game.Tests.Resources
|
||||
StarRating = diff,
|
||||
Length = length,
|
||||
BPM = bpm,
|
||||
MaxCombo = 1000,
|
||||
Hash = Guid.NewGuid().ToString().ComputeMD5Hash(),
|
||||
Ruleset = rulesetInfo,
|
||||
Metadata = metadata,
|
||||
|
@ -9,6 +9,7 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Models;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Overlays.BeatmapSet.Scores;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Scoring;
|
||||
using Realms;
|
||||
@ -169,7 +170,12 @@ namespace osu.Game.Beatmaps
|
||||
[Ignored]
|
||||
public APIBeatmap? OnlineInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum achievable combo on this beatmap, populated for online info purposes only.
|
||||
/// Todo: This should never be used nor exist, but is still relied on in <see cref="ScoresContainer.Scores"/> since <see cref="IBeatmapInfo"/> can't be used yet. For now this is obsoleted until it is removed.
|
||||
/// </summary>
|
||||
[Ignored]
|
||||
[Obsolete("Use ScoreManager.GetMaximumAchievableComboAsync instead.")]
|
||||
public int? MaxCombo { get; set; }
|
||||
|
||||
[Ignored]
|
||||
|
@ -53,9 +53,6 @@ namespace osu.Game.Beatmaps
|
||||
[NotMapped]
|
||||
public APIBeatmap OnlineInfo { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public int? MaxCombo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The playable length in milliseconds of this beatmap.
|
||||
/// </summary>
|
||||
|
@ -295,7 +295,6 @@ namespace osu.Game.Database
|
||||
TimelineZoom = beatmap.TimelineZoom,
|
||||
Countdown = beatmap.Countdown,
|
||||
CountdownOffset = beatmap.CountdownOffset,
|
||||
MaxCombo = beatmap.MaxCombo,
|
||||
Bookmarks = beatmap.Bookmarks,
|
||||
BeatmapSet = realmBeatmapSet,
|
||||
};
|
||||
|
@ -173,7 +173,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
{
|
||||
Text = score.MaxCombo.ToLocalisableString(@"0\x"),
|
||||
Font = OsuFont.GetFont(size: text_size),
|
||||
#pragma warning disable 618
|
||||
Colour = score.MaxCombo == score.BeatmapInfo.MaxCombo ? highAccuracyColour : Color4.White
|
||||
#pragma warning restore 618
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -78,7 +78,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
// TODO: temporary. should be removed once `OrderByTotalScore` can accept `IScoreInfo`.
|
||||
var beatmapInfo = new BeatmapInfo
|
||||
{
|
||||
#pragma warning disable 618
|
||||
MaxCombo = apiBeatmap.MaxCombo,
|
||||
#pragma warning restore 618
|
||||
Status = apiBeatmap.Status,
|
||||
MD5Hash = apiBeatmap.MD5Hash
|
||||
};
|
||||
|
@ -157,7 +157,7 @@ namespace osu.Game.Scoring
|
||||
public LocalisableString DisplayAccuracy => Accuracy.FormatAccuracy();
|
||||
|
||||
/// <summary>
|
||||
/// Whether this <see cref="EFScoreInfo"/> represents a legacy (osu!stable) score.
|
||||
/// Whether this <see cref="ScoreInfo"/> represents a legacy (osu!stable) score.
|
||||
/// </summary>
|
||||
[Ignored]
|
||||
public bool IsLegacyScore => Mods.OfType<ModClassic>().Any();
|
||||
|
@ -134,35 +134,9 @@ namespace osu.Game.Scoring
|
||||
if (string.IsNullOrEmpty(score.BeatmapInfo.MD5Hash))
|
||||
return score.TotalScore;
|
||||
|
||||
int beatmapMaxCombo;
|
||||
|
||||
if (score.IsLegacyScore)
|
||||
{
|
||||
// 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.
|
||||
if (score.BeatmapInfo.MaxCombo != null)
|
||||
beatmapMaxCombo = score.BeatmapInfo.MaxCombo.Value;
|
||||
else
|
||||
{
|
||||
if (difficulties == null)
|
||||
return score.TotalScore;
|
||||
|
||||
// We can compute the max combo locally after the async beatmap difficulty computation.
|
||||
var difficulty = await difficulties().GetDifficultyAsync(score.BeatmapInfo, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Something failed during difficulty calculation. Fall back to provided score.
|
||||
if (difficulty == null)
|
||||
return score.TotalScore;
|
||||
|
||||
beatmapMaxCombo = difficulty.Value.MaxCombo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is guaranteed to be a non-legacy score.
|
||||
// The combo must be determined through the score's statistics, as both the beatmap's max combo and the difficulty calculator will provide osu!stable combo values.
|
||||
beatmapMaxCombo = Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetValueOrDefault(r)).Sum();
|
||||
}
|
||||
int? beatmapMaxCombo = await GetMaximumAchievableComboAsync(score, cancellationToken).ConfigureAwait(false);
|
||||
if (beatmapMaxCombo == null)
|
||||
return score.TotalScore;
|
||||
|
||||
if (beatmapMaxCombo == 0)
|
||||
return 0;
|
||||
@ -171,7 +145,37 @@ namespace osu.Game.Scoring
|
||||
var scoreProcessor = ruleset.CreateScoreProcessor();
|
||||
scoreProcessor.Mods.Value = score.Mods;
|
||||
|
||||
return (long)Math.Round(scoreProcessor.ComputeFinalLegacyScore(mode, score, beatmapMaxCombo));
|
||||
return (long)Math.Round(scoreProcessor.ComputeFinalLegacyScore(mode, score, beatmapMaxCombo.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the maximum achievable combo for the provided score.
|
||||
/// </summary>
|
||||
/// <param name="score">The <see cref="ScoreInfo"/> to compute the maximum achievable combo for.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the process.</param>
|
||||
/// <returns>The maximum achievable combo. A <see langword="null"/> return value indicates the difficulty cache has failed to retrieve the combo.</returns>
|
||||
public async Task<int?> GetMaximumAchievableComboAsync([NotNull] ScoreInfo score, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (score.IsLegacyScore)
|
||||
{
|
||||
// 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.
|
||||
#pragma warning disable CS0618
|
||||
if (score.BeatmapInfo.MaxCombo != null)
|
||||
return score.BeatmapInfo.MaxCombo.Value;
|
||||
#pragma warning restore CS0618
|
||||
|
||||
if (difficulties == null)
|
||||
return null;
|
||||
|
||||
// We can compute the max combo locally after the async beatmap difficulty computation.
|
||||
var difficulty = await difficulties().GetDifficultyAsync(score.BeatmapInfo, score.Ruleset, score.Mods, cancellationToken).ConfigureAwait(false);
|
||||
return difficulty?.MaxCombo;
|
||||
}
|
||||
|
||||
// This is guaranteed to be a non-legacy score.
|
||||
// The combo must be determined through the score's statistics, as both the beatmap's max combo and the difficulty calculator will provide osu!stable combo values.
|
||||
return Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r.AffectsCombo()).Select(r => score.Statistics.GetValueOrDefault(r)).Sum();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,10 +65,12 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
var metadata = beatmap.BeatmapSet?.Metadata ?? beatmap.Metadata;
|
||||
string creator = metadata.Author.Username;
|
||||
|
||||
int? beatmapMaxCombo = scoreManager.GetMaximumAchievableComboAsync(score).GetResultSafely();
|
||||
|
||||
var topStatistics = new List<StatisticDisplay>
|
||||
{
|
||||
new AccuracyStatistic(score.Accuracy),
|
||||
new ComboStatistic(score.MaxCombo, beatmap.MaxCombo, score.Statistics.All(stat => !stat.Key.BreaksCombo() || stat.Value == 0)),
|
||||
new ComboStatistic(score.MaxCombo, beatmapMaxCombo),
|
||||
new PerformanceStatistic(score),
|
||||
};
|
||||
|
||||
@ -80,8 +82,6 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
statisticDisplays.AddRange(topStatistics);
|
||||
statisticDisplays.AddRange(bottomStatistics);
|
||||
|
||||
var starDifficulty = beatmapDifficultyCache.GetDifficultyAsync(beatmap, score.Ruleset, score.Mods).GetResultSafely();
|
||||
|
||||
AddInternal(new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
@ -224,6 +224,8 @@ namespace osu.Game.Screens.Ranking.Expanded
|
||||
if (score.Date != default)
|
||||
AddInternal(new PlayedOnText(score.Date));
|
||||
|
||||
var starDifficulty = beatmapDifficultyCache.GetDifficultyAsync(beatmap, score.Ruleset, score.Mods).GetResultSafely();
|
||||
|
||||
if (starDifficulty != null)
|
||||
{
|
||||
starAndModDisplay.Add(new StarRatingDisplay(starDifficulty.Value)
|
||||
|
@ -26,11 +26,10 @@ namespace osu.Game.Screens.Ranking.Expanded.Statistics
|
||||
/// </summary>
|
||||
/// <param name="combo">The combo to be displayed.</param>
|
||||
/// <param name="maxCombo">The maximum value of <paramref name="combo"/>.</param>
|
||||
/// <param name="isPerfect">Whether this is a perfect combo.</param>
|
||||
public ComboStatistic(int combo, int? maxCombo, bool isPerfect)
|
||||
public ComboStatistic(int combo, int? maxCombo)
|
||||
: base("combo", combo, maxCombo)
|
||||
{
|
||||
this.isPerfect = isPerfect;
|
||||
isPerfect = combo == maxCombo;
|
||||
}
|
||||
|
||||
public override void Appear()
|
||||
|
Loading…
Reference in New Issue
Block a user