2021-11-09 12:34:56 +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.
2021-11-19 07:07:55 +00:00
using System.IO ;
2021-11-25 07:33:35 +00:00
using System.Linq ;
2021-11-09 12:34:56 +00:00
using osu.Game.Beatmaps ;
2021-11-15 05:34:50 +00:00
using osu.Game.Database ;
2021-11-19 07:07:55 +00:00
using osu.Game.IO ;
2021-11-16 03:44:20 +00:00
using osu.Game.Online.API.Requests.Responses ;
2021-11-09 12:34:56 +00:00
using osu.Game.Rulesets ;
using osu.Game.Scoring ;
using osu.Game.Users ;
2021-11-15 05:38:01 +00:00
#nullable enable
2021-11-09 12:34:56 +00:00
namespace osu.Game.Extensions
{
public static class ModelExtensions
{
2021-11-19 07:07:55 +00:00
/// <summary>
/// Get the relative path in osu! storage for this file.
/// </summary>
/// <param name="fileInfo">The file info.</param>
/// <returns>A relative file path.</returns>
public static string GetStoragePath ( this IFileInfo fileInfo ) = > Path . Combine ( fileInfo . Hash . Remove ( 1 ) , fileInfo . Hash . Remove ( 2 ) , fileInfo . Hash ) ;
2021-11-09 12:34:56 +00:00
/// <summary>
/// Returns a user-facing string representing the <paramref name="model"/>.
/// </summary>
/// <remarks>
/// <para>
/// Non-interface types without special handling will fall back to <see cref="object.ToString()"/>.
/// </para>
/// <para>
/// Warning: This method is _purposefully_ not called <c>GetDisplayTitle()</c> like the others, because otherwise
/// extension method type inference rules cause this method to call itself and cause a stack overflow.
/// </para>
/// </remarks>
2021-11-15 05:38:01 +00:00
public static string GetDisplayString ( this object? model )
2021-11-09 12:34:56 +00:00
{
2021-11-15 05:38:01 +00:00
string? result = null ;
2021-11-09 12:34:56 +00:00
switch ( model )
{
case IBeatmapSetInfo beatmapSetInfo :
2021-11-24 06:01:45 +00:00
result = beatmapSetInfo . Metadata . GetDisplayTitle ( ) ;
2021-11-09 12:34:56 +00:00
break ;
case IBeatmapInfo beatmapInfo :
result = beatmapInfo . GetDisplayTitle ( ) ;
break ;
case IBeatmapMetadataInfo metadataInfo :
result = metadataInfo . GetDisplayTitle ( ) ;
break ;
case IScoreInfo scoreInfo :
result = scoreInfo . GetDisplayTitle ( ) ;
break ;
case IRulesetInfo rulesetInfo :
result = rulesetInfo . Name ;
break ;
case IUser user :
result = user . Username ;
break ;
}
// fallback in case none of the above happens to match.
2021-11-12 06:25:59 +00:00
result ? ? = model ? . ToString ( ) ? ? @"null" ;
2021-11-09 12:34:56 +00:00
return result ;
}
2021-11-15 05:34:50 +00:00
2022-03-03 05:15:25 +00:00
/// <summary>
/// Check whether this <see cref="IRulesetInfo"/>'s online ID is within the range that defines it as a legacy ruleset (ie. either osu!, osu!taiko, osu!catch or osu!mania).
/// </summary>
public static bool IsLegacyRuleset ( this IRulesetInfo ruleset ) = > ruleset . OnlineID > = 0 & & ruleset . OnlineID < = ILegacyRuleset . MAX_LEGACY_RULESET_ID ;
2021-11-15 05:34:50 +00:00
/// <summary>
2021-11-16 03:37:47 +00:00
/// Check whether the online ID of two <see cref="IBeatmapSetInfo"/>s match.
2021-11-15 05:34:50 +00:00
/// </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>
2021-11-16 03:37:47 +00:00
public static bool MatchesOnlineID ( this IBeatmapSetInfo ? instance , IBeatmapSetInfo ? other ) = > matchesOnlineID ( instance , other ) ;
/// <summary>
/// Check whether the online ID of two <see cref="IBeatmapInfo"/>s match.
/// </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 IBeatmapInfo ? instance , IBeatmapInfo ? other ) = > matchesOnlineID ( instance , other ) ;
/// <summary>
/// Check whether the online ID of two <see cref="IRulesetInfo"/>s match.
/// </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 IRulesetInfo ? instance , IRulesetInfo ? other ) = > matchesOnlineID ( instance , other ) ;
2021-11-16 03:44:20 +00:00
/// <summary>
/// Check whether the online ID of two <see cref="APIUser"/>s match.
/// </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 APIUser ? instance , APIUser ? other ) = > matchesOnlineID ( instance , other ) ;
2021-12-10 09:32:06 +00:00
/// <summary>
/// Check whether the online ID of two <see cref="IScoreInfo"/>s match.
/// </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 ) ;
2021-11-16 03:37:47 +00:00
private static bool matchesOnlineID ( this IHasOnlineID < long > ? instance , IHasOnlineID < long > ? other )
2021-11-15 05:34:50 +00:00
{
2021-11-15 05:38:01 +00:00
if ( instance = = null | | other = = null )
return false ;
2021-11-15 05:34:50 +00:00
if ( instance . OnlineID < 0 | | other . OnlineID < 0 )
return false ;
return instance . OnlineID . Equals ( other . OnlineID ) ;
}
2021-11-16 03:37:47 +00:00
private static bool matchesOnlineID ( this IHasOnlineID < int > ? instance , IHasOnlineID < int > ? other )
2021-11-15 05:34:50 +00:00
{
2021-11-15 05:38:01 +00:00
if ( instance = = null | | other = = null )
return false ;
2021-11-15 05:34:50 +00:00
if ( instance . OnlineID < 0 | | other . OnlineID < 0 )
return false ;
return instance . OnlineID . Equals ( other . OnlineID ) ;
}
2021-11-25 07:33:35 +00:00
private static readonly char [ ] invalid_filename_characters = Path . GetInvalidFileNameChars ( )
// Backslash is added to avoid issues when exporting to zip.
// See SharpCompress filename normalisation https://github.com/adamhathcock/sharpcompress/blob/a1e7c0068db814c9aa78d86a94ccd1c761af74bd/src/SharpCompress/Writers/Zip/ZipWriter.cs#L143.
. Append ( '\\' )
. ToArray ( ) ;
/// <summary>
/// Get a valid filename for use inside a zip file. Avoids backslashes being incorrectly converted to directories.
/// </summary>
public static string GetValidArchiveContentFilename ( this string filename )
{
foreach ( char c in invalid_filename_characters )
filename = filename . Replace ( c , '_' ) ;
return filename ;
}
2021-11-09 12:34:56 +00:00
}
}