diff --git a/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs b/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs new file mode 100644 index 0000000000..cf475de1f0 --- /dev/null +++ b/osu.Game.Tests/Visual/TestCaseMatchLeaderboard.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Multiplayer; +using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual +{ + public class TestCaseMatchLeaderboard : OsuTestCase + { + public TestCaseMatchLeaderboard() + { + Add(new MatchLeaderboard(new Room { RoomID = { Value = 3 } }) + { + Origin = Anchor.Centre, + Anchor = Anchor.Centre, + Size = new Vector2(550f, 450f), + Scope = MatchLeaderboardScope.Overall, + }); + } + + [Resolved] + private APIAccess api { get; set; } + + [BackgroundDependencyLoader] + private void load() + { + var req = new GetRoomScoresRequest(); + req.Success += v => { }; + req.Failure += _ => { }; + + api.Queue(req); + } + + private class GetRoomScoresRequest : APIRequest> + { + protected override string Target => "rooms/3/leaderboard"; + } + + private class RoomScore + { + [JsonProperty("user")] + public User User { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty("total_score")] + public int TotalScore { get; set; } + + [JsonProperty("pp")] + public double PP { get; set; } + + [JsonProperty("attempts")] + public int TotalAttempts { get; set; } + + [JsonProperty("completed")] + public int CompletedAttempts { get; set; } + } + } +} diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 8e83c8ad5a..83cc289bc1 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -13,7 +13,6 @@ using osu.Framework.Threading; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; -using osu.Game.Screens.Select.Leaderboards; using osuTK; using osuTK.Graphics; diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs new file mode 100644 index 0000000000..ef1021bac6 --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs @@ -0,0 +1,119 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.Leaderboards; +using osu.Game.Online.Multiplayer; +using osu.Game.Rulesets.Mods; +using osu.Game.Scoring; +using osu.Game.Users; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class MatchLeaderboard : Leaderboard + { + private readonly Room room; + + public MatchLeaderboard(Room room) + { + this.room = room; + } + + [BackgroundDependencyLoader] + private void load() + { + room.RoomID.BindValueChanged(_ => + { + Scores = null; + UpdateScores(); + }, true); + } + + protected override APIRequest FetchScores(Action> scoresCallback) + { + if (room.RoomID == null) + return null; + + var req = new GetRoomScoresRequest(room.RoomID.Value ?? 0); + + req.Success += r => scoresCallback?.Invoke(r); + + return req; + } + + protected override LeaderboardScore CreateScoreVisualiser(RoomScore model, int index) => new MatchLeaderboardScore(model, index); + + private class GetRoomScoresRequest : APIRequest> + { + private readonly int roomId; + + public GetRoomScoresRequest(int roomId) + { + this.roomId = roomId; + } + + protected override string Target => $@"rooms/{roomId}/leaderboard"; + } + } + + public class MatchLeaderboardScore : LeaderboardScore + { + public MatchLeaderboardScore(RoomScore score, int rank) + : base(score, rank) + { + } + + [BackgroundDependencyLoader] + private void load() + { + RankContainer.Alpha = 0; + } + + protected override User GetUser(RoomScore model) => model.User; + + protected override IEnumerable GetMods(RoomScore model) => Enumerable.Empty(); // Not implemented yet + + protected override IEnumerable<(FontAwesome icon, string value, string name)> GetStatistics(RoomScore model) => new[] + { + (FontAwesome.fa_crosshairs, string.Format(model.Accuracy % 1 == 0 ? @"{0:P0}" : @"{0:P2}", model.Accuracy), "Accuracy"), + (FontAwesome.fa_refresh, model.TotalAttempts.ToString(), "Total Attempts"), + (FontAwesome.fa_check, model.CompletedAttempts.ToString(), "Completed Beatmaps"), + }; + + protected override int GetTotalScore(RoomScore model) => model.TotalScore; + + protected override ScoreRank GetRank(RoomScore model) => ScoreRank.S; + } + + public enum MatchLeaderboardScope + { + Overall + } + + public class RoomScore + { + [JsonProperty("user")] + public User User { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty("total_score")] + public int TotalScore { get; set; } + + [JsonProperty("pp")] + public double PP { get; set; } + + [JsonProperty("attempts")] + public int TotalAttempts { get; set; } + + [JsonProperty("completed")] + public int CompletedAttempts { get; set; } + } +} diff --git a/osu.Game/Screens/Multi/Match/MatchScreen.cs b/osu.Game/Screens/Multi/Match/MatchScreen.cs index abcec16089..d4e73308c3 100644 --- a/osu.Game/Screens/Multi/Match/MatchScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchScreen.cs @@ -76,7 +76,26 @@ namespace osu.Game.Screens.Multi.Match { new Drawable[] { header = new Components.Header { Depth = -1 } }, new Drawable[] { info = new Info { OnStart = onStart } }, - new Drawable[] { participants = new Participants { RelativeSizeAxes = Axes.Both } }, + new Drawable[] + { + new GridContainer + { + RelativeSizeAxes = Axes.Both, + Content = new[] + { + new Drawable[] + { + participants = new Participants { RelativeSizeAxes = Axes.Both }, + new MatchLeaderboard(room) { RelativeSizeAxes = Axes.Both } + }, + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.Relative, 0.5f), + } + } + }, }, RowDimensions = new[] {