diff --git a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs index 5eea346836df..1fe38ca04add 100644 --- a/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Mania/ManiaDifficultyCalculator.cs @@ -6,6 +6,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mods; using System; +using System.Linq; using System.Collections.Generic; namespace osu.Game.Rulesets.Mania @@ -31,6 +32,51 @@ internal class ManiaDifficultyCalculator : DifficultyCalculator /// private readonly List difficultyHitObjects = new List(); + /// + /// Number of sections to keep in memory for calculating average strain. 1 = 400ms + /// 150 = 60 seconds + /// + private const int memory = 150; + + /// + /// Strain over AverageStrain factor threshold for applying a stability penalty + /// Increasing this value will add more leniency towards harder than normal patterns + /// + private const double overweight_factor = 1.4; + + /// + /// Strain over AverageStrain factor minimum for not applying a stability penalty + /// Increasing this value will give more penalty for easier than normal patterns + /// + private const double underweight_factor = 0.7; + + + /// + /// The highest stability strain factor that can be applied + /// Increasing this value will encourage stable parts of the map + /// + private const double max_stability = 1.12; + + /// + /// The lowest stability strain factor that can be applied + /// Increasing this value will encourage difficulty variation + /// + private const double min_stability = 0.9; + + /// + /// The pace at which stability will decrease when on an over/underweighted part of the map + /// Increasing this value will result in quicker reaction to stability drop + /// The step is applied after each 400ms section + /// + private const double stability_step_decrease = 0.04; + + /// + /// The pace at which stability will increase when on an normally weighted part of the map + /// Increasing this value will result in quicker reaction to stability recovery + /// The step is applied after each 400ms section + /// + private const double stability_step_increase = 0.01; + public ManiaDifficultyCalculator(Beatmap beatmap) : base(beatmap) { @@ -130,14 +176,71 @@ private double calculateDifficulty() // Build the weighted sum over the highest strains for each interval double difficulty = 0; double weight = 1; + + // Averages the map strain, can be used instead of the moving average but needs commenting some code + //double averageStrain = highestStrains.Average(strain => strain); + + Queue currentStrains = new Queue(); + + List factors = new List(); + + double stability = 1; // Stability base + // Weight strains according to the stability to avoid burst overrating + foreach (double strain in highestStrains) + { + // Use a queue tu keep "memory" seconds of strain + currentStrains.Enqueue(strain); + if (currentStrains.Count > memory) + { + currentStrains.Dequeue(); + } + // Average those + double averageStrain = currentStrains.Average(); + + double factor = strain / averageStrain; + + // Move the stability according to our constants + if (factor > overweight_factor) + { + stability -= stability_step_decrease; + } + else + if (factor < underweight_factor) + { + stability -= stability_step_decrease; + } + else + { + stability += stability_step_increase; + } + + // The stability is capped + if (stability > max_stability) { stability = max_stability; } + if (stability < min_stability) { stability = min_stability; } + + // Add difficulty according to strain and stability + factors.Add(stability); + } + + // Apply stability to each strains - CAN be improved I'm sure + // The best would be applying it while going though the previous block + int index = 0; + foreach (double stabilityFactor in factors) + { + highestStrains[index] *= stabilityFactor; + index++; + } + highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain. + // Weighted sum foreach (double strain in highestStrains) { difficulty += weight * strain; weight *= decay_weight; } + return difficulty; } diff --git a/osu.Game/osu.nuspec b/osu.Game/osu.nuspec index bb7d382cee4d..c25ed79c6ec8 100644 --- a/osu.Game/osu.nuspec +++ b/osu.Game/osu.nuspec @@ -1,26 +1,26 @@ - - - - osulazer - 0.0.0 - osulazer - ppy Pty Ltd - Dean Herbert - https://osu.ppy.sh/ - https://puu.sh/tYyXZ/9a01a5d1b0.ico - false - click the circles. to the beat. - click the circles. - testing - Copyright ppy Pty Ltd 2007-2018 - en-AU - - - - - - - - - - + + + + osulazer + 0.0.0 + osulazer + ppy Pty Ltd + Dean Herbert + https://osu.ppy.sh/ + https://puu.sh/tYyXZ/9a01a5d1b0.ico + false + click the circles. to the beat. + click the circles. + testing + Copyright ppy Pty Ltd 2007-2018 + en-AU + + + + + + + + + + diff --git a/osu.licenseheader b/osu.licenseheader index 798b25e55014..4f22d07b24f8 100644 --- a/osu.licenseheader +++ b/osu.licenseheader @@ -1,9 +1,9 @@ -extensions: .cs -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -extensions: .xml .config .xsd - \ No newline at end of file