internal void CalcStrain(CatchDifficultyHitObject lastHitObject, double timeRate) { var time = (HitObject.Offset - lastHitObject.HitObject.Offset) / timeRate; var decay = Math.Pow(Constants.DecayBase, time / 1000d); Offset = MathUtlity.Clamp( lastHitObject.ScaledPosition + lastHitObject.Offset, ScaledPosition - (Constants.NormalizedHitobjectRadius - _errorMargin), ScaledPosition + (Constants.NormalizedHitobjectRadius - _errorMargin)) - ScaledPosition; LastMovement = Math.Abs(ScaledPosition - lastHitObject.ScaledPosition + Offset - lastHitObject.Offset); var addition = Math.Pow(LastMovement, 1.3) / 500; if (ScaledPosition < lastHitObject.ScaledPosition) { LastMovement *= -1; } var additionBonus = 0d; var sqrtTime = Math.Sqrt(Math.Max(time, 25)); if (Math.Abs(LastMovement) > 0.1) { if (Math.Abs(lastHitObject.LastMovement) > 0.1 && MathUtlity.Sign(LastMovement) != MathUtlity.Sign(lastHitObject.LastMovement)) { var bonus = Constants.DirectionChangeBonus / sqrtTime; var bonusFactor = Math.Min(_errorMargin, Math.Abs(LastMovement)) / _errorMargin; addition += bonus * bonusFactor; if (lastHitObject.HyperdashDistance <= 10) { additionBonus += 0.3 * bonusFactor; } } addition += 7.5 * Math.Min(Math.Abs(LastMovement), Constants.NormalizedHitobjectRadius * 2) / (Constants.NormalizedHitobjectRadius * 6) / sqrtTime; } if (lastHitObject.HyperdashDistance <= 10) { if (!lastHitObject.HyperDash) { additionBonus += 1; } else { Offset = 0; } addition *= 1 + additionBonus * ((10 - lastHitObject.HyperdashDistance) / 10); } addition *= 850.0 / Math.Max(time, 25); Strain = lastHitObject.Strain * decay + addition; }
double CalcDifficulty() { double strainStep = Constants.StrainStep * TimeRate; List <double> highestStrain = new List <double>(); double interval = strainStep; double maxStrain = 0; CatchDifficultyHitObject last = null; foreach (var difficultyHitObject in DifficultyHitObjects) { while (difficultyHitObject.HitObject.Offset > interval) { highestStrain.Add(maxStrain); if (last is null) { maxStrain = 0; } else { double decay = Math.Pow(Constants.DecayBase, (interval - last.HitObject.Offset) / 1000); maxStrain = last.Strain * decay; } interval += strainStep; } if (difficultyHitObject.Strain > maxStrain) { maxStrain = difficultyHitObject.Strain; } last = difficultyHitObject; } double difficulty = 0, weight = 1; var revserSortedList = from l in highestStrain orderby(int) l descending select l; foreach (var strain in revserSortedList) { difficulty += weight * strain; weight *= Constants.DecayWeight; } return(difficulty); }