using Microsoft.VisualBasic.CompilerServices;
using Newtonsoft.Json.Linq;
using RhythmBase.Components;
using RhythmBase.Events;
using RhythmBase.Exceptions;
using RhythmBase.Utils;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.RegularExpressions;
namespace RhythmBase.Extensions
{
///
/// Extensions
///
[StandardModule]
public static partial class Extensions
{
private static (float start, float end) GetRange(OrderedEventCollection e, Index index)
{
(float, float) GetRange;
try
{
IBaseEvent firstEvent = e.First();
IBaseEvent lastEvent = e.Last();
GetRange = index.IsFromEnd
? (lastEvent.Beat._calculator!.BarBeatToBeatOnly((uint)(lastEvent.Beat.BarBeat.bar - index.Value), 1f),
lastEvent.Beat._calculator.BarBeatToBeatOnly((uint)(lastEvent.Beat.BarBeat.bar - index.Value + 1), 1f))
: (firstEvent.Beat._calculator!.BarBeatToBeatOnly((uint)index.Value, 1f),
firstEvent.Beat._calculator.BarBeatToBeatOnly((uint)(index.Value + 1), 1f));
}
catch
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return GetRange;
}
private static (float start, float end) GetRange(OrderedEventCollection e, Range range)
{
(float start, float end) GetRange;
try
{
IBaseEvent firstEvent = e.First();
IBaseEvent lastEvent = e.Last();
GetRange = ((range.Start.IsFromEnd
? lastEvent.Beat._calculator!.BarBeatToBeatOnly((uint)(((ulong)lastEvent.Beat.BarBeat.bar) - (ulong)((long)range.Start.Value)), 1f)
: firstEvent.Beat._calculator!.BarBeatToBeatOnly((uint)Math.Max(range.Start.Value, 1), 1f),
range.End.IsFromEnd
? lastEvent.Beat._calculator!.BarBeatToBeatOnly((uint)(((ulong)lastEvent.Beat.BarBeat.bar) - (ulong)((long)range.End.Value) + 1UL), 1f)
: firstEvent.Beat._calculator!.BarBeatToBeatOnly((uint)(range.End.Value + 1), 1f)));
}
catch
{
throw new ArgumentOutOfRangeException(nameof(range));
}
return GetRange;
}
///
/// Null or equal.
///
/// one item.
/// another item.
///
///
/// - When neither item is empty,
Returns true only if both are equal
/// - when one of the two is empty,
Returns true.
/// - when both are empty,
Returns false.
///
///
public static bool NullableEquals(this float? e, float? obj) => ((e != null && obj != null) && e.Value == obj.Value) || (e == null && obj == null);
///
///
///
///
public static bool IsNullOrEmpty([NotNullWhen(false)] this string? e) => e == null || e.Length == 0;
///
/// Make strings follow the Upper Camel Case.
///
/// The result.
public static string ToUpperCamelCase(this string e)
{
char[] S = [.. e];
S[0] = (S[0].ToString().ToUpper()[0]);
return string.Join("", [new string(S)]);
}
///
/// Make a specific key of a JObject follow the Upper Camel Case.
///
internal static void ToUpperCamelCase(this JObject e, string key)
{
JToken token = e[key] ?? throw new NullReferenceException();
e.Remove(key);
e[key.ToUpperCamelCase()] = token;
}
///
/// Make strings follow the Lower Camel Case.
///
/// The result.
public static string ToLowerCamelCase(this string e)
{
char[] S = [.. e];
S[0] = (S[0].ToString().ToLower()[0]);
return string.Join("", [new string(S)]);
}
///
/// Make a specific key of a JObject follow the Lower Camel Case.
///
internal static void ToLowerCamelCase(this JObject e, string key)
{
JToken token = e[key] ?? throw new NullReferenceException();
e.Remove(key);
e[key.ToLowerCamelCase()] = token;
}
///
/// Convert color format from RGBA to ARGB
///
public static int RgbaToArgb(this int Rgba) => (Rgba >> 8 & 16777215) | (Rgba << 24 & -16777216);
///
/// Convert color format from ARGB to RGBA
///
public static int ArgbToRgba(this int Argb) => (Argb >> 24 & 255) | (Argb << 8 & -256);
///
/// Calculate the fraction of equal to the nearest floating point number.
///
///
/// 2.236f.FixFraction(4) == 2.25f
/// float.Pi.FixFraction(5) == 3.2f
/// float.E.Fixfraction(2) == 2.5f
///
///
///
/// The float number.
/// Indicate what fraction this is.
///
public static float FixFraction(this float beat, uint splitBase) => (float)(Math.Round((double)(beat * splitBase)) / splitBase);
///
/// Calculate the fraction of equal to the nearest floating point number.
///
public static RDBeat FixFraction(this RDBeat beat, uint splitBase) => new(beat.BeatOnly.FixFraction(splitBase));
///
/// Converting enumeration constants to in-game colors。
///
/// Collection
/// The in-game color.
public static RDColor ToColor(this Bookmark.BookmarkColors e) => e switch
{
Bookmark.BookmarkColors.Blue => RDColor.FromRgba(11, 125, 206),
Bookmark.BookmarkColors.Red => RDColor.FromRgba(219, 41, 41),
Bookmark.BookmarkColors.Yellow => RDColor.FromRgba(212, 212, 51),
Bookmark.BookmarkColors.Green => RDColor.FromRgba(54, 215, 54),
_ => throw new NotSupportedException(),
};
///
/// Add a range of events.
///
/// Collection
///
public static void AddRange(this OrderedEventCollection e, IEnumerable items) where TEvent : IBaseEvent
{
foreach (TEvent item in items)
e.Add(item);
}
///
/// Filters a sequence of events based on a predicate.
///
/// Collection
/// A function to test each event for a condition.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent =>
((IEnumerable)e.eventsBeatOrder
.SelectMany(i => i.Value)).Where(predicate);
///
/// Filters a sequence of events located at a time.
///
/// Collection
/// Specified beat.
public static IEnumerable Where(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent
{
IEnumerable Where = [];
if (e.eventsBeatOrder.TryGetValue(beat, out TypedEventCollection? value))
Where = value.Cast().AsEnumerable();
return Where;
}
///
/// Filters a sequence of events located at a range of time.
///
/// Collection
/// Specified start beat.
/// Specified end beat.
public static IEnumerable Where(this OrderedEventCollection e, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent =>
e.eventsBeatOrder
.TakeWhile(i => i.Key < endBeat)
.SkipWhile(i => i.Key < startBeat)
.SelectMany(i => i.Value.OfType());
///
/// Filters a sequence of events located at a bar.
///
/// Collection
/// Specified bar.
public static IEnumerable Where(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent
{
var (start, end) = GetRange(e, bar);
return e.eventsBeatOrder
.TakeWhile(i => i.Key.BeatOnly < end)
.SkipWhile(i => i.Key.BeatOnly < start)
.SelectMany(i => i.Value.OfType());
}
///
/// Filters a sequence of events located at a range of beat.
///
/// Collection
/// Specified beat range.
///
public static IEnumerable Where(this OrderedEventCollection e, RDRange range) where TEvent : IBaseEvent =>
(IEnumerable)e.eventsBeatOrder
.TakeWhile(i => range.End == null || i.Key < range.End)
.SkipWhile(i => range.Start != null && i.Key < range.Start)
.SelectMany(i => i.Value);
///
/// Filters a sequence of events located at a range of bar.
///
/// Collection
/// Specified bar range.
public static IEnumerable Where(this OrderedEventCollection e, Range bars) where TEvent : IBaseEvent
{
var (start, end) = GetRange(e, bars);
return e.eventsBeatOrder
.TakeWhile(i => i.Key.BeatOnly < end)
.SkipWhile(i => i.Key.BeatOnly < start)
.SelectMany(i => i.Value.OfType());
}
///
/// Filters a sequence of events based on a predicate in specified beat.
///
/// Collection
/// A function to test each event for a condition.
/// Specified beat.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, RDBeat beat) where TEvent : IBaseEvent => e.Where(beat).Where(predicate);
///
/// Filters a sequence of events based on a predicate in specified range of beat.
///
/// Collection
/// A function to test each event for a condition.
/// Specified start beat.
/// Specified end beat.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.Where(startBeat, endBeat).Where(predicate);
///
/// Filters a sequence of events based on a predicate in specified range of beat.
///
/// Collection
/// A function to test each event for a condition.
/// Specified beat range.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, RDRange range) where TEvent : IBaseEvent => e.Where(range).Where(predicate);
///
/// Filters a sequence of events based on a predicate in specified bar.
///
/// Collection
/// A function to test each event for a condition.
/// Specified bar.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, Index bar) where TEvent : IBaseEvent => e.Where(bar).Where(predicate);
///
/// Filters a sequence of events based on a predicate in specified range of bar.
///
/// Collection
/// A function to test each event for a condition.
/// Specified bar range.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, Range bars) where TEvent : IBaseEvent => e.Where(bars).Where(predicate);
///
/// Filters a sequence of events in specified event type.
///
///
/// Collection
public static IEnumerable Where(this OrderedEventCollection e) where TEvent : IBaseEvent
{
EventType[] enums = EventTypeUtils.ToEnums();
return e.eventsBeatOrder
.Where(i => i.Value._types
.Any(enums.Contains))
.SelectMany(i => i.Value).OfType();
}
///
/// Filters a sequence of events located at a beat in specified event type.
///
/// Specified event type.
/// Collection
/// Specified beat.
public static IEnumerable Where(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent
{
TypedEventCollection value;
return (e.eventsBeatOrder.TryGetValue(beat, out value!) ? value.OfType() : []) ?? [];
}
///
/// Filters a sequence of events located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// Specified start beat.
/// Specified end beat.
public static IEnumerable Where(this OrderedEventCollection e, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.eventsBeatOrder
.TakeWhile(i => i.Key < endBeat)
.SkipWhile(i => i.Key < startBeat)
.SelectMany(i => i.Value.OfType());
///
/// Filters a sequence of events located at a bar in specified event type.
///
/// Specified event type.
/// Collection
/// Specified bar.
public static IEnumerable Where(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent
{
(float, float) rg = GetRange(e, bar);
return e.eventsBeatOrder
.TakeWhile((KeyValuePair> i) => i.Key.BeatOnly < rg.Item2)
.SkipWhile((KeyValuePair> i) => i.Key.BeatOnly < rg.Item1)
.SelectMany(i => i.Value.OfType());
}
///
/// Filters a sequence of events located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// Specified beat range.
public static IEnumerable Where(this OrderedEventCollection e, RDRange range) where TEvent : IBaseEvent => e.eventsBeatOrder
.TakeWhile(i => range.End == null || i.Key < range.End)
.SkipWhile(i => range.Start != null && i.Key < range.Start)
.SelectMany(i => i.Value.OfType());
///
/// Filters a sequence of events located at a range of bar in specified event type.
///
/// Specified event type.
/// Collection
/// Specified bar range.
public static IEnumerable Where(this OrderedEventCollection e, Range bars) where TEvent : IBaseEvent
{
(float start, float end) = GetRange(e, bars);
return e.eventsBeatOrder
.TakeWhile(i => i.Key.BeatOnly < end)
.SkipWhile(i => i.Key.BeatOnly < start)
.SelectMany(i => i.Value.OfType());
}
///
/// Filters a sequence of events based on a predicate located at a range of bar in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.Where().Where(predicate);
///
/// Filters a sequence of events based on a predicate located at a beat in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified beat.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, RDBeat beat) where TEvent : IBaseEvent => e.Where(beat).Where(predicate);
///
/// Filters a sequence of events based on a predicate located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified start beat.
/// Specified end beat.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.Where(startBeat, endBeat).Where(predicate);
///
/// Filters a sequence of events based on a predicate located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified beat range.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, RDRange range) where TEvent : IBaseEvent => e.Where(range).Where(predicate);
///
/// Filters a sequence of events based on a predicate located at a bar in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified bar.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, Index bar) where TEvent : IBaseEvent => e.Where(bar).Where(predicate);
///
/// Filters a sequence of events based on a predicate located at a range of bar in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified bar range.
public static IEnumerable Where(this OrderedEventCollection e, Func predicate, Range bars) where TEvent : IBaseEvent => e.Where(bars).Where(predicate);
///
/// Remove a sequence of events based on a predicate.
///
/// Collection
/// A function to test each event for a condition.
public static int RemoveAll(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate)));
///
/// Remove a sequence of events located at a time.
///
/// Collection
/// Specified beat.
public static int RemoveAll(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(beat)));
///
/// Remove a sequence of events located at a range of time.
///
/// Collection
/// Specified start beat.
/// Specified end beat.
public static int RemoveAll(this OrderedEventCollection e, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(startBeat, endBeat)));
///
/// Remove a sequence of events located at a bar.
///
/// Collection
/// Specified bar.
public static int RemoveAll(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(bar)));
///
/// Remove a sequence of events located at a range of beat.
///
/// Collection
/// Specified beat range.
///
public static int RemoveAll(this OrderedEventCollection e, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(range)));
///
/// Remove a sequence of events located at a range of bar.
///
/// Collection
/// Specified bar range.
public static int RemoveAll(this OrderedEventCollection e, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(bars)));
///
/// Remove a sequence of events based on a predicate in specified beat.
///
/// Collection
/// A function to test each event for a condition.
/// Specified beat.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, beat)));
///
/// Remove a sequence of events based on a predicate in specified range of beat.
///
/// Collection
/// A function to test each event for a condition.
/// Specified start beat.
/// Specified end beat.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, startBeat, endBeat)));
///
/// Remove a sequence of events based on a predicate in specified range of beat.
///
/// Collection
/// A function to test each event for a condition.
/// Specified beat range.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, range)));
///
/// Remove a sequence of events based on a predicate in specified bar.
///
/// Collection
/// A function to test each event for a condition.
/// Specified bar.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, bar)));
///
/// Remove a sequence of events based on a predicate in specified range of bar.
///
/// Collection
/// A function to test each event for a condition.
/// Specified bar range.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, bars)));
///
/// Remove a sequence of events in specified event type.
///
///
/// Collection
public static int RemoveAll(this OrderedEventCollection e) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where()));
///
/// Remove a sequence of events located at a beat in specified event type.
///
/// Specified event type.
/// Collection
/// Specified beat.
public static int RemoveAll(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(beat)));
///
/// Remove a sequence of events located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// Specified start beat.
/// Specified end beat.
public static int RemoveAll(this OrderedEventCollection e, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(startBeat, endBeat)));
///
/// Filters a sequence of events located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// Specified beat range.
public static int RemoveAll(this OrderedEventCollection e, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(range)));
///
/// Remove a sequence of events located at a bar in specified event type.
///
/// Specified event type.
/// Collection
/// Specified bar.
public static int RemoveAll(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(bar)));
///
/// Remove a sequence of events located at a range of bar in specified event type.
///
/// Specified event type.
/// Collection
/// Specified bar range.
public static int RemoveAll(this OrderedEventCollection e, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(bars)));
///
/// Remove a sequence of events based on a predicate located at a range of bar in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
public static int RemoveAll(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate)));
///
/// Remove a sequence of events based on a predicate located at a beat in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified beat.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, beat)));
///
/// Remove a sequence of events based on a predicate located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified start beat.
/// Specified end beat.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, startBeat, endBeat)));
///
/// Remove a sequence of events based on a predicate located at a range of beat in specified event type.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// Specified beat range.
public static int RemoveAll(this OrderedEventCollection e, Func predicate, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, range)));
///
/// Filters a sequence of events based on a predicate located at a bar in specified event type.
///
/// Specified event type.
/// A function to test each event for a condition.
/// Specified bar.
/// Collection
public static int RemoveAll(this OrderedEventCollection e, Func predicate, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, bar)));
///
/// Filters a sequence of events based on a predicate located at a range of bar in specified event type.
///
/// Specified event type.
/// A function to test each event for a condition.
/// Specified bar range.
/// Collection
public static int RemoveAll(this OrderedEventCollection e, Func predicate, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List(e.Where(predicate, bars)));
///
/// Returns the first element of the collection.
///
/// Collection
public static TEvent First(this OrderedEventCollection e) where TEvent : IBaseEvent => (TEvent)e.eventsBeatOrder.First().Value.First();
///
/// Returns the first element of the collection that satisfies a specified condition.
///
/// A function to test each event for a condition.
/// Collection
public static TEvent First(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.ConcatAll().First(predicate);
///
/// Returns the first element of the collection in specified event type.
///
/// Collection
public static TEvent First(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where().First();
///
/// Returns the first element of the collection that satisfies a specified condition in specified event type.
///
/// A function to test each event for a condition.
/// Collection
public static TEvent First(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.Where().First(predicate);
///
/// Returns the first event in the collection or the default value if the collection is empty.
///
/// The type of event in the collection.
/// The ordered event collection.
/// The first event in the collection or the default value if the collection is empty.
public static TEvent? FirstOrDefault(this OrderedEventCollection e) where TEvent : IBaseEvent
{
TypedEventCollection value = e.eventsBeatOrder.FirstOrDefault().Value;
return (TEvent?)(value?.FirstOrDefault());
}
///
/// Returns the first element of the collection, or if collection contains no elements.
///
/// The default value to return if contains no elements.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().FirstOrDefault(defaultValue);
///
/// Returns the first element of the collection that satisfies a specified condition, or if matches no elements.
///
/// A function to test each event for a condition.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.ConcatAll().OfType().FirstOrDefault(predicate);
///
/// Returns the first element of the collection that satisfies a specified condition, or if matches no elements.
///
/// A function to test each event for a condition.
/// The default value to return if matches no elements.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e, Func predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().FirstOrDefault(predicate, defaultValue);
///
/// Returns the first element of the collection in specified event type, or if matches no elements.
///
/// Specified event type.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where().FirstOrDefault();
///
/// Returns the first element of the collection in specified event type, or if matches no elements.
///
/// Specified event type.
/// The default value to return if matches no elements.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e, TEvent defaultValue) where TEvent : IBaseEvent => e.Where().FirstOrDefault(defaultValue);
///
/// Returns the first element of the collection that satisfies a specified condition in specified event type, or if matches no elements.
///
/// Specified event type.
/// A function to test each event for a condition.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.Where().FirstOrDefault(predicate);
///
/// Returns the first element of the collection that satisfies a specified condition in specified event type, or if matches no elements.
///
/// Specified event type.
/// A function to test each event for a condition.
/// The default value to return if matches no elements.
/// Collection
public static TEvent? FirstOrDefault(this OrderedEventCollection e, Func predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.Where().FirstOrDefault(predicate, defaultValue);
///
/// Returns the last element of the collection.
///
public static TEvent Last(this OrderedEventCollection e) where TEvent : IBaseEvent => (TEvent)e.eventsBeatOrder.Last().Value.Last();
///
/// Returns the last element of the collection that satisfies a specified condition.
///
/// A function to test each event for a condition.
/// Collection
public static TEvent Last(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.ConcatAll().Last(predicate);
///
/// Returns the last element of the collection in specified event type.
///
/// Collection
public static TEvent Last(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where().Last();
///
/// Returns the last element of the collection that satisfies a specified condition in specified event type.
///
/// A function to test each event for a condition.
/// Collection
public static TEvent Last(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.Where().Last(predicate);
///
/// Returns the last element of the collection, or if collection contains no elements.
///
public static TEvent? LastOrDefault(this OrderedEventCollection e) where TEvent : IBaseEvent
{
IEnumerable value = e.eventsBeatOrder.LastOrDefault().Value.AsEnumerable();
return (TEvent?)(value?.LastOrDefault());
}
///
/// Returns the last element of the collection, or if collection contains no elements.
///
/// Collection
/// The default value to return if contains no elements.
public static TEvent LastOrDefault(this OrderedEventCollection e, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().LastOrDefault(defaultValue);
///
/// Returns the last element of the collection that satisfies a specified condition, or if matches no elements.
///
/// Collection
/// A function to test each event for a condition.
public static TEvent? LastOrDefault(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.ConcatAll().LastOrDefault(predicate);
///
/// Returns the last element of the collection that satisfies a specified condition, or if matches no elements.
///
/// Collection
/// A function to test each event for a condition.
/// The default value to return if matches no elements.
public static TEvent LastOrDefault(this OrderedEventCollection e, Func predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().LastOrDefault(predicate, defaultValue);
///
/// Returns the last element of the collection in specified event type, or if matches no elements.
///
/// Specified event type.
/// Collection
public static TEvent? LastOrDefault(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where().LastOrDefault();
///
/// Returns the last element of the collection in specified event type, or if matches no elements.
///
/// Specified event type.
/// Collection
/// The default value to return if matches no elements.
public static TEvent LastOrDefault(this OrderedEventCollection e, TEvent defaultValue) where TEvent : IBaseEvent => e.Where().LastOrDefault(defaultValue);
///
/// Returns the last element of the collection that satisfies a specified condition in specified event type, or if matches no elements.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
public static TEvent? LastOrDefault(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent => e.Where().LastOrDefault(predicate);
///
/// Returns the last element of the collection that satisfies a specified condition in specified event type, or if matches no elements.
///
/// Specified event type.
/// Collection
/// A function to test each event for a condition.
/// The default value to return if matches no elements.
public static TEvent LastOrDefault(this OrderedEventCollection e, Func predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.Where().LastOrDefault(predicate, defaultValue);
///
/// Returns events from a collection as long as it less than or equal to .
///
/// Collection
/// Specified beat.
public static IEnumerable TakeWhile(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent
{
foreach (TEvent item in e.Where())
if (item.Beat <= beat) yield return item;
else break;
}
///
/// Returns events from a collection as long as it less than or equal to .
///
/// Collection
/// Specified bar.
public static IEnumerable TakeWhile(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent
{
TEvent firstEvent = e.First();
TEvent lastEvent = e.Last();
return e.TakeWhile(checked(bar.IsFromEnd
? lastEvent.Beat._calculator!.BeatOf((uint)(lastEvent.Beat.BarBeat.bar - (uint)bar.Value + 1U), 1f)
: firstEvent.Beat._calculator!.BeatOf((uint)(bar.Value + 1), 1f)));
}
///
/// Returns events from a collection as long as a specified condition is true.
///
/// Collection
/// A function to test each event for a condition.
public static IEnumerable TakeWhile(this OrderedEventCollection e, Func predicate) where TEvent : IBaseEvent =>
(IEnumerable)e.eventsBeatOrder
.SelectMany(i => i.Value)
.TakeWhile((Func)(object)predicate);
///
/// Returns events from a collection as long as a specified condition is true and also less than or equal to .
///
/// A function to test each event for a condition.
/// Collection
/// Specified beat.
public static IEnumerable TakeWhile(this OrderedEventCollection e, Func