using System;
namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
{
///
/// Stores colour compression information for a .
///
public class TaikoDifficultyHitObjectColour
{
private const int max_repetition_interval = 16;
private TaikoDifficultyHitObjectColour previous;
///
/// True if the current colour is different from the previous colour.
///
public bool Delta { get; private set; }
///
/// How many notes are Delta repeated
///
public int DeltaRunLength { get; private set; }
///
/// How many notes between the current and previous identical .
/// Negative number means that there is no repetition in range.
/// If no repetition is found this will have a value of + 1.
///
public int RepetitionInterval { get; private set; }
///
/// Get the instance for the given hitObject. This is implemented
/// as a static function instead of constructor to allow for reusing existing instances.
/// TODO: findRepetitionInterval needs to be called a final time after all hitObjects have been processed.
///
public static TaikoDifficultyHitObjectColour GetInstanceFor(TaikoDifficultyHitObject hitObject)
{
TaikoDifficultyHitObject lastObject = hitObject.PreviousNote(0);
TaikoDifficultyHitObjectColour previous = lastObject?.Colour;
bool delta = lastObject == null || hitObject.HitType != lastObject.HitType;
if (previous != null && delta == previous.Delta)
{
previous.DeltaRunLength += 1;
return previous;
}
// Calculate RepetitionInterval for previous
previous?.FindRepetitionInterval();
return new TaikoDifficultyHitObjectColour()
{
Delta = delta,
DeltaRunLength = 1,
RepetitionInterval = max_repetition_interval + 1,
previous = previous
};
}
///
/// Finds the closest previous that has the identical delta value
/// and run length with the current instance, and returns the amount of notes between them.
///
public void FindRepetitionInterval()
{
if (previous?.previous == null)
{
RepetitionInterval = max_repetition_interval + 1;
return;
}
int interval = previous.DeltaRunLength;
TaikoDifficultyHitObjectColour other = previous.previous;
while (other != null && interval < max_repetition_interval)
{
interval += other.DeltaRunLength;
if (other.Delta == Delta && other.DeltaRunLength == DeltaRunLength)
{
RepetitionInterval = Math.Min(interval, max_repetition_interval);
return;
}
other = other.previous;
}
RepetitionInterval = max_repetition_interval + 1;
}
}
}