From cf438b1a44781bfc0bee8597f8945eddec5a2036 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Jun 2022 18:01:54 +0900 Subject: [PATCH 1/7] Add index on `MD5Hash` property Reduces actual query overhead significantly --- osu.Game/Beatmaps/BeatmapInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index abc9020dc6..5925dd7064 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -90,6 +90,7 @@ namespace osu.Game.Beatmaps public double StarRating { get; set; } + [Indexed] public string MD5Hash { get; set; } = string.Empty; [JsonIgnore] From 42cd7d9e6ea9942edad6e2751c008d1281718aec Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Jun 2022 18:23:09 +0900 Subject: [PATCH 2/7] Change `CollectionManager` to only store MD5 hashes instead of full `BeatmapInfo` --- .../TestSceneManageCollectionsDialog.cs | 6 +++--- .../Visual/SongSelect/TestSceneFilterControl.cs | 6 +++--- osu.Game/Collections/BeatmapCollection.cs | 4 ++-- .../Collections/CollectionFilterDropdown.cs | 10 +++++----- osu.Game/Collections/CollectionManager.cs | 17 ++++++----------- osu.Game/Overlays/Music/Playlist.cs | 17 ++++++++++++++++- .../Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- .../Select/Carousel/DrawableCarouselBeatmap.cs | 6 +++--- .../Carousel/DrawableCarouselBeatmapSet.cs | 8 ++++---- 9 files changed, 43 insertions(+), 33 deletions(-) diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index 888002eb36..caf3473c45 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -152,7 +152,7 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add two collections with same name", () => manager.Collections.AddRange(new[] { new BeatmapCollection { Name = { Value = "1" } }, - new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0] } }, + new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); } @@ -162,7 +162,7 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add two collections", () => manager.Collections.AddRange(new[] { new BeatmapCollection { Name = { Value = "1" } }, - new BeatmapCollection { Name = { Value = "2" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0] } }, + new BeatmapCollection { Name = { Value = "2" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); assertCollectionCount(2); @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Collections { AddStep("add two collections", () => manager.Collections.AddRange(new[] { - new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0] } }, + new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); assertCollectionCount(1); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs index b7ec128596..db49ec06f8 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs @@ -151,7 +151,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } })); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); - AddStep("add beatmap to collection", () => collectionManager.Collections[0].Beatmaps.Add(Beatmap.Value.BeatmapInfo)); + AddStep("add beatmap to collection", () => collectionManager.Collections[0].Beatmaps.Add(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare)); AddStep("remove beatmap from collection", () => collectionManager.Collections[0].Beatmaps.Clear()); @@ -169,11 +169,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); addClickAddOrRemoveButtonStep(1); - AddAssert("collection contains beatmap", () => collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo)); + AddAssert("collection contains beatmap", () => collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare)); addClickAddOrRemoveButtonStep(1); - AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo)); + AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); } diff --git a/osu.Game/Collections/BeatmapCollection.cs b/osu.Game/Collections/BeatmapCollection.cs index 7e4b15ecf9..ca0f57f638 100644 --- a/osu.Game/Collections/BeatmapCollection.cs +++ b/osu.Game/Collections/BeatmapCollection.cs @@ -23,9 +23,9 @@ namespace osu.Game.Collections public readonly Bindable Name = new Bindable(); /// - /// The beatmaps contained by the collection. + /// The es of beatmaps contained by the collection. /// - public readonly BindableList Beatmaps = new BindableList(); + public readonly BindableList Beatmaps = new BindableList(); /// /// The date when this collection was last modified. diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index c46ba8e06e..97e5711d75 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -38,7 +38,7 @@ namespace osu.Game.Collections } private readonly IBindableList collections = new BindableList(); - private readonly IBindableList beatmaps = new BindableList(); + private readonly IBindableList beatmaps = new BindableList(); private readonly BindableList filters = new BindableList(); [Resolved(CanBeNull = true)] @@ -196,7 +196,7 @@ namespace osu.Game.Collections private IBindable beatmap { get; set; } [CanBeNull] - private readonly BindableList collectionBeatmaps; + private readonly BindableList collectionBeatmaps; [NotNull] private readonly Bindable collectionName; @@ -258,7 +258,7 @@ namespace osu.Game.Collections { Debug.Assert(collectionBeatmaps != null); - beatmapInCollection = collectionBeatmaps.Contains(beatmap.Value.BeatmapInfo); + beatmapInCollection = collectionBeatmaps.Contains(beatmap.Value.BeatmapInfo.MD5Hash); addOrRemoveButton.Enabled.Value = !beatmap.IsDefault; addOrRemoveButton.Icon = beatmapInCollection ? FontAwesome.Solid.MinusSquare : FontAwesome.Solid.PlusSquare; @@ -285,8 +285,8 @@ namespace osu.Game.Collections { Debug.Assert(collectionBeatmaps != null); - if (!collectionBeatmaps.Remove(beatmap.Value.BeatmapInfo)) - collectionBeatmaps.Add(beatmap.Value.BeatmapInfo); + if (!collectionBeatmaps.Remove(beatmap.Value.BeatmapInfo.MD5Hash)) + collectionBeatmaps.Add(beatmap.Value.BeatmapInfo.MD5Hash); } protected override Drawable CreateContent() => content = (Content)base.CreateContent(); diff --git a/osu.Game/Collections/CollectionManager.cs b/osu.Game/Collections/CollectionManager.cs index 700b0f5dcb..30171a71af 100644 --- a/osu.Game/Collections/CollectionManager.cs +++ b/osu.Game/Collections/CollectionManager.cs @@ -13,7 +13,6 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Logging; using osu.Framework.Platform; -using osu.Game.Beatmaps; using osu.Game.Database; using osu.Game.IO; using osu.Game.IO.Legacy; @@ -40,9 +39,6 @@ namespace osu.Game.Collections public readonly BindableList Collections = new BindableList(); - [Resolved] - private BeatmapManager beatmaps { get; set; } - private readonly Storage storage; public CollectionManager(Storage storage) @@ -173,7 +169,7 @@ namespace osu.Game.Collections if (existing == null) Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } }); - foreach (var newBeatmap in newCol.Beatmaps) + foreach (string newBeatmap in newCol.Beatmaps) { if (!existing.Beatmaps.Contains(newBeatmap)) existing.Beatmaps.Add(newBeatmap); @@ -226,9 +222,7 @@ namespace osu.Game.Collections string checksum = sr.ReadString(); - var beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == checksum); - if (beatmap != null) - collection.Beatmaps.Add(beatmap); + collection.Beatmaps.Add(checksum); } if (notification != null) @@ -299,11 +293,12 @@ namespace osu.Game.Collections { sw.Write(c.Name.Value); - var beatmapsCopy = c.Beatmaps.ToArray(); + string[] beatmapsCopy = c.Beatmaps.ToArray(); + sw.Write(beatmapsCopy.Length); - foreach (var b in beatmapsCopy) - sw.Write(b.MD5Hash); + foreach (string b in beatmapsCopy) + sw.Write(b); } } diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 24d867141c..4653a65041 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -30,7 +30,22 @@ namespace osu.Game.Overlays.Music var items = (SearchContainer>>)ListContainer; foreach (var item in items.OfType()) - item.InSelectedCollection = criteria.Collection?.Beatmaps.Any(b => item.Model.ID == b.BeatmapSet?.ID) ?? true; + { + var beatmapHashes = item.Model.Value.Beatmaps.Select(b => b.MD5Hash); + + bool contained = false; + + foreach (string hash in beatmapHashes) + { + if (criteria.Collection?.Beatmaps.Contains(hash) == true) + { + contained = true; + break; + } + } + + item.InSelectedCollection = contained; + } items.SearchTerm = criteria.SearchText; } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index fd6a869938..de9899f288 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -72,7 +72,7 @@ namespace osu.Game.Screens.Select.Carousel } if (match) - match &= criteria.Collection?.Beatmaps.Contains(BeatmapInfo) ?? true; + match &= criteria.Collection?.Beatmaps.Contains(BeatmapInfo.MD5Hash) ?? true; if (match && criteria.RulesetCriteria != null) match &= criteria.RulesetCriteria.Matches(BeatmapInfo); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 98b885eb43..79d27e9d9d 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -256,12 +256,12 @@ namespace osu.Game.Screens.Select.Carousel return new ToggleMenuItem(collection.Name.Value, MenuItemType.Standard, s => { if (s) - collection.Beatmaps.Add(beatmapInfo); + collection.Beatmaps.Add(beatmapInfo.MD5Hash); else - collection.Beatmaps.Remove(beatmapInfo); + collection.Beatmaps.Remove(beatmapInfo.MD5Hash); }) { - State = { Value = collection.Beatmaps.Contains(beatmapInfo) } + State = { Value = collection.Beatmaps.Contains(beatmapInfo.MD5Hash) } }; } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 2d70b1aecb..ade89c5b35 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -245,7 +245,7 @@ namespace osu.Game.Screens.Select.Carousel TernaryState state; - int countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b)); + int countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b.MD5Hash)); if (countExisting == beatmapSet.Beatmaps.Count) state = TernaryState.True; @@ -261,14 +261,14 @@ namespace osu.Game.Screens.Select.Carousel switch (s) { case TernaryState.True: - if (collection.Beatmaps.Contains(b)) + if (collection.Beatmaps.Contains(b.MD5Hash)) continue; - collection.Beatmaps.Add(b); + collection.Beatmaps.Add(b.MD5Hash); break; case TernaryState.False: - collection.Beatmaps.Remove(b); + collection.Beatmaps.Remove(b.MD5Hash); break; } } From 3d4d87bcb2194ad2c48aa9d41569170a0d91913a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Jun 2022 18:34:28 +0900 Subject: [PATCH 3/7] Update test expectations --- osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs index 5cbede54f5..db6e93206d 100644 --- a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs +++ b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs @@ -50,10 +50,10 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.Zero); + Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(1)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.Zero); + Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.EqualTo(12)); } finally { From 6aa84425a28eb420c0388d20b93d38cc26f61f17 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Jun 2022 19:26:34 +0900 Subject: [PATCH 4/7] Add comment explaining test expectations --- osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs index db6e93206d..73152c33d9 100644 --- a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs +++ b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs @@ -49,6 +49,11 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); + // Even with no beatmaps imported, collections are tracking the hashes and will continue to. + // In the future this whole mechanism will be replaced with having the collections in realm, + // but until that happens it makes rough sense that we want to track not-yet-imported beatmaps + // and have them associate with collections if/when they become available. + Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(1)); From c22bffaa012ed7750c011fc3796e9ef6d997786b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Jun 2022 19:30:18 +0900 Subject: [PATCH 5/7] Fix filter failure when no collection is selected --- osu.Game/Overlays/Music/Playlist.cs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 4653a65041..1d8163b57b 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -31,20 +31,25 @@ namespace osu.Game.Overlays.Music foreach (var item in items.OfType()) { - var beatmapHashes = item.Model.Value.Beatmaps.Select(b => b.MD5Hash); - - bool contained = false; - - foreach (string hash in beatmapHashes) + if (criteria.Collection == null) + item.InSelectedCollection = true; + else { - if (criteria.Collection?.Beatmaps.Contains(hash) == true) - { - contained = true; - break; - } - } + var beatmapHashes = item.Model.Value.Beatmaps.Select(b => b.MD5Hash); - item.InSelectedCollection = contained; + bool contained = false; + + foreach (string hash in beatmapHashes) + { + if (criteria.Collection?.Beatmaps.Contains(hash) == true) + { + contained = true; + break; + } + } + + item.InSelectedCollection = contained; + } } items.SearchTerm = criteria.SearchText; From 3b229624dd2c257b7ccbc85d9b057eb3938a7ed3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Jun 2022 14:02:58 +0900 Subject: [PATCH 6/7] Simplify contains check to use LINQ the whole way --- osu.Game/Overlays/Music/Playlist.cs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 1d8163b57b..9d31af256f 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -35,20 +35,8 @@ namespace osu.Game.Overlays.Music item.InSelectedCollection = true; else { - var beatmapHashes = item.Model.Value.Beatmaps.Select(b => b.MD5Hash); - - bool contained = false; - - foreach (string hash in beatmapHashes) - { - if (criteria.Collection?.Beatmaps.Contains(hash) == true) - { - contained = true; - break; - } - } - - item.InSelectedCollection = contained; + item.InSelectedCollection = item.Model.Value.Beatmaps.Select(b => b.MD5Hash) + .Any(criteria.Collection.Beatmaps.Contains); } } From 4a5e86e451733c7b0fe9fdf7622f0392905be4fb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 10 Jun 2022 14:03:51 +0900 Subject: [PATCH 7/7] Rename `Beatmaps` to `BeatmapHashes` for clarity --- .../Collections/IO/ImportCollectionsTest.cs | 16 ++++++++-------- .../TestSceneManageCollectionsDialog.cs | 6 +++--- .../Visual/SongSelect/TestSceneFilterControl.cs | 8 ++++---- osu.Game/Collections/BeatmapCollection.cs | 4 ++-- osu.Game/Collections/CollectionFilterDropdown.cs | 6 +++--- osu.Game/Collections/CollectionManager.cs | 10 +++++----- osu.Game/Collections/DeleteCollectionDialog.cs | 2 +- .../Collections/DrawableCollectionListItem.cs | 2 +- osu.Game/Overlays/Music/Playlist.cs | 2 +- .../Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- .../Select/Carousel/DrawableCarouselBeatmap.cs | 6 +++--- .../Carousel/DrawableCarouselBeatmapSet.cs | 8 ++++---- 12 files changed, 36 insertions(+), 36 deletions(-) diff --git a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs index 73152c33d9..41bc075803 100644 --- a/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs +++ b/osu.Game.Tests/Collections/IO/ImportCollectionsTest.cs @@ -55,10 +55,10 @@ namespace osu.Game.Tests.Collections.IO // and have them associate with collections if/when they become available. Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(1)); + Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(1)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.EqualTo(12)); + Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(12)); } finally { @@ -81,10 +81,10 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(1)); + Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(1)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.EqualTo(12)); + Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(12)); } finally { @@ -147,8 +147,8 @@ namespace osu.Game.Tests.Collections.IO await importCollectionsFromStream(osu, TestResources.OpenResource("Collections/collections.db")); // Move first beatmap from second collection into the first. - osu.CollectionManager.Collections[0].Beatmaps.Add(osu.CollectionManager.Collections[1].Beatmaps[0]); - osu.CollectionManager.Collections[1].Beatmaps.RemoveAt(0); + osu.CollectionManager.Collections[0].BeatmapHashes.Add(osu.CollectionManager.Collections[1].BeatmapHashes[0]); + osu.CollectionManager.Collections[1].BeatmapHashes.RemoveAt(0); // Rename the second collecction. osu.CollectionManager.Collections[1].Name.Value = "Another"; @@ -169,10 +169,10 @@ namespace osu.Game.Tests.Collections.IO Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First")); - Assert.That(osu.CollectionManager.Collections[0].Beatmaps.Count, Is.EqualTo(2)); + Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(2)); Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Another")); - Assert.That(osu.CollectionManager.Collections[1].Beatmaps.Count, Is.EqualTo(11)); + Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(11)); } finally { diff --git a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs index caf3473c45..602c7c84b8 100644 --- a/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs +++ b/osu.Game.Tests/Visual/Collections/TestSceneManageCollectionsDialog.cs @@ -152,7 +152,7 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add two collections with same name", () => manager.Collections.AddRange(new[] { new BeatmapCollection { Name = { Value = "1" } }, - new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, + new BeatmapCollection { Name = { Value = "1" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); } @@ -162,7 +162,7 @@ namespace osu.Game.Tests.Visual.Collections AddStep("add two collections", () => manager.Collections.AddRange(new[] { new BeatmapCollection { Name = { Value = "1" } }, - new BeatmapCollection { Name = { Value = "2" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, + new BeatmapCollection { Name = { Value = "2" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); assertCollectionCount(2); @@ -198,7 +198,7 @@ namespace osu.Game.Tests.Visual.Collections { AddStep("add two collections", () => manager.Collections.AddRange(new[] { - new BeatmapCollection { Name = { Value = "1" }, Beatmaps = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, + new BeatmapCollection { Name = { Value = "1" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } }, })); assertCollectionCount(1); diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs index db49ec06f8..b42ce3ff87 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneFilterControl.cs @@ -151,10 +151,10 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } })); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); - AddStep("add beatmap to collection", () => collectionManager.Collections[0].Beatmaps.Add(Beatmap.Value.BeatmapInfo.MD5Hash)); + AddStep("add beatmap to collection", () => collectionManager.Collections[0].BeatmapHashes.Add(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare)); - AddStep("remove beatmap from collection", () => collectionManager.Collections[0].Beatmaps.Clear()); + AddStep("remove beatmap from collection", () => collectionManager.Collections[0].BeatmapHashes.Clear()); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); } @@ -169,11 +169,11 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); addClickAddOrRemoveButtonStep(1); - AddAssert("collection contains beatmap", () => collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); + AddAssert("collection contains beatmap", () => collectionManager.Collections[0].BeatmapHashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare)); addClickAddOrRemoveButtonStep(1); - AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].Beatmaps.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); + AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].BeatmapHashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash)); AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare)); } diff --git a/osu.Game/Collections/BeatmapCollection.cs b/osu.Game/Collections/BeatmapCollection.cs index ca0f57f638..cf95c74b46 100644 --- a/osu.Game/Collections/BeatmapCollection.cs +++ b/osu.Game/Collections/BeatmapCollection.cs @@ -25,7 +25,7 @@ namespace osu.Game.Collections /// /// The es of beatmaps contained by the collection. /// - public readonly BindableList Beatmaps = new BindableList(); + public readonly BindableList BeatmapHashes = new BindableList(); /// /// The date when this collection was last modified. @@ -34,7 +34,7 @@ namespace osu.Game.Collections public BeatmapCollection() { - Beatmaps.CollectionChanged += (_, __) => onChange(); + BeatmapHashes.CollectionChanged += (_, __) => onChange(); Name.ValueChanged += _ => onChange(); } diff --git a/osu.Game/Collections/CollectionFilterDropdown.cs b/osu.Game/Collections/CollectionFilterDropdown.cs index 97e5711d75..100074d186 100644 --- a/osu.Game/Collections/CollectionFilterDropdown.cs +++ b/osu.Game/Collections/CollectionFilterDropdown.cs @@ -95,10 +95,10 @@ namespace osu.Game.Collections beatmaps.CollectionChanged -= filterBeatmapsChanged; if (filter.OldValue?.Collection != null) - beatmaps.UnbindFrom(filter.OldValue.Collection.Beatmaps); + beatmaps.UnbindFrom(filter.OldValue.Collection.BeatmapHashes); if (filter.NewValue?.Collection != null) - beatmaps.BindTo(filter.NewValue.Collection.Beatmaps); + beatmaps.BindTo(filter.NewValue.Collection.BeatmapHashes); beatmaps.CollectionChanged += filterBeatmapsChanged; @@ -208,7 +208,7 @@ namespace osu.Game.Collections public CollectionDropdownMenuItem(MenuItem item) : base(item) { - collectionBeatmaps = Item.Collection?.Beatmaps.GetBoundCopy(); + collectionBeatmaps = Item.Collection?.BeatmapHashes.GetBoundCopy(); collectionName = Item.CollectionName.GetBoundCopy(); } diff --git a/osu.Game/Collections/CollectionManager.cs b/osu.Game/Collections/CollectionManager.cs index 30171a71af..104ec4beb2 100644 --- a/osu.Game/Collections/CollectionManager.cs +++ b/osu.Game/Collections/CollectionManager.cs @@ -169,10 +169,10 @@ namespace osu.Game.Collections if (existing == null) Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } }); - foreach (string newBeatmap in newCol.Beatmaps) + foreach (string newBeatmap in newCol.BeatmapHashes) { - if (!existing.Beatmaps.Contains(newBeatmap)) - existing.Beatmaps.Add(newBeatmap); + if (!existing.BeatmapHashes.Contains(newBeatmap)) + existing.BeatmapHashes.Add(newBeatmap); } } @@ -222,7 +222,7 @@ namespace osu.Game.Collections string checksum = sr.ReadString(); - collection.Beatmaps.Add(checksum); + collection.BeatmapHashes.Add(checksum); } if (notification != null) @@ -293,7 +293,7 @@ namespace osu.Game.Collections { sw.Write(c.Name.Value); - string[] beatmapsCopy = c.Beatmaps.ToArray(); + string[] beatmapsCopy = c.BeatmapHashes.ToArray(); sw.Write(beatmapsCopy.Length); diff --git a/osu.Game/Collections/DeleteCollectionDialog.cs b/osu.Game/Collections/DeleteCollectionDialog.cs index e5a2f6fb81..e59adb14a6 100644 --- a/osu.Game/Collections/DeleteCollectionDialog.cs +++ b/osu.Game/Collections/DeleteCollectionDialog.cs @@ -13,7 +13,7 @@ namespace osu.Game.Collections public DeleteCollectionDialog(BeatmapCollection collection, Action deleteAction) { HeaderText = "Confirm deletion of"; - BodyText = $"{collection.Name.Value} ({"beatmap".ToQuantity(collection.Beatmaps.Count)})"; + BodyText = $"{collection.Name.Value} ({"beatmap".ToQuantity(collection.BeatmapHashes.Count)})"; Icon = FontAwesome.Regular.TrashAlt; diff --git a/osu.Game/Collections/DrawableCollectionListItem.cs b/osu.Game/Collections/DrawableCollectionListItem.cs index 5a20b7e7bd..5064041737 100644 --- a/osu.Game/Collections/DrawableCollectionListItem.cs +++ b/osu.Game/Collections/DrawableCollectionListItem.cs @@ -225,7 +225,7 @@ namespace osu.Game.Collections { background.FlashColour(Color4.White, 150); - if (collection.Beatmaps.Count == 0) + if (collection.BeatmapHashes.Count == 0) deleteCollection(); else dialogOverlay?.Push(new DeleteCollectionDialog(collection, deleteCollection)); diff --git a/osu.Game/Overlays/Music/Playlist.cs b/osu.Game/Overlays/Music/Playlist.cs index 9d31af256f..ff8f3197f9 100644 --- a/osu.Game/Overlays/Music/Playlist.cs +++ b/osu.Game/Overlays/Music/Playlist.cs @@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Music else { item.InSelectedCollection = item.Model.Value.Beatmaps.Select(b => b.MD5Hash) - .Any(criteria.Collection.Beatmaps.Contains); + .Any(criteria.Collection.BeatmapHashes.Contains); } } diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index de9899f288..c3f6b3ad83 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -72,7 +72,7 @@ namespace osu.Game.Screens.Select.Carousel } if (match) - match &= criteria.Collection?.Beatmaps.Contains(BeatmapInfo.MD5Hash) ?? true; + match &= criteria.Collection?.BeatmapHashes.Contains(BeatmapInfo.MD5Hash) ?? true; if (match && criteria.RulesetCriteria != null) match &= criteria.RulesetCriteria.Matches(BeatmapInfo); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 79d27e9d9d..065a29b53c 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -256,12 +256,12 @@ namespace osu.Game.Screens.Select.Carousel return new ToggleMenuItem(collection.Name.Value, MenuItemType.Standard, s => { if (s) - collection.Beatmaps.Add(beatmapInfo.MD5Hash); + collection.BeatmapHashes.Add(beatmapInfo.MD5Hash); else - collection.Beatmaps.Remove(beatmapInfo.MD5Hash); + collection.BeatmapHashes.Remove(beatmapInfo.MD5Hash); }) { - State = { Value = collection.Beatmaps.Contains(beatmapInfo.MD5Hash) } + State = { Value = collection.BeatmapHashes.Contains(beatmapInfo.MD5Hash) } }; } diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index ade89c5b35..80f1231454 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -245,7 +245,7 @@ namespace osu.Game.Screens.Select.Carousel TernaryState state; - int countExisting = beatmapSet.Beatmaps.Count(b => collection.Beatmaps.Contains(b.MD5Hash)); + int countExisting = beatmapSet.Beatmaps.Count(b => collection.BeatmapHashes.Contains(b.MD5Hash)); if (countExisting == beatmapSet.Beatmaps.Count) state = TernaryState.True; @@ -261,14 +261,14 @@ namespace osu.Game.Screens.Select.Carousel switch (s) { case TernaryState.True: - if (collection.Beatmaps.Contains(b.MD5Hash)) + if (collection.BeatmapHashes.Contains(b.MD5Hash)) continue; - collection.Beatmaps.Add(b.MD5Hash); + collection.BeatmapHashes.Add(b.MD5Hash); break; case TernaryState.False: - collection.Beatmaps.Remove(b.MD5Hash); + collection.BeatmapHashes.Remove(b.MD5Hash); break; } }