mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:37:28 +08:00
Refactoring
This commit is contained in:
parent
e291dff5ad
commit
09bc8e45de
@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
if (ComputeLegacyScoringValues)
|
||||||
{
|
{
|
||||||
CatchScoreV1Processor sv1Processor = new CatchScoreV1Processor();
|
CatchLegacyScoreProcessor sv1Processor = new CatchLegacyScoreProcessor();
|
||||||
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
||||||
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
||||||
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
||||||
|
@ -14,22 +14,12 @@ using osu.Game.Rulesets.Scoring;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Difficulty
|
namespace osu.Game.Rulesets.Catch.Difficulty
|
||||||
{
|
{
|
||||||
internal class CatchScoreV1Processor : ILegacyScoreProcessor
|
internal class CatchLegacyScoreProcessor : ILegacyScoreProcessor
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The accuracy portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
public int AccuracyScore { get; private set; }
|
public int AccuracyScore { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The combo-multiplied portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
public int ComboScore { get; private set; }
|
public int ComboScore { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A ratio of <c>new_bonus_score / old_bonus_score</c> for converting the bonus score of legacy scores to the new scoring.
|
|
||||||
/// This is made up of all judgements that would be <see cref="HitResult.SmallBonus"/> or <see cref="HitResult.LargeBonus"/>.
|
|
||||||
/// </summary>
|
|
||||||
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
||||||
|
|
||||||
private int legacyBonusScore;
|
private int legacyBonusScore;
|
@ -62,7 +62,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
if (ComputeLegacyScoringValues)
|
||||||
{
|
{
|
||||||
ManiaScoreV1Processor sv1Processor = new ManiaScoreV1Processor();
|
ManiaLegacyScoreProcessor sv1Processor = new ManiaLegacyScoreProcessor();
|
||||||
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
||||||
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
||||||
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
||||||
|
@ -10,7 +10,7 @@ using osu.Game.Rulesets.Scoring;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Mania.Difficulty
|
namespace osu.Game.Rulesets.Mania.Difficulty
|
||||||
{
|
{
|
||||||
internal class ManiaScoreV1Processor : ILegacyScoreProcessor
|
internal class ManiaLegacyScoreProcessor : ILegacyScoreProcessor
|
||||||
{
|
{
|
||||||
public int AccuracyScore => 0;
|
public int AccuracyScore => 0;
|
||||||
public int ComboScore { get; private set; }
|
public int ComboScore { get; private set; }
|
@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
if (ComputeLegacyScoringValues)
|
||||||
{
|
{
|
||||||
OsuScoreV1Processor sv1Processor = new OsuScoreV1Processor();
|
OsuLegacyScoreProcessor sv1Processor = new OsuLegacyScoreProcessor();
|
||||||
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
||||||
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
||||||
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
||||||
|
@ -14,22 +14,12 @@ using osu.Game.Rulesets.Scoring;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Difficulty
|
namespace osu.Game.Rulesets.Osu.Difficulty
|
||||||
{
|
{
|
||||||
internal class OsuScoreV1Processor : ILegacyScoreProcessor
|
internal class OsuLegacyScoreProcessor : ILegacyScoreProcessor
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The accuracy portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
public int AccuracyScore { get; private set; }
|
public int AccuracyScore { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The combo-multiplied portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
public int ComboScore { get; private set; }
|
public int ComboScore { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A ratio of <c>new_bonus_score / old_bonus_score</c> for converting the bonus score of legacy scores to the new scoring.
|
|
||||||
/// This is made up of all judgements that would be <see cref="HitResult.SmallBonus"/> or <see cref="HitResult.LargeBonus"/>.
|
|
||||||
/// </summary>
|
|
||||||
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
||||||
|
|
||||||
private int legacyBonusScore;
|
private int legacyBonusScore;
|
@ -323,6 +323,6 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
|
|
||||||
public override RulesetSetupSection CreateEditorSetupSection() => new OsuSetupSection();
|
public override RulesetSetupSection CreateEditorSetupSection() => new OsuSetupSection();
|
||||||
|
|
||||||
public override ILegacyScoreProcessor CreateLegacyScoreProcessor() => new OsuScoreV1Processor();
|
public override ILegacyScoreProcessor CreateLegacyScoreProcessor() => new OsuLegacyScoreProcessor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
|
|
||||||
if (ComputeLegacyScoringValues)
|
if (ComputeLegacyScoringValues)
|
||||||
{
|
{
|
||||||
TaikoScoreV1Processor sv1Processor = new TaikoScoreV1Processor();
|
TaikoLegacyScoreProcessor sv1Processor = new TaikoLegacyScoreProcessor();
|
||||||
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
sv1Processor.Simulate(workingBeatmap, beatmap, mods);
|
||||||
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
attributes.LegacyAccuracyScore = sv1Processor.AccuracyScore;
|
||||||
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
attributes.LegacyComboScore = sv1Processor.ComboScore;
|
||||||
|
@ -14,22 +14,12 @@ using osu.Game.Rulesets.Taiko.Objects;
|
|||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Difficulty
|
namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||||
{
|
{
|
||||||
internal class TaikoScoreV1Processor : ILegacyScoreProcessor
|
internal class TaikoLegacyScoreProcessor : ILegacyScoreProcessor
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The accuracy portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
public int AccuracyScore { get; private set; }
|
public int AccuracyScore { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The combo-multiplied portion of the legacy (ScoreV1) total score.
|
|
||||||
/// </summary>
|
|
||||||
public int ComboScore { get; private set; }
|
public int ComboScore { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A ratio of <c>new_bonus_score / old_bonus_score</c> for converting the bonus score of legacy scores to the new scoring.
|
|
||||||
/// This is made up of all judgements that would be <see cref="HitResult.SmallBonus"/> or <see cref="HitResult.LargeBonus"/>.
|
|
||||||
/// </summary>
|
|
||||||
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
public double BonusScoreRatio => legacyBonusScore == 0 ? 0 : (double)modernBonusScore / legacyBonusScore;
|
||||||
|
|
||||||
private int legacyBonusScore;
|
private int legacyBonusScore;
|
@ -18,6 +18,7 @@ using osu.Game.Overlays;
|
|||||||
using osu.Game.Overlays.Notifications;
|
using osu.Game.Overlays.Notifications;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Scoring.Legacy;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
namespace osu.Game
|
namespace osu.Game
|
||||||
@ -27,6 +28,9 @@ namespace osu.Game
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private RulesetStore rulesetStore { get; set; } = null!;
|
private RulesetStore rulesetStore { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private BeatmapManager beatmapManager { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private ScoreManager scoreManager { get; set; } = null!;
|
private ScoreManager scoreManager { get; set; } = null!;
|
||||||
|
|
||||||
@ -241,7 +245,7 @@ namespace osu.Game
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var score = scoreManager.Query(s => s.ID == id);
|
var score = scoreManager.Query(s => s.ID == id);
|
||||||
long newTotalScore = scoreManager.ConvertFromLegacyTotalScore(score);
|
long newTotalScore = StandardisedScoreMigrationTools.ConvertFromLegacyTotalScore(score, beatmapManager);
|
||||||
|
|
||||||
// Can't use async overload because we're not on the update thread.
|
// Can't use async overload because we're not on the update thread.
|
||||||
// ReSharper disable once MethodHasAsyncOverload
|
// ReSharper disable once MethodHasAsyncOverload
|
||||||
@ -249,7 +253,7 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
ScoreInfo s = r.Find<ScoreInfo>(id);
|
ScoreInfo s = r.Find<ScoreInfo>(id);
|
||||||
s.TotalScore = newTotalScore;
|
s.TotalScore = newTotalScore;
|
||||||
s.Version = 30000003;
|
s.Version = LegacyScoreEncoder.LATEST_VERSION;
|
||||||
});
|
});
|
||||||
|
|
||||||
Logger.Log($"Converted total score for score {id}");
|
Logger.Log($"Converted total score for score {id}");
|
||||||
|
@ -78,7 +78,7 @@ namespace osu.Game.Database
|
|||||||
/// 28 2023-06-08 Added IsLegacyScore to ScoreInfo, parsed from replay files.
|
/// 28 2023-06-08 Added IsLegacyScore to ScoreInfo, parsed from replay files.
|
||||||
/// 29 2023-06-12 Run migration of old lazer scores to be best-effort in the new scoring number space. No actual realm changes.
|
/// 29 2023-06-12 Run migration of old lazer scores to be best-effort in the new scoring number space. No actual realm changes.
|
||||||
/// 30 2023-06-16 Run migration of old lazer scores again. This time with more correct rounding considerations.
|
/// 30 2023-06-16 Run migration of old lazer scores again. This time with more correct rounding considerations.
|
||||||
/// 31 2023-06-26 Add Version and LegacyTotalScore to ScoreInfo, set Version to 30000002 and move TotalScore into LegacyTotalScore for legacy scores.
|
/// 31 2023-06-26 Add Version and LegacyTotalScore to ScoreInfo, set Version to 30000002 and copy TotalScore into LegacyTotalScore for legacy scores.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const int schema_version = 31;
|
private const int schema_version = 31;
|
||||||
|
|
||||||
@ -974,8 +974,15 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
foreach (var score in scores)
|
foreach (var score in scores)
|
||||||
{
|
{
|
||||||
score.LegacyTotalScore = score.TotalScore;
|
if (score.IsLegacyScore)
|
||||||
score.Version = 30000002; // Last version before legacy total score conversion.
|
{
|
||||||
|
score.LegacyTotalScore = score.TotalScore;
|
||||||
|
|
||||||
|
// Scores with this version will trigger the update process in BackgroundBeatmapProcessor.
|
||||||
|
score.Version = 30000002;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
score.Version = LegacyScoreEncoder.LATEST_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Difficulty;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -185,6 +186,92 @@ namespace osu.Game.Database
|
|||||||
return (long)Math.Round((1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore) * modMultiplier);
|
return (long)Math.Round((1000000 * (accuracyPortion * accuracyScore + (1 - accuracyPortion) * comboScore) + bonusScore) * modMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from <see cref="ScoreInfo.LegacyTotalScore"/> to the new standardised scoring of <see cref="ScoreProcessor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="score">The score to convert the total score of.</param>
|
||||||
|
/// <param name="beatmaps">A <see cref="BeatmapManager"/> used for <see cref="WorkingBeatmap"/> lookups.</param>
|
||||||
|
/// <returns>The standardised total score.</returns>
|
||||||
|
public static long ConvertFromLegacyTotalScore(ScoreInfo score, BeatmapManager beatmaps)
|
||||||
|
{
|
||||||
|
if (!score.IsLegacyScore)
|
||||||
|
return score.TotalScore;
|
||||||
|
|
||||||
|
var beatmap = beatmaps.GetWorkingBeatmap(score.BeatmapInfo);
|
||||||
|
var ruleset = score.Ruleset.CreateInstance();
|
||||||
|
|
||||||
|
var sv1Processor = ruleset.CreateLegacyScoreProcessor();
|
||||||
|
if (sv1Processor == null)
|
||||||
|
return score.TotalScore;
|
||||||
|
|
||||||
|
sv1Processor.Simulate(beatmap, beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, score.Mods), score.Mods);
|
||||||
|
|
||||||
|
return ConvertFromLegacyTotalScore(score, new DifficultyAttributes
|
||||||
|
{
|
||||||
|
LegacyAccuracyScore = sv1Processor.AccuracyScore,
|
||||||
|
LegacyComboScore = sv1Processor.ComboScore,
|
||||||
|
LegacyBonusScoreRatio = sv1Processor.BonusScoreRatio
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from <see cref="ScoreInfo.LegacyTotalScore"/> to the new standardised scoring of <see cref="ScoreProcessor"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="score">The score to convert the total score of.</param>
|
||||||
|
/// <param name="attributes">Difficulty attributes providing the legacy scoring values
|
||||||
|
/// (<see cref="DifficultyAttributes.LegacyAccuracyScore"/>, <see cref="DifficultyAttributes.LegacyComboScore"/>, and <see cref="DifficultyAttributes.LegacyBonusScoreRatio"/>)
|
||||||
|
/// for the beatmap which the score was set on.</param>
|
||||||
|
/// <returns>The standardised total score.</returns>
|
||||||
|
public static long ConvertFromLegacyTotalScore(ScoreInfo score, DifficultyAttributes attributes)
|
||||||
|
{
|
||||||
|
if (!score.IsLegacyScore)
|
||||||
|
return score.TotalScore;
|
||||||
|
|
||||||
|
int maximumLegacyAccuracyScore = attributes.LegacyAccuracyScore;
|
||||||
|
int maximumLegacyComboScore = attributes.LegacyComboScore;
|
||||||
|
double maximumLegacyBonusRatio = attributes.LegacyBonusScoreRatio;
|
||||||
|
double modMultiplier = score.Mods.Select(m => m.ScoreMultiplier).Aggregate(1.0, (c, n) => c * n);
|
||||||
|
|
||||||
|
// The part of total score that doesn't include bonus.
|
||||||
|
int maximumLegacyBaseScore = maximumLegacyAccuracyScore + maximumLegacyComboScore;
|
||||||
|
|
||||||
|
// The combo proportion is calculated as a proportion of maximumLegacyBaseScore.
|
||||||
|
double comboProportion = Math.Min(1, (double)score.LegacyTotalScore / maximumLegacyBaseScore);
|
||||||
|
|
||||||
|
// The bonus proportion makes up the rest of the score that exceeds maximumLegacyBaseScore.
|
||||||
|
double bonusProportion = Math.Max(0, (score.LegacyTotalScore - maximumLegacyBaseScore) * maximumLegacyBonusRatio);
|
||||||
|
|
||||||
|
switch (score.Ruleset.OnlineID)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return (long)Math.Round((
|
||||||
|
700000 * comboProportion
|
||||||
|
+ 300000 * Math.Pow(score.Accuracy, 10)
|
||||||
|
+ bonusProportion) * modMultiplier);
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return (long)Math.Round((
|
||||||
|
250000 * comboProportion
|
||||||
|
+ 750000 * Math.Pow(score.Accuracy, 3.6)
|
||||||
|
+ bonusProportion) * modMultiplier);
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
return (long)Math.Round((
|
||||||
|
600000 * comboProportion
|
||||||
|
+ 400000 * score.Accuracy
|
||||||
|
+ bonusProportion) * modMultiplier);
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
return (long)Math.Round((
|
||||||
|
990000 * comboProportion
|
||||||
|
+ 10000 * Math.Pow(score.Accuracy, 2 + 2 * score.Accuracy)
|
||||||
|
+ bonusProportion) * modMultiplier);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return score.TotalScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class FakeHit : HitObject
|
private class FakeHit : HitObject
|
||||||
{
|
{
|
||||||
private readonly Judgement judgement;
|
private readonly Judgement judgement;
|
||||||
|
@ -99,7 +99,7 @@ namespace osu.Game
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const double global_track_volume_adjust = 0.8;
|
private const double global_track_volume_adjust = 0.8;
|
||||||
|
|
||||||
public virtual bool UseDevelopmentServer => DebugUtils.IsDebugBuild;
|
public virtual bool UseDevelopmentServer => false;
|
||||||
|
|
||||||
public virtual EndpointConfiguration CreateEndpoints() =>
|
public virtual EndpointConfiguration CreateEndpoints() =>
|
||||||
UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ExperimentalEndpointConfiguration();
|
UseDevelopmentServer ? new DevelopmentEndpointConfiguration() : new ExperimentalEndpointConfiguration();
|
||||||
|
@ -25,6 +25,13 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
double BonusScoreRatio { get; }
|
double BonusScoreRatio { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs the simulation, computing the maximum <see cref="AccuracyScore"/>, <see cref="ComboScore"/>,
|
||||||
|
/// and <see cref="BonusScoreRatio"/> achievable for the given beatmap.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workingBeatmap">The working beatmap.</param>
|
||||||
|
/// <param name="playableBeatmap">A playable version of the beatmap for the ruleset.</param>
|
||||||
|
/// <param name="mods">The applied mods.</param>
|
||||||
void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods);
|
void Simulate(IWorkingBeatmap workingBeatmap, IBeatmap playableBeatmap, IReadOnlyList<Mod> mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Scoring.Legacy
|
|||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item><description>30000001: Appends <see cref="LegacyReplaySoloScoreInfo"/> to the end of scores.</description></item>
|
/// <item><description>30000001: Appends <see cref="LegacyReplaySoloScoreInfo"/> to the end of scores.</description></item>
|
||||||
/// <item><description>30000002: Score stored to replay calculated using the Score V2 algorithm.</description></item>
|
/// <item><description>30000002: Score stored to replay calculated using the Score V2 algorithm.</description></item>
|
||||||
/// <item><description>30000003: First version after legacy total score migration.</description></item>
|
/// <item><description>30000003: First version after converting legacy total score to standardised.</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public const int LATEST_VERSION = 30000003;
|
public const int LATEST_VERSION = 30000003;
|
||||||
|
@ -89,7 +89,7 @@ namespace osu.Game.Scoring
|
|||||||
if (StandardisedScoreMigrationTools.ShouldMigrateToNewStandardised(model))
|
if (StandardisedScoreMigrationTools.ShouldMigrateToNewStandardised(model))
|
||||||
model.TotalScore = StandardisedScoreMigrationTools.GetNewStandardised(model);
|
model.TotalScore = StandardisedScoreMigrationTools.GetNewStandardised(model);
|
||||||
else if (model.IsLegacyScore)
|
else if (model.IsLegacyScore)
|
||||||
model.TotalScore = ConvertFromLegacyTotalScore(model);
|
model.TotalScore = StandardisedScoreMigrationTools.ConvertFromLegacyTotalScore(model, beatmaps());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -153,65 +153,6 @@ namespace osu.Game.Scoring
|
|||||||
#pragma warning restore CS0618
|
#pragma warning restore CS0618
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ConvertFromLegacyTotalScore(ScoreInfo score)
|
|
||||||
{
|
|
||||||
if (!score.IsLegacyScore)
|
|
||||||
return score.TotalScore;
|
|
||||||
|
|
||||||
var beatmap = beatmaps().GetWorkingBeatmap(score.BeatmapInfo);
|
|
||||||
var ruleset = score.Ruleset.CreateInstance();
|
|
||||||
|
|
||||||
var sv1Processor = ruleset.CreateLegacyScoreProcessor();
|
|
||||||
if (sv1Processor == null)
|
|
||||||
return score.TotalScore;
|
|
||||||
|
|
||||||
sv1Processor.Simulate(beatmap, beatmap.GetPlayableBeatmap(ruleset.RulesetInfo, score.Mods), score.Mods);
|
|
||||||
|
|
||||||
int maximumLegacyAccuracyScore = sv1Processor.AccuracyScore;
|
|
||||||
int maximumLegacyComboScore = sv1Processor.ComboScore;
|
|
||||||
double maximumLegacyBonusRatio = sv1Processor.BonusScoreRatio;
|
|
||||||
double modMultiplier = score.Mods.Select(m => m.ScoreMultiplier).Aggregate(1.0, (c, n) => c * n);
|
|
||||||
|
|
||||||
// The part of total score that doesn't include bonus.
|
|
||||||
int maximumLegacyBaseScore = maximumLegacyAccuracyScore + maximumLegacyComboScore;
|
|
||||||
|
|
||||||
// The combo proportion is calculated as a proportion of maximumLegacyBaseScore.
|
|
||||||
double comboProportion = Math.Min(1, (double)score.LegacyTotalScore / maximumLegacyBaseScore);
|
|
||||||
|
|
||||||
// The bonus proportion makes up the rest of the score that exceeds maximumLegacyBaseScore.
|
|
||||||
double bonusProportion = Math.Max(0, (score.LegacyTotalScore - maximumLegacyBaseScore) * maximumLegacyBonusRatio);
|
|
||||||
|
|
||||||
switch (ruleset.RulesetInfo.OnlineID)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return (long)Math.Round((
|
|
||||||
700000 * comboProportion
|
|
||||||
+ 300000 * Math.Pow(score.Accuracy, 10)
|
|
||||||
+ bonusProportion) * modMultiplier);
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
return (long)Math.Round((
|
|
||||||
250000 * comboProportion
|
|
||||||
+ 750000 * Math.Pow(score.Accuracy, 3.6)
|
|
||||||
+ bonusProportion) * modMultiplier);
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return (long)Math.Round((
|
|
||||||
600000 * comboProportion
|
|
||||||
+ 400000 * score.Accuracy
|
|
||||||
+ bonusProportion) * modMultiplier);
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
return (long)Math.Round((
|
|
||||||
990000 * comboProportion
|
|
||||||
+ 10000 * Math.Pow(score.Accuracy, 2 + 2 * score.Accuracy)
|
|
||||||
+ bonusProportion) * modMultiplier);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return score.TotalScore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Very naive local caching to improve performance of large score imports (where the username is usually the same for most or all scores).
|
// Very naive local caching to improve performance of large score imports (where the username is usually the same for most or all scores).
|
||||||
private readonly Dictionary<string, APIUser> usernameLookupCache = new Dictionary<string, APIUser>();
|
private readonly Dictionary<string, APIUser> usernameLookupCache = new Dictionary<string, APIUser>();
|
||||||
|
|
||||||
|
@ -57,6 +57,9 @@ namespace osu.Game.Scoring
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to preserve the total score for legacy scores.
|
/// Used to preserve the total score for legacy scores.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Not populated if <see cref="IsLegacyScore"/> is <c>false</c>.
|
||||||
|
/// </remarks>
|
||||||
public long LegacyTotalScore { get; set; }
|
public long LegacyTotalScore { get; set; }
|
||||||
|
|
||||||
public int MaxCombo { get; set; }
|
public int MaxCombo { get; set; }
|
||||||
@ -69,6 +72,14 @@ namespace osu.Game.Scoring
|
|||||||
|
|
||||||
public double? PP { get; set; }
|
public double? PP { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The version of this score as stored in the database.
|
||||||
|
/// If this does not match <see cref="LegacyScoreEncoder.LATEST_VERSION"/>,
|
||||||
|
/// then the score has not yet been updated to reflect the current scoring values.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This may not match the version stored in the replay files.
|
||||||
|
/// </remarks>
|
||||||
public int Version { get; set; } = LegacyScoreEncoder.LATEST_VERSION;
|
public int Version { get; set; } = LegacyScoreEncoder.LATEST_VERSION;
|
||||||
|
|
||||||
[Indexed]
|
[Indexed]
|
||||||
|
@ -169,8 +169,6 @@ namespace osu.Game.Scoring
|
|||||||
/// <param name="score">The score to populate the statistics of.</param>
|
/// <param name="score">The score to populate the statistics of.</param>
|
||||||
public void PopulateMaximumStatistics(ScoreInfo score) => scoreImporter.PopulateMaximumStatistics(score);
|
public void PopulateMaximumStatistics(ScoreInfo score) => scoreImporter.PopulateMaximumStatistics(score);
|
||||||
|
|
||||||
public long ConvertFromLegacyTotalScore(ScoreInfo score) => scoreImporter.ConvertFromLegacyTotalScore(score);
|
|
||||||
|
|
||||||
#region Implementation of IPresentImports<ScoreInfo>
|
#region Implementation of IPresentImports<ScoreInfo>
|
||||||
|
|
||||||
public Action<IEnumerable<Live<ScoreInfo>>> PresentImport
|
public Action<IEnumerable<Live<ScoreInfo>>> PresentImport
|
||||||
|
Loading…
Reference in New Issue
Block a user