// Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; using System.Collections.Generic; using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Logging; using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns { /// /// Generator to create a pattern from a hit object. /// internal abstract class PatternGenerator { /// /// An arbitrary maximum amount of iterations to perform in . /// The specific value is not super important - enough such that no false-positives occur. /// /// /b/933228 requires at least 23 iterations. /// private const int max_rng_iterations = 30; /// /// The last pattern. /// protected readonly Pattern PreviousPattern; /// /// The hit object to create the pattern for. /// protected readonly HitObject HitObject; /// /// The beatmap which is a part of. /// protected readonly ManiaBeatmap Beatmap; protected readonly int TotalColumns; protected PatternGenerator(HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern) { if (hitObject == null) throw new ArgumentNullException(nameof(hitObject)); if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); HitObject = hitObject; Beatmap = beatmap; PreviousPattern = previousPattern; TotalColumns = Beatmap.TotalColumns; } protected void RunWhile([InstantHandle] Func condition, Action action) { int iterations = 0; while (condition()) { if (iterations++ >= max_rng_iterations) { // log an error but don't throw. we want to continue execution. Logger.Error(new ExceededAllowedIterationsException(new StackTrace(0)), "Conversion encountered errors. The beatmap may not be correctly converted."); return; } action(); } } /// /// Generates the patterns for , each filled with hit objects. /// /// The s containing the hit objects. public abstract IEnumerable Generate(); /// /// Denotes when a single conversion operation is in an infinitely looping state. /// public class ExceededAllowedIterationsException : Exception { private readonly string stackTrace; public ExceededAllowedIterationsException(StackTrace stackTrace) { this.stackTrace = stackTrace.ToString(); } public override string StackTrace => stackTrace; public override string ToString() => $"{GetType().Name}: {Message}\r\n{StackTrace}"; } } }