1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:12:54 +08:00
This commit is contained in:
smoogipoo 2021-09-01 15:41:52 +09:00
parent 2de076a74b
commit 88fc53200e
4 changed files with 59 additions and 40 deletions

View File

@ -14,7 +14,6 @@ using osu.Game.Beatmaps;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Configuration;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring; using osu.Game.Scoring;
@ -67,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
if (value?.Scores.Any() != true) if (value?.Scores.Any() != true)
return; return;
scoreManager.GetOrderedScoresAsync(value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token) scoreManager.OrderByTotalScoreAsync(value.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token)
.ContinueWith(ordered => Schedule(() => .ContinueWith(ordered => Schedule(() =>
{ {
if (loadCancellationSource.IsCancellationRequested) if (loadCancellationSource.IsCancellationRequested)

View File

@ -34,7 +34,6 @@ 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;
@ -52,8 +51,6 @@ 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)
@ -106,14 +103,20 @@ namespace osu.Game.Scoring
=> base.CheckLocalAvailability(model, items) => base.CheckLocalAvailability(model, items)
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID)); || (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
public async Task<ScoreInfo[]> GetOrderedScoresAsync(ScoreInfo[] scores, CancellationToken cancellationToken = default) /// <summary>
/// Orders an array of <see cref="ScoreInfo"/>s by total score.
/// </summary>
/// <param name="scores">The array of <see cref="ScoreInfo"/>s to reorder.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the process.</param>
/// <returns>The given <paramref name="scores"/> ordered by decreasing total score.</returns>
public async Task<ScoreInfo[]> OrderByTotalScoreAsync(ScoreInfo[] scores, CancellationToken cancellationToken = default)
{ {
var difficultyCache = difficulties?.Invoke(); var difficultyCache = difficulties?.Invoke();
if (difficultyCache == null) if (difficultyCache == null)
return orderByTotalScore(scores); return orderByTotalScore(scores);
// Compute difficulties asynchronously first to prevent blocks on the main thread. // Compute difficulties asynchronously first to prevent blocking via the GetTotalScore() call below.
foreach (var s in scores) foreach (var s in scores)
{ {
await difficultyCache.GetDifficultyAsync(s.Beatmap, s.Ruleset, s.Mods, cancellationToken).ConfigureAwait(false); await difficultyCache.GetDifficultyAsync(s.Beatmap, s.Ruleset, s.Mods, cancellationToken).ConfigureAwait(false);
@ -122,7 +125,7 @@ namespace osu.Game.Scoring
return orderByTotalScore(scores); return orderByTotalScore(scores);
ScoreInfo[] orderByTotalScore(IEnumerable<ScoreInfo> incoming) => incoming.OrderByDescending(GetTotalScore).ThenBy(s => s.OnlineScoreID).ToArray(); ScoreInfo[] orderByTotalScore(IEnumerable<ScoreInfo> incoming) => incoming.OrderByDescending(s => GetTotalScore(s)).ThenBy(s => s.OnlineScoreID).ToArray();
} }
/// <summary> /// <summary>
@ -150,9 +153,22 @@ 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));
public long GetTotalScore(ScoreInfo score) => GetTotalScoreAsync(score).Result; /// <summary>
/// Retrieves the total score of a <see cref="ScoreInfo"/> in the given <see cref="ScoringMode"/>.
/// </summary>
/// <param name="score">The <see cref="ScoreInfo"/> to calculate the total score of.</param>
/// <param name="mode">The <see cref="ScoringMode"/> to return the total score as.</param>
/// <returns>The total score.</returns>
public long GetTotalScore(ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) => GetTotalScoreAsync(score).Result;
public async Task<long> GetTotalScoreAsync(ScoreInfo score, CancellationToken cancellationToken = default) /// <summary>
/// Retrieves the total score of a <see cref="ScoreInfo"/> in the given <see cref="ScoringMode"/>.
/// </summary>
/// <param name="score">The <see cref="ScoreInfo"/> to calculate the total score of.</param>
/// <param name="mode">The <see cref="ScoringMode"/> to return the total score as.</param>
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the process.</param>
/// <returns>The total score.</returns>
public async Task<long> GetTotalScoreAsync(ScoreInfo score, ScoringMode mode = ScoringMode.Standardised, CancellationToken cancellationToken = default)
{ {
if (score.Beatmap == null) if (score.Beatmap == null)
return score.TotalScore; return score.TotalScore;
@ -204,7 +220,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.GetScore(scoringMode.Value, beatmapMaxCombo, accuracy, (double)score.MaxCombo / beatmapMaxCombo, score.Statistics)); return (long)Math.Round(scoreProcessor.GetScore(mode, beatmapMaxCombo, accuracy, (double)score.MaxCombo / beatmapMaxCombo, score.Statistics));
} }
/// <summary> /// <summary>
@ -221,7 +237,7 @@ namespace osu.Game.Scoring
/// <param name="scoreManager">The <see cref="ScoreManager"/>.</param> /// <param name="scoreManager">The <see cref="ScoreManager"/>.</param>
public TotalScoreBindable(ScoreInfo score, ScoreManager scoreManager) public TotalScoreBindable(ScoreInfo score, ScoreManager scoreManager)
{ {
ScoringMode.BindValueChanged(_ => Value = scoreManager.GetTotalScore(score), true); ScoringMode.BindValueChanged(mode => Value = scoreManager.GetTotalScore(score, mode.NewValue), true);
} }
} }

View File

@ -11,6 +11,7 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Scoring; using osu.Game.Scoring;
using osuTK; using osuTK;
@ -65,6 +66,9 @@ namespace osu.Game.Screens.Ranking
[Resolved] [Resolved]
private ScoreManager scoreManager { get; set; } private ScoreManager scoreManager { get; set; }
[Resolved]
private BeatmapDifficultyCache difficultyCache { get; set; }
private readonly CancellationTokenSource loadCancellationSource = new CancellationTokenSource(); private readonly CancellationTokenSource loadCancellationSource = new CancellationTokenSource();
private readonly Flow flow; private readonly Flow flow;
private readonly Scroll scroll; private readonly Scroll scroll;
@ -120,33 +124,33 @@ namespace osu.Game.Screens.Ranking
}; };
}); });
scoreManager.GetOrderedScoresAsync(new[] { score }) difficultyCache.GetDifficultyAsync(score.Beatmap, score.Ruleset, score.Mods)
.ContinueWith(_ => Schedule(() => .ContinueWith(_ => Schedule(() =>
{ {
flow.Add(panel.CreateTrackingContainer().With(d => flow.Add(panel.CreateTrackingContainer().With(d =>
{ {
d.Anchor = Anchor.Centre; d.Anchor = Anchor.Centre;
d.Origin = Anchor.Centre; d.Origin = Anchor.Centre;
})); }));
if (SelectedScore.Value == score) if (SelectedScore.Value == score)
{ {
SelectedScore.TriggerChange(); SelectedScore.TriggerChange();
} }
else else
{ {
// We want the scroll position to remain relative to the expanded panel. When a new panel is added after the expanded panel, nothing needs to be done. // We want the scroll position to remain relative to the expanded panel. When a new panel is added after the expanded panel, nothing needs to be done.
// But when a panel is added before the expanded panel, we need to offset the scroll position by the width of the new panel. // But when a panel is added before the expanded panel, we need to offset the scroll position by the width of the new panel.
if (expandedPanel != null && flow.GetPanelIndex(score) < flow.GetPanelIndex(expandedPanel.Score)) if (expandedPanel != null && flow.GetPanelIndex(score) < flow.GetPanelIndex(expandedPanel.Score))
{ {
// A somewhat hacky property is used here because we need to: // A somewhat hacky property is used here because we need to:
// 1) Scroll after the scroll container's visible range is updated. // 1) Scroll after the scroll container's visible range is updated.
// 2) Scroll before the scroll container's scroll position is updated. // 2) Scroll before the scroll container's scroll position is updated.
// Without this, we would have a 1-frame positioning error which looks very jarring. // Without this, we would have a 1-frame positioning error which looks very jarring.
scroll.InstantScrollTarget = (scroll.InstantScrollTarget ?? scroll.Target) + ScorePanel.CONTRACTED_WIDTH + panel_spacing; scroll.InstantScrollTarget = (scroll.InstantScrollTarget ?? scroll.Target) + ScorePanel.CONTRACTED_WIDTH + panel_spacing;
} }
} }
})); }));
return panel; return panel;
} }

View File

@ -156,7 +156,7 @@ namespace osu.Game.Screens.Select.Leaderboards
scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym))); scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym)));
} }
scoreManager.GetOrderedScoresAsync(scores.ToArray(), loadCancellationSource.Token) scoreManager.OrderByTotalScoreAsync(scores.ToArray(), loadCancellationSource.Token)
.ContinueWith(ordered => scoresCallback?.Invoke(ordered.Result), TaskContinuationOptions.OnlyOnRanToCompletion); .ContinueWith(ordered => scoresCallback?.Invoke(ordered.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
return null; return null;
@ -192,7 +192,7 @@ namespace osu.Game.Screens.Select.Leaderboards
req.Success += r => req.Success += r =>
{ {
scoreManager.GetOrderedScoresAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token) scoreManager.OrderByTotalScoreAsync(r.Scores.Select(s => s.CreateScoreInfo(rulesets)).ToArray(), loadCancellationSource.Token)
.ContinueWith(ordered => Schedule(() => .ContinueWith(ordered => Schedule(() =>
{ {
if (loadCancellationSource.IsCancellationRequested) if (loadCancellationSource.IsCancellationRequested)