private void calculateSpecificStrain(OsuHitObjectDifficulty previousHitObject, OsuDifficultyCalculator.DifficultyType type, double timeRate) { double addition = 0; double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate; double decay = Math.Pow(DECAY_BASE[(int)type], timeElapsed / 1000); if (BaseHitObject is Spinner) { // Do nothing for spinners } else if (BaseHitObject is Slider) { switch (type) { case OsuDifficultyCalculator.DifficultyType.Speed: // For speed strain we treat the whole slider as a single spacing entity, since "Speed" is about how hard it is to click buttons fast. // The spacing weight exists to differentiate between being able to easily alternate or having to single. addition = spacingWeight(previousHitObject.lazySliderLength + DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type]; break; case OsuDifficultyCalculator.DifficultyType.Aim: // For Aim strain we treat each slider segment and the jump after the end of the slider as separate jumps, since movement-wise there is no difference // to multiple jumps. addition = ( spacingWeight(previousHitObject.lazySliderLength, type) + spacingWeight(DistanceTo(previousHitObject), type) ) * spacing_weight_scaling[(int)type]; break; } } else if (BaseHitObject is HitCircle) { addition = spacingWeight(DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type]; } // Scale addition by the time, that elapsed. Filter out HitObjects that are too close to be played anyway to avoid crazy values by division through close to zero. // You will never find maps that require this amongst ranked maps. addition /= Math.Max(timeElapsed, 50); Strains[(int)type] = previousHitObject.Strains[(int)type] * decay + addition; }
internal double DistanceTo(OsuHitObjectDifficulty other) { // Scale the distance by circle size. return((startPosition - other.endPosition).Length * scalingFactor); }
internal void CalculateStrains(OsuHitObjectDifficulty previousHitObject, double timeRate) { calculateSpecificStrain(previousHitObject, OsuDifficultyCalculator.DifficultyType.Speed, timeRate); calculateSpecificStrain(previousHitObject, OsuDifficultyCalculator.DifficultyType.Aim, timeRate); }