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

Change strains list to be SortedList in StrainSkill #30241

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 14 additions & 9 deletions osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Linq;
using System.Collections.Generic;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
using System.Linq;
using osu.Framework.Utils;
using osu.Framework.Lists;

namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
Expand Down Expand Up @@ -36,22 +37,26 @@ public override double DifficultyValue()
Difficulty = 0;
double weight = 1;

// Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
// These sections will not contribute to the difficulty.
var peaks = GetCurrentStrainPeaks().Where(p => p > 0);
SortedList<double> strains = GetCurrentStrainsSorted();

List<double> strains = peaks.OrderDescending().ToList();
int reducedSectionCount = Math.Min(strains.Count, ReducedSectionCount);
double[] reducedStrains = new double[reducedSectionCount];

// We are reducing the highest strains first to account for extreme difficulty spikes
for (int i = 0; i < Math.Min(strains.Count, ReducedSectionCount); i++)
for (int i = 0; i < reducedSectionCount; i++)
{
double scale = Math.Log10(Interpolation.Lerp(1, 10, Math.Clamp((float)i / ReducedSectionCount, 0, 1)));
strains[i] *= Interpolation.Lerp(ReducedStrainBaseline, 1.0, scale);
reducedStrains[i] = strains[i] * Interpolation.Lerp(ReducedStrainBaseline, 1.0, scale);
}

// Remove reduced strains as they are no longer sorted
strains.RemoveRange(0, reducedSectionCount);

// Insert them back
strains.AddRange(reducedStrains);

// Difficulty is the weighted sum of the highest strains from every section.
// We're sorting from highest to lowest strain.
foreach (double strain in strains.OrderDescending())
foreach (double strain in strains)
{
Difficulty += strain * weight;
weight *= DecayWeight;
Expand Down
39 changes: 34 additions & 5 deletions osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Lists;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;

Expand Down Expand Up @@ -102,19 +103,47 @@ public override double DifficultyValue()
double difficulty = 0;
double weight = 1;

// Sections with 0 strain are excluded to avoid worst-case time complexity of the following sort (e.g. /b/2351871).
// These sections will not contribute to the difficulty.
var peaks = GetCurrentStrainPeaks().Where(p => p > 0);

// Difficulty is the weighted sum of the highest strains from every section.
// We're sorting from highest to lowest strain.
foreach (double strain in peaks.OrderDescending())
foreach (double strain in GetCurrentStrainsSorted())
{
difficulty += strain * weight;
weight *= DecayWeight;
}

return difficulty;
}

/// <summary>
/// Amount of strains that will be saved in the sorted strains list.
/// Use value = 0 in case you want all strains to be saved.
/// </summary>
protected virtual int MaxStrainCount => 200;

protected SortedList<double> GetCurrentStrainsSorted()
{
int newStrainsToAdd = strainPeaks.Count - amountOfStrainsAddedSinceSave;

var peaks = strainPeaks.TakeLast(newStrainsToAdd).Where(s => s > 0);
savedSortedStrains.AddRange(peaks);
amountOfStrainsAddedSinceSave = strainPeaks.Count;

// We're saving only the largest 200 strains
int excessStrainsCount = savedSortedStrains.Count - MaxStrainCount;

if (MaxStrainCount > 0 && excessStrainsCount > 0)
{
savedSortedStrains.RemoveRange(savedSortedStrains.Count - excessStrainsCount, excessStrainsCount);
}

var strainsWithCurrent = new SortedList<double>((a, b) => a < b ? 1 : (a > b ? -1 : 0));
strainsWithCurrent.AddRange(savedSortedStrains);
strainsWithCurrent.Add(currentSectionPeak);

return strainsWithCurrent;
}

private readonly SortedList<double> savedSortedStrains = new SortedList<double>((a, b) => a < b ? 1 : (a > b ? -1 : 0));
private int amountOfStrainsAddedSinceSave;
}
}
Loading