diff --git a/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs b/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs
index 580dcee18c..d3be240d4c 100644
--- a/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs
+++ b/osu.Game/Beatmaps/BeatmapOnlineLookupQueue.cs
@@ -102,6 +102,8 @@ namespace osu.Game.Beatmaps
beatmapInfo.BeatmapSet.Status = res.BeatmapSet?.Status ?? BeatmapOnlineStatus.None;
beatmapInfo.BeatmapSet.OnlineID = res.OnlineBeatmapSetID;
+ beatmapInfo.BeatmapSet.DateRanked = res.BeatmapSet?.Ranked;
+ beatmapInfo.BeatmapSet.DateSubmitted = res.BeatmapSet?.Submitted;
beatmapInfo.OnlineMD5Hash = res.MD5Hash;
beatmapInfo.LastOnlineUpdate = res.LastUpdated;
@@ -194,7 +196,8 @@ namespace osu.Game.Beatmaps
using (var cmd = db.CreateCommand())
{
- cmd.CommandText = "SELECT beatmapset_id, beatmap_id, approved, user_id, checksum, last_update FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineID OR filename = @Path";
+ cmd.CommandText =
+ "SELECT beatmapset_id, beatmap_id, approved, user_id, checksum, last_update FROM osu_beatmaps WHERE checksum = @MD5Hash OR beatmap_id = @OnlineID OR filename = @Path";
cmd.Parameters.Add(new SqliteParameter("@MD5Hash", beatmapInfo.MD5Hash));
cmd.Parameters.Add(new SqliteParameter("@OnlineID", beatmapInfo.OnlineID));
@@ -212,6 +215,7 @@ namespace osu.Game.Beatmaps
beatmapInfo.BeatmapSet.Status = status;
beatmapInfo.BeatmapSet.OnlineID = reader.GetInt32(0);
+ // TODO: DateSubmitted and DateRanked are not provided by local cache.
beatmapInfo.OnlineID = reader.GetInt32(1);
beatmapInfo.Metadata.Author.OnlineID = reader.GetInt32(3);
diff --git a/osu.Game/Beatmaps/BeatmapSetInfo.cs b/osu.Game/Beatmaps/BeatmapSetInfo.cs
index ead280a75e..b404f0b34d 100644
--- a/osu.Game/Beatmaps/BeatmapSetInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapSetInfo.cs
@@ -26,6 +26,16 @@ namespace osu.Game.Beatmaps
public DateTimeOffset DateAdded { get; set; }
+ ///
+ /// The date this beatmap set was first submitted.
+ ///
+ public DateTimeOffset? DateSubmitted { get; set; }
+
+ ///
+ /// The date this beatmap set was ranked.
+ ///
+ public DateTimeOffset? DateRanked { get; set; }
+
[JsonIgnore]
public IBeatmapMetadataInfo Metadata => Beatmaps.FirstOrDefault()?.Metadata ?? new BeatmapMetadata();
diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs
index 28870617cc..dff2bdddbd 100644
--- a/osu.Game/Database/RealmAccess.cs
+++ b/osu.Game/Database/RealmAccess.cs
@@ -62,8 +62,9 @@ namespace osu.Game.Database
/// 16 2022-07-15 Removed HasReplay from ScoreInfo.
/// 17 2022-07-16 Added CountryCode to RealmUser.
/// 18 2022-07-19 Added OnlineMD5Hash and LastOnlineUpdate to BeatmapInfo.
+ /// 19 2022-07-19 Added DateSubmitted and DateRanked to BeatmapSetInfo.
///
- private const int schema_version = 18;
+ private const int schema_version = 19;
///
/// Lock object which is held during sections, blocking realm retrieval during blocking periods.
diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs
index c57cbcfba4..81734745c4 100644
--- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs
+++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs
@@ -55,6 +55,8 @@ namespace osu.Game.Screens.Select.Carousel
match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(BeatmapInfo.Metadata.Artist) ||
criteria.Artist.Matches(BeatmapInfo.Metadata.ArtistUnicode);
+ match &= criteria.Sort != SortMode.DateRanked || BeatmapInfo.BeatmapSet?.DateRanked != null;
+
match &= !criteria.UserStarDifficulty.HasFilter || criteria.UserStarDifficulty.IsInRange(BeatmapInfo.StarRating);
if (match && criteria.SearchTerms.Length > 0)
diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs
index 94d911692c..bd7b1f12a4 100644
--- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs
+++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs
@@ -81,6 +81,13 @@ namespace osu.Game.Screens.Select.Carousel
case SortMode.DateAdded:
return otherSet.BeatmapSet.DateAdded.CompareTo(BeatmapSet.DateAdded);
+ case SortMode.DateRanked:
+ // Beatmaps which have no ranked date should already be filtered away in this mode.
+ if (BeatmapSet.DateRanked == null || otherSet.BeatmapSet.DateRanked == null)
+ return 0;
+
+ return otherSet.BeatmapSet.DateRanked.Value.CompareTo(BeatmapSet.DateRanked.Value);
+
case SortMode.LastPlayed:
return -compareUsingAggregateMax(otherSet, b => (b.LastPlayed ?? DateTimeOffset.MinValue).ToUnixTimeSeconds());
diff --git a/osu.Game/Screens/Select/Filter/SortMode.cs b/osu.Game/Screens/Select/Filter/SortMode.cs
index 4227114618..1e60ea3bac 100644
--- a/osu.Game/Screens/Select/Filter/SortMode.cs
+++ b/osu.Game/Screens/Select/Filter/SortMode.cs
@@ -23,6 +23,9 @@ namespace osu.Game.Screens.Select.Filter
[Description("Date Added")]
DateAdded,
+ [Description("Date Ranked")]
+ DateRanked,
+
[Description("Last Played")]
LastPlayed,