1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-20 19:35:34 +08:00

Add LegacyScoreInfo for statistics preservation/conversion

This commit is contained in:
smoogipoo 2019-03-27 16:55:46 +09:00
parent 1a6c2022ea
commit 8fcb75809d
3 changed files with 154 additions and 59 deletions

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
using osuTK;
namespace osu.Game.Rulesets.Catch.Difficulty
@ -18,11 +19,12 @@ namespace osu.Game.Rulesets.Catch.Difficulty
protected new CatchDifficultyAttributes Attributes => (CatchDifficultyAttributes)base.Attributes;
private Mod[] mods;
private int countGreat;
private int countGood;
private int countKatu;
private int countMeh;
private int countMiss;
private int fruitsHit;
private int ticksHit;
private int tinyTicksHit;
private int tinyTicksMissed;
private int misses;
public CatchPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
: base(ruleset, beatmap, score)
@ -32,11 +34,14 @@ namespace osu.Game.Rulesets.Catch.Difficulty
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
{
mods = Score.Mods;
countGreat = Convert.ToInt32(Score.Statistics[HitResult.Great]);
countGood = Convert.ToInt32(Score.Statistics[HitResult.Good]);
countKatu = Convert.ToInt32(Score.Statistics[HitResult.Ok]);
countMeh = Convert.ToInt32(Score.Statistics[HitResult.Meh]);
countMiss = Convert.ToInt32(Score.Statistics[HitResult.Miss]);
var legacyScore = Score as LegacyScoreInfo;
fruitsHit = legacyScore?.Count300 ?? Score.Statistics[HitResult.Perfect];
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
if (mods.Any(m => !m.Ranked))
@ -57,7 +62,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
value *= lengthBonus;
// 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
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 int totalHits() => countMeh + countGood + countGreat + countMiss + countKatu;
private int totalSuccessfulHits() => countMeh + countGood + countGreat;
private int totalComboHits() => countMiss + countGood + countGreat;
private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed;
private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit;
private int totalComboHits() => misses + ticksHit + fruitsHit;
}
}

View 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;
}
}
}

View File

@ -34,7 +34,9 @@ namespace osu.Game.Scoring.Legacy
using (SerializationReader sr = new SerializationReader(stream))
{
currentRuleset = GetRuleset(sr.ReadByte());
score.ScoreInfo = new ScoreInfo { Ruleset = currentRuleset.RulesetInfo };
var scoreInfo = new LegacyScoreInfo { Ruleset = currentRuleset.RulesetInfo };
scoreInfo = scoreInfo;
var version = sr.ReadInt32();
@ -43,69 +45,39 @@ namespace osu.Game.Scoring.Legacy
throw new BeatmapNotFoundException();
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
sr.ReadString();
var count300 = (int)sr.ReadUInt16();
var count100 = (int)sr.ReadUInt16();
var count50 = (int)sr.ReadUInt16();
var countGeki = (int)sr.ReadUInt16();
var countKatu = (int)sr.ReadUInt16();
var countMiss = (int)sr.ReadUInt16();
scoreInfo.Count300 = sr.ReadUInt16();
scoreInfo.Count100 = sr.ReadUInt16();
scoreInfo.Count50 = sr.ReadUInt16();
scoreInfo.CountGeki = sr.ReadUInt16();
scoreInfo.CountKatu = sr.ReadUInt16();
scoreInfo.CountMiss = sr.ReadUInt16();
switch (currentRuleset.LegacyID)
{
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();
scoreInfo.TotalScore = sr.ReadInt32();
scoreInfo.MaxCombo = sr.ReadUInt16();
/* score.Perfect = */
sr.ReadBoolean();
score.ScoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray();
scoreInfo.Mods = currentRuleset.ConvertLegacyMods((LegacyMods)sr.ReadInt32()).ToArray();
/* score.HpGraphString = */
sr.ReadString();
score.ScoreInfo.Date = sr.ReadDateTime();
scoreInfo.Date = sr.ReadDateTime();
var compressedReplay = sr.ReadByteArray();
if (version >= 20140721)
score.ScoreInfo.OnlineScoreID = sr.ReadInt64();
scoreInfo.OnlineScoreID = sr.ReadInt64();
else if (version >= 20121008)
score.ScoreInfo.OnlineScoreID = sr.ReadInt32();
scoreInfo.OnlineScoreID = sr.ReadInt32();
if (compressedReplay?.Length > 0)
{