Archived
forked from RDTKEditor/RDTKEditor
1069 lines
56 KiB
C#
1069 lines
56 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// Extensions
|
|
/// </summary>
|
|
[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>();
|
|
IBaseEvent lastEvent = e.Last<IBaseEvent>();
|
|
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>();
|
|
IBaseEvent lastEvent = e.Last<IBaseEvent>();
|
|
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;
|
|
}
|
|
/// <summary>
|
|
/// Null or equal.
|
|
/// </summary>
|
|
/// <param name="e">one item.</param>
|
|
/// <param name="obj">another item.</param>
|
|
/// <returns>
|
|
/// <list type="table">
|
|
/// <item>When neither item is empty,<br />Returns true only if both are equal</item>
|
|
/// <item>when one of the two is empty,<br />Returns true.</item>
|
|
/// <item>when both are empty,<br />Returns false.</item>
|
|
/// </list>
|
|
/// </returns>
|
|
public static bool NullableEquals(this float? e, float? obj) => ((e != null && obj != null) && e.Value == obj.Value) || (e == null && obj == null);
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
public static bool IsNullOrEmpty([NotNullWhen(false)] this string? e) => e == null || e.Length == 0;
|
|
/// <summary>
|
|
/// Make strings follow the Upper Camel Case.
|
|
/// </summary>
|
|
/// <returns>The result.</returns>
|
|
public static string ToUpperCamelCase(this string e)
|
|
{
|
|
char[] S = [.. e];
|
|
S[0] = (S[0].ToString().ToUpper()[0]);
|
|
return string.Join("", [new string(S)]);
|
|
}
|
|
/// <summary>
|
|
/// Make a specific key of a JObject follow the Upper Camel Case.
|
|
/// </summary>
|
|
internal static void ToUpperCamelCase(this JObject e, string key)
|
|
{
|
|
JToken token = e[key] ?? throw new NullReferenceException();
|
|
e.Remove(key);
|
|
e[key.ToUpperCamelCase()] = token;
|
|
}
|
|
/// <summary>
|
|
/// Make strings follow the Lower Camel Case.
|
|
/// </summary>
|
|
/// <returns>The result.</returns>
|
|
public static string ToLowerCamelCase(this string e)
|
|
{
|
|
char[] S = [.. e];
|
|
S[0] = (S[0].ToString().ToLower()[0]);
|
|
return string.Join("", [new string(S)]);
|
|
}
|
|
/// <summary>
|
|
/// Make a specific key of a JObject follow the Lower Camel Case.
|
|
/// </summary>
|
|
internal static void ToLowerCamelCase(this JObject e, string key)
|
|
{
|
|
JToken token = e[key] ?? throw new NullReferenceException();
|
|
e.Remove(key);
|
|
e[key.ToLowerCamelCase()] = token;
|
|
}
|
|
/// <summary>
|
|
/// Convert color format from RGBA to ARGB
|
|
/// </summary>
|
|
public static int RgbaToArgb(this int Rgba) => (Rgba >> 8 & 16777215) | (Rgba << 24 & -16777216);
|
|
/// <summary>
|
|
/// Convert color format from ARGB to RGBA
|
|
/// </summary>
|
|
public static int ArgbToRgba(this int Argb) => (Argb >> 24 & 255) | (Argb << 8 & -256);
|
|
/// <summary>
|
|
/// Calculate the fraction of <paramref name="splitBase" /> equal to the nearest floating point number.
|
|
/// <example>
|
|
/// <code>
|
|
/// 2.236f.FixFraction(4) == 2.25f
|
|
/// float.Pi.FixFraction(5) == 3.2f
|
|
/// float.E.Fixfraction(2) == 2.5f
|
|
/// </code>
|
|
/// </example>
|
|
/// </summary>
|
|
/// <param name="beat">The float number.</param>
|
|
/// <param name="splitBase">Indicate what fraction this is.</param>
|
|
/// <returns></returns>
|
|
public static float FixFraction(this float beat, uint splitBase) => (float)(Math.Round((double)(beat * splitBase)) / splitBase);
|
|
/// <summary>
|
|
/// Calculate the fraction of <paramref name="splitBase" /> equal to the nearest floating point number.
|
|
/// </summary>
|
|
public static RDBeat FixFraction(this RDBeat beat, uint splitBase) => new(beat.BeatOnly.FixFraction(splitBase));
|
|
/// <summary>
|
|
/// Converting enumeration constants to in-game colors。
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <returns>The in-game color.</returns>
|
|
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(),
|
|
};
|
|
/// <summary>
|
|
/// Add a range of events.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="items"></param>
|
|
public static void AddRange<TEvent>(this OrderedEventCollection<TEvent> e, IEnumerable<TEvent> items) where TEvent : IBaseEvent
|
|
{
|
|
foreach (TEvent item in items)
|
|
e.Add(item);
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent =>
|
|
((IEnumerable<TEvent>)e.eventsBeatOrder
|
|
.SelectMany(i => i.Value)).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a time.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, RDBeat beat) where TEvent : IBaseEvent
|
|
{
|
|
IEnumerable<TEvent> Where = [];
|
|
if (e.eventsBeatOrder.TryGetValue(beat, out TypedEventCollection<IBaseEvent>? value))
|
|
Where = value.Cast<TEvent>().AsEnumerable();
|
|
return Where;
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of time.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> 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<TEvent>());
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> 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<TEvent>());
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
/// <returns></returns>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, RDRange range) where TEvent : IBaseEvent =>
|
|
(IEnumerable<TEvent>)e.eventsBeatOrder
|
|
.TakeWhile(i => range.End == null || i.Key < range.End)
|
|
.SkipWhile(i => range.Start != null && i.Key < range.Start)
|
|
.SelectMany(i => i.Value);
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> 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<TEvent>());
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate in specified beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDBeat beat) where TEvent : IBaseEvent => e.Where(beat).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate in specified range of beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.Where(startBeat, endBeat).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate in specified range of beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDRange range) where TEvent : IBaseEvent => e.Where(range).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate in specified bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, Index bar) where TEvent : IBaseEvent => e.Where(bar).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate in specified range of bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, Range bars) where TEvent : IBaseEvent => e.Where(bars).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent"></typeparam>
|
|
/// <param name="e">Collection</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e) where TEvent : IBaseEvent
|
|
{
|
|
EventType[] enums = EventTypeUtils.ToEnums<TEvent>();
|
|
return e.eventsBeatOrder
|
|
.Where(i => i.Value._types
|
|
.Any(enums.Contains))
|
|
.SelectMany(i => i.Value).OfType<TEvent>();
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent
|
|
{
|
|
TypedEventCollection<IBaseEvent> value;
|
|
return (e.eventsBeatOrder.TryGetValue(beat, out value!) ? value.OfType<TEvent>() : []) ?? [];
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(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<TEvent>());
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent
|
|
{
|
|
(float, float) rg = GetRange(e, bar);
|
|
return e.eventsBeatOrder
|
|
.TakeWhile((KeyValuePair<RDBeat, TypedEventCollection<IBaseEvent>> i) => i.Key.BeatOnly < rg.Item2)
|
|
.SkipWhile((KeyValuePair<RDBeat, TypedEventCollection<IBaseEvent>> i) => i.Key.BeatOnly < rg.Item1)
|
|
.SelectMany(i => i.Value.OfType<TEvent>());
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(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<TEvent>());
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(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<TEvent>());
|
|
}
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a range of bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.Where<TEvent>().Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDBeat beat) where TEvent : IBaseEvent => e.Where<TEvent>(beat).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.Where<TEvent>(startBeat, endBeat).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDRange range) where TEvent : IBaseEvent => e.Where<TEvent>(range).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, Index bar) where TEvent : IBaseEvent => e.Where<TEvent>(bar).Where(predicate);
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a range of bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static IEnumerable<TEvent> Where<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, Range bars) where TEvent : IBaseEvent => e.Where<TEvent>(bars).Where(predicate);
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a time.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(beat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a range of time.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(startBeat, endBeat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(bar)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a range of beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
/// <returns></returns>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(range)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a range of bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(bars)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate in specified beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, beat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate in specified range of beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, startBeat, endBeat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate in specified range of beat.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, range)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate in specified bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, bar)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate in specified range of bar.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, bars)));
|
|
/// <summary>
|
|
/// Remove a sequence of events in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent"></typeparam>
|
|
/// <param name="e">Collection</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where<TEvent>()));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where<TEvent>(beat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where<TEvent>(startBeat, endBeat)));
|
|
/// <summary>
|
|
/// Filters a sequence of events located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where<TEvent>(range)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where<TEvent>(bar)));
|
|
/// <summary>
|
|
/// Remove a sequence of events located at a range of bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where<TEvent>(bars)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate located at a range of bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate located at a beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDBeat beat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, beat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="startBeat">Specified start beat.</param>
|
|
/// <param name="endBeat">Specified end beat.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDBeat startBeat, RDBeat endBeat) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, startBeat, endBeat)));
|
|
/// <summary>
|
|
/// Remove a sequence of events based on a predicate located at a range of beat in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="range">Specified beat range.</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDRange range) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, range)));
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, Index bar) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, bar)));
|
|
/// <summary>
|
|
/// Filters a sequence of events based on a predicate located at a range of bar in specified event type.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="bars">Specified bar range.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static int RemoveAll<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, Range bars) where TEvent : IBaseEvent => e.RemoveRange(new List<TEvent>(e.Where(predicate, bars)));
|
|
/// <summary>
|
|
/// Returns the first element of the collection.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent First<TEvent>(this OrderedEventCollection<TEvent> e) where TEvent : IBaseEvent => (TEvent)e.eventsBeatOrder.First().Value.First();
|
|
/// <summary>
|
|
/// Returns the first element of the collection that satisfies a specified condition.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent First<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.ConcatAll().First(predicate);
|
|
/// <summary>
|
|
/// Returns the first element of the collection in specified event type.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent First<TEvent>(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where<TEvent>().First();
|
|
/// <summary>
|
|
/// Returns the first element of the collection that satisfies a specified condition in specified event type.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent First<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.Where<TEvent>().First(predicate);
|
|
/// <summary>
|
|
/// Returns the first event in the collection or the default value if the collection is empty.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">The type of event in the collection.</typeparam>
|
|
/// <param name="e">The ordered event collection.</param>
|
|
/// <returns>The first event in the collection or the default value if the collection is empty.</returns>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection<TEvent> e) where TEvent : IBaseEvent
|
|
{
|
|
TypedEventCollection<IBaseEvent> value = e.eventsBeatOrder.FirstOrDefault().Value;
|
|
return (TEvent?)(value?.FirstOrDefault());
|
|
}
|
|
/// <summary>
|
|
/// Returns the first element of the collection, or <paramref name="defaultValue" /> if collection contains no elements.
|
|
/// </summary>
|
|
/// <param name="defaultValue">The default value to return if contains no elements.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection<TEvent> e, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().FirstOrDefault(defaultValue);
|
|
/// <summary>
|
|
/// Returns the first element of the collection that satisfies a specified condition, or <see langword="null" /> if matches no elements.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.ConcatAll().OfType<TEvent>().FirstOrDefault(predicate);
|
|
/// <summary>
|
|
/// Returns the first element of the collection that satisfies a specified condition, or <paramref name="defaultValue" /> if matches no elements.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="defaultValue">The default value to return if matches no elements.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().FirstOrDefault(predicate, defaultValue);
|
|
/// <summary>
|
|
/// Returns the first element of the collection in specified event type, or <see langword="null" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where<TEvent>().FirstOrDefault();
|
|
/// <summary>
|
|
/// Returns the first element of the collection in specified event type, or <paramref name="defaultValue" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="defaultValue">The default value to return if matches no elements.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection e, TEvent defaultValue) where TEvent : IBaseEvent => e.Where<TEvent>().FirstOrDefault(defaultValue);
|
|
/// <summary>
|
|
/// Returns the first element of the collection that satisfies a specified condition in specified event type, or <see langword="null" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.Where<TEvent>().FirstOrDefault(predicate);
|
|
/// <summary>
|
|
/// Returns the first element of the collection that satisfies a specified condition in specified event type, or <paramref name="defaultValue" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="defaultValue">The default value to return if matches no elements.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? FirstOrDefault<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.Where<TEvent>().FirstOrDefault(predicate, defaultValue);
|
|
/// <summary>
|
|
/// Returns the last element of the collection.
|
|
/// </summary>
|
|
public static TEvent Last<TEvent>(this OrderedEventCollection<TEvent> e) where TEvent : IBaseEvent => (TEvent)e.eventsBeatOrder.Last().Value.Last();
|
|
/// <summary>
|
|
/// Returns the last element of the collection that satisfies a specified condition.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent Last<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.ConcatAll().Last(predicate);
|
|
/// <summary>
|
|
/// Returns the last element of the collection in specified event type.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent Last<TEvent>(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where<TEvent>().Last();
|
|
/// <summary>
|
|
/// Returns the last element of the collection that satisfies a specified condition in specified event type.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent Last<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.Where<TEvent>().Last(predicate);
|
|
/// <summary>
|
|
/// Returns the last element of the collection, or <see langword="null" /> if collection contains no elements.
|
|
/// </summary>
|
|
public static TEvent? LastOrDefault<TEvent>(this OrderedEventCollection<TEvent> e) where TEvent : IBaseEvent
|
|
{
|
|
IEnumerable<IBaseEvent> value = e.eventsBeatOrder.LastOrDefault().Value.AsEnumerable();
|
|
return (TEvent?)(value?.LastOrDefault());
|
|
}
|
|
/// <summary>
|
|
/// Returns the last element of the collection, or <paramref name="defaultValue" /> if collection contains no elements.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="defaultValue">The default value to return if contains no elements.</param>
|
|
public static TEvent LastOrDefault<TEvent>(this OrderedEventCollection<TEvent> e, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().LastOrDefault(defaultValue);
|
|
/// <summary>
|
|
/// Returns the last element of the collection that satisfies a specified condition, or <see langword="null" /> if matches no elements.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static TEvent? LastOrDefault<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.ConcatAll().LastOrDefault(predicate);
|
|
/// <summary>
|
|
/// Returns the last element of the collection that satisfies a specified condition, or <paramref name="defaultValue" /> if matches no elements.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="defaultValue">The default value to return if matches no elements.</param>
|
|
public static TEvent LastOrDefault<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.ConcatAll().LastOrDefault(predicate, defaultValue);
|
|
/// <summary>
|
|
/// Returns the last element of the collection in specified event type, or <see langword="null" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
public static TEvent? LastOrDefault<TEvent>(this OrderedEventCollection e) where TEvent : IBaseEvent => e.Where<TEvent>().LastOrDefault();
|
|
/// <summary>
|
|
/// Returns the last element of the collection in specified event type, or <paramref name="defaultValue" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="defaultValue">The default value to return if matches no elements.</param>
|
|
public static TEvent LastOrDefault<TEvent>(this OrderedEventCollection e, TEvent defaultValue) where TEvent : IBaseEvent => e.Where<TEvent>().LastOrDefault(defaultValue);
|
|
/// <summary>
|
|
/// Returns the last element of the collection that satisfies a specified condition in specified event type, or <see langword="null" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static TEvent? LastOrDefault<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.Where<TEvent>().LastOrDefault(predicate);
|
|
/// <summary>
|
|
/// Returns the last element of the collection that satisfies a specified condition in specified event type, or <paramref name="defaultValue" /> if matches no elements.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="defaultValue">The default value to return if matches no elements.</param>
|
|
public static TEvent LastOrDefault<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, TEvent defaultValue) where TEvent : IBaseEvent => e.Where<TEvent>().LastOrDefault(predicate, defaultValue);
|
|
/// <summary>
|
|
/// Returns events from a collection as long as it less than or equal to <paramref name="beat" />.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection<TEvent> e, RDBeat beat) where TEvent : IBaseEvent
|
|
{
|
|
foreach (TEvent item in e.Where<TEvent>())
|
|
if (item.Beat <= beat) yield return item;
|
|
else break;
|
|
}
|
|
/// <summary>
|
|
/// Returns events from a collection as long as it less than or equal to <paramref name="bar" />.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection<TEvent> 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)));
|
|
}
|
|
/// <summary>
|
|
/// Returns events from a collection as long as a specified condition is true.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent =>
|
|
(IEnumerable<TEvent>)e.eventsBeatOrder
|
|
.SelectMany(i => i.Value)
|
|
.TakeWhile((Func<IBaseEvent, bool>)(object)predicate);
|
|
/// <summary>
|
|
/// Returns events from a collection as long as a specified condition is true and also less than or equal to <paramref name="beat" />.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, RDBeat beat) where TEvent : IBaseEvent => e.TakeWhile(beat).TakeWhile(predicate);
|
|
/// <summary>
|
|
/// Returns events from a collection as long as a specified condition is true and also less than or equal to <paramref name="bar" />.
|
|
/// </summary>
|
|
/// <param name="predicate">A function to test each event for a condition.</param>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection<TEvent> e, Func<TEvent, bool> predicate, Index bar) where TEvent : IBaseEvent => e.TakeWhile(bar).TakeWhile(predicate);
|
|
/// <summary>
|
|
/// Returns events from a collection in specified event type as long as it less than or equal to <paramref name="beat" />.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection e, RDBeat beat) where TEvent : IBaseEvent
|
|
{
|
|
foreach (TEvent item in e.Where<TEvent>())
|
|
if (item.Beat <= beat) yield return item;
|
|
else break;
|
|
}
|
|
/// <summary>
|
|
/// Returns events from a collection in specified event type as long as it less than or in <paramref name="bar" />.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="bar">Specified bar.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection e, Index bar) where TEvent : IBaseEvent
|
|
{
|
|
IBaseEvent firstEvent = e.First<IBaseEvent>();
|
|
IBaseEvent lastEvent = e.Last<IBaseEvent>();
|
|
return e.TakeWhile<TEvent>(checked(bar.IsFromEnd
|
|
? lastEvent.Beat._calculator!.BeatOf((uint)(lastEvent.Beat.BarBeat.bar - (ulong)bar.Value + 1U), 1f)
|
|
: firstEvent.Beat._calculator!.BeatOf((uint)(bar.Value + 1), 1f)));
|
|
}
|
|
/// <summary>
|
|
/// Returns events from a collection in specified event type as long as a specified condition is true.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">Specified condition.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate) where TEvent : IBaseEvent => e.Where<TEvent>().TakeWhile(predicate);
|
|
/// <summary>
|
|
/// Returns events from a collection in specified event type as long as a specified condition is true and its beat less than or equal to <paramref name="beat" />.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">Specified condition.</param>
|
|
/// <param name="beat">Specified beat.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, RDBeat beat) where TEvent : IBaseEvent => e.TakeWhile<TEvent>(beat).TakeWhile(predicate);
|
|
/// <summary>
|
|
/// Returns events from a collection in specified event type as long as a specified condition is true and its beat less than or equal to <paramref name="bar" />.
|
|
/// </summary>
|
|
/// <typeparam name="TEvent">Specified event type.</typeparam>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="predicate">Specified condition.</param>
|
|
/// <param name="bar">Specified beat.</param>
|
|
public static IEnumerable<TEvent> TakeWhile<TEvent>(this OrderedEventCollection e, Func<TEvent, bool> predicate, Index bar) where TEvent : IBaseEvent => e.TakeWhile<TEvent>(bar).TakeWhile(predicate);
|
|
/// <summary>
|
|
/// Remove a range of events.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="items">A range of events.</param>
|
|
/// <returns>The number of events successfully removed.</returns>
|
|
public static int RemoveRange<TEvent>(this OrderedEventCollection e, IEnumerable<TEvent> items) where TEvent : IBaseEvent
|
|
{
|
|
int count = 0;
|
|
foreach (var item in items)
|
|
count += e.Remove(item) ? 1 : 0;
|
|
return count;
|
|
}
|
|
/// <summary>
|
|
/// Remove a range of events.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="items">A range of events.</param>
|
|
/// <returns>The number of events successfully removed.</returns>
|
|
public static int RemoveRange<TEvent>(this OrderedEventCollection<TEvent> e, IEnumerable<TEvent> items) where TEvent : IBaseEvent
|
|
{
|
|
int count = 0;
|
|
foreach (var item in items)
|
|
count += e.Remove(item) ? 1 : 0;
|
|
return count;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all the hit of the level.
|
|
/// </summary>
|
|
public static IEnumerable<RDHit> GetHitBeat(this RDLevel e)
|
|
{
|
|
List<RDHit> L = [];
|
|
foreach (RowEventCollection item in e.Rows)
|
|
{
|
|
L.AddRange(item.HitBeats());
|
|
}
|
|
return L;
|
|
}
|
|
/// <summary>
|
|
/// Get all the hit event of the level.
|
|
/// </summary>
|
|
public static IEnumerable<BaseBeat> GetHitEvents(this RDLevel e) => e.Where<BaseBeat>(IsHitable);
|
|
/// <summary>
|
|
/// Get all events with the specified tag.
|
|
/// </summary>
|
|
/// <param name="e">Collection</param>
|
|
/// <param name="name">Tag name.</param>
|
|
/// <param name="strict">Indicates whether the label is strictly matched.
|
|
/// If <see langword="true" />, determine If it contains the specified tag.
|
|
/// If <see langword="false" />, determine If it Is equal to the specified tag.</param>
|
|
/// <returns>An <see cref="T:System.Linq.IGrouping`2" />, categorized by tag name.</returns>
|
|
public static IEnumerable<IGrouping<string, TEvent>> GetTaggedEvents<TEvent>(this OrderedEventCollection<TEvent> e, string name, bool strict) where TEvent : IBaseEvent
|
|
{
|
|
if (name.IsNullOrEmpty())
|
|
return [];
|
|
if (strict)
|
|
return e
|
|
.Where(i => i.Tag == name).GroupBy(i => i.Tag);
|
|
else
|
|
return e
|
|
.Where(i => i.Tag?.Contains(name) ?? false).GroupBy(i => i.Tag);
|
|
}
|
|
/// <summary>
|
|
/// Get all classic beat events and their variants.
|
|
/// </summary>
|
|
private static IEnumerable<BaseBeat> ClassicBeats(this RowEventCollection e) => e.Where((BaseBeat i) => i.Type == EventType.AddClassicBeat | i.Type == EventType.AddFreeTimeBeat | i.Type == EventType.PulseFreeTimeBeat);
|
|
/// <summary>
|
|
/// Get all oneshot beat events.
|
|
/// </summary>
|
|
private static IEnumerable<BaseBeat> OneshotBeats(this RowEventCollection e) => e.Where((BaseBeat i) => i.Type == EventType.AddOneshotBeat);
|
|
/// <summary>
|
|
/// Get all hits of all beats.
|
|
/// </summary>
|
|
public static IEnumerable<RDHit> HitBeats(this RowEventCollection e)
|
|
{
|
|
RowType rowType = e.RowType;
|
|
IEnumerable<RDHit> HitBeats;
|
|
if (rowType != RowType.Classic)
|
|
{
|
|
if (rowType != RowType.Oneshot)
|
|
throw new RhythmBaseException("How?");
|
|
HitBeats = e.OneshotBeats().SelectMany((BaseBeat i) => i.HitTimes());
|
|
}
|
|
else
|
|
HitBeats = e.ClassicBeats().SelectMany((BaseBeat i) => i.HitTimes());
|
|
return HitBeats;
|
|
}
|
|
/// <summary>
|
|
/// Get an instance of the beat associated with the level.
|
|
/// </summary>
|
|
/// <param name="e">RDLevel</param>
|
|
/// <param name="beatOnly">Total number of 1-based beats.</param>
|
|
public static RDBeat BeatOf(this RDLevel e, float beatOnly) => e.Calculator.BeatOf(beatOnly);
|
|
/// <summary>
|
|
/// Get an instance of the beat associated with the level.
|
|
/// </summary>
|
|
/// <param name="e">RDLevel</param>
|
|
/// <param name="bar">The 1-based bar.</param>
|
|
/// <param name="beat">The 1-based beat of the bar.</param>
|
|
public static RDBeat BeatOf(this RDLevel e, uint bar, float beat) => e.Calculator.BeatOf(bar, beat);
|
|
/// <summary>
|
|
/// Get an instance of the beat associated with the level.
|
|
/// </summary>
|
|
/// <param name="e">RDLevel</param>
|
|
/// <param name="timeSpan">Total time span of the beat.</param>
|
|
public static RDBeat BeatOf(this RDLevel e, TimeSpan timeSpan) => e.Calculator.BeatOf(timeSpan);
|
|
/// <summary>
|
|
/// Get the row beat status
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
/// <exception cref="RhythmBaseException"></exception>
|
|
public static SortedDictionary<float, int[]> GetRowBeatStatus(this RowEventCollection e)
|
|
{
|
|
SortedDictionary<float, int[]> L = [];
|
|
RowType rowType = e.RowType;
|
|
switch (rowType)
|
|
{
|
|
case RowType.Classic:
|
|
int[] value = new int[7];
|
|
L.Add(0f, value);
|
|
foreach (IBaseEvent beat in e)
|
|
switch (beat.Type)
|
|
{
|
|
case EventType.AddClassicBeat:
|
|
AddClassicBeat trueBeat = (AddClassicBeat)beat;
|
|
int i = 0;
|
|
do
|
|
{
|
|
int[] statusArray = L[beat.Beat.BeatOnly] ?? new int[7];
|
|
int[] array = statusArray;
|
|
int num = i;
|
|
ref int ptr = ref array[num];
|
|
array[num] = ptr + 1;
|
|
L[beat.Beat.BeatOnly] = statusArray;
|
|
i++;
|
|
}
|
|
while (i <= 6);
|
|
break;
|
|
default:
|
|
throw new NotImplementedException();
|
|
}
|
|
break;
|
|
case RowType.Oneshot:
|
|
throw new NotImplementedException();
|
|
default:
|
|
throw new RhythmBaseException("How");
|
|
}
|
|
return L;
|
|
}
|
|
/// <summary>
|
|
/// Get all beats of the row.
|
|
/// </summary>
|
|
public static IEnumerable<BaseBeat> Beats(this RowEventCollection e)
|
|
{
|
|
RowType rowType = e.RowType;
|
|
IEnumerable<BaseBeat> Beats;
|
|
if (rowType != RowType.Classic)
|
|
{
|
|
if (rowType != RowType.Oneshot)
|
|
throw new RhythmBaseException("How?");
|
|
Beats = e.OneshotBeats();
|
|
}
|
|
else
|
|
Beats = e.ClassicBeats();
|
|
return Beats;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns all previous events of the same type, including events of the same beat but executed before itself.
|
|
/// </summary>
|
|
public static IEnumerable<TEvent> Before<TEvent>(this TEvent e) where TEvent : IBaseEvent => e.Beat.BaseLevel?.Where<TEvent>(e.Beat.BaseLevel.DefaultBeat, e.Beat) ?? [];
|
|
/// <summary>
|
|
/// Returns all previous events of the specified type, including events of the same beat but executed before itself.
|
|
/// </summary>
|
|
public static IEnumerable<TEvent> Before<TEvent>(this IBaseEvent e) where TEvent : IBaseEvent => e.Beat.BaseLevel?.Where<TEvent>(e.Beat.BaseLevel.DefaultBeat, e.Beat) ?? [];
|
|
/// <summary>
|
|
/// Returns all events of the same type that follow, including events of the same beat but executed after itself.
|
|
/// </summary>
|
|
public static IEnumerable<TEvent> After<TEvent>(this TEvent e) where TEvent : IBaseEvent => e.Beat.BaseLevel?.Where<TEvent>(i => i.Beat > e.Beat) ?? [];
|
|
/// <summary>
|
|
/// Returns all events of the specified type that follow, including events of the same beat but executed after itself.
|
|
/// </summary>
|
|
public static IEnumerable<TEvent> After<TEvent>(this IBaseEvent e) where TEvent : IBaseEvent => e.Beat.BaseLevel?.Where<TEvent>(i => i.Beat > e.Beat) ?? [];
|
|
/// <summary>
|
|
/// Returns the previous event of the same type, including events of the same beat but executed before itself.
|
|
/// </summary>
|
|
public static TEvent Front<TEvent>(this TEvent e) where TEvent : IBaseEvent => e.Before().Last();
|
|
/// <summary>
|
|
/// Returns the previous event of the specified type, including events of the same beat but executed before itself.
|
|
/// </summary>
|
|
public static TEvent Front<TEvent>(this IBaseEvent e) where TEvent : IBaseEvent => e.Before<TEvent>().Last();
|
|
/// <summary>
|
|
/// Returns the previous event of the same type, including events of the same beat but executed before itself. Returns <see langword="null" /> if it does not exist.
|
|
/// </summary>
|
|
public static TEvent? FrontOrDefault<TEvent>(this TEvent e) where TEvent : IBaseEvent => e.Before().LastOrDefault();
|
|
/// <summary>
|
|
/// Returns the previous event of the specified type, including events of the same beat but executed before itself. Returns <see langword="null" /> if it does not exist.
|
|
/// </summary>
|
|
public static TEvent? FrontOrDefault<TEvent>(this IBaseEvent e) where TEvent : IBaseEvent => e.Before<TEvent>().LastOrDefault();
|
|
/// <summary>
|
|
/// Returns the next event of the same type, including events of the same beat but executed after itself.
|
|
/// </summary>
|
|
public static TEvent Next<TEvent>(this TEvent e) where TEvent : IBaseEvent => e.After().First();
|
|
/// <summary>
|
|
/// Returns the next event of the specified type, including events of the same beat but executed after itself.
|
|
/// </summary>
|
|
public static TEvent Next<TEvent>(this IBaseEvent e) where TEvent : IBaseEvent => e.After<TEvent>().First();
|
|
/// <summary>
|
|
/// Returns the next event of the same type, including events of the same beat but executed after itself. Returns <see langword="null" /> if it does not exist.
|
|
/// </summary>
|
|
public static TEvent? NextOrDefault<TEvent>(this TEvent e) where TEvent : IBaseEvent => e.After().FirstOrDefault();
|
|
/// <summary>
|
|
/// Returns the next event of the specified type, including events of the same beat but executed after itself. Returns <see langword="null" /> if it does not exist.
|
|
/// </summary>
|
|
public static TEvent? NextOrDefault<TEvent>(this IBaseEvent e) where TEvent : IBaseEvent => e.After<TEvent>().FirstOrDefault(); //?
|
|
|
|
/// <summary>
|
|
/// Shallow copy.
|
|
/// </summary>
|
|
public static TEvent MemberwiseClone<TEvent>(this TEvent e) where TEvent : IBaseEvent, new() => (TEvent)e.MClone();
|
|
internal static object MClone(this object e)
|
|
{
|
|
if (e != null)
|
|
{
|
|
Type type = e.GetType();
|
|
object copy = Activator.CreateInstance(type)!;
|
|
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
foreach (PropertyInfo p in properties)
|
|
{
|
|
if (p.CanWrite)
|
|
{
|
|
p.SetValue(copy, p.GetValue(e));
|
|
}
|
|
}
|
|
return copy;
|
|
}
|
|
throw new NullReferenceException();
|
|
}
|
|
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
|
public enum Wavetype
|
|
{
|
|
BoomAndRush,
|
|
Spring,
|
|
Spike,
|
|
SpikeHuge,
|
|
Ball,
|
|
Single
|
|
}
|
|
public enum ShockWaveType
|
|
{
|
|
size,
|
|
distortion,
|
|
duration
|
|
}
|
|
public enum Particle
|
|
{
|
|
HitExplosion,
|
|
leveleventexplosion
|
|
}
|
|
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
|
|
}
|
|
}
|