private double CalculateDifficulty(DifficultyType Type)
{
// Find the highest strain value within each strain step
List<double> HighestStrains = new List<double>();
double IntervalEndTime = STRAIN_STEP;
double MaximumStrain = 0; // We need to keep track of the maximum strain in the current interval
tpHitObject PreviousHitObject = null;
foreach (tpHitObject hitObject in tpHitObjects)
{
// While we are beyond the current interval push the currently available maximum to our strain list
while(hitObject.BaseHitObject.StartTime > IntervalEndTime)
{
HighestStrains.Add(MaximumStrain);
// The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay
// until the beginning of the next interval.
if(PreviousHitObject == null)
{
MaximumStrain = 0;
}
else
{
double Decay = Math.Pow(tpHitObject.DECAY_BASE[(int)Type], (double)(IntervalEndTime - PreviousHitObject.BaseHitObject.StartTime) / 1000);
MaximumStrain = PreviousHitObject.Strains[(int)Type] * Decay;
}
// Go to the next time interval
IntervalEndTime += STRAIN_STEP;
}
// Obtain maximum strain
if (hitObject.Strains[(int)Type] > MaximumStrain)
{
MaximumStrain = hitObject.Strains[(int)Type];
}
PreviousHitObject = hitObject;
}
// Build the weighted sum over the highest strains for each interval
double Difficulty = 0;
double Weight = 1;
HighestStrains.Sort((a,b) => b.CompareTo(a)); // Sort from highest to lowest strain.
foreach(double Strain in HighestStrains)
{
Difficulty += Weight * Strain;
Weight *= DECAY_WEIGHT;
}
return Difficulty;
}