1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 09:07:25 +08:00

Implement basic score recalculation

This commit is contained in:
smoogipoo 2020-08-28 19:16:46 +09:00
parent 85bda29b71
commit 4d15f0fe52
6 changed files with 55 additions and 16 deletions

View File

@ -201,11 +201,11 @@ namespace osu.Game.Beatmaps
var calculator = ruleset.CreateDifficultyCalculator(beatmapManager.GetWorkingBeatmap(beatmapInfo));
var attributes = calculator.Calculate(key.Mods);
return difficultyCache[key] = new StarDifficulty(attributes.StarRating);
return difficultyCache[key] = new StarDifficulty(attributes.StarRating, attributes.MaxCombo);
}
catch
{
return difficultyCache[key] = new StarDifficulty(0);
return difficultyCache[key] = new StarDifficulty();
}
}
@ -227,7 +227,7 @@ namespace osu.Game.Beatmaps
if (beatmapInfo.ID == 0 || rulesetInfo.ID == null)
{
// If not, fall back to the existing star difficulty (e.g. from an online source).
existingDifficulty = new StarDifficulty(beatmapInfo.StarDifficulty);
existingDifficulty = new StarDifficulty(beatmapInfo.StarDifficulty, beatmapInfo.MaxCombo ?? 0);
key = default;
return true;
@ -292,10 +292,12 @@ namespace osu.Game.Beatmaps
public readonly struct StarDifficulty
{
public readonly double Stars;
public readonly int MaxCombo;
public StarDifficulty(double stars)
public StarDifficulty(double stars, int maxCombo)
{
Stars = stars;
MaxCombo = maxCombo;
// Todo: Add more members (BeatmapInfo.DifficultyRating? Attributes? Etc...)
}

View File

@ -72,7 +72,7 @@ namespace osu.Game.Online.Leaderboards
}
[BackgroundDependencyLoader]
private void load(IAPIProvider api, OsuColour colour)
private void load(IAPIProvider api, OsuColour colour, ScoreManager scoreManager)
{
var user = score.User;
@ -194,7 +194,7 @@ namespace osu.Game.Online.Leaderboards
{
TextColour = Color4.White,
GlowColour = Color4Extensions.FromHex(@"83ccfa"),
Text = score.TotalScore.ToString(@"N0"),
Text = scoreManager.GetTotalScore(score).ToString(@"N0"),
Font = OsuFont.Numeric.With(size: 23),
},
RankContainer = new Container

View File

@ -57,6 +57,8 @@ namespace osu.Game
protected ScoreManager ScoreManager;
protected BeatmapDifficultyManager DifficultyManager;
protected SkinManager SkinManager;
protected RulesetStore RulesetStore;
@ -194,7 +196,7 @@ namespace osu.Game
dependencies.Cache(FileStore = new FileStore(contextFactory, Storage));
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host));
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => DifficultyManager));
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap));
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary
@ -218,9 +220,8 @@ namespace osu.Game
ScoreManager.Undelete(getBeatmapScores(item), true);
});
var difficultyManager = new BeatmapDifficultyManager();
dependencies.Cache(difficultyManager);
AddInternal(difficultyManager);
dependencies.Cache(DifficultyManager = new BeatmapDifficultyManager());
AddInternal(DifficultyManager);
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));

View File

@ -25,6 +25,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private const float row_height = 22;
private const int text_size = 12;
[Resolved]
private ScoreManager scoreManager { get; set; }
private readonly FillFlowContainer backgroundFlow;
private Color4 highAccuracyColour;
@ -121,7 +124,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
new OsuSpriteText
{
Margin = new MarginPadding { Right = horizontal_inset },
Text = $@"{score.TotalScore:N0}",
Text = $@"{scoreManager.GetTotalScore(score):N0}",
Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium)
},
new OsuSpriteText

View File

@ -203,19 +203,24 @@ namespace osu.Game.Rulesets.Scoring
}
private double getScore(ScoringMode mode)
{
return GetScore(baseScore / maxBaseScore, HighestCombo.Value / maxHighestCombo, bonusScore, mode);
}
public double GetScore(double accuracyRatio, double comboRatio, double bonus, ScoringMode mode)
{
switch (mode)
{
default:
case ScoringMode.Standardised:
double accuracyScore = accuracyPortion * baseScore / maxBaseScore;
double comboScore = comboPortion * HighestCombo.Value / maxHighestCombo;
double accuracyScore = accuracyPortion * accuracyRatio;
double comboScore = comboPortion * comboRatio;
return (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
return (max_score * (accuracyScore + comboScore) + bonus) * scoreMultiplier;
case ScoringMode.Classic:
// should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1)
return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo.Value - 1) * scoreMultiplier / 25);
return bonus + (accuracyRatio * maxBaseScore) * (1 + Math.Max(0, (comboRatio * maxHighestCombo) - 1) * scoreMultiplier / 25);
}
}

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using osu.Framework.Logging;
using osu.Framework.Platform;
@ -15,6 +16,7 @@ using osu.Game.IO.Archives;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring.Legacy;
namespace osu.Game.Scoring
@ -30,11 +32,16 @@ namespace osu.Game.Scoring
private readonly RulesetStore rulesets;
private readonly Func<BeatmapManager> beatmaps;
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IAPIProvider api, IDatabaseContextFactory contextFactory, IIpcHost importHost = null)
[CanBeNull]
private readonly Func<BeatmapDifficultyManager> difficulties;
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IAPIProvider api, IDatabaseContextFactory contextFactory, IIpcHost importHost = null,
Func<BeatmapDifficultyManager> difficulties = null)
: base(storage, contextFactory, api, new ScoreStore(contextFactory, storage), importHost)
{
this.rulesets = rulesets;
this.beatmaps = beatmaps;
this.difficulties = difficulties;
}
protected override ScoreInfo CreateModel(ArchiveReader archive)
@ -72,5 +79,26 @@ namespace osu.Game.Scoring
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items)
=> base.CheckLocalAvailability(model, items)
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
public long GetTotalScore(ScoreInfo score)
{
int? beatmapMaxCombo = score.Beatmap.MaxCombo;
if (beatmapMaxCombo == null)
{
if (score.Beatmap.ID == 0 || difficulties == null)
return score.TotalScore; // Can't do anything.
// We can compute the max combo locally.
beatmapMaxCombo = difficulties().GetDifficulty(score.Beatmap, score.Ruleset, score.Mods).MaxCombo;
}
var ruleset = score.Ruleset.CreateInstance();
var scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = score.Mods;
return (long)Math.Round(scoreProcessor.GetScore(score.Accuracy, (double)score.MaxCombo / beatmapMaxCombo.Value, 0, ScoringMode.Standardised));
}
}
}