Skip to content

Commit d31cb55

Browse files
committed
WIP
1 parent 7d0a948 commit d31cb55

File tree

8 files changed

+96
-16
lines changed

8 files changed

+96
-16
lines changed

osu.Game/Beatmaps/DifficultyRecommender.cs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22
// See the LICENCE file in the repository root for full licence text.
33

4-
#nullable disable
5-
64
using System;
75
using System.Collections.Generic;
86
using System.Linq;
9-
using JetBrains.Annotations;
107
using osu.Framework.Allocation;
118
using osu.Framework.Bindables;
129
using osu.Framework.Extensions.ObjectExtensions;
@@ -23,10 +20,12 @@ namespace osu.Game.Beatmaps
2320
/// </summary>
2421
public partial class DifficultyRecommender : Component
2522
{
23+
public event Action? StarRatingUpdated;
24+
2625
private readonly LocalUserStatisticsProvider statisticsProvider;
2726

2827
[Resolved]
29-
private Bindable<RulesetInfo> gameRuleset { get; set; }
28+
private Bindable<RulesetInfo> gameRuleset { get; set; } = null!;
3029

3130
[Resolved]
3231
private RulesetStore rulesets { get; set; } = null!;
@@ -80,6 +79,13 @@ private void updateMapping(RulesetInfo ruleset, UserStatistics statistics)
8079
{
8180
// algorithm taken from https://github.com/ppy/osu-web/blob/e6e2825516449e3d0f3f5e1852c6bdd3428c3437/app/Models/User.php#L1505
8281
recommendedDifficultyMapping[ruleset.ShortName] = Math.Pow((double)(statistics.PP ?? 0), 0.4) * 0.195;
82+
83+
StarRatingUpdated?.Invoke();
84+
}
85+
86+
public double GetRecommendedStarRatingFor(RulesetInfo ruleset)
87+
{
88+
return recommendedDifficultyMapping[ruleset.ShortName];
8389
}
8490

8591
/// <summary>
@@ -90,15 +96,14 @@ private void updateMapping(RulesetInfo ruleset, UserStatistics statistics)
9096
/// </remarks>
9197
/// <param name="beatmaps">A collection of beatmaps to select a difficulty from.</param>
9298
/// <returns>The recommended difficulty, or null if a recommendation could not be provided.</returns>
93-
[CanBeNull]
94-
public BeatmapInfo GetRecommendedBeatmap(IEnumerable<BeatmapInfo> beatmaps)
99+
public BeatmapInfo? GetRecommendedBeatmap(IEnumerable<BeatmapInfo> beatmaps)
95100
{
96101
foreach (string r in orderedRulesets)
97102
{
98103
if (!recommendedDifficultyMapping.TryGetValue(r, out double recommendation))
99104
continue;
100105

101-
BeatmapInfo beatmapInfo = beatmaps.Where(b => b.Ruleset.ShortName.Equals(r, StringComparison.Ordinal)).MinBy(b =>
106+
BeatmapInfo? beatmapInfo = beatmaps.Where(b => b.Ruleset.ShortName.Equals(r, StringComparison.Ordinal)).MinBy(b =>
102107
{
103108
double difference = b.StarRating - recommendation;
104109
return difference >= 0 ? difference * 2 : difference * -1; // prefer easier over harder

osu.Game/Beatmaps/Drawables/StarRatingDisplay.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using osu.Game.Graphics;
1515
using osu.Game.Graphics.Sprites;
1616
using osu.Game.Overlays;
17+
using osu.Game.Utils;
1718
using osuTK;
1819
using osuTK.Graphics;
1920

@@ -156,7 +157,7 @@ protected override void LoadComplete()
156157

157158
displayedStars.BindValueChanged(s =>
158159
{
159-
starsText.Text = s.NewValue < 0 ? "-" : s.NewValue.ToLocalisableString("0.00");
160+
starsText.Text = s.NewValue < 0 ? "-" : s.NewValue.FormatStarRating();
160161

161162
background.Colour = colours.ForStarDifficulty(s.NewValue);
162163

osu.Game/OsuGameBase.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public partial class OsuGameBase : Framework.Game, ICanAcceptFiles, IBeatSyncPro
103103
/// </summary>
104104
private const double global_track_volume_adjust = 0.8;
105105

106-
public virtual bool UseDevelopmentServer => DebugUtils.IsDebugBuild;
106+
public virtual bool UseDevelopmentServer => false;
107107

108108
public virtual EndpointConfiguration CreateEndpoints() =>
109109
UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ProductionEndpointConfiguration();

osu.Game/Overlays/BeatmapListing/BeatmapListingSearchControl.cs

+8-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public APIBeatmapSet BeatmapSet
6767
}
6868

6969
private readonly BeatmapSearchTextBox textBox;
70-
private readonly BeatmapSearchMultipleSelectionFilterRow<SearchGeneral> generalFilter;
70+
private readonly BeatmapSearchGeneralFilterRow generalFilter;
7171
private readonly BeatmapSearchRulesetFilterRow modeFilter;
7272
private readonly BeatmapSearchFilterRow<SearchCategory> categoryFilter;
7373
private readonly BeatmapSearchFilterRow<SearchGenre> genreFilter;
@@ -165,6 +165,13 @@ private void load(OverlayColourProvider colourProvider, OsuConfigManager config)
165165
}, true);
166166
}
167167

168+
protected override void LoadComplete()
169+
{
170+
base.LoadComplete();
171+
172+
generalFilter.Ruleset.BindTo(Ruleset);
173+
}
174+
168175
public void TakeFocus() => textBox.TakeFocus();
169176

170177
private partial class BeatmapSearchTextBox : BasicSearchTextBox

osu.Game/Overlays/BeatmapListing/BeatmapSearchGeneralFilterRow.cs

+64-4
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,95 @@
44
using System;
55
using osu.Framework.Allocation;
66
using osu.Framework.Bindables;
7+
using osu.Framework.Extensions;
78
using osu.Framework.Graphics.Sprites;
89
using osu.Framework.Input.Events;
10+
using osu.Framework.Localisation;
11+
using osu.Game.Beatmaps;
912
using osu.Game.Configuration;
13+
using osu.Game.Extensions;
1014
using osu.Game.Graphics;
1115
using osu.Game.Localisation;
16+
using osu.Game.Online.API;
1217
using osu.Game.Overlays.Dialog;
1318
using osu.Game.Resources.Localisation.Web;
19+
using osu.Game.Rulesets;
20+
using osu.Game.Utils;
1421
using osuTK.Graphics;
1522
using CommonStrings = osu.Game.Resources.Localisation.Web.CommonStrings;
1623

1724
namespace osu.Game.Overlays.BeatmapListing
1825
{
1926
public partial class BeatmapSearchGeneralFilterRow : BeatmapSearchMultipleSelectionFilterRow<SearchGeneral>
2027
{
28+
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
29+
2130
public BeatmapSearchGeneralFilterRow()
2231
: base(BeatmapsStrings.ListingSearchFiltersGeneral)
2332
{
2433
}
2534

26-
protected override MultipleSelectionFilter CreateMultipleSelectionFilter() => new GeneralFilter();
35+
protected override MultipleSelectionFilter CreateMultipleSelectionFilter() => new GeneralFilter
36+
{
37+
Ruleset = { BindTarget = Ruleset }
38+
};
2739

2840
private partial class GeneralFilter : MultipleSelectionFilter
2941
{
42+
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
43+
3044
protected override MultipleSelectionFilterTabItem CreateTabItem(SearchGeneral value)
3145
{
32-
if (value == SearchGeneral.FeaturedArtists)
33-
return new FeaturedArtistsTabItem();
46+
switch (value)
47+
{
48+
case SearchGeneral.Recommended:
49+
return new RecommendedDifficultyTabItem
50+
{
51+
Ruleset = { BindTarget = Ruleset }
52+
};
53+
54+
case SearchGeneral.FeaturedArtists:
55+
return new FeaturedArtistsTabItem();
56+
57+
default:
58+
return new MultipleSelectionFilterTabItem(value);
59+
}
60+
}
61+
}
62+
63+
private partial class RecommendedDifficultyTabItem : MultipleSelectionFilterTabItem
64+
{
65+
public readonly IBindable<RulesetInfo> Ruleset = new Bindable<RulesetInfo>();
66+
67+
[Resolved]
68+
private DifficultyRecommender? recommender { get; set; }
69+
70+
[Resolved]
71+
private IAPIProvider api { get; set; } = null!;
72+
73+
[Resolved]
74+
private RulesetStore rulesets { get; set; } = null!;
75+
76+
public RecommendedDifficultyTabItem()
77+
: base(SearchGeneral.Recommended)
78+
{
79+
}
80+
81+
protected override void LoadComplete()
82+
{
83+
base.LoadComplete();
84+
85+
if (recommender != null) recommender.StarRatingUpdated += updateText;
3486

35-
return new MultipleSelectionFilterTabItem(value);
87+
Ruleset.BindValueChanged(_ => updateText(), true);
88+
}
89+
90+
private void updateText()
91+
{
92+
// fallback to profile default game mode if beatmap listing mode filter is set to Any
93+
// TODO: find a way to update `PlayMode` when the profile default game mode has changed
94+
var ruleset = Ruleset.Value.IsLegacyRuleset() ? Ruleset.Value : rulesets.GetRuleset(api.LocalUser.Value.PlayMode)!;
95+
Text.Text = LocalisableString.Interpolate($"{Value.GetLocalisableDescription()} ({recommender?.GetRecommendedStarRatingFor(ruleset).FormatStarRating()})");
3696
}
3797
}
3898

osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using osu.Game.Online.API.Requests.Responses;
2222
using osu.Game.Resources.Localisation.Web;
2323
using osu.Game.Rulesets;
24+
using osu.Game.Utils;
2425
using osuTK;
2526

2627
namespace osu.Game.Overlays.BeatmapSet
@@ -185,7 +186,7 @@ private void updateDisplay()
185186
OnHovered = beatmap =>
186187
{
187188
showBeatmap(beatmap);
188-
starRating.Text = beatmap.StarRating.ToLocalisableString(@"0.00");
189+
starRating.Text = beatmap.StarRating.FormatStarRating();
189190
starRatingContainer.FadeIn(100);
190191
},
191192
OnClicked = beatmap => { Beatmap.Value = beatmap; },

osu.Game/Skinning/Components/BeatmapAttributeText.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private LocalisableString getValueString(BeatmapAttribute attribute)
226226
return computeDifficulty().ApproachRate.ToLocalisableString(@"0.##");
227227

228228
case BeatmapAttribute.StarRating:
229-
return (starDifficulty?.Stars ?? 0).ToLocalisableString(@"F2");
229+
return (starDifficulty?.Stars ?? 0).FormatStarRating();
230230

231231
case BeatmapAttribute.MaxPP:
232232
return Math.Round(starDifficulty?.PerformanceAttributes?.Total ?? 0, MidpointRounding.AwayFromZero).ToLocalisableString();

osu.Game/Utils/FormatUtils.cs

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ public static LocalisableString FormatAccuracy(this double accuracy)
3232
/// <param name="rank">The rank/position to be formatted.</param>
3333
public static string FormatRank(this int rank) => rank.ToMetric(decimals: rank < 100_000 ? 1 : 0);
3434

35+
/// <summary>
36+
/// Formats the supplied star rating in a consistent, simplified way.
37+
/// </summary>
38+
/// <param name="starRating">The star rating to be formatted.</param>
39+
public static LocalisableString FormatStarRating(this double starRating) => starRating.ToLocalisableString("0.00");
40+
3541
/// <summary>
3642
/// Finds the number of digits after the decimal.
3743
/// </summary>

0 commit comments

Comments
 (0)