diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs index 1335fc2d23..3673e79159 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceAttributes.cs @@ -1,11 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Catch.Difficulty { - public class CatchPerformanceAttributes : PerformanceAttributes + public struct CatchPerformanceAttributes : IPerformanceAttributes { + /// + /// Calculated score performance points. + /// + [JsonProperty("pp")] + public double Total { get; set; } + + public IEnumerable GetAttributesForDisplay() + { + yield return new PerformanceDisplayAttribute(nameof(Total), "Achieved PP", Total); + } } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs index 55232a9598..efca1e5e77 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchPerformanceCalculator.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty { } - protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) { var catchAttributes = (CatchDifficultyAttributes)attributes; diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs index 64f8b026c2..6a90a6f117 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceAttributes.cs @@ -7,16 +7,20 @@ using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Mania.Difficulty { - public class ManiaPerformanceAttributes : PerformanceAttributes + public struct ManiaPerformanceAttributes : IPerformanceAttributes { + /// + /// Calculated score performance points. + /// + [JsonProperty("pp")] + public double Total { get; set; } + [JsonProperty("difficulty")] public double Difficulty { get; set; } - public override IEnumerable GetAttributesForDisplay() + public IEnumerable GetAttributesForDisplay() { - foreach (var attribute in base.GetAttributesForDisplay()) - yield return attribute; - + yield return new PerformanceDisplayAttribute(nameof(Total), "Achieved PP", Total); yield return new PerformanceDisplayAttribute(nameof(Difficulty), "Difficulty", Difficulty); } } diff --git a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs index 778d569cf2..4d1b9b5766 100644 --- a/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Mania/Difficulty/ManiaPerformanceCalculator.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty { } - protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) { var maniaAttributes = (ManiaDifficultyAttributes)attributes; diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs index 0aeaf7669f..aefe416d87 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceAttributes.cs @@ -7,8 +7,14 @@ using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Osu.Difficulty { - public class OsuPerformanceAttributes : PerformanceAttributes + public struct OsuPerformanceAttributes : IPerformanceAttributes { + /// + /// Calculated score performance points. + /// + [JsonProperty("pp")] + public double Total { get; set; } + [JsonProperty("aim")] public double Aim { get; set; } @@ -24,11 +30,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty [JsonProperty("effective_miss_count")] public double EffectiveMissCount { get; set; } - public override IEnumerable GetAttributesForDisplay() + public IEnumerable GetAttributesForDisplay() { - foreach (var attribute in base.GetAttributesForDisplay()) - yield return attribute; - + yield return new PerformanceDisplayAttribute(nameof(Total), "Achieved PP", Total); yield return new PerformanceDisplayAttribute(nameof(Aim), "Aim", Aim); yield return new PerformanceDisplayAttribute(nameof(Speed), "Speed", Speed); yield return new PerformanceDisplayAttribute(nameof(Accuracy), "Accuracy", Accuracy); diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs index ddabf866ff..8425f437cc 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs @@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty { } - protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) { var osuAttributes = (OsuDifficultyAttributes)attributes; diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs index 7c74e43db1..496311a9aa 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceAttributes.cs @@ -7,8 +7,14 @@ using osu.Game.Rulesets.Difficulty; namespace osu.Game.Rulesets.Taiko.Difficulty { - public class TaikoPerformanceAttributes : PerformanceAttributes + public struct TaikoPerformanceAttributes : IPerformanceAttributes { + /// + /// Calculated score performance points. + /// + [JsonProperty("pp")] + public double Total { get; set; } + [JsonProperty("difficulty")] public double Difficulty { get; set; } @@ -21,11 +27,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty [JsonProperty("estimated_unstable_rate")] public double? EstimatedUnstableRate { get; set; } - public override IEnumerable GetAttributesForDisplay() + public IEnumerable GetAttributesForDisplay() { - foreach (var attribute in base.GetAttributesForDisplay()) - yield return attribute; - + yield return new PerformanceDisplayAttribute(nameof(Total), "Achieved PP", Total); yield return new PerformanceDisplayAttribute(nameof(Difficulty), "Difficulty", Difficulty); yield return new PerformanceDisplayAttribute(nameof(Accuracy), "Accuracy", Accuracy); } diff --git a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs index e42b015176..29eadf417f 100644 --- a/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs +++ b/osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty { } - protected override PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) + protected override IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes) { var taikoAttributes = (TaikoDifficultyAttributes)attributes; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs b/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs index e8c4c71913..bf4e8bd247 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceAttributes.cs @@ -6,7 +6,7 @@ using Newtonsoft.Json; namespace osu.Game.Rulesets.Difficulty { - public class PerformanceAttributes + public interface IPerformanceAttributes { /// /// Calculated score performance points. @@ -19,9 +19,6 @@ namespace osu.Game.Rulesets.Difficulty /// Some attributes may be omitted if they are not meant for display. /// /// - public virtual IEnumerable GetAttributesForDisplay() - { - yield return new PerformanceDisplayAttribute(nameof(Total), "Achieved PP", Total); - } + public IEnumerable GetAttributesForDisplay(); } } diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs index 6e41855ca3..31b9909999 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdown.cs @@ -11,19 +11,19 @@ namespace osu.Game.Rulesets.Difficulty /// /// Actual gameplay performance. /// - public PerformanceAttributes Performance { get; set; } + public IPerformanceAttributes Performance { get; set; } /// /// Performance of a perfect play for comparison. /// - public PerformanceAttributes PerfectPerformance { get; set; } + public IPerformanceAttributes PerfectPerformance { get; set; } /// /// Create a new performance breakdown. /// /// Actual gameplay performance. /// Performance of a perfect play for comparison. - public PerformanceBreakdown(PerformanceAttributes performance, PerformanceAttributes perfectPerformance) + public PerformanceBreakdown(IPerformanceAttributes performance, IPerformanceAttributes perfectPerformance) { Performance = performance; PerfectPerformance = perfectPerformance; diff --git a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs index 946d83b14b..994d8cc52c 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceBreakdownCalculator.cs @@ -41,18 +41,18 @@ namespace osu.Game.Rulesets.Difficulty cancellationToken.ThrowIfCancellationRequested(); - PerformanceAttributes[] performanceArray = await Task.WhenAll( + IPerformanceAttributes[] performanceArray = await Task.WhenAll( // compute actual performance performanceCalculator.CalculateAsync(score, attributes.Value.Attributes, cancellationToken), // compute performance for perfect play getPerfectPerformance(score, cancellationToken) ).ConfigureAwait(false); - return new PerformanceBreakdown(performanceArray[0] ?? new PerformanceAttributes(), performanceArray[1] ?? new PerformanceAttributes()); + return new PerformanceBreakdown(performanceArray[0] ?? new EmptyPerformanceAttributes(), performanceArray[1] ?? new EmptyPerformanceAttributes()); } [ItemCanBeNull] - private Task getPerfectPerformance(ScoreInfo score, CancellationToken cancellationToken = default) + private Task getPerfectPerformance(ScoreInfo score, CancellationToken cancellationToken = default) { return Task.Run(async () => { @@ -117,5 +117,12 @@ namespace osu.Game.Rulesets.Difficulty yield return hitObject.Judgement.MaxResult; } + + public class EmptyPerformanceAttributes : IPerformanceAttributes + { + public double Total { get; set; } = 0; + + public IEnumerable GetAttributesForDisplay() => []; + } } } diff --git a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs index 966da0ff12..ee7f02f9be 100644 --- a/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/PerformanceCalculator.cs @@ -17,20 +17,20 @@ namespace osu.Game.Rulesets.Difficulty Ruleset = ruleset; } - public Task CalculateAsync(ScoreInfo score, DifficultyAttributes attributes, CancellationToken cancellationToken) + public Task CalculateAsync(ScoreInfo score, DifficultyAttributes attributes, CancellationToken cancellationToken) => Task.Run(() => CreatePerformanceAttributes(score, attributes), cancellationToken); - public PerformanceAttributes Calculate(ScoreInfo score, DifficultyAttributes attributes) + public IPerformanceAttributes Calculate(ScoreInfo score, DifficultyAttributes attributes) => CreatePerformanceAttributes(score, attributes); - public PerformanceAttributes Calculate(ScoreInfo score, IWorkingBeatmap beatmap) + public IPerformanceAttributes Calculate(ScoreInfo score, IWorkingBeatmap beatmap) => Calculate(score, Ruleset.CreateDifficultyCalculator(beatmap).Calculate(score.Mods)); /// - /// Creates to describe a score's performance. + /// Creates to describe a score's performance. /// /// The score to create the attributes for. /// The difficulty attributes for the beatmap relating to the score. - protected abstract PerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes); + protected abstract IPerformanceAttributes CreatePerformanceAttributes(ScoreInfo score, DifficultyAttributes attributes); } } diff --git a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs index b5eed2d12a..cbbd6d016b 100644 --- a/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs +++ b/osu.Game/Screens/Ranking/Statistics/PerformanceBreakdownChart.cs @@ -156,8 +156,8 @@ namespace osu.Game.Screens.Ranking.Statistics var perfectDisplayAttributes = breakdown.PerfectPerformance.GetAttributesForDisplay(); setTotalValues( - displayAttributes.First(a => a.PropertyName == nameof(PerformanceAttributes.Total)), - perfectDisplayAttributes.First(a => a.PropertyName == nameof(PerformanceAttributes.Total)) + displayAttributes.First(a => a.PropertyName == nameof(IPerformanceAttributes.Total)), + perfectDisplayAttributes.First(a => a.PropertyName == nameof(IPerformanceAttributes.Total)) ); var rowDimensions = new List(); @@ -165,7 +165,7 @@ namespace osu.Game.Screens.Ranking.Statistics foreach (PerformanceDisplayAttribute attr in displayAttributes) { - if (attr.PropertyName == nameof(PerformanceAttributes.Total)) continue; + if (attr.PropertyName == nameof(IPerformanceAttributes.Total)) continue; var row = createAttributeRow(attr, perfectDisplayAttributes.First(a => a.PropertyName == attr.PropertyName));