1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 16:52:54 +08:00

Merge pull request #4000 from m2307/master

Implement clear scores on beatmap
This commit is contained in:
Dan Balasescu 2019-03-01 21:39:21 +09:00 committed by GitHub
commit 10a3b409b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 24 deletions

View File

@ -12,7 +12,7 @@ namespace osu.Game.Beatmaps
/// <summary>
/// Handles the storage and retrieval of Beatmaps/BeatmapSets to the database backing
/// </summary>
public class BeatmapStore : MutableDatabaseBackedStore<BeatmapSetInfo>
public class BeatmapStore : MutableDatabaseBackedStoreWithFileIncludes<BeatmapSetInfo, BeatmapSetFileInfo>
{
public event Action<BeatmapInfo> BeatmapHidden;
public event Action<BeatmapInfo> BeatmapRestored;
@ -64,18 +64,17 @@ namespace osu.Game.Beatmaps
protected override IQueryable<BeatmapSetInfo> AddIncludesForDeletion(IQueryable<BeatmapSetInfo> query) =>
base.AddIncludesForDeletion(query)
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
.Include(s => s.Metadata)
.Include(s => s.Beatmaps).ThenInclude(b => b.Scores);
.Include(s => s.Beatmaps).ThenInclude(b => b.Scores)
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata);
protected override IQueryable<BeatmapSetInfo> AddIncludesForConsumption(IQueryable<BeatmapSetInfo> query) =>
base.AddIncludesForConsumption(query)
.Include(s => s.Metadata)
.Include(s => s.Beatmaps).ThenInclude(s => s.Ruleset)
.Include(s => s.Beatmaps).ThenInclude(b => b.BaseDifficulty)
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata)
.Include(s => s.Files).ThenInclude(f => f.FileInfo);
.Include(s => s.Beatmaps).ThenInclude(b => b.Metadata);
protected override void Purge(List<BeatmapSetInfo> items, OsuDbContext context)
{

View File

@ -108,7 +108,7 @@ namespace osu.Game.Database
a.Invoke();
}
protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStore<TModel> modelStore, IIpcHost importHost = null)
protected ArchiveModelManager(Storage storage, IDatabaseContextFactory contextFactory, MutableDatabaseBackedStoreWithFileIncludes<TModel, TFileModel> modelStore, IIpcHost importHost = null)
{
ContextFactory = contextFactory;

View File

@ -0,0 +1,27 @@
// 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.Linq;
using Microsoft.EntityFrameworkCore;
using osu.Framework.Platform;
namespace osu.Game.Database
{
public abstract class MutableDatabaseBackedStoreWithFileIncludes<T, U> : MutableDatabaseBackedStore<T>
where T : class, IHasPrimaryKey, ISoftDelete, IHasFiles<U>
where U : INamedFileInfo
{
protected MutableDatabaseBackedStoreWithFileIncludes(IDatabaseContextFactory contextFactory, Storage storage = null)
: base(contextFactory, storage)
{
}
protected override IQueryable<T> AddIncludesForConsumption(IQueryable<T> query) =>
base.AddIncludesForConsumption(query)
.Include(s => s.Files).ThenInclude(f => f.FileInfo);
protected override IQueryable<T> AddIncludesForDeletion(IQueryable<T> query) =>
base.AddIncludesForDeletion(query)
.Include(s => s.Files); // don't include FileInfo. these are handled by the FileStore itself.
}
}

View File

@ -8,7 +8,7 @@ using osu.Game.Database;
namespace osu.Game.Scoring
{
public class ScoreStore : MutableDatabaseBackedStore<ScoreInfo>
public class ScoreStore : MutableDatabaseBackedStoreWithFileIncludes<ScoreInfo, ScoreFileInfo>
{
public ScoreStore(IDatabaseContextFactory factory, Storage storage)
: base(factory, storage)
@ -17,7 +17,6 @@ namespace osu.Game.Scoring
protected override IQueryable<ScoreInfo> AddIncludesForConsumption(IQueryable<ScoreInfo> query)
=> base.AddIncludesForConsumption(query)
.Include(s => s.Files).ThenInclude(f => f.FileInfo)
.Include(s => s.Beatmap)
.Include(s => s.Ruleset);
}

View File

@ -0,0 +1,48 @@
// 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 osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Overlays.Dialog;
using osu.Game.Scoring;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace osu.Game.Screens.Select
{
public class BeatmapClearScoresDialog : PopupDialog
{
private ScoreManager scoreManager;
public BeatmapClearScoresDialog(BeatmapInfo beatmap, Action onCompletion)
{
BodyText = $@"{beatmap.Metadata?.Artist} - {beatmap.Metadata?.Title}";
Icon = FontAwesome.fa_eraser;
HeaderText = @"Clearing all local scores. Are you sure?";
Buttons = new PopupDialogButton[]
{
new PopupDialogOkButton
{
Text = @"Yes. Please.",
Action = () =>
{
Task.Run(() => scoreManager.Delete(scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == beatmap.ID).ToList()))
.ContinueWith(_ => onCompletion);
}
},
new PopupDialogCancelButton
{
Text = @"No, I'm still attached.",
},
};
}
[BackgroundDependencyLoader]
private void load(ScoreManager scoreManager)
{
this.scoreManager = scoreManager;
}
}
}

View File

@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select.Leaderboards
{
if (Scope == BeatmapLeaderboardScope.Local)
{
Scores = scoreManager.QueryScores(s => s.Beatmap.ID == Beatmap.ID).ToArray();
Scores = scoreManager.QueryScores(s => !s.DeletePending && s.Beatmap.ID == Beatmap.ID).ToArray();
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
return null;
}

View File

@ -1,11 +1,6 @@
// 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.Collections.Generic;
using System.Linq;
using osuTK;
using osuTK.Input;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
@ -13,8 +8,8 @@ using osu.Framework.Audio.Track;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Framework.Input.Events;
using osu.Framework.Logging;
using osu.Framework.Screens;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
@ -31,7 +26,12 @@ using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
using osu.Game.Screens.Select.Options;
using osu.Game.Skinning;
using osuTK;
using osuTK.Graphics;
using osuTK.Input;
using System;
using System.Collections.Generic;
using System.Linq;
namespace osu.Game.Screens.Select
{
@ -226,7 +226,7 @@ namespace osu.Game.Screens.Select
BeatmapOptions.AddButton(@"Delete", @"all difficulties", FontAwesome.fa_trash, colours.Pink, () => delete(Beatmap.Value.BeatmapSetInfo), Key.Number4, float.MaxValue);
BeatmapOptions.AddButton(@"Remove", @"from unplayed", FontAwesome.fa_times_circle_o, colours.Purple, null, Key.Number1);
BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, null, Key.Number2);
BeatmapOptions.AddButton(@"Clear", @"local scores", FontAwesome.fa_eraser, colours.Purple, () => clearScores(Beatmap.Value.BeatmapInfo), Key.Number2);
}
if (this.beatmaps == null)
@ -621,6 +621,15 @@ namespace osu.Game.Screens.Select
dialogOverlay?.Push(new BeatmapDeleteDialog(beatmap));
}
private void clearScores(BeatmapInfo beatmap)
{
if (beatmap == null || beatmap.ID <= 0) return;
dialogOverlay?.Push(new BeatmapClearScoresDialog(beatmap, () =>
// schedule done here rather than inside the dialog as the dialog may fade out and never callback.
Schedule(() => BeatmapDetails.Leaderboard.RefreshScores())));
}
public override bool OnPressed(GlobalAction action)
{
if (!this.IsCurrentScreen()) return false;

View File

@ -1,22 +1,16 @@
// 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.Linq;
using Microsoft.EntityFrameworkCore;
using osu.Framework.Platform;
using osu.Game.Database;
namespace osu.Game.Skinning
{
public class SkinStore : MutableDatabaseBackedStore<SkinInfo>
public class SkinStore : MutableDatabaseBackedStoreWithFileIncludes<SkinInfo, SkinFileInfo>
{
public SkinStore(DatabaseContextFactory contextFactory, Storage storage = null)
: base(contextFactory, storage)
{
}
protected override IQueryable<SkinInfo> AddIncludesForConsumption(IQueryable<SkinInfo> query) =>
base.AddIncludesForConsumption(query)
.Include(s => s.Files).ThenInclude(f => f.FileInfo);
}
}