2021-09-30 05:46:01 +00:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System ;
2021-11-24 03:16:08 +00:00
using System.Diagnostics ;
2022-08-02 06:50:16 +00:00
using System.Linq ;
2021-09-30 05:46:01 +00:00
using osu.Framework.Platform ;
using osu.Game.Online.API ;
namespace osu.Game.Beatmaps
{
2021-09-30 05:46:07 +00:00
/// <summary>
/// A component which handles population of online IDs for beatmaps using a two part lookup procedure.
/// </summary>
2022-07-28 07:08:27 +00:00
public class BeatmapUpdaterMetadataLookup : IDisposable
2021-09-30 05:46:01 +00:00
{
2023-05-07 11:10:59 +00:00
private readonly IOnlineBeatmapMetadataSource apiMetadataSource ;
private readonly IOnlineBeatmapMetadataSource localCachedMetadataSource ;
2021-09-30 05:46:01 +00:00
2022-07-28 07:08:27 +00:00
public BeatmapUpdaterMetadataLookup ( IAPIProvider api , Storage storage )
2023-05-07 11:10:59 +00:00
: this ( new APIBeatmapMetadataSource ( api ) , new LocalCachedBeatmapMetadataSource ( storage ) )
2021-09-30 05:46:01 +00:00
{
2023-05-07 11:10:59 +00:00
}
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
internal BeatmapUpdaterMetadataLookup ( IOnlineBeatmapMetadataSource apiMetadataSource , IOnlineBeatmapMetadataSource localCachedMetadataSource )
{
this . apiMetadataSource = apiMetadataSource ;
this . localCachedMetadataSource = localCachedMetadataSource ;
2021-09-30 05:46:01 +00:00
}
2022-07-28 07:55:46 +00:00
/// <summary>
/// Queue an update for a beatmap set.
/// </summary>
2022-08-02 03:12:02 +00:00
/// <remarks>
/// This may happen during initial import, or at a later stage in response to a user action or server event.
/// </remarks>
2022-07-28 07:55:46 +00:00
/// <param name="beatmapSet">The beatmap set to update. Updates will be applied directly (so a transaction should be started if this instance is managed).</param>
/// <param name="preferOnlineFetch">Whether metadata from an online source should be preferred. If <c>true</c>, the local cache will be skipped to ensure the freshest data state possible.</param>
public void Update ( BeatmapSetInfo beatmapSet , bool preferOnlineFetch )
2022-01-13 07:13:30 +00:00
{
2023-05-07 11:10:59 +00:00
foreach ( var beatmapInfo in beatmapSet . Beatmaps )
2021-09-30 05:46:01 +00:00
{
2023-05-07 11:10:59 +00:00
var res = lookup ( beatmapSet , beatmapInfo , preferOnlineFetch ) ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
if ( res = = null )
2022-01-13 07:13:30 +00:00
{
2022-07-25 09:51:19 +00:00
beatmapInfo . ResetOnlineInfo ( ) ;
2023-05-07 11:10:59 +00:00
continue ;
2021-09-30 05:46:01 +00:00
}
2023-05-07 11:10:59 +00:00
beatmapInfo . OnlineID = res . BeatmapID ;
beatmapInfo . OnlineMD5Hash = res . MD5Hash ;
beatmapInfo . LastOnlineUpdate = res . LastUpdated ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
Debug . Assert ( beatmapInfo . BeatmapSet ! = null ) ;
beatmapInfo . BeatmapSet . OnlineID = res . BeatmapSetID ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
// Some metadata should only be applied if there's no local changes.
if ( shouldSaveOnlineMetadata ( beatmapInfo ) )
2021-09-30 05:46:01 +00:00
{
2023-05-07 11:10:59 +00:00
beatmapInfo . Status = res . BeatmapStatus ;
beatmapInfo . Metadata . Author . OnlineID = res . AuthorID ;
2021-09-30 05:46:01 +00:00
}
2023-05-07 11:10:59 +00:00
if ( beatmapInfo . BeatmapSet . Beatmaps . All ( shouldSaveOnlineMetadata ) )
2022-05-09 03:15:54 +00:00
{
2023-05-07 11:10:59 +00:00
beatmapInfo . BeatmapSet . Status = res . BeatmapSetStatus ? ? BeatmapOnlineStatus . None ;
beatmapInfo . BeatmapSet . DateRanked = res . DateRanked ;
beatmapInfo . BeatmapSet . DateSubmitted = res . DateSubmitted ;
2022-05-09 03:15:54 +00:00
}
2023-05-07 11:10:59 +00:00
}
2021-09-30 05:46:01 +00:00
}
2023-05-07 11:10:59 +00:00
private OnlineBeatmapMetadata ? lookup ( BeatmapSetInfo set , BeatmapInfo beatmapInfo , bool preferOnlineFetch )
2021-09-30 05:46:01 +00:00
{
2023-05-07 11:10:59 +00:00
OnlineBeatmapMetadata ? result = null ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
bool useLocalCache = ! apiMetadataSource . Available | | ! preferOnlineFetch ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
if ( useLocalCache )
result = localCachedMetadataSource . Lookup ( beatmapInfo ) ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
if ( result ! = null )
return result ;
2021-09-30 05:46:01 +00:00
2023-05-07 11:10:59 +00:00
if ( apiMetadataSource . Available )
result = apiMetadataSource . Lookup ( beatmapInfo ) ;
2022-08-02 06:49:22 +00:00
2023-05-07 11:10:59 +00:00
return result ;
2021-09-30 05:46:01 +00:00
}
2022-08-04 08:26:54 +00:00
/// <summary>
/// Check whether the provided beatmap is in a state where online "ranked" status metadata should be saved against it.
/// Handles the case where a user may have locally modified a beatmap in the editor and expects the local status to stick.
/// </summary>
private static bool shouldSaveOnlineMetadata ( BeatmapInfo beatmapInfo ) = > beatmapInfo . MatchesOnlineVersion | | beatmapInfo . Status ! = BeatmapOnlineStatus . LocallyModified ;
2021-09-30 05:46:01 +00:00
public void Dispose ( )
{
2023-05-07 11:10:59 +00:00
apiMetadataSource . Dispose ( ) ;
localCachedMetadataSource . Dispose ( ) ;
2021-09-30 05:46:01 +00:00
}
}
}