diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs index 46b8b154bf..281918fd37 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs @@ -51,8 +51,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountTopWeightedStrains(); double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountTopWeightedStrains(); - double aimTopWeightedSliderFactor = ((OsuStrainSkill)skills[0]).CalculateTopWeightedSliderFactor(); - double speedTopWeightedSliderFactor = ((OsuStrainSkill)skills[2]).CalculateTopWeightedSliderFactor(); + double aimTopWeightedSliderCount = ((OsuStrainSkill)skills[0]).CountTopWeightedSliders(); + // We know that slider count + circle count = total count, so circle count = total count - slider count. + // This means we only need to calculate on sliders, and then work from the total count + double aimTopWeightedSliderFactor = aimTopWeightedSliderCount / (aimDifficultyStrainCount - aimTopWeightedSliderCount); + double speedTopWeightedSliderCount = ((OsuStrainSkill)skills[2]).CountTopWeightedSliders(); + double speedTopWeightedSliderFactor = speedTopWeightedSliderCount / (speedDifficultyStrainCount - speedTopWeightedSliderCount); if (mods.Any(m => m is OsuModTouchDevice)) { diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs index 773c76043d..bbd13b68f7 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs @@ -38,15 +38,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills currentStrain *= strainDecay(current.DeltaTime); currentStrain += AimEvaluator.EvaluateDifficultyOf(current, withSliders) * skillMultiplier; - TypedObjectStrains.Add((currentStrain, current.BaseObject is Slider)); + if (current.BaseObject is Slider) + sliderStrains.Add(currentStrain); return currentStrain; } public double GetDifficultSliders() { - IEnumerable sliderStrains = TypedObjectStrains.Where(typedObjectStrain => typedObjectStrain.isSlider).Select(typedObjectStrain => typedObjectStrain.difficulty); - if (!sliderStrains.Any()) + if (sliderStrains.Count == 0) return 0; double[] sortedStrains = sliderStrains.OrderDescending().ToArray(); diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs index 857144245b..e12d0a45b0 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills /// protected virtual double ReducedStrainBaseline => 0.75; - protected List<(double difficulty, bool isSlider)> TypedObjectStrains = new List<(double, bool)>(); + protected readonly List sliderStrains = new List(); protected OsuStrainSkill(Mod[] mods) : base(mods) @@ -59,22 +59,18 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills return difficulty; } - public double CalculateTopWeightedSliderFactor() + public double CountTopWeightedSliders() { - if (TypedObjectStrains.Count == 0) + if (sliderStrains.Count == 0) return 0; double consistentTopStrain = DifficultyValue() / 10; // What would the top strain be if all strain values were identical - List sliderStrains = TypedObjectStrains.Where(typedObjectStrain => typedObjectStrain.isSlider).Select(typedObjectStrain => typedObjectStrain.difficulty).ToList(); - List circleStrains = TypedObjectStrains.Where(typedObjectStrain => !typedObjectStrain.isSlider).Select(typedObjectStrain => typedObjectStrain.difficulty).ToList(); if (consistentTopStrain == 0) - return (double)sliderStrains.Count / circleStrains.Count; + return 0; // Use a weighted sum of all strains. Constants are arbitrary and give nice values - double sliderObjects = sliderStrains.Sum(s => 1.1 / (1 + Math.Exp(-10 * (s / consistentTopStrain - 0.88)))); - double circleObjects = circleStrains.Sum(s => 1.1 / (1 + Math.Exp(-10 * (s / consistentTopStrain - 0.88)))); - return sliderObjects / circleObjects; + return sliderStrains.Sum(s => 1.1 / (1 + Math.Exp(-10 * (s / consistentTopStrain - 0.88)))); } public static double DifficultyToPerformance(double difficulty) => Math.Pow(5.0 * Math.Max(1.0, difficulty / 0.0675) - 4.0, 3.0) / 100000.0; diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs index 76d113fa49..c79de5db3b 100644 --- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs +++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs @@ -41,7 +41,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current); double totalStrain = currentStrain * currentRhythm; - TypedObjectStrains.Add((totalStrain, current.BaseObject is Slider)); + if (current.BaseObject is Slider) + sliderStrains.Add(totalStrain); return totalStrain; }