diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index ef89a86e79..da033e324c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -73,10 +73,10 @@ namespace osu.Game.Tests.Visual.Online Ranked = DateTime.Now, BPM = 111, HasVideo = true, + Ratings = Enumerable.Range(0, 11).ToArray(), HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -153,8 +153,8 @@ namespace osu.Game.Tests.Visual.Online Covers = new BeatmapSetOnlineCovers(), Language = new BeatmapSetOnlineLanguage { Id = 3, Name = "English" }, Genre = new BeatmapSetOnlineGenre { Id = 4, Name = "Rock" }, + Ratings = Enumerable.Range(0, 11).ToArray(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -228,8 +228,8 @@ namespace osu.Game.Tests.Visual.Online OnlineInfo = new APIBeatmapSet { Covers = new BeatmapSetOnlineCovers(), + Ratings = Enumerable.Range(0, 11).ToArray(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = beatmaps }); }); @@ -316,8 +316,8 @@ namespace osu.Game.Tests.Visual.Online HasVideo = true, HasStoryboard = true, Covers = new BeatmapSetOnlineCovers(), + Ratings = Enumerable.Range(0, 11).ToArray(), }, - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() }, Beatmaps = beatmaps, }; } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs index c15c9f44e4..f16d5aaa23 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlayDetails.cs @@ -39,14 +39,13 @@ namespace osu.Game.Tests.Visual.Online var secondSet = createSet(); AddStep("set first set", () => details.BeatmapSet = firstSet); - AddAssert("ratings set", () => details.Ratings.Metrics == firstSet.Metrics); + AddAssert("ratings set", () => details.Ratings.Ratings == firstSet.Ratings); AddStep("set second set", () => details.BeatmapSet = secondSet); - AddAssert("ratings set", () => details.Ratings.Metrics == secondSet.Metrics); + AddAssert("ratings set", () => details.Ratings.Ratings == secondSet.Ratings); static BeatmapSetInfo createSet() => new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray() }, Beatmaps = new List { new BeatmapInfo @@ -60,6 +59,7 @@ namespace osu.Game.Tests.Visual.Online }, OnlineInfo = new APIBeatmapSet { + Ratings = Enumerable.Range(0, 11).Select(_ => RNG.Next(10)).ToArray(), Status = BeatmapSetOnlineStatus.Ranked } }; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index d5b4fb9a80..6b508878bf 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -6,6 +6,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect @@ -34,7 +35,10 @@ namespace osu.Game.Tests.Visual.SongSelect { BeatmapSet = new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + OnlineInfo = new APIBeatmapSet + { + Ratings = Enumerable.Range(0, 11).ToArray(), + } }, Version = "All Metrics", Metadata = new BeatmapMetadata @@ -65,7 +69,10 @@ namespace osu.Game.Tests.Visual.SongSelect { BeatmapSet = new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + OnlineInfo = new APIBeatmapSet + { + Ratings = Enumerable.Range(0, 11).ToArray(), + } }, Version = "All Metrics", Metadata = new BeatmapMetadata @@ -95,7 +102,10 @@ namespace osu.Game.Tests.Visual.SongSelect { BeatmapSet = new BeatmapSetInfo { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + OnlineInfo = new APIBeatmapSet + { + Ratings = Enumerable.Range(0, 11).ToArray(), + } }, Version = "Only Ratings", Metadata = new BeatmapMetadata diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index 3bcc00f5de..6da50657a6 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -16,7 +16,7 @@ namespace osu.Game.Beatmaps { [ExcludeFromDynamicCompile] [Serializable] - public class BeatmapInfo : IEquatable, IHasPrimaryKey, IBeatmapInfo + public class BeatmapInfo : IEquatable, IHasPrimaryKey, IBeatmapInfo, IBeatmapOnlineInfo { public int ID { get; set; } diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 0c032e1482..ae32ad000e 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -38,9 +38,6 @@ namespace osu.Game.Beatmaps [NotMapped] public APIBeatmapSet OnlineInfo { get; set; } - [NotMapped] - public BeatmapSetMetrics Metrics { get; set; } - /// /// The maximum star difficulty of all beatmaps in this set. /// @@ -172,6 +169,10 @@ namespace osu.Game.Beatmaps [JsonIgnore] public int? TrackId => OnlineInfo?.TrackId; + [NotMapped] + [JsonIgnore] + public int[] Ratings => OnlineInfo?.Ratings; + #endregion } } diff --git a/osu.Game/Beatmaps/BeatmapSetMetrics.cs b/osu.Game/Beatmaps/BeatmapSetMetrics.cs deleted file mode 100644 index 51c5de19a6..0000000000 --- a/osu.Game/Beatmaps/BeatmapSetMetrics.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using Newtonsoft.Json; - -namespace osu.Game.Beatmaps -{ - public class BeatmapSetMetrics - { - /// - /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). - /// - [JsonProperty("ratings")] - public int[] Ratings { get; set; } = Array.Empty(); - } -} diff --git a/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs new file mode 100644 index 0000000000..4898e45c56 --- /dev/null +++ b/osu.Game/Beatmaps/IBeatmapOnlineInfo.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +namespace osu.Game.Beatmaps +{ + /// + /// Beatmap info retrieved for previewing locally. + /// + public interface IBeatmapOnlineInfo + { + int? MaxCombo { get; } + + BeatmapMetrics? Metrics { get; } + } +} diff --git a/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs index 1d2bb46bde..6def6ec21d 100644 --- a/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs +++ b/osu.Game/Beatmaps/IBeatmapSetOnlineInfo.cs @@ -97,5 +97,10 @@ namespace osu.Game.Beatmaps /// Non-null only if the track is linked to a featured artist track entry. /// int? TrackId { get; } + + /// + /// Total vote counts of user ratings on a scale of 0..10 where 0 is unused (probably will be fixed at API?). + /// + int[]? Ratings { get; } } } diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 6e43ac5504..6a05811bba 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -10,7 +10,7 @@ using osu.Game.Rulesets; namespace osu.Game.Online.API.Requests.Responses { - public class APIBeatmap : IBeatmapInfo + public class APIBeatmap : IBeatmapInfo, IBeatmapOnlineInfo { [JsonProperty(@"id")] public int OnlineID { get; set; } @@ -69,10 +69,10 @@ namespace osu.Game.Online.API.Requests.Responses public string DifficultyName { get; set; } = string.Empty; [JsonProperty(@"failtimes")] - private BeatmapMetrics? metrics { get; set; } + public BeatmapMetrics? Metrics { get; set; } [JsonProperty(@"max_combo")] - private int? maxCombo { get; set; } + public int? MaxCombo { get; set; } public virtual BeatmapInfo ToBeatmapInfo(RulesetStore rulesets) { @@ -90,8 +90,8 @@ namespace osu.Game.Online.API.Requests.Responses Status = Status, MD5Hash = Checksum, BeatmapSet = set, - Metrics = metrics, - MaxCombo = maxCombo, + Metrics = Metrics, + MaxCombo = MaxCombo, BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index 24d0e09649..17b1e9d3fe 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -58,8 +58,8 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"last_updated")] public DateTimeOffset? LastUpdated { get; set; } - [JsonProperty(@"ratings")] - private int[] ratings { get; set; } = Array.Empty(); + [JsonProperty("ratings")] + public int[] Ratings { get; set; } = Array.Empty(); [JsonProperty(@"track_id")] public int? TrackId { get; set; } @@ -128,7 +128,6 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapSetID = OnlineID, Metadata = metadata, Status = Status, - Metrics = new BeatmapSetMetrics { Ratings = ratings }, OnlineInfo = this }; diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 92361ae4f8..d6720e5f35 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -52,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet private void updateDisplay() { - Ratings.Metrics = BeatmapSet?.Metrics; + Ratings.Ratings = BeatmapSet?.Ratings; ratingBox.Alpha = BeatmapSet?.OnlineInfo?.Status > 0 ? 1 : 0; } diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 6ace92370c..8dbe438ab5 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -29,7 +29,7 @@ namespace osu.Game.Screens.Select private const float transition_duration = 250; private readonly AdvancedStats advanced; - private readonly UserRatings ratings; + private readonly UserRatings ratingsDisplay; private readonly MetadataSection description, source, tags; private readonly Container failRetryContainer; private readonly FailRetryGraph failRetryGraph; @@ -43,6 +43,9 @@ namespace osu.Game.Screens.Select private BeatmapInfo beatmapInfo; + private BeatmapMetrics metrics; + private int[] ratings; + public BeatmapInfo BeatmapInfo { get => beatmapInfo; @@ -52,6 +55,9 @@ namespace osu.Game.Screens.Select beatmapInfo = value; + metrics = beatmapInfo?.Metrics; + ratings = beatmapInfo?.BeatmapSet.Ratings; + Scheduler.AddOnce(updateStatistics); } } @@ -110,7 +116,7 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.X, Height = 134, Padding = new MarginPadding { Horizontal = spacing, Top = spacing }, - Child = ratings = new UserRatings + Child = ratingsDisplay = new UserRatings { RelativeSizeAxes = Axes.Both, }, @@ -176,7 +182,7 @@ namespace osu.Game.Screens.Select tags.Text = BeatmapInfo?.Metadata?.Tags; // metrics may have been previously fetched - if (BeatmapInfo?.BeatmapSet?.Metrics != null && BeatmapInfo?.Metrics != null) + if (ratings != null && metrics != null) { updateMetrics(); return; @@ -201,14 +207,8 @@ namespace osu.Game.Screens.Select // the beatmap has been changed since we started the lookup. return; - var b = res.ToBeatmapInfo(rulesets); - - if (requestedBeatmap.BeatmapSet == null) - requestedBeatmap.BeatmapSet = b.BeatmapSet; - else - requestedBeatmap.BeatmapSet.Metrics = b.BeatmapSet.Metrics; - - requestedBeatmap.Metrics = b.Metrics; + ratings = res.BeatmapSet?.Ratings; + metrics = res.Metrics; updateMetrics(); }); @@ -232,24 +232,23 @@ namespace osu.Game.Screens.Select private void updateMetrics() { - var hasRatings = beatmapInfo?.BeatmapSet?.Metrics?.Ratings?.Any() ?? false; - var hasRetriesFails = (beatmapInfo?.Metrics?.Retries?.Any() ?? false) || (beatmapInfo?.Metrics?.Fails?.Any() ?? false); + var hasMetrics = (metrics?.Retries?.Any() ?? false) || (metrics?.Fails?.Any() ?? false); - if (hasRatings) + if (ratings?.Any() ?? false) { - ratings.Metrics = beatmapInfo.BeatmapSet.Metrics; - ratings.FadeIn(transition_duration); + ratingsDisplay.Ratings = ratings; + ratingsDisplay.FadeIn(transition_duration); } else { // loading or just has no data server-side. - ratings.Metrics = new BeatmapSetMetrics { Ratings = new int[10] }; - ratings.FadeTo(0.25f, transition_duration); + ratingsDisplay.Ratings = new int[10]; + ratingsDisplay.FadeTo(0.25f, transition_duration); } - if (hasRetriesFails) + if (hasMetrics) { - failRetryGraph.Metrics = beatmapInfo.Metrics; + failRetryGraph.Metrics = metrics; failRetryContainer.FadeIn(transition_duration); } else diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index eabc476db9..aa316d6e40 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -1,15 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; -using System.Linq; -using osu.Framework.Extensions.LocalisationExtensions; -using osu.Game.Beatmaps; using osu.Game.Resources.Localisation.Web; namespace osu.Game.Screens.Select.Details @@ -22,20 +21,20 @@ namespace osu.Game.Screens.Select.Details private readonly Container graphContainer; private readonly BarGraph graph; - private BeatmapSetMetrics metrics; + private int[] ratings; - public BeatmapSetMetrics Metrics + public int[] Ratings { - get => metrics; + get => ratings; set { - if (value == metrics) return; + if (value == ratings) return; - metrics = value; + ratings = value; const int rating_range = 10; - if (metrics == null) + if (ratings == null) { negativeRatings.Text = 0.ToLocalisableString(@"N0"); positiveRatings.Text = 0.ToLocalisableString(@"N0"); @@ -44,15 +43,15 @@ namespace osu.Game.Screens.Select.Details } else { - var ratings = Metrics.Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. + var usableRange = Ratings.Skip(1).Take(rating_range); // adjust for API returning weird empty data at 0. - var negativeCount = ratings.Take(rating_range / 2).Sum(); - var totalCount = ratings.Sum(); + var negativeCount = usableRange.Take(rating_range / 2).Sum(); + var totalCount = usableRange.Sum(); negativeRatings.Text = negativeCount.ToLocalisableString(@"N0"); positiveRatings.Text = (totalCount - negativeCount).ToLocalisableString(@"N0"); ratingsBar.Length = totalCount == 0 ? 0 : (float)negativeCount / totalCount; - graph.Values = ratings.Take(rating_range).Select(r => (float)r); + graph.Values = usableRange.Take(rating_range).Select(r => (float)r); } } }