mirror of
https://github.com/ppy/osu.git
synced 2024-12-05 02:53:21 +08:00
Introduce LocalUserStatisticsProvider
component
This commit is contained in:
parent
b0420f7ed9
commit
91fb59ee15
@ -0,0 +1,141 @@
|
||||
// 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.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Rulesets.Catch;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Rulesets.Taiko;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
public partial class TestSceneLocalUserStatisticsProvider : OsuTestScene
|
||||
{
|
||||
private LocalUserStatisticsProvider statisticsProvider = null!;
|
||||
|
||||
private readonly Dictionary<(int userId, string rulesetName), UserStatistics> serverSideStatistics = new Dictionary<(int userId, string rulesetName), UserStatistics>();
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("clear statistics", () => serverSideStatistics.Clear());
|
||||
|
||||
setUser(1000);
|
||||
|
||||
AddStep("setup provider", () =>
|
||||
{
|
||||
OsuSpriteText text;
|
||||
|
||||
((DummyAPIAccess)API).HandleRequest = r =>
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case GetUserRequest userRequest:
|
||||
int userId = int.Parse(userRequest.Lookup);
|
||||
string rulesetName = userRequest.Ruleset!.ShortName;
|
||||
var response = new APIUser
|
||||
{
|
||||
Id = userId,
|
||||
Statistics = tryGetStatistics(userId, rulesetName)
|
||||
};
|
||||
|
||||
userRequest.TriggerSuccess(response);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Clear();
|
||||
Add(statisticsProvider = new LocalUserStatisticsProvider());
|
||||
Add(text = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
});
|
||||
|
||||
statisticsProvider.Statistics.BindValueChanged(s =>
|
||||
{
|
||||
text.Text = s.NewValue == null
|
||||
? "Statistics: (null)"
|
||||
: $"Statistics: (total score: {s.NewValue.TotalScore:N0})";
|
||||
});
|
||||
|
||||
Ruleset.Value = new OsuRuleset().RulesetInfo;
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInitialStatistics()
|
||||
{
|
||||
AddAssert("initial statistics populated", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(4_000_000));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRulesetChanges()
|
||||
{
|
||||
AddAssert("statistics from osu", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(4_000_000));
|
||||
AddStep("change ruleset to taiko", () => Ruleset.Value = new TaikoRuleset().RulesetInfo);
|
||||
AddAssert("statistics from taiko", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(3_000_000));
|
||||
AddStep("change ruleset to catch", () => Ruleset.Value = new CatchRuleset().RulesetInfo);
|
||||
AddAssert("statistics from catch", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(2_000_000));
|
||||
AddStep("change ruleset to mania", () => Ruleset.Value = new ManiaRuleset().RulesetInfo);
|
||||
AddAssert("statistics from mania", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(1_000_000));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestUserChanges()
|
||||
{
|
||||
setUser(1001);
|
||||
|
||||
AddStep("update statistics for user 1000", () =>
|
||||
{
|
||||
serverSideStatistics[(1000, "osu")] = new UserStatistics { TotalScore = 5_000_000 };
|
||||
serverSideStatistics[(1000, "taiko")] = new UserStatistics { TotalScore = 6_000_000 };
|
||||
});
|
||||
|
||||
AddAssert("statistics matches user 1001 from osu", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(4_000_000));
|
||||
|
||||
AddStep("change ruleset to taiko", () => Ruleset.Value = new TaikoRuleset().RulesetInfo);
|
||||
AddAssert("statistics matches user 1001 from taiko", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(3_000_000));
|
||||
|
||||
AddStep("change ruleset to osu", () => Ruleset.Value = new OsuRuleset().RulesetInfo);
|
||||
setUser(1000, false);
|
||||
|
||||
AddAssert("statistics matches user 1000 from osu", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(5_000_000));
|
||||
|
||||
AddStep("change ruleset to osu", () => Ruleset.Value = new TaikoRuleset().RulesetInfo);
|
||||
AddAssert("statistics matches user 1000 from taiko", () => statisticsProvider.Statistics.Value.AsNonNull().TotalScore, () => Is.EqualTo(6_000_000));
|
||||
}
|
||||
|
||||
private UserStatistics tryGetStatistics(int userId, string rulesetName)
|
||||
=> serverSideStatistics.TryGetValue((userId, rulesetName), out var stats) ? stats : new UserStatistics();
|
||||
|
||||
private void setUser(int userId, bool generateStatistics = true)
|
||||
{
|
||||
AddStep($"set local user to {userId}", () =>
|
||||
{
|
||||
if (generateStatistics)
|
||||
{
|
||||
serverSideStatistics[(userId, "osu")] = new UserStatistics { TotalScore = 4_000_000 };
|
||||
serverSideStatistics[(userId, "taiko")] = new UserStatistics { TotalScore = 3_000_000 };
|
||||
serverSideStatistics[(userId, "fruits")] = new UserStatistics { TotalScore = 2_000_000 };
|
||||
serverSideStatistics[(userId, "mania")] = new UserStatistics { TotalScore = 1_000_000 };
|
||||
}
|
||||
|
||||
((DummyAPIAccess)API).LocalUser.Value = new APIUser { Id = userId };
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
94
osu.Game/Online/LocalUserStatisticsProvider.cs
Normal file
94
osu.Game/Online/LocalUserStatisticsProvider.cs
Normal file
@ -0,0 +1,94 @@
|
||||
// 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.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Users;
|
||||
|
||||
namespace osu.Game.Online
|
||||
{
|
||||
/// <summary>
|
||||
/// A component that is responsible for providing the latest statistics of the logged-in user for the game-wide selected ruleset.
|
||||
/// </summary>
|
||||
public partial class LocalUserStatisticsProvider : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The statistics of the logged-in user for the game-wide selected ruleset.
|
||||
/// </summary>
|
||||
public IBindable<UserStatistics?> Statistics => statistics;
|
||||
|
||||
private readonly Bindable<UserStatistics?> statistics = new Bindable<UserStatistics?>();
|
||||
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
private readonly Dictionary<string, UserStatistics> allStatistics = new Dictionary<string, UserStatistics>();
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
statistics.BindValueChanged(v =>
|
||||
{
|
||||
if (api.LocalUser.Value != null && v.NewValue != null)
|
||||
api.LocalUser.Value.Statistics = v.NewValue;
|
||||
});
|
||||
|
||||
ruleset.BindValueChanged(_ => updateStatisticsBindable());
|
||||
|
||||
api.LocalUser.BindValueChanged(_ =>
|
||||
{
|
||||
allStatistics.Clear();
|
||||
updateStatisticsBindable();
|
||||
}, true);
|
||||
}
|
||||
|
||||
private GetUserRequest? currentRequest;
|
||||
|
||||
private void updateStatisticsBindable() => Schedule(() =>
|
||||
{
|
||||
statistics.Value = null;
|
||||
|
||||
if (api.LocalUser.Value == null || api.LocalUser.Value.OnlineID <= 1 || !ruleset.Value.IsLegacyRuleset())
|
||||
{
|
||||
statistics.Value = new UserStatistics();
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentRequest?.CompletionState == APIRequestCompletionState.Waiting)
|
||||
{
|
||||
currentRequest.Cancel();
|
||||
currentRequest = null;
|
||||
}
|
||||
|
||||
if (allStatistics.TryGetValue(ruleset.Value.ShortName, out var existing))
|
||||
statistics.Value = existing;
|
||||
else
|
||||
requestStatistics(ruleset.Value);
|
||||
});
|
||||
|
||||
private void requestStatistics(RulesetInfo ruleset)
|
||||
{
|
||||
currentRequest = new GetUserRequest(api.LocalUser.Value.OnlineID, ruleset);
|
||||
currentRequest.Success += u => statistics.Value = allStatistics[ruleset.ShortName] = u.Statistics;
|
||||
api.Queue(currentRequest);
|
||||
}
|
||||
|
||||
internal void UpdateStatistics(UserStatistics statistics, RulesetInfo statisticsRuleset)
|
||||
{
|
||||
allStatistics[statisticsRuleset.ShortName] = statistics;
|
||||
|
||||
if (statisticsRuleset.ShortName == ruleset.Value.ShortName)
|
||||
updateStatisticsBindable();
|
||||
}
|
||||
}
|
||||
}
|
@ -208,6 +208,7 @@ namespace osu.Game
|
||||
|
||||
private MetadataClient metadataClient;
|
||||
private SoloStatisticsWatcher soloStatisticsWatcher;
|
||||
private LocalUserStatisticsProvider localUserStatisticsProvider;
|
||||
|
||||
private RealmAccess realm;
|
||||
|
||||
@ -328,7 +329,9 @@ namespace osu.Game
|
||||
dependencies.CacheAs(SpectatorClient = new OnlineSpectatorClient(endpoints));
|
||||
dependencies.CacheAs(MultiplayerClient = new OnlineMultiplayerClient(endpoints));
|
||||
dependencies.CacheAs(metadataClient = new OnlineMetadataClient(endpoints));
|
||||
dependencies.CacheAs(soloStatisticsWatcher = new SoloStatisticsWatcher());
|
||||
|
||||
dependencies.CacheAs(localUserStatisticsProvider = new LocalUserStatisticsProvider());
|
||||
dependencies.CacheAs(soloStatisticsWatcher = new SoloStatisticsWatcher(localUserStatisticsProvider));
|
||||
|
||||
base.Content.Add(new BeatmapOnlineChangeIngest(beatmapUpdater, realm, metadataClient));
|
||||
|
||||
@ -371,6 +374,7 @@ namespace osu.Game
|
||||
base.Content.Add(SpectatorClient);
|
||||
base.Content.Add(MultiplayerClient);
|
||||
base.Content.Add(metadataClient);
|
||||
base.Content.Add(localUserStatisticsProvider);
|
||||
base.Content.Add(soloStatisticsWatcher);
|
||||
|
||||
base.Content.Add(rulesetConfigCache);
|
||||
|
Loading…
Reference in New Issue
Block a user