// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing.Colour.Data { /// /// Encodes a list of s, grouped together by back and forth repetition of the same /// . Also stores the repetition interval between this and the previous . /// public class RepeatingHitPatterns { /// /// Maximum amount of s to look back to find a repetition. /// private const int max_repetition_interval = 16; /// /// The s that are grouped together within this . /// public readonly List AlternatingMonoPatterns = new List(); /// /// The first in this /// public TaikoDifficultyHitObject FirstHitObject => AlternatingMonoPatterns[0].FirstHitObject; /// /// The previous . This is used to determine the repetition interval. /// public readonly RepeatingHitPatterns? Previous; /// /// How many between the current and previous identical . /// If no repetition is found this will have a value of + 1. /// public int RepetitionInterval { get; private set; } = max_repetition_interval + 1; public RepeatingHitPatterns(RepeatingHitPatterns? previous) { Previous = previous; } /// /// Returns true if other is considered a repetition of this pattern. This is true if other's first two payloads /// have identical mono lengths. /// private bool isRepetitionOf(RepeatingHitPatterns other) { if (AlternatingMonoPatterns.Count != other.AlternatingMonoPatterns.Count) return false; for (int i = 0; i < Math.Min(AlternatingMonoPatterns.Count, 2); i++) { if (!AlternatingMonoPatterns[i].HasIdenticalMonoLength(other.AlternatingMonoPatterns[i])) return false; } return true; } /// /// Finds the closest previous that has the identical . /// Interval is defined as the amount of chunks between the current and repeated patterns. /// public void FindRepetitionInterval() { if (Previous == null) { RepetitionInterval = max_repetition_interval + 1; return; } RepeatingHitPatterns? other = Previous; int interval = 1; while (interval < max_repetition_interval) { if (isRepetitionOf(other)) { RepetitionInterval = Math.Min(interval, max_repetition_interval); return; } other = other.Previous; if (other == null) break; ++interval; } RepetitionInterval = max_repetition_interval + 1; } } }