mirror of
https://github.com/ppy/osu.git
synced 2026-05-13 19:54:15 +08:00
Merge pull request #32579 from bdach/allow-tagging-if-local-score-present
Allow tagging already played beatmaps without playing another time
This commit is contained in:
@@ -8,11 +8,15 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
@@ -27,6 +31,7 @@ using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mania;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Ranking.Statistics;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
@@ -43,6 +48,22 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
{
|
||||
private DummyAPIAccess dummyAPI => (DummyAPIAccess)API;
|
||||
|
||||
private ScoreManager scoreManager = null!;
|
||||
private RulesetStore rulesetStore = null!;
|
||||
private BeatmapManager beatmapManager = null!;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
{
|
||||
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
|
||||
dependencies.Cache(rulesetStore = new RealmRulesetStore(Realm));
|
||||
dependencies.Cache(beatmapManager = new BeatmapManager(LocalStorage, Realm, null, dependencies.Get<AudioManager>(), Resources, dependencies.Get<GameHost>(), Beatmap.Default));
|
||||
dependencies.Cache(scoreManager = new ScoreManager(rulesetStore, () => beatmapManager, LocalStorage, Realm, API));
|
||||
Dependencies.Cache(Realm);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestScoreWithPositionStatistics()
|
||||
{
|
||||
@@ -163,6 +184,24 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo();
|
||||
|
||||
setUpTaggingRequests(() => score.BeatmapInfo);
|
||||
AddStep("load panel", () =>
|
||||
{
|
||||
Child = new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new StatisticsPanel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = { Value = Visibility.Visible },
|
||||
Score = { Value = score },
|
||||
AchievedScore = score,
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void setUpTaggingRequests(Func<BeatmapInfo> beatmap) =>
|
||||
AddStep("set up network requests", () =>
|
||||
{
|
||||
dummyAPI.HandleRequest = request =>
|
||||
@@ -176,7 +215,11 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
Tags =
|
||||
[
|
||||
new APITag { Id = 1, Name = "tech", Description = "Tests uncommon skills.", },
|
||||
new APITag { Id = 2, Name = "alt", Description = "Colloquial term for maps which use rhythms that encourage the player to alternate notes. Typically distinct from burst or stream maps.", },
|
||||
new APITag
|
||||
{
|
||||
Id = 2, Name = "alt",
|
||||
Description = "Colloquial term for maps which use rhythms that encourage the player to alternate notes. Typically distinct from burst or stream maps.",
|
||||
},
|
||||
new APITag { Id = 3, Name = "aim", Description = "Category for difficulty relating to cursor movement.", },
|
||||
new APITag { Id = 4, Name = "tap", Description = "Category for difficulty relating to tapping input.", },
|
||||
]
|
||||
@@ -186,7 +229,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
|
||||
case GetBeatmapSetRequest getBeatmapSetRequest:
|
||||
{
|
||||
var beatmapSet = CreateAPIBeatmapSet(score.BeatmapInfo);
|
||||
var beatmapSet = CreateAPIBeatmapSet(beatmap.Invoke());
|
||||
beatmapSet.Beatmaps.Single().TopTags =
|
||||
[
|
||||
new APIBeatmapTag { TagId = 3, VoteCount = 9 },
|
||||
@@ -206,21 +249,6 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
return false;
|
||||
};
|
||||
});
|
||||
AddStep("load panel", () =>
|
||||
{
|
||||
Child = new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new StatisticsPanel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = { Value = Visibility.Visible },
|
||||
Score = { Value = score },
|
||||
AchievedScore = score,
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTaggingWhenRankTooLow()
|
||||
@@ -266,6 +294,78 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTaggingInteractionWithLocalScores()
|
||||
{
|
||||
BeatmapInfo beatmapInfo = null!;
|
||||
|
||||
AddStep(@"Import beatmap", () =>
|
||||
{
|
||||
beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely();
|
||||
beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
|
||||
});
|
||||
|
||||
AddStep("import bad score", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo();
|
||||
score.BeatmapInfo = beatmapInfo;
|
||||
score.BeatmapHash = beatmapInfo.Hash;
|
||||
score.Ruleset = beatmapInfo.Ruleset;
|
||||
score.Rank = ScoreRank.D;
|
||||
score.User = API.LocalUser.Value;
|
||||
scoreManager.Import(score);
|
||||
});
|
||||
|
||||
AddStep("import score by another user", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo();
|
||||
score.BeatmapInfo = beatmapInfo;
|
||||
score.BeatmapHash = beatmapInfo.Hash;
|
||||
score.Ruleset = beatmapInfo.Ruleset;
|
||||
score.Rank = ScoreRank.D;
|
||||
score.User = new APIUser { Username = "notme", Id = 5678 };
|
||||
scoreManager.Import(score);
|
||||
});
|
||||
|
||||
AddStep("import convert score", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo();
|
||||
score.BeatmapInfo = beatmapInfo;
|
||||
score.BeatmapHash = beatmapInfo.Hash;
|
||||
score.Ruleset = new OsuRuleset().RulesetInfo;
|
||||
score.User = API.LocalUser.Value;
|
||||
scoreManager.Import(score);
|
||||
});
|
||||
|
||||
AddStep("import correct score", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo();
|
||||
score.BeatmapInfo = beatmapInfo;
|
||||
score.BeatmapHash = beatmapInfo.Hash;
|
||||
score.Ruleset = beatmapInfo.Ruleset;
|
||||
score.User = API.LocalUser.Value;
|
||||
scoreManager.Import(score);
|
||||
});
|
||||
|
||||
setUpTaggingRequests(() => beatmapInfo);
|
||||
AddStep("load panel", () =>
|
||||
{
|
||||
var score = TestResources.CreateTestScoreInfo();
|
||||
score.BeatmapInfo = beatmapInfo;
|
||||
|
||||
Child = new PopoverContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new StatisticsPanel
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
State = { Value = Visibility.Visible },
|
||||
Score = { Value = score },
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void loadPanel(ScoreInfo score) => AddStep("load panel", () =>
|
||||
{
|
||||
Child = new StatisticsPanel
|
||||
|
||||
@@ -14,14 +14,18 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Models;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Placeholders;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Screens.Ranking.Statistics.User;
|
||||
using osuTK;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Screens.Ranking.Statistics
|
||||
{
|
||||
@@ -43,6 +47,9 @@ namespace osu.Game.Screens.Ranking.Statistics
|
||||
[Resolved]
|
||||
private BeatmapManager beatmapManager { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private RealmAccess realm { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
|
||||
@@ -231,17 +238,29 @@ namespace osu.Game.Screens.Ranking.Statistics
|
||||
});
|
||||
}
|
||||
|
||||
if (AchievedScore != null
|
||||
&& newScore.BeatmapInfo!.OnlineID > 0
|
||||
if (newScore.BeatmapInfo!.OnlineID > 0
|
||||
&& api.IsLoggedIn)
|
||||
{
|
||||
string? preventTaggingReason = null;
|
||||
|
||||
// We may want to iterate on the following conditions further in the future
|
||||
|
||||
if (AchievedScore.Ruleset.OnlineID != AchievedScore.BeatmapInfo!.Ruleset.OnlineID)
|
||||
var localUserScore = AchievedScore ?? realm.Run(r =>
|
||||
r.All<ScoreInfo>()
|
||||
.Filter($@"{nameof(ScoreInfo.User)}.{nameof(RealmUser.OnlineID)} == $0"
|
||||
+ $@" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $1"
|
||||
+ $@" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.BeatmapHash)}"
|
||||
+ $@" && {nameof(ScoreInfo.DeletePending)} == false", api.LocalUser.Value.Id, newScore.BeatmapInfo.ID, newScore.BeatmapInfo.Ruleset.ShortName)
|
||||
.AsEnumerable()
|
||||
.OrderByDescending(score => score.Ruleset.MatchesOnlineID(newScore.BeatmapInfo.Ruleset))
|
||||
.ThenByDescending(score => score.Rank)
|
||||
.FirstOrDefault());
|
||||
|
||||
if (localUserScore == null)
|
||||
preventTaggingReason = "Play the beatmap to contribute to beatmap tags!";
|
||||
else if (localUserScore.Ruleset.OnlineID != newScore.BeatmapInfo!.Ruleset.OnlineID)
|
||||
preventTaggingReason = "Play the beatmap in its original ruleset to contribute to beatmap tags!";
|
||||
else if (AchievedScore.Rank < ScoreRank.C)
|
||||
else if (localUserScore.Rank < ScoreRank.C)
|
||||
preventTaggingReason = "Set a better score to contribute to beatmap tags!";
|
||||
|
||||
if (preventTaggingReason == null)
|
||||
|
||||
Reference in New Issue
Block a user