From 78edc7554e65898cefa200c744abf2b45b631825 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 12:05:34 +0900 Subject: [PATCH 1/5] Fix `BeatmapSetInfo`'s `Status` value being marked as non-databased --- osu.Game/Beatmaps/BeatmapSetInfo.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs index 79cd8253f7..0c032e1482 100644 --- a/osu.Game/Beatmaps/BeatmapSetInfo.cs +++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs @@ -117,7 +117,6 @@ namespace osu.Game.Beatmaps [JsonIgnore] public DateTimeOffset? LastUpdated => OnlineInfo.LastUpdated; - [NotMapped] [JsonIgnore] public BeatmapSetOnlineStatus Status { get; set; } = BeatmapSetOnlineStatus.None; From 7c99193ada60807bab91c9b27e0eb37e3f01c174 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 16:45:46 +0900 Subject: [PATCH 2/5] Add tournament `LadderInfo` serialisation tests --- .../NonVisual/LadderInfoSerialisationTest.cs | 65 +++++++++++++++++++ .../TournamentTestScene.cs | 12 +++- osu.Game.Tournament/TournamentSceneManager.cs | 2 +- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs diff --git a/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs new file mode 100644 index 0000000000..13cbcd3caf --- /dev/null +++ b/osu.Game.Tournament.Tests/NonVisual/LadderInfoSerialisationTest.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; +using NUnit.Framework; +using osu.Game.Tournament.Models; + +namespace osu.Game.Tournament.Tests.NonVisual +{ + [TestFixture] + public class LadderInfoSerialisationTest + { + [Test] + public void TestDeserialise() + { + var ladder = createSampleLadder(); + string serialised = JsonConvert.SerializeObject(ladder); + + JsonConvert.DeserializeObject(serialised, new JsonPointConverter()); + } + + [Test] + public void TestSerialise() + { + var ladder = createSampleLadder(); + JsonConvert.SerializeObject(ladder); + } + + private static LadderInfo createSampleLadder() + { + var match = TournamentTestScene.CreateSampleMatch(); + + return new LadderInfo + { + PlayersPerTeam = { Value = 4 }, + Teams = + { + match.Team1.Value, + match.Team2.Value, + }, + Rounds = + { + new TournamentRound + { + Beatmaps = + { + new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmapInfo() }, + new RoundBeatmap { BeatmapInfo = TournamentTestScene.CreateSampleBeatmapInfo() }, + } + } + }, + + Matches = + { + match, + }, + Progressions = + { + new TournamentProgression(1, 2), + new TournamentProgression(1, 3, true), + } + }; + } + } +} diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 93e1e018a5..3ea58e9867 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -8,6 +8,7 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.IO; @@ -152,7 +153,16 @@ namespace osu.Game.Tournament.Tests }; public static BeatmapInfo CreateSampleBeatmapInfo() => - new BeatmapInfo { Metadata = new BeatmapMetadata { Title = "Test Title", Artist = "Test Artist", ID = RNG.Next(0, 1000000) } }; + new BeatmapInfo + { + Metadata = new BeatmapMetadata + { + Title = "Test Title", + Artist = "Test Artist", + ID = RNG.Next(0, 1000000) + }, + OnlineInfo = new BeatmapOnlineInfo(), + }; protected override ITestSceneTestRunner CreateRunner() => new TournamentTestSceneTestRunner(); diff --git a/osu.Game.Tournament/TournamentSceneManager.cs b/osu.Game.Tournament/TournamentSceneManager.cs index ced1a8ec72..914d1163ad 100644 --- a/osu.Game.Tournament/TournamentSceneManager.cs +++ b/osu.Game.Tournament/TournamentSceneManager.cs @@ -237,7 +237,7 @@ namespace osu.Game.Tournament { Type = type; BackgroundColour = OsuColour.Gray(0.2f); - Action = () => RequestSelection(type); + Action = () => RequestSelection?.Invoke(type); RelativeSizeAxes = Axes.X; } From 7111f58bfee77791652f4059b5e2032ea08a4bf9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 16:46:07 +0900 Subject: [PATCH 3/5] Fix tournament client silently failing on error during parsing --- osu.Game.Tournament/TournamentGame.cs | 136 ++++++++++++---------- osu.Game.Tournament/TournamentGameBase.cs | 122 ++++++++++--------- 2 files changed, 142 insertions(+), 116 deletions(-) diff --git a/osu.Game.Tournament/TournamentGame.cs b/osu.Game.Tournament/TournamentGame.cs index 7a43fee013..f3927bb852 100644 --- a/osu.Game.Tournament/TournamentGame.cs +++ b/osu.Game.Tournament/TournamentGame.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Handlers.Mouse; +using osu.Framework.Logging; using osu.Framework.Platform; using osu.Game.Graphics; using osu.Game.Graphics.Cursor; @@ -60,72 +61,89 @@ namespace osu.Game.Tournament loadingSpinner.Show(); - BracketLoadTask.ContinueWith(_ => LoadComponentsAsync(new[] + BracketLoadTask.ContinueWith(t => { - new Container + if (t.IsFaulted) { - CornerRadius = 10, - Depth = float.MinValue, - Position = new Vector2(5), - Masking = true, - AutoSizeAxes = Axes.Both, - Anchor = Anchor.BottomRight, - Origin = Anchor.BottomRight, - Children = new Drawable[] + Schedule(() => { - new Box - { - Colour = OsuColour.Gray(0.2f), - RelativeSizeAxes = Axes.Both, - }, - new TourneyButton - { - Text = "Save Changes", - Width = 140, - Height = 50, - Padding = new MarginPadding - { - Top = 10, - Left = 10, - }, - Margin = new MarginPadding - { - Right = 10, - Bottom = 10, - }, - Action = SaveChanges, - }, - } - }, - heightWarning = new WarningBox("Please make the window wider") - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Margin = new MarginPadding(20), - }, - new OsuContextMenuContainer - { - RelativeSizeAxes = Axes.Both, - Child = new TournamentSceneManager() + loadingSpinner.Hide(); + loadingSpinner.Expire(); + + Logger.Error(t.Exception, "Couldn't load bracket with error"); + Add(new WarningBox("Your bracket.json file could not be parsed. Please check runtime.log for more details.")); + }); + + return; } - }, drawables => - { - loadingSpinner.Hide(); - loadingSpinner.Expire(); - AddRange(drawables); - - windowSize.BindValueChanged(size => ScheduleAfterChildren(() => + LoadComponentsAsync(new[] { - var minWidth = (int)(size.NewValue.Height / 768f * TournamentSceneManager.REQUIRED_WIDTH) - 1; - heightWarning.Alpha = size.NewValue.Width < minWidth ? 1 : 0; - }), true); - - windowMode.BindValueChanged(mode => ScheduleAfterChildren(() => + new Container + { + CornerRadius = 10, + Depth = float.MinValue, + Position = new Vector2(5), + Masking = true, + AutoSizeAxes = Axes.Both, + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Children = new Drawable[] + { + new Box + { + Colour = OsuColour.Gray(0.2f), + RelativeSizeAxes = Axes.Both, + }, + new TourneyButton + { + Text = "Save Changes", + Width = 140, + Height = 50, + Padding = new MarginPadding + { + Top = 10, + Left = 10, + }, + Margin = new MarginPadding + { + Right = 10, + Bottom = 10, + }, + Action = SaveChanges, + }, + } + }, + heightWarning = new WarningBox("Please make the window wider") + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Margin = new MarginPadding(20), + }, + new OsuContextMenuContainer + { + RelativeSizeAxes = Axes.Both, + Child = new TournamentSceneManager() + } + }, drawables => { - windowMode.Value = WindowMode.Windowed; - }), true); - })); + loadingSpinner.Hide(); + loadingSpinner.Expire(); + + AddRange(drawables); + + windowSize.BindValueChanged(size => ScheduleAfterChildren(() => + { + var minWidth = (int)(size.NewValue.Height / 768f * TournamentSceneManager.REQUIRED_WIDTH) - 1; + heightWarning.Alpha = size.NewValue.Width < minWidth ? 1 : 0; + }), true); + + windowMode.BindValueChanged(mode => ScheduleAfterChildren(() => + { + windowMode.Value = WindowMode.Windowed; + }), true); + }); + }); } } } diff --git a/osu.Game.Tournament/TournamentGameBase.cs b/osu.Game.Tournament/TournamentGameBase.cs index bdf7269c83..a6b0fa5cfc 100644 --- a/osu.Game.Tournament/TournamentGameBase.cs +++ b/osu.Game.Tournament/TournamentGameBase.cs @@ -58,75 +58,83 @@ namespace osu.Game.Tournament private void readBracket() { - if (storage.Exists(bracket_filename)) + try { - using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) - using (var sr = new StreamReader(stream)) - ladder = JsonConvert.DeserializeObject(sr.ReadToEnd(), new JsonPointConverter()); - } - - ladder ??= new LadderInfo(); - - ladder.Ruleset.Value = RulesetStore.GetRuleset(ladder.Ruleset.Value?.ShortName) - ?? RulesetStore.AvailableRulesets.First(); - - bool addedInfo = false; - - // assign teams - foreach (var match in ladder.Matches) - { - match.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team1Acronym); - match.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team2Acronym); - - foreach (var conditional in match.ConditionalMatches) + if (storage.Exists(bracket_filename)) { - conditional.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team1Acronym); - conditional.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team2Acronym); - conditional.Round.Value = match.Round.Value; + using (Stream stream = storage.GetStream(bracket_filename, FileAccess.Read, FileMode.Open)) + using (var sr = new StreamReader(stream)) + ladder = JsonConvert.DeserializeObject(sr.ReadToEnd(), new JsonPointConverter()); } - } - // assign progressions - foreach (var pair in ladder.Progressions) - { - var src = ladder.Matches.FirstOrDefault(p => p.ID == pair.SourceID); - var dest = ladder.Matches.FirstOrDefault(p => p.ID == pair.TargetID); + ladder ??= new LadderInfo(); - if (src == null) - continue; + ladder.Ruleset.Value = RulesetStore.GetRuleset(ladder.Ruleset.Value?.ShortName) + ?? RulesetStore.AvailableRulesets.First(); - if (dest != null) + bool addedInfo = false; + + // assign teams + foreach (var match in ladder.Matches) { - if (pair.Losers) - src.LosersProgression.Value = dest; - else - src.Progression.Value = dest; - } - } + match.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team1Acronym); + match.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == match.Team2Acronym); - // link matches to rounds - foreach (var round in ladder.Rounds) - { - foreach (var id in round.Matches) - { - var found = ladder.Matches.FirstOrDefault(p => p.ID == id); - - if (found != null) + foreach (var conditional in match.ConditionalMatches) { - found.Round.Value = round; - if (round.StartDate.Value > found.Date.Value) - found.Date.Value = round.StartDate.Value; + conditional.Team1.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team1Acronym); + conditional.Team2.Value = ladder.Teams.FirstOrDefault(t => t.Acronym.Value == conditional.Team2Acronym); + conditional.Round.Value = match.Round.Value; } } + + // assign progressions + foreach (var pair in ladder.Progressions) + { + var src = ladder.Matches.FirstOrDefault(p => p.ID == pair.SourceID); + var dest = ladder.Matches.FirstOrDefault(p => p.ID == pair.TargetID); + + if (src == null) + continue; + + if (dest != null) + { + if (pair.Losers) + src.LosersProgression.Value = dest; + else + src.Progression.Value = dest; + } + } + + // link matches to rounds + foreach (var round in ladder.Rounds) + { + foreach (var id in round.Matches) + { + var found = ladder.Matches.FirstOrDefault(p => p.ID == id); + + if (found != null) + { + found.Round.Value = round; + if (round.StartDate.Value > found.Date.Value) + found.Date.Value = round.StartDate.Value; + } + } + } + + addedInfo |= addPlayers(); + addedInfo |= addBeatmaps(); + + if (addedInfo) + SaveChanges(); + + ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value); + } + catch (Exception e) + { + taskCompletionSource.SetException(e); + return; } - - addedInfo |= addPlayers(); - addedInfo |= addBeatmaps(); - - if (addedInfo) - SaveChanges(); - - ladder.CurrentMatch.Value = ladder.Matches.FirstOrDefault(p => p.Current.Value); Schedule(() => { From b65d199f6ab7e54695b9a1b459c988a53b55d2de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Oct 2021 17:01:47 +0900 Subject: [PATCH 4/5] Fix incorrect length when calling `APIBeatmap.ToBeatmapInfo` --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index 6e43ac5504..fee3e56859 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -54,7 +54,7 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"accuracy")] private float overallDifficulty { get; set; } - public double Length => lengthInSeconds * 1000; + public double Length => TimeSpan.FromSeconds(lengthInSeconds).TotalMilliseconds; [JsonProperty(@"total_length")] private double lengthInSeconds { get; set; } @@ -86,7 +86,7 @@ namespace osu.Game.Online.API.Requests.Responses OnlineBeatmapID = OnlineID, Version = DifficultyName, // this is actually an incorrect mapping (Length is calculated as drain length in lazer's import process, see BeatmapManager.calculateLength). - Length = TimeSpan.FromSeconds(Length).TotalMilliseconds, + Length = Length, Status = Status, MD5Hash = Checksum, BeatmapSet = set, From 3f91e74e576a9a18594a7b2830ee5c35c57a20c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 25 Oct 2021 19:26:52 +0200 Subject: [PATCH 5/5] Remove unused using directive --- osu.Game.Tournament.Tests/TournamentTestScene.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tournament.Tests/TournamentTestScene.cs b/osu.Game.Tournament.Tests/TournamentTestScene.cs index 3ea58e9867..bd079eb8de 100644 --- a/osu.Game.Tournament.Tests/TournamentTestScene.cs +++ b/osu.Game.Tournament.Tests/TournamentTestScene.cs @@ -8,7 +8,6 @@ using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets; using osu.Game.Tests.Visual; using osu.Game.Tournament.IO;