mirror of
https://github.com/ppy/osu.git
synced 2025-01-27 04:42:55 +08:00
Reimplement all query methods
This commit is contained in:
parent
53792811b2
commit
4f6a05ce3d
@ -142,7 +142,7 @@ namespace osu.Game.Tests.Scores.IO
|
||||
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
||||
|
||||
beatmapManager.Delete(beatmapManager.QueryBeatmapSet(s => s.Beatmaps.Any(b => b.ID == imported.BeatmapInfo.ID)));
|
||||
Assert.That(scoreManager.Query(s => s.Equals(imported)).DeletePending, Is.EqualTo(true));
|
||||
Assert.That(scoreManager.Query(s => s.Equals(imported)).Value.DeletePending, Is.EqualTo(true));
|
||||
|
||||
var secondImport = await LoadScoreIntoOsu(osu, imported);
|
||||
Assert.That(secondImport, Is.Null);
|
||||
@ -187,7 +187,7 @@ namespace osu.Game.Tests.Scores.IO
|
||||
var scoreManager = osu.Dependencies.Get<ScoreManager>();
|
||||
await scoreManager.Import(score, archive);
|
||||
|
||||
return scoreManager.GetAllUsableScores().FirstOrDefault();
|
||||
return scoreManager.Query(_ => true).Value;
|
||||
}
|
||||
|
||||
internal class TestArchiveReader : ArchiveReader
|
||||
|
@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
|
||||
private void clearScores()
|
||||
{
|
||||
AddStep("Clear all scores", () => scoreManager.Delete(scoreManager.GetAllUsableScores()));
|
||||
AddStep("Clear all scores", () => scoreManager.Delete());
|
||||
}
|
||||
|
||||
private void checkCount(int expected) =>
|
||||
|
@ -44,6 +44,9 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
|
||||
private BeatmapInfo beatmapInfo;
|
||||
|
||||
[Resolved]
|
||||
private RealmContextFactory realmFactory { get; set; }
|
||||
|
||||
[Cached]
|
||||
private readonly DialogOverlay dialogOverlay;
|
||||
|
||||
@ -112,8 +115,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
[SetUp]
|
||||
public void Setup() => Schedule(() =>
|
||||
{
|
||||
// Due to soft deletions, we can re-use deleted scores between test runs
|
||||
scoreManager.Undelete(scoreManager.QueryScores(s => s.DeletePending).ToList());
|
||||
using (var realm = realmFactory.CreateContext())
|
||||
{
|
||||
// Due to soft deletions, we can re-use deleted scores between test runs
|
||||
scoreManager.Undelete(realm.All<ScoreInfo>().Where(s => s.DeletePending).ToList());
|
||||
}
|
||||
|
||||
leaderboard.Scores = null;
|
||||
leaderboard.FinishTransforms(true); // After setting scores, we may be waiting for transforms to expire drawables
|
||||
|
@ -488,10 +488,10 @@ namespace osu.Game
|
||||
ScoreInfo databasedScoreInfo = null;
|
||||
|
||||
if (score.OnlineID > 0)
|
||||
databasedScoreInfo = ScoreManager.Query(s => s.OnlineID == score.OnlineID);
|
||||
databasedScoreInfo = ScoreManager.Query(s => s.OnlineID == score.OnlineID)?.Value;
|
||||
|
||||
if (score is ScoreInfo scoreInfo)
|
||||
databasedScoreInfo ??= ScoreManager.Query(s => s.Hash == scoreInfo.Hash);
|
||||
databasedScoreInfo ??= ScoreManager.Query(s => s.Hash == scoreInfo.Hash)?.Value;
|
||||
|
||||
if (databasedScoreInfo == null)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
|
||||
dialogOverlay?.Push(new MassDeleteConfirmationDialog(() =>
|
||||
{
|
||||
deleteScoresButton.Enabled.Value = false;
|
||||
Task.Run(() => scores.Delete(scores.GetAllUsableScores())).ContinueWith(t => Schedule(() => deleteScoresButton.Enabled.Value = true));
|
||||
Task.Run(() => scores.Delete()).ContinueWith(t => Schedule(() => deleteScoresButton.Enabled.Value = true));
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
@ -26,6 +26,7 @@ namespace osu.Game.Scoring
|
||||
{
|
||||
public class ScoreManager : IModelManager<ScoreInfo>, IModelImporter<ScoreInfo>
|
||||
{
|
||||
private readonly RealmContextFactory contextFactory;
|
||||
private readonly Scheduler scheduler;
|
||||
private readonly Func<BeatmapDifficultyCache> difficulties;
|
||||
private readonly OsuConfigManager configManager;
|
||||
@ -34,6 +35,7 @@ namespace osu.Game.Scoring
|
||||
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, RealmContextFactory contextFactory, Scheduler scheduler,
|
||||
IIpcHost importHost = null, Func<BeatmapDifficultyCache> difficulties = null, OsuConfigManager configManager = null)
|
||||
{
|
||||
this.contextFactory = contextFactory;
|
||||
this.scheduler = scheduler;
|
||||
this.difficulties = difficulties;
|
||||
this.configManager = configManager;
|
||||
@ -43,11 +45,16 @@ namespace osu.Game.Scoring
|
||||
|
||||
public Score GetScore(ScoreInfo score) => scoreModelManager.GetScore(score);
|
||||
|
||||
public List<ScoreInfo> GetAllUsableScores() => scoreModelManager.GetAllUsableScores();
|
||||
|
||||
public IEnumerable<ScoreInfo> QueryScores(Expression<Func<ScoreInfo, bool>> query) => scoreModelManager.QueryScores(query);
|
||||
|
||||
public ScoreInfo Query(Expression<Func<ScoreInfo, bool>> query) => scoreModelManager.Query(query);
|
||||
/// <summary>
|
||||
/// Perform a lookup query on available <see cref="ScoreInfo"/>s.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <returns>The first result for the provided query, or null if no results were found.</returns>
|
||||
public ILive<ScoreInfo> Query(Expression<Func<ScoreInfo, bool>> query)
|
||||
{
|
||||
using (var context = contextFactory.CreateContext())
|
||||
return context.All<ScoreInfo>().FirstOrDefault(query)?.ToLive();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Orders an array of <see cref="ScoreInfo"/>s by total score.
|
||||
@ -267,6 +274,20 @@ namespace osu.Game.Scoring
|
||||
return scoreModelManager.Delete(item);
|
||||
}
|
||||
|
||||
public void Delete([CanBeNull] Expression<Func<ScoreInfo, bool>> filter = null, bool silent = false)
|
||||
{
|
||||
using (var context = contextFactory.CreateContext())
|
||||
{
|
||||
var items = context.All<ScoreInfo>()
|
||||
.Where(s => !s.DeletePending);
|
||||
|
||||
if (filter != null)
|
||||
items = items.Where(filter);
|
||||
|
||||
scoreModelManager.Delete(items.ToList(), silent);
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(List<ScoreInfo> items, bool silent = false)
|
||||
{
|
||||
scoreModelManager.Delete(items, silent);
|
||||
|
@ -1,14 +1,13 @@
|
||||
// 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.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays.Dialog;
|
||||
using osu.Game.Scoring;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
||||
namespace osu.Game.Screens.Select
|
||||
{
|
||||
@ -29,7 +28,7 @@ namespace osu.Game.Screens.Select
|
||||
Text = @"Yes. Please.",
|
||||
Action = () =>
|
||||
{
|
||||
Task.Run(() => scoreManager.Delete(scoreManager.QueryScores(s => !s.DeletePending && s.BeatmapInfo.ID == beatmapInfo.ID).ToList()))
|
||||
Task.Run(() => scoreManager.Delete(s => !s.DeletePending && s.BeatmapInfo.ID == beatmapInfo.ID))
|
||||
.ContinueWith(_ => onCompletion);
|
||||
}
|
||||
},
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
using osu.Game.Rulesets;
|
||||
@ -24,6 +25,9 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private RealmContextFactory realmFactory { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
@ -54,7 +58,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
private void fetchAndLoadTopScore()
|
||||
{
|
||||
var rank = fetchTopScore()?.Rank;
|
||||
var rank = fetchTopScoreRank();
|
||||
scheduledRankUpdate = Schedule(() =>
|
||||
{
|
||||
Rank = rank;
|
||||
@ -67,14 +71,18 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
// We're present if a rank is set, or if there is a pending rank update (IsPresent = true is required for the scheduler to run).
|
||||
public override bool IsPresent => base.IsPresent && (Rank != null || scheduledRankUpdate?.Completed == false);
|
||||
|
||||
private ScoreInfo fetchTopScore()
|
||||
private ScoreRank? fetchTopScoreRank()
|
||||
{
|
||||
if (scores == null || beatmapInfo == null || ruleset?.Value == null || api?.LocalUser.Value == null)
|
||||
if (realmFactory == null || beatmapInfo == null || ruleset?.Value == null || api?.LocalUser.Value == null)
|
||||
return null;
|
||||
|
||||
return scores.QueryScores(s => s.UserID == api.LocalUser.Value.Id && s.BeatmapInfoID == beatmapInfo.ID && s.RulesetID == ruleset.Value.ID && !s.DeletePending)
|
||||
.OrderByDescending(s => s.TotalScore)
|
||||
.FirstOrDefault();
|
||||
using (var realm = realmFactory.CreateContext())
|
||||
{
|
||||
return realm.All<ScoreInfo>().Where(s => s.UserID == api.LocalUser.Value.Id && s.BeatmapInfoID == beatmapInfo.ID && s.RulesetID == ruleset.Value.ID && !s.DeletePending)
|
||||
.OrderByDescending(s => s.TotalScore)
|
||||
.FirstOrDefault()
|
||||
?.Rank;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
|
@ -10,6 +10,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.Leaderboards;
|
||||
@ -26,6 +27,9 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private RealmContextFactory realmFactory { get; set; }
|
||||
|
||||
private BeatmapInfo beatmapInfo;
|
||||
|
||||
public BeatmapInfo BeatmapInfo
|
||||
@ -126,26 +130,28 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
|
||||
if (Scope == BeatmapLeaderboardScope.Local)
|
||||
{
|
||||
var scores = scoreManager
|
||||
.QueryScores(s => !s.DeletePending && s.BeatmapInfo.ID == fetchBeatmapInfo.ID && s.Ruleset.OnlineID == ruleset.Value.ID);
|
||||
|
||||
if (filterMods && !mods.Value.Any())
|
||||
using (var realm = realmFactory.CreateContext())
|
||||
{
|
||||
// we need to filter out all scores that have any mods to get all local nomod scores
|
||||
scores = scores.Where(s => !s.Mods.Any());
|
||||
}
|
||||
else if (filterMods)
|
||||
{
|
||||
// otherwise find all the scores that have *any* of the currently selected mods (similar to how web applies mod filters)
|
||||
// we're creating and using a string list representation of selected mods so that it can be translated into the DB query itself
|
||||
var selectedMods = mods.Value.Select(m => m.Acronym);
|
||||
scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym)));
|
||||
}
|
||||
var scores = realm.All<ScoreInfo>().Where(s => !s.DeletePending && s.BeatmapInfo.ID == fetchBeatmapInfo.ID && s.Ruleset.OnlineID == ruleset.Value.ID);
|
||||
|
||||
scoreManager.OrderByTotalScoreAsync(scores.ToArray(), cancellationToken)
|
||||
.ContinueWith(task => scoresCallback?.Invoke(task.GetResultSafely()), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
if (filterMods && !mods.Value.Any())
|
||||
{
|
||||
// we need to filter out all scores that have any mods to get all local nomod scores
|
||||
scores = scores.Where(s => !s.Mods.Any());
|
||||
}
|
||||
else if (filterMods)
|
||||
{
|
||||
// otherwise find all the scores that have *any* of the currently selected mods (similar to how web applies mod filters)
|
||||
// we're creating and using a string list representation of selected mods so that it can be translated into the DB query itself
|
||||
var selectedMods = mods.Value.Select(m => m.Acronym);
|
||||
scores = scores.Where(s => s.Mods.Any(m => selectedMods.Contains(m.Acronym)));
|
||||
}
|
||||
|
||||
return null;
|
||||
scoreManager.OrderByTotalScoreAsync(scores.ToArray(), cancellationToken)
|
||||
.ContinueWith(ordered => scoresCallback?.Invoke(ordered.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (api?.IsLoggedIn != true)
|
||||
|
Loading…
Reference in New Issue
Block a user