mirror of
https://github.com/ppy/osu.git
synced 2025-02-21 23:23:52 +08:00
Add LegacyScoreInfo for statistics preservation/conversion
This commit is contained in:
parent
1a6c2022ea
commit
8fcb75809d
@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
using osu.Game.Scoring.Legacy;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Difficulty
|
namespace osu.Game.Rulesets.Catch.Difficulty
|
||||||
@ -18,11 +19,12 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
protected new CatchDifficultyAttributes Attributes => (CatchDifficultyAttributes)base.Attributes;
|
protected new CatchDifficultyAttributes Attributes => (CatchDifficultyAttributes)base.Attributes;
|
||||||
|
|
||||||
private Mod[] mods;
|
private Mod[] mods;
|
||||||
private int countGreat;
|
|
||||||
private int countGood;
|
private int fruitsHit;
|
||||||
private int countKatu;
|
private int ticksHit;
|
||||||
private int countMeh;
|
private int tinyTicksHit;
|
||||||
private int countMiss;
|
private int tinyTicksMissed;
|
||||||
|
private int misses;
|
||||||
|
|
||||||
public CatchPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
|
public CatchPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
|
||||||
: base(ruleset, beatmap, score)
|
: base(ruleset, beatmap, score)
|
||||||
@ -32,11 +34,14 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
|
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
|
||||||
{
|
{
|
||||||
mods = Score.Mods;
|
mods = Score.Mods;
|
||||||
countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]);
|
|
||||||
countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]);
|
var legacyScore = Score as LegacyScoreInfo;
|
||||||
countKatu = Convert.ToInt32(Score.Statistics[HitResult.Ok]);
|
|
||||||
countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]);
|
fruitsHit = legacyScore?.Count300 ?? Score.Statistics[HitResult.Perfect];
|
||||||
countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]);
|
ticksHit = legacyScore?.Count100 ?? 0;
|
||||||
|
tinyTicksHit = legacyScore?.Count50 ?? 0;
|
||||||
|
tinyTicksMissed = legacyScore?.CountKatu ?? 0;
|
||||||
|
misses = Score.Statistics[HitResult.Miss];
|
||||||
|
|
||||||
// Don't count scores made with supposedly unranked mods
|
// Don't count scores made with supposedly unranked mods
|
||||||
if (mods.Any(m => !m.Ranked))
|
if (mods.Any(m => !m.Ranked))
|
||||||
@ -57,7 +62,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
value *= lengthBonus;
|
value *= lengthBonus;
|
||||||
|
|
||||||
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available
|
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available
|
||||||
value *= Math.Pow(0.97f, countMiss);
|
value *= Math.Pow(0.97f, misses);
|
||||||
|
|
||||||
// Combo scaling
|
// Combo scaling
|
||||||
float beatmapMaxCombo = Attributes.MaxCombo;
|
float beatmapMaxCombo = Attributes.MaxCombo;
|
||||||
@ -92,8 +97,8 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
}
|
}
|
||||||
|
|
||||||
private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f);
|
private float accuracy() => totalHits() == 0 ? 0 : MathHelper.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f);
|
||||||
private int totalHits() => countMeh + countGood + countGreat + countMiss + countKatu;
|
private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed;
|
||||||
private int totalSuccessfulHits() => countMeh + countGood + countGreat;
|
private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit;
|
||||||
private int totalComboHits() => countMiss + countGood + countGreat;
|
private int totalComboHits() => misses + ticksHit + fruitsHit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
118
osu.Game/Scoring/Legacy/LegacyScoreInfo.cs
Normal file
118
osu.Game/Scoring/Legacy/LegacyScoreInfo.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
// 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.Game.Rulesets.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Scoring.Legacy
|
||||||
|
{
|
||||||
|
public class LegacyScoreInfo : ScoreInfo
|
||||||
|
{
|
||||||
|
private int countGeki;
|
||||||
|
|
||||||
|
public int CountGeki
|
||||||
|
{
|
||||||
|
get => countGeki;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
countGeki = value;
|
||||||
|
|
||||||
|
switch (Ruleset?.ID ?? RulesetID)
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
Statistics[HitResult.Perfect] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int count300;
|
||||||
|
|
||||||
|
public int Count300
|
||||||
|
{
|
||||||
|
get => count300;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
count300 = value;
|
||||||
|
|
||||||
|
switch (Ruleset?.ID ?? RulesetID)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 3:
|
||||||
|
Statistics[HitResult.Great] = value;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Statistics[HitResult.Perfect] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countKatu;
|
||||||
|
|
||||||
|
public int CountKatu
|
||||||
|
{
|
||||||
|
get => countKatu;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
countKatu = value;
|
||||||
|
|
||||||
|
switch (Ruleset?.ID ?? RulesetID)
|
||||||
|
{
|
||||||
|
case 3:
|
||||||
|
Statistics[HitResult.Good] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int count100;
|
||||||
|
|
||||||
|
public int Count100
|
||||||
|
{
|
||||||
|
get => count100;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
count100 = value;
|
||||||
|
|
||||||
|
switch (Ruleset?.ID ?? RulesetID)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
Statistics[HitResult.Good] = value;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Statistics[HitResult.Ok] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int count50;
|
||||||
|
|
||||||
|
public int Count50
|
||||||
|
{
|
||||||
|
get => count50;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
count50 = value;
|
||||||
|
|
||||||
|
switch (Ruleset?.ID ?? RulesetID)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
Statistics[HitResult.Meh] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CountMiss
|
||||||
|
{
|
||||||
|
get => Statistics[HitResult.Miss];
|
||||||
|
set => Statistics[HitResult.Miss] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,9 @@ namespace osu.Game.Scoring.Legacy
|
|||||||
using (SerializationReader sr = new SerializationReader(stream))
|
using (SerializationReader sr = new SerializationReader(stream))
|
||||||
{
|
{
|
||||||
currentRuleset = GetRuleset(sr.ReadByte());
|
currentRuleset = GetRuleset(sr.ReadByte());
|
||||||
score.ScoreInfo = new ScoreInfo { Ruleset = currentRuleset.RulesetInfo };
|
var scoreInfo = new LegacyScoreInfo { Ruleset = currentRuleset.RulesetInfo };
|
||||||
|
|
||||||
|
scoreInfo = scoreInfo;
|
||||||
|
|
||||||
var version = sr.ReadInt32();
|
var version = sr.ReadInt32();
|
||||||
|
|
||||||
@ -43,69 +45,39 @@ namespace osu.Game.Scoring.Legacy
|
|||||||
throw new BeatmapNotFoundException();
|
throw new BeatmapNotFoundException();
|
||||||
|
|
||||||
currentBeatmap = workingBeatmap.Beatmap;
|
currentBeatmap = workingBeatmap.Beatmap;
|
||||||
score.ScoreInfo.Beatmap = currentBeatmap.BeatmapInfo;
|
scoreInfo.Beatmap = currentBeatmap.BeatmapInfo;
|
||||||
|
|
||||||
score.ScoreInfo.User = new User { Username = sr.ReadString() };
|
scoreInfo.User = new User { Username = sr.ReadString() };
|
||||||
|
|
||||||
// MD5Hash
|
// MD5Hash
|
||||||
sr.ReadString();
|
sr.ReadString();
|
||||||
|
|
||||||
var count300 = (int)sr.ReadUInt16();
|
scoreInfo.Count300 = sr.ReadUInt16();
|
||||||
var count100 = (int)sr.ReadUInt16();
|
scoreInfo.Count100 = sr.ReadUInt16();
|
||||||
var count50 = (int)sr.ReadUInt16();
|
scoreInfo.Count50 = sr.ReadUInt16();
|
||||||
var countGeki = (int)sr.ReadUInt16();
|
scoreInfo.CountGeki = sr.ReadUInt16();
|
||||||
var countKatu = (int)sr.ReadUInt16();
|
scoreInfo.CountKatu = sr.ReadUInt16();
|
||||||
var countMiss = (int)sr.ReadUInt16();
|
scoreInfo.CountMiss = sr.ReadUInt16();
|
||||||
|
|
||||||
switch (currentRuleset.LegacyID)
|
scoreInfo.TotalScore = sr.ReadInt32();
|
||||||
{
|
scoreInfo.MaxCombo = sr.ReadUInt16();
|
||||||
case 0:
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Great] = count300;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Good] = count100;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Meh] = count50;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Great] = count300;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Good] = count100;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Great] = count300;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Good] = count100;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Ok] = countKatu;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Meh] = count50;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Perfect] = countGeki;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Great] = count300;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Good] = countKatu;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Ok] = count100;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Meh] = count50;
|
|
||||||
score.ScoreInfo.Statistics[HitResult.Miss] = countMiss;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
score.ScoreInfo.TotalScore = sr.ReadInt32();
|
|
||||||
score.ScoreInfo.MaxCombo = sr.ReadUInt16();
|
|
||||||
|
|
||||||
/* score.Perfect = */
|
/* score.Perfect = */
|
||||||
sr.ReadBoolean();
|
sr.ReadBoolean();
|
||||||
|
|
||||||
score.ScoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray();
|
scoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray();
|
||||||
|
|
||||||
/* score.HpGraphString = */
|
/* score.HpGraphString = */
|
||||||
sr.ReadString();
|
sr.ReadString();
|
||||||
|
|
||||||
score.ScoreInfo.Date = sr.ReadDateTime();
|
scoreInfo.Date = sr.ReadDateTime();
|
||||||
|
|
||||||
var compressedReplay = sr.ReadByteArray();
|
var compressedReplay = sr.ReadByteArray();
|
||||||
|
|
||||||
if (version >= 20140721)
|
if (version >= 20140721)
|
||||||
score.ScoreInfo.OnlineScoreID = sr.ReadInt64();
|
scoreInfo.OnlineScoreID = sr.ReadInt64();
|
||||||
else if (version >= 20121008)
|
else if (version >= 20121008)
|
||||||
score.ScoreInfo.OnlineScoreID = sr.ReadInt32();
|
scoreInfo.OnlineScoreID = sr.ReadInt32();
|
||||||
|
|
||||||
if (compressedReplay?.Length > 0)
|
if (compressedReplay?.Length > 0)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user