Add `LegacyOnlineID` handling to places that definitely need it

Mostly places that can interact with imported replays.

There are other places that use the online ID as a sort tiebreaker, or
to check presence of a score on results screens, but they should
probably still continue to only use `OnlineID`, since all scores with a
legacy online ID should have an online ID, but the converse is not
generally true.
This commit is contained in:
Bartłomiej Dach 2023-09-04 12:21:23 +02:00
parent c53f4c144c
commit b144cfd55c
No known key found for this signature in database
5 changed files with 31 additions and 4 deletions

View File

@ -114,8 +114,24 @@ public static string GetDisplayString(this object? model)
/// </summary>
/// <param name="instance">The instance to compare.</param>
/// <param name="other">The other instance to compare against.</param>
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
public static bool MatchesOnlineID(this IScoreInfo? instance, IScoreInfo? other) => matchesOnlineID(instance, other);
/// <returns>
/// Whether online IDs match.
/// Both <see cref="IHasOnlineID{T}.OnlineID"/> and <see cref="IScoreInfo.LegacyOnlineID"/> are checked, in that order.
/// If either instance is missing an online ID, this will return false.
/// </returns>
public static bool MatchesOnlineID(this IScoreInfo? instance, IScoreInfo? other)
{
if (matchesOnlineID(instance, other))
return true;
if (instance == null || other == null)
return false;
if (instance.LegacyOnlineID < 0 || other.LegacyOnlineID < 0)
return false;
return instance.LegacyOnlineID.Equals(other.LegacyOnlineID);
}
private static bool matchesOnlineID(this IHasOnlineID<long>? instance, IHasOnlineID<long>? other)
{

View File

@ -39,7 +39,8 @@ protected override void LoadComplete()
var scoreInfo = new ScoreInfo
{
ID = TrackedItem.ID,
OnlineID = TrackedItem.OnlineID
OnlineID = TrackedItem.OnlineID,
LegacyOnlineID = TrackedItem.LegacyOnlineID
};
Downloader.DownloadBegan += downloadBegan;
@ -47,6 +48,7 @@ protected override void LoadComplete()
realmSubscription = realm.RegisterForNotifications(r => r.All<ScoreInfo>().Where(s =>
((s.OnlineID > 0 && s.OnlineID == TrackedItem.OnlineID)
|| (s.LegacyOnlineID > 0 && s.LegacyOnlineID == TrackedItem.LegacyOnlineID)
|| (!string.IsNullOrEmpty(s.Hash) && s.Hash == TrackedItem.Hash))
&& !s.DeletePending), (items, _) =>
{

View File

@ -678,6 +678,9 @@ public void PresentScore(IScoreInfo score, ScorePresentType presentType = ScoreP
if (score.OnlineID > 0)
databasedScoreInfo = ScoreManager.Query(s => s.OnlineID == score.OnlineID);
if (score.LegacyOnlineID > 0)
databasedScoreInfo ??= ScoreManager.Query(s => s.LegacyOnlineID == score.LegacyOnlineID);
if (score is ScoreInfo scoreInfo)
databasedScoreInfo ??= ScoreManager.Query(s => s.Hash == scoreInfo.Hash);

View File

@ -24,6 +24,8 @@ public interface IScoreInfo : IHasOnlineID<long>, IHasNamedFiles
bool HasReplay { get; }
long LegacyOnlineID { get; }
DateTimeOffset Date { get; }
double? PP { get; }

View File

@ -150,7 +150,11 @@ public void Delete(BeatmapInfo beatmap, bool silent = false)
public Task Import(ImportTask[] imports, ImportParameters parameters = default) => scoreImporter.Import(imports, parameters);
public override bool IsAvailableLocally(ScoreInfo model) => Realm.Run(realm => realm.All<ScoreInfo>().Any(s => s.OnlineID == model.OnlineID));
public override bool IsAvailableLocally(ScoreInfo model)
=> Realm.Run(realm => realm.All<ScoreInfo>()
// this basically inlines `ModelExtension.MatchesOnlineID(IScoreInfo, IScoreInfo)`,
// because that method can't be used here, as realm can't translate it to its query language.
.Any(s => s.OnlineID == model.OnlineID || s.LegacyOnlineID == model.LegacyOnlineID));
public IEnumerable<string> HandledExtensions => scoreImporter.HandledExtensions;