internal void CalculateStrains(DifficultyHitObjectFruits PreviousHitObject, double TimeRate)
        {
            // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make.
            // See Taiko feedback thread.
            double TimeElapsed = (double)(BaseHitObject.StartTime - PreviousHitObject.BaseHitObject.StartTime) / TimeRate;
            double Decay       = Math.Pow(DECAY_BASE, TimeElapsed / 1000);

            // Update new position with lazy movement.
            PlayerPositionOffset =
                OsuMathHelper.Clamp(
                    PreviousHitObject.ActualNormalizedPosition,
                    NormalizedPosition - (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError),
                    NormalizedPosition + (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player.
                - NormalizedPosition;                                                            // Subtract HitObject position to obtain offset

            LastMovement = DistanceTo(PreviousHitObject);
            double Addition = SpacingWeight(LastMovement);

            if (NormalizedPosition < PreviousHitObject.NormalizedPosition)
            {
                LastMovement = -LastMovement;
            }

            HitCircleFruits previousHitCircle = PreviousHitObject.BaseHitObject as HitCircleFruits;

            double additionBonus = 0;
            double sqrtTime      = Math.Sqrt(Math.Max(TimeElapsed, 25));

            // Direction changes give an extra point!
            if (Math.Abs(LastMovement) > 0.1)
            {
                if (Math.Abs(PreviousHitObject.LastMovement) > 0.1 && Math.Sign(LastMovement) != Math.Sign(PreviousHitObject.LastMovement))
                {
                    double bonus = DIRECTION_CHANGE_BONUS / sqrtTime;

                    // Weight bonus by how
                    double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError;

                    // We want time to play a role twice here!
                    Addition += bonus * bonusFactor;

                    // Bonus for tougher direction switches and "almost" hyperdashes at this point
                    if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10)
                    {
                        additionBonus += 0.3 * bonusFactor;
                    }
                }

                // Base bonus for every movement, giving some weight to streams.
                Addition += 7.5 * Math.Min(Math.Abs(LastMovement), NORMALIZED_HITOBJECT_RADIUS * 2) / (NORMALIZED_HITOBJECT_RADIUS * 6) / sqrtTime;
            }

            // Bonus for "almost" hyperdashes at corner points
            if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10)
            {
                if (!previousHitCircle.HyperDash)
                {
                    additionBonus += 1.0;
                }
                else
                {
                    // After a hyperdash we ARE in the correct position. Always!
                    PlayerPositionOffset = 0;
                }

                Addition *= 1.0 + additionBonus * ((10 - previousHitCircle.DistanceToHyperDash) / 10);
            }

            Addition *= 850.0 / Math.Max(TimeElapsed, 25);

            Strain = PreviousHitObject.Strain * Decay + Addition;
        }
 internal float DistanceTo(DifficultyHitObjectFruits other)
 {
     return(Math.Abs(ActualNormalizedPosition - other.ActualNormalizedPosition));
 }