Add new interface base types for models

This commit is contained in:
Dean Herbert 2021-10-01 14:34:11 +09:00
parent b8b61a196f
commit 619dfe0690
8 changed files with 440 additions and 0 deletions

View File

@ -0,0 +1,90 @@
// 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.
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// A representation of all top-level difficulty settings for a beatmap.
/// </summary>
public interface IBeatmapDifficultyInfo
{
/// <summary>
/// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>.
/// </summary>
const float DEFAULT_DIFFICULTY = 5;
/// <summary>
/// The drain rate of the associated beatmap.
/// </summary>
float DrainRate { get; }
/// <summary>
/// The circle size of the associated beatmap.
/// </summary>
float CircleSize { get; }
/// <summary>
/// The overall difficulty of the associated beatmap.
/// </summary>
float OverallDifficulty { get; }
/// <summary>
/// The approach rate of the associated beatmap.
/// </summary>
float ApproachRate { get; }
/// <summary>
/// The slider multiplier of the associated beatmap.
/// </summary>
double SliderMultiplier { get; }
/// <summary>
/// The slider tick rate of the associated beatmap.
/// </summary>
double SliderTickRate { get; }
/// <summary>
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
/// </summary>
/// <param name="difficulty">The difficulty value to be mapped.</param>
/// <param name="min">Minimum of the resulting range which will be achieved by a difficulty value of 0.</param>
/// <param name="mid">Midpoint of the resulting range which will be achieved by a difficulty value of 5.</param>
/// <param name="max">Maximum of the resulting range which will be achieved by a difficulty value of 10.</param>
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
static double DifficultyRange(double difficulty, double min, double mid, double max)
{
if (difficulty > 5)
return mid + (max - mid) * (difficulty - 5) / 5;
if (difficulty < 5)
return mid - (mid - min) * (5 - difficulty) / 5;
return mid;
}
/// <summary>
/// Maps a difficulty value [0, 10] to a two-piece linear range of values.
/// </summary>
/// <param name="difficulty">The difficulty value to be mapped.</param>
/// <param name="range">The values that define the two linear ranges.
/// <list type="table">
/// <item>
/// <term>od0</term>
/// <description>Minimum of the resulting range which will be achieved by a difficulty value of 0.</description>
/// </item>
/// <item>
/// <term>od5</term>
/// <description>Midpoint of the resulting range which will be achieved by a difficulty value of 5.</description>
/// </item>
/// <item>
/// <term>od10</term>
/// <description>Maximum of the resulting range which will be achieved by a difficulty value of 10.</description>
/// </item>
/// </list>
/// </param>
/// <returns>Value to which the difficulty value maps in the specified range.</returns>
public static double DifficultyRange(double difficulty, (double od0, double od5, double od10) range)
=> DifficultyRange(difficulty, range.od0, range.od5, range.od10);
}
}

View File

@ -0,0 +1,74 @@
// 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 osu.Framework.Localisation;
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// A single beatmap difficulty.
/// </summary>
public interface IBeatmapInfo : IHasOnlineID
{
/// <summary>
/// The user-specified name given to this beatmap.
/// </summary>
string DifficultyName { get; }
/// <summary>
/// The metadata representing this beatmap. May be shared between multiple beatmaps.
/// </summary>
IBeatmapMetadataInfo Metadata { get; }
/// <summary>
/// The difficulty settings for this beatmap.
/// </summary>
IBeatmapDifficultyInfo Difficulty { get; }
/// <summary>
/// The playable length in milliseconds of this beatmap.
/// </summary>
double Length { get; }
/// <summary>
/// The most common BPM of this beatmap.
/// </summary>
double BPM { get; }
/// <summary>
/// The SHA-256 hash representing this beatmap's contents.
/// </summary>
string Hash { get; }
/// <summary>
/// MD5 is kept for legacy support (matching against replays, osu-web-10 etc.).
/// </summary>
string MD5Hash { get; }
/// <summary>
/// The ruleset this beatmap was made for.
/// </summary>
IRulesetInfo Ruleset { get; }
/// <summary>
/// The basic star rating for this beatmap (with no mods applied).
/// </summary>
double StarRating { get; }
string DisplayTitle => $"{Metadata} {versionString}".Trim();
RomanisableString DisplayTitleRomanisable
{
get
{
var metadata = Metadata.DisplayTitleRomanisable;
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
}
}
private string versionString => string.IsNullOrEmpty(DifficultyName) ? string.Empty : $"[{DifficultyName}]";
}
}

View File

@ -0,0 +1,117 @@
// 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;
using System.Linq;
using osu.Framework.Localisation;
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// Metadata representing a beatmap. May be shared between multiple beatmap difficulties.
/// </summary>
public interface IBeatmapMetadataInfo : IEquatable<IBeatmapMetadataInfo>
{
/// <summary>
/// The romanised title of this beatmap.
/// </summary>
string Title { get; }
/// <summary>
/// The unicode title of this beatmap.
/// </summary>
string TitleUnicode { get; }
/// <summary>
/// The romanised artist of this beatmap.
/// </summary>
string Artist { get; }
/// <summary>
/// The unicode artist of this beatmap.
/// </summary>
string ArtistUnicode { get; }
/// <summary>
/// The author of this beatmap.
/// </summary>
string Author { get; } // eventually should be linked to a persisted User.
/// <summary>
/// The source of this beatmap.
/// </summary>
string Source { get; }
/// <summary>
/// The tags of this beatmap.
/// </summary>
string Tags { get; }
/// <summary>
/// The time in milliseconds to begin playing the track for preview purposes.
/// If -1, the track should begin playing at 40% of its length.
/// </summary>
int PreviewTime { get; }
/// <summary>
/// The filename of the audio file consumed by this beatmap.
/// </summary>
string AudioFile { get; }
/// <summary>
/// The filename of the background image file consumed by this beatmap.
/// </summary>
string BackgroundFile { get; }
string DisplayTitle
{
get
{
string author = string.IsNullOrEmpty(Author) ? string.Empty : $"({Author})";
return $"{Artist} - {Title} {author}".Trim();
}
}
RomanisableString DisplayTitleRomanisable
{
get
{
string author = string.IsNullOrEmpty(Author) ? string.Empty : $"({Author})";
var artistUnicode = string.IsNullOrEmpty(ArtistUnicode) ? Artist : ArtistUnicode;
var titleUnicode = string.IsNullOrEmpty(TitleUnicode) ? Title : TitleUnicode;
return new RomanisableString($"{artistUnicode} - {titleUnicode} {author}".Trim(), $"{Artist} - {Title} {author}".Trim());
}
}
string[] SearchableTerms => new[]
{
Author,
Artist,
ArtistUnicode,
Title,
TitleUnicode,
Source,
Tags
}.Where(s => !string.IsNullOrEmpty(s)).ToArray();
bool IEquatable<IBeatmapMetadataInfo>.Equals(IBeatmapMetadataInfo? other)
{
if (other == null)
return false;
return Title == other.Title
&& TitleUnicode == other.TitleUnicode
&& Artist == other.Artist
&& ArtistUnicode == other.ArtistUnicode
&& Author == other.Author
&& Source == other.Source
&& Tags == other.Tags
&& PreviewTime == other.PreviewTime
&& AudioFile == other.AudioFile
&& BackgroundFile == other.BackgroundFile;
}
}
}

View File

@ -0,0 +1,57 @@
// 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;
using System.Collections.Generic;
using System.Linq;
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// A representation of a collection of beatmap difficulties, generally packaged as an ".osz" archive.
/// </summary>
public interface IBeatmapSetInfo : IHasOnlineID
{
/// <summary>
/// The date when this beatmap was imported.
/// </summary>
DateTimeOffset DateAdded { get; }
/// <summary>
/// The best-effort metadata representing this set. In the case metadata differs between contained beatmaps, one is arbitrarily chosen.
/// </summary>
IBeatmapMetadataInfo? Metadata { get; }
/// <summary>
/// All beatmaps contained in this set.
/// </summary>
IEnumerable<IBeatmapInfo> Beatmaps { get; }
/// <summary>
/// All files used by this set.
/// </summary>
IEnumerable<INamedFileUsage> Files { get; }
/// <summary>
/// The maximum star difficulty of all beatmaps in this set.
/// </summary>
double MaxStarDifficulty { get; }
/// <summary>
/// The maximum playable length in milliseconds of all beatmaps in this set.
/// </summary>
double MaxLength { get; }
/// <summary>
/// The maximum BPM of all beatmaps in this set.
/// </summary>
double MaxBPM { get; }
/// <summary>
/// The filename for the storyboard.
/// </summary>
string StoryboardFile => Files.FirstOrDefault(f => f.Filename.EndsWith(".osb", StringComparison.OrdinalIgnoreCase))?.Filename ?? string.Empty;
}
}

View File

@ -0,0 +1,18 @@
// 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.
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// A representation of a tracked file.
/// </summary>
public interface IFileInfo
{
/// <summary>
/// SHA-256 hash of the file content.
/// </summary>
string Hash { get; }
}
}

View File

@ -0,0 +1,15 @@
// 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.
#nullable enable
namespace osu.Game.Beatmaps
{
public interface IHasOnlineID
{
/// <summary>
/// The server-side ID representing this instance, if one exists.
/// </summary>
int? OnlineID { get; }
}
}

View File

@ -0,0 +1,23 @@
// 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.
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// A usage of a file, with a local filename attached.
/// </summary>
public interface INamedFileUsage
{
/// <summary>
/// The underlying file on disk.
/// </summary>
IFileInfo File { get; }
/// <summary>
/// The filename for this usage.
/// </summary>
string Filename { get; }
}
}

View File

@ -0,0 +1,46 @@
// 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;
using osu.Game.Rulesets;
#nullable enable
namespace osu.Game.Beatmaps
{
/// <summary>
/// A representation of a ruleset's metadata.
/// </summary>
public interface IRulesetInfo : IHasOnlineID
{
/// <summary>
/// The user-exposed name of this ruleset.
/// </summary>
string Name { get; }
/// <summary>
/// An acronym defined by the ruleset that can be used as a permanent identifier.
/// </summary>
string ShortName { get; }
/// <summary>
/// A string representation of this ruleset, to be used with reflection to instantiate the ruleset represented by this metadata.
/// </summary>
string InstantiationInfo { get; }
public Ruleset? CreateInstance()
{
var type = Type.GetType(InstantiationInfo);
if (type == null)
return null;
var ruleset = Activator.CreateInstance(type) as Ruleset;
// overwrite the pre-populated RulesetInfo with a potentially database attached copy.
// ruleset.RulesetInfo = this;
return ruleset;
}
}
}