Skip to content

Commit

Permalink
Merge pull request #14917 from peppy/new-interfaces
Browse files Browse the repository at this point in the history
Add new read-only interfaces for all remaining model types
  • Loading branch information
smoogipoo authored Oct 6, 2021
2 parents 9491e5a + 4bbff2e commit 13bea78
Show file tree
Hide file tree
Showing 34 changed files with 553 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
return new CatchDifficultyAttributes { Mods = mods, Skills = skills };

// this is the same as osu!, so there's potential to share the implementation... maybe
double preempt = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
double preempt = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;

return new CatchDifficultyAttributes
{
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, B
{
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);

TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450);

Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
}
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Catch/UI/DrawableCatchRuleset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public DrawableCatchRuleset(Ruleset ruleset, IBeatmap beatmap, IReadOnlyList<Mod
: base(ruleset, beatmap, mods)
{
Direction.Value = ScrollingDirection.Down;
TimeRange.Value = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
TimeRange.Value = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450);
}

protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat

double starRating = basePerformance > 0.00001 ? Math.Cbrt(1.12) * 0.027 * (Math.Cbrt(100000 / Math.Pow(2, 1 / 1.1) * basePerformance) + 4) : 0;

double preempt = (int)BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;
double preempt = (int)IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.ApproachRate, 1800, 1200, 450) / clockRate;

int maxCombo = beatmap.HitObjects.Count;
// Add the ticks + tail of the slider. 1 is subtracted because the head circle would be counted twice (once for the slider itself in the line above)
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, B
{
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);

TimePreempt = (float)BeatmapDifficulty.DifficultyRange(difficulty.ApproachRate, 1800, 1200, PREEMPT_MIN);
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, PREEMPT_MIN);

// Preempt time can go below 450ms. Normally, this is achieved via the DT mod which uniformly speeds up all animations game wide regardless of AR.
// This uniform speedup is hard to match 1:1, however we can at least make AR>10 (via mods) feel good by extending the upper linear function above.
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Osu/Objects/Spinner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, B

double secondsDuration = Duration / 1000;

double minimumRotationsPerSecond = stable_matching_fudge * BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);
double minimumRotationsPerSecond = stable_matching_fudge * IBeatmapDifficultyInfo.DifficultyRange(difficulty.OverallDifficulty, 3, 5, 7.5);

SpinsRequired = (int)(secondsDuration * minimumRotationsPerSecond);
MaximumBonusSpins = (int)((maximum_rotations_per_second - minimumRotationsPerSecond) * secondsDuration);
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ protected override IEnumerable<TaikoHitObject> ConvertHitObject(HitObject obj, I

case IHasDuration endTimeData:
{
double hitMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;
double hitMultiplier = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 3, 5, 7.5) * swell_hit_multiplier;

yield return new Swell
{
Expand Down
4 changes: 2 additions & 2 deletions osu.Game.Rulesets.Taiko/Scoring/TaikoHealthProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public override void ApplyBeatmap(IBeatmap beatmap)
{
base.ApplyBeatmap(beatmap);

hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
hpMissMultiplier = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
hpMultiplier = 1 / (object_count_factor * Math.Max(1, beatmap.HitObjects.OfType<Hit>().Count()) * IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.5, 0.75, 0.98));
hpMissMultiplier = IBeatmapDifficultyInfo.DifficultyRange(beatmap.BeatmapInfo.BaseDifficulty.DrainRate, 0.0018, 0.0075, 0.0120);
}

protected override double GetHealthIncreaseFor(JudgementResult result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void TestRomanisation()
Title = "Romanised title",
TitleUnicode = "Unicode Title"
};
var romanisableString = metadata.ToRomanisableString();
var romanisableString = metadata.GetDisplayTitleRomanisable();

Assert.AreEqual(metadata.ToString(), romanisableString.Romanised);
Assert.AreEqual($"{metadata.ArtistUnicode} - {metadata.TitleUnicode}", romanisableString.Original);
Expand All @@ -33,7 +33,7 @@ public void TestRomanisationNoUnicode()
Artist = "Romanised Artist",
Title = "Romanised title"
};
var romanisableString = metadata.ToRomanisableString();
var romanisableString = metadata.GetDisplayTitleRomanisable();

Assert.AreEqual(romanisableString.Romanised, romanisableString.Original);
}
Expand Down
2 changes: 1 addition & 1 deletion osu.Game.Tournament/Components/SongBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private void update()
if ((mods & LegacyMods.DoubleTime) > 0)
{
// temporary local calculation (taken from OsuDifficultyCalculator)
double preempt = (int)BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / 1.5;
double preempt = (int)IBeatmapDifficultyInfo.DifficultyRange(ar, 1800, 1200, 450) / 1.5;
ar = (float)(preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5);

bpm *= 1.5f;
Expand Down
44 changes: 1 addition & 43 deletions osu.Game/Beatmaps/BeatmapDifficulty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace osu.Game.Beatmaps
{
public class BeatmapDifficulty : IHasPrimaryKey
public class BeatmapDifficulty : IHasPrimaryKey, IBeatmapDifficultyInfo
{
/// <summary>
/// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>.
Expand Down Expand Up @@ -49,47 +49,5 @@ public void CopyTo(BeatmapDifficulty difficulty)
difficulty.SliderMultiplier = SliderMultiplier;
difficulty.SliderTickRate = SliderTickRate;
}

/// <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>
public 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);
}
}
33 changes: 19 additions & 14 deletions osu.Game/Beatmaps/BeatmapInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Localisation;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Rulesets;
Expand All @@ -17,7 +16,7 @@ namespace osu.Game.Beatmaps
{
[ExcludeFromDynamicCompile]
[Serializable]
public class BeatmapInfo : IEquatable<BeatmapInfo>, IHasPrimaryKey
public class BeatmapInfo : IEquatable<BeatmapInfo>, IHasPrimaryKey, IBeatmapInfo
{
public int ID { get; set; }

Expand Down Expand Up @@ -152,18 +151,7 @@ public string StoredBookmarks
[JsonIgnore]
public DifficultyRating DifficultyRating => BeatmapDifficultyCache.GetDifficultyRating(StarDifficulty);

public string[] SearchableTerms => new[]
{
Version
}.Concat(Metadata?.SearchableTerms ?? Enumerable.Empty<string>()).Where(s => !string.IsNullOrEmpty(s)).ToArray();

public override string ToString() => $"{Metadata ?? BeatmapSet?.Metadata} {versionString}".Trim();

public RomanisableString ToRomanisableString()
{
var metadata = (Metadata ?? BeatmapSet?.Metadata)?.ToRomanisableString() ?? new RomanisableString(null, null);
return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
}
public override string ToString() => this.GetDisplayTitle();

public bool Equals(BeatmapInfo other)
{
Expand All @@ -187,5 +175,22 @@ public bool BackgroundEquals(BeatmapInfo other) => other != null && BeatmapSet !
/// Returns a shallow-clone of this <see cref="BeatmapInfo"/>.
/// </summary>
public BeatmapInfo Clone() => (BeatmapInfo)MemberwiseClone();

#region Implementation of IHasOnlineID

public int? OnlineID => OnlineBeatmapID;

#endregion

#region Implementation of IBeatmapInfo

string IBeatmapInfo.DifficultyName => Version;
IBeatmapMetadataInfo IBeatmapInfo.Metadata => Metadata;
IBeatmapDifficultyInfo IBeatmapInfo.Difficulty => BaseDifficulty;
IBeatmapSetInfo IBeatmapInfo.BeatmapSet => BeatmapSet;
IRulesetInfo IBeatmapInfo.Ruleset => Ruleset;
double IBeatmapInfo.StarRating => StarDifficulty;

#endregion
}
}
38 changes: 38 additions & 0 deletions osu.Game/Beatmaps/BeatmapInfoExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Linq;
using osu.Framework.Localisation;

namespace osu.Game.Beatmaps
{
public static class BeatmapInfoExtensions
{
/// <summary>
/// A user-presentable display title representing this beatmap.
/// </summary>
public static string GetDisplayTitle(this IBeatmapInfo beatmapInfo) => $"{getClosestMetadata(beatmapInfo)} {getVersionString(beatmapInfo)}".Trim();

/// <summary>
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
/// </summary>
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapInfo beatmapInfo)
{
var metadata = getClosestMetadata(beatmapInfo).GetDisplayTitleRomanisable();
var versionString = getVersionString(beatmapInfo);

return new RomanisableString($"{metadata.GetPreferred(true)} {versionString}".Trim(), $"{metadata.GetPreferred(false)} {versionString}".Trim());
}

public static string[] GetSearchableTerms(this IBeatmapInfo beatmapInfo) => new[]
{
beatmapInfo.DifficultyName
}.Concat(getClosestMetadata(beatmapInfo).GetSearchableTerms()).Where(s => !string.IsNullOrEmpty(s)).ToArray();

private static string getVersionString(IBeatmapInfo beatmapInfo) => string.IsNullOrEmpty(beatmapInfo.DifficultyName) ? string.Empty : $"[{beatmapInfo.DifficultyName}]";

// temporary helper methods until we figure which metadata should be where.
private static IBeatmapMetadataInfo getClosestMetadata(IBeatmapInfo beatmapInfo) =>
beatmapInfo.Metadata ?? beatmapInfo.BeatmapSet?.Metadata ?? new BeatmapMetadata();
}
}
49 changes: 5 additions & 44 deletions osu.Game/Beatmaps/BeatmapMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Localisation;
using osu.Framework.Testing;
using osu.Game.Database;
using osu.Game.Users;
Expand All @@ -15,7 +13,7 @@ namespace osu.Game.Beatmaps
{
[ExcludeFromDynamicCompile]
[Serializable]
public class BeatmapMetadata : IEquatable<BeatmapMetadata>, IHasPrimaryKey
public class BeatmapMetadata : IEquatable<BeatmapMetadata>, IHasPrimaryKey, IBeatmapMetadataInfo
{
public int ID { get; set; }

Expand Down Expand Up @@ -83,50 +81,13 @@ public string AuthorString
public int PreviewTime { get; set; }

public string AudioFile { get; set; }
public string BackgroundFile { get; set; }

public override string ToString()
{
string author = Author == null ? string.Empty : $"({Author})";
return $"{Artist} - {Title} {author}".Trim();
}
public string BackgroundFile { get; set; }

public RomanisableString ToRomanisableString()
{
string author = Author == null ? string.Empty : $"({Author})";
var artistUnicode = string.IsNullOrEmpty(ArtistUnicode) ? Artist : ArtistUnicode;
var titleUnicode = string.IsNullOrEmpty(TitleUnicode) ? Title : TitleUnicode;
public bool Equals(BeatmapMetadata other) => ((IBeatmapMetadataInfo)this).Equals(other);

return new RomanisableString($"{artistUnicode} - {titleUnicode} {author}".Trim(), $"{Artist} - {Title} {author}".Trim());
}
public override string ToString() => this.GetDisplayTitle();

[JsonIgnore]
public string[] SearchableTerms => new[]
{
Author?.Username,
Artist,
ArtistUnicode,
Title,
TitleUnicode,
Source,
Tags
}.Where(s => !string.IsNullOrEmpty(s)).ToArray();

public bool Equals(BeatmapMetadata other)
{
if (other == null)
return false;

return Title == other.Title
&& TitleUnicode == other.TitleUnicode
&& Artist == other.Artist
&& ArtistUnicode == other.ArtistUnicode
&& AuthorString == other.AuthorString
&& Source == other.Source
&& Tags == other.Tags
&& PreviewTime == other.PreviewTime
&& AudioFile == other.AudioFile
&& BackgroundFile == other.BackgroundFile;
}
string IBeatmapMetadataInfo.Author => AuthorString;
}
}
46 changes: 46 additions & 0 deletions osu.Game/Beatmaps/BeatmapMetadataInfoExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Linq;
using osu.Framework.Localisation;

namespace osu.Game.Beatmaps
{
public static class BeatmapMetadataInfoExtensions
{
/// <summary>
/// An array of all searchable terms provided in contained metadata.
/// </summary>
public static string[] GetSearchableTerms(this IBeatmapMetadataInfo metadataInfo) => new[]
{
metadataInfo.Author,
metadataInfo.Artist,
metadataInfo.ArtistUnicode,
metadataInfo.Title,
metadataInfo.TitleUnicode,
metadataInfo.Source,
metadataInfo.Tags
}.Where(s => !string.IsNullOrEmpty(s)).ToArray();

/// <summary>
/// A user-presentable display title representing this metadata.
/// </summary>
public static string GetDisplayTitle(this IBeatmapMetadataInfo metadataInfo)
{
string author = string.IsNullOrEmpty(metadataInfo.Author) ? string.Empty : $"({metadataInfo.Author})";
return $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim();
}

/// <summary>
/// A user-presentable display title representing this beatmap, with localisation handling for potentially romanisable fields.
/// </summary>
public static RomanisableString GetDisplayTitleRomanisable(this IBeatmapMetadataInfo metadataInfo)
{
string author = string.IsNullOrEmpty(metadataInfo.Author) ? string.Empty : $"({metadataInfo.Author})";
var artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode;
var titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode;

return new RomanisableString($"{artistUnicode} - {titleUnicode} {author}".Trim(), $"{metadataInfo.Artist} - {metadataInfo.Title} {author}".Trim());
}
}
}
4 changes: 3 additions & 1 deletion osu.Game/Beatmaps/BeatmapSetFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace osu.Game.Beatmaps
{
public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey
public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey, INamedFileUsage
{
public int ID { get; set; }

Expand All @@ -19,5 +19,7 @@ public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey

[Required]
public string Filename { get; set; }

public IFileInfo File => FileInfo;
}
}
Loading

0 comments on commit 13bea78

Please sign in to comment.