Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove combo scaling from Aim and Speed from osu! performance calculation #16280

Merged
merged 44 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
cff9dab
Remove combo scaling and change miss penalty
apollo-dw Dec 14, 2021
86ad42a
Nerf length bonus
apollo-dw Dec 14, 2021
489aa43
Make miss penalty harsher
apollo-dw Dec 14, 2021
bac4cfe
Use frost's miss count penalty
apollo-dw Dec 16, 2021
60e2a8e
Use MathNet for miss penalty calculation, and use old penalty formula…
apollo-dw Dec 21, 2021
5640918
New miss penalty formula, using relevant difficult notes in each skil…
apollo-dw Dec 26, 2021
e9589e5
Fix logical error
apollo-dw Dec 27, 2021
d514567
Merge master
apollo-dw Dec 29, 2021
8ce6e3c
Remove mathnet
apollo-dw Dec 29, 2021
4f257d6
Clean up unsuccessful merge
apollo-dw Dec 29, 2021
fd1028f
Use clockrate in the difficult strain count method
apollo-dw Dec 29, 2021
d2b815b
Add miss penalty comment
apollo-dw Jan 2, 2022
75be4e8
Remove abusable 0.66 threshold by averaging
Luminiscental Jan 3, 2022
1320790
Remove unnecessary truncation
Luminiscental Jan 4, 2022
391110c
Remove abusable 0.66 threshold by averaging
apollo-dw Jan 4, 2022
443640a
Revert "Remove abusable 0.66 threshold by averaging"
apollo-dw Jan 4, 2022
f07bfcd
Merge pull request #6 from apollo-dw/revert-5-no-combo-scaling
apollo-dw Jan 4, 2022
dcb9693
Weight difficult strain count against the top strain
apollo-dw Jan 4, 2022
b3e90c3
Merge
apollo-dw Jan 4, 2022
400abc1
Add attribute ids to mapping functions
smoogipoo Jan 6, 2022
5989467
Reword comment and rename argument
apollo-dw Jan 12, 2022
1ae8ff0
Merge branch 'master' into no-combo-scaling
apollo-dw Feb 10, 2022
da31ca1
Use note strains instead of sectional strains
apollo-dw Feb 14, 2022
94a46ab
Rescale miss penalty for note strains
apollo-dw Feb 14, 2022
c18df86
Remove clockrate factor
apollo-dw Feb 19, 2022
580e43b
Merge branch 'master' into no-combo-scaling
apollo-dw Mar 3, 2022
0d4fe96
Merge branch 'master' into no-combo-scaling
apollo-dw Mar 17, 2022
2f335a7
Switch to using osuAttributes
apollo-dw Mar 17, 2022
23d0c03
Merge branch 'master' into no-combo-scaling
apollo-dw Oct 24, 2022
7d34542
use difficulty instead of topstrain
TextAdventurer12 Feb 22, 2024
0db910d
cap each note at adding 1 difficult strain count
TextAdventurer12 Feb 22, 2024
9f5f6b5
stop capping difficult strains per note
TextAdventurer12 Apr 6, 2024
b32d73e
adjust weighting function
TextAdventurer12 Apr 12, 2024
e2a5d19
adjust count difficult strains formula
TextAdventurer12 Apr 16, 2024
1d19bd2
Merge pull request #7 from TextAdventurer12/no-combo-scaling
apollo-dw May 11, 2024
9b60abe
Merge branch 'ppy:master' into no-combo-scaling
apollo-dw May 11, 2024
c1efcc0
Change miss penalty (nerf longer maps)
TextAdventurer12 May 21, 2024
9ff277c
Merge pull request #9 from TextAdventurer12/no-combo-scaling
apollo-dw May 21, 2024
20c54ab
Apply code quality changes
apollo-dw May 23, 2024
61afda1
Fix NaN case when difficulty is 0
apollo-dw May 26, 2024
c25e1bd
Use correct operation for 0 difficulty case
apollo-dw May 26, 2024
a7e1d35
Update osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs
apollo-dw Sep 11, 2024
f54a5a5
Merge branch 'master' into no-combo-scaling
tsunyoku Oct 3, 2024
f30ac5d
Merge branch 'master' into no-combo-scaling
bdach Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public class OsuDifficultyAttributes : DifficultyAttributes
[JsonProperty("slider_factor")]
public double SliderFactor { get; set; }

[JsonProperty("aim_difficult_strain_count")]
public double AimDifficultStrainCount { get; set; }

[JsonProperty("speed_difficult_strain_count")]
public double SpeedDifficultStrainCount { get; set; }

[JsonProperty("approach_rate")]
public double ApproachRate { get; set; }

Expand Down Expand Up @@ -54,6 +60,8 @@ public class OsuDifficultyAttributes : DifficultyAttributes
yield return (ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty);

yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor);
yield return (ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT, AimDifficultStrainCount);
yield return (ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT, SpeedDifficultStrainCount);
}

public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values)
Expand All @@ -68,6 +76,8 @@ public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> val
StarRating = values[ATTRIB_ID_DIFFICULTY];
FlashlightDifficulty = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT);
SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR];
AimDifficultStrainCount = values[ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT];
SpeedDifficultStrainCount = values[ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT];
}

#region Newtonsoft.Json implicit ShouldSerialize() methods
Expand Down
5 changes: 5 additions & 0 deletions osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat

double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;

double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);

if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;

Expand Down Expand Up @@ -78,6 +81,8 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
SpeedDifficulty = speedRating,
FlashlightDifficulty = flashlightRating,
SliderFactor = sliderFactor,
AimDifficultStrainCount = aimDifficultyStrainCount,
SpeedDifficultStrainCount = speedDifficultyStrainCount,
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
OverallDifficulty = (80 - hitWindowGreat) / 6,
DrainRate = drainRate,
Expand Down
14 changes: 6 additions & 8 deletions osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,8 @@ private double computeAimValue()
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
aimValue *= lengthBonus;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);

aimValue *= getComboScalingFactor();
aimValue *= calculateMissPenalty(effectiveMissCount, Attributes.AimDifficultStrainCount);
Copy link

@SensouShin SensouShin Dec 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should calculate miss penalty only once and save it into a variable in my opinion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the penalties for aim and speed are different because AimDifficultStrainCount and SpeedDifficultStrainCount are different, so there is no repetition...


double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
Expand Down Expand Up @@ -142,11 +139,8 @@ private double computeSpeedValue()
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
speedValue *= lengthBonus;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));

speedValue *= getComboScalingFactor();
speedValue *= calculateMissPenalty(effectiveMissCount, Attributes.SpeedDifficultStrainCount);

double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
Expand Down Expand Up @@ -262,6 +256,10 @@ private int calculateEffectiveMissCount()
return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
}

// Miss penalty assumes that a player will miss on the hardest parts of a map,
// so we use the amount of relatively difficult sections to adjust miss penalty
// to make it more punishing on maps with lower amount of hard sections.
private double calculateMissPenalty(double missCount, double difficultStrainCount) => 0.95 / ((missCount / (3 * Math.Sqrt(difficultStrainCount))) + 1);
private double getComboScalingFactor() => Attributes.MaxCombo <= 0 ? 1.0 : Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
Expand Down
13 changes: 13 additions & 0 deletions osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,18 @@ public override double DifficultyValue()

return difficulty * DifficultyMultiplier;
}

/// <summary>
/// Returns the number of strains weighted against the top strain.
/// The result is scaled by clock rate as it affects the total number of strains.
/// </summary>
public double CountDifficultStrains(double clockRate)
{
List<double> strains = GetCurrentStrainPeaks().ToList();
double topStrain = strains.Max();

double realtimeCount = strains.Sum(s => Math.Pow(s / topStrain, 4));
return clockRate * realtimeCount;
}
}
}
2 changes: 2 additions & 0 deletions osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class DifficultyAttributes
protected const int ATTRIB_ID_SCORE_MULTIPLIER = 15;
protected const int ATTRIB_ID_FLASHLIGHT = 17;
protected const int ATTRIB_ID_SLIDER_FACTOR = 19;
protected const int ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT = 21;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this really intended to be duplicate of ATTRIB_ID_SPEED_NOTE_COUNT ?

Copy link
Collaborator

@bdach bdach Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good (and very scary) catch. I can see how this could have happened, the speed note count thing was added in #15035 which precedes the open date of this PR.

That said I'm not sure I would trust any sheet results at this point given this revelation because I'm not sure what this means for correct calculation. Probably needs a full diffcalc re-run and re-verification of results after fixing.

Copy link
Member

@tsunyoku tsunyoku Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh dear.. luckily no sheets were generated for the latest changes. osu-tools isn't using these attribute IDs and the huismetbenen website that is used by users also doesn't use these so I'm not concerned about the values - but obviously, this needs to be fixed before anything which does use these can be relied upon.

protected const int ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT = 23;

/// <summary>
/// The mods which were applied to the beatmap.
Expand Down