// 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; using System.Linq; namespace osu.Game.Utils { /// /// Represents a tracking component used for whether a specific time instant falls into any of the provided periods. /// public class PeriodTracker { private readonly List periods; private int nearestIndex; public PeriodTracker(IEnumerable periods) { this.periods = periods.OrderBy(period => period.Start).ToList(); } /// /// Whether the provided time is in any of the added periods. /// /// The time value to check. public bool IsInAny(double time) { if (periods.Count == 0) return false; if (time > periods[nearestIndex].End) { while (time > periods[nearestIndex].End && nearestIndex < periods.Count - 1) nearestIndex++; } else { while (time < periods[nearestIndex].Start && nearestIndex > 0) nearestIndex--; } var nearest = periods[nearestIndex]; return time >= nearest.Start && time <= nearest.End; } } public readonly struct Period { /// /// The start time of this period. /// public readonly double Start; /// /// The end time of this period. /// public readonly double End; public Period(double start, double end) { if (start >= end) throw new ArgumentException($"Invalid period provided, {nameof(start)} must be less than {nameof(end)}"); Start = start; End = end; } } }