using System.Collections; using System.Collections.Generic; using System.Text; using System; using Godot; namespace Rokojori { public class ListView { List _list; int _offset; int _length; public ListView( List list, int offset, int length ) { _list = list; _offset = offset; _length = length; } public T this[ int index ] { get => _list[ index - _offset ]; set => _list[ index - _offset ] = value; } public int Count => _length; public void ForEach( Action action ) { for ( int i = 0; i < _length; i++ ) { action( this[ i ] ); } } public List GetList() { return _list; } public List SubList() { return _list.Sub( _offset, _length ); } } public static class Lists { public static void Union( this List list, List other ) { var set = new HashSet( list ); set.UnionWith( other ); list.Clear(); list.AddRange( [.. set ] ); } public static void AddIfNotPresent( this List values, T value ) { if ( values.Contains( value ) ) { return; } values.Add( value ); } public static bool IsOneOf( T value, params T[] values ) { for ( int i = 0; i < values.Length; i++ ) { if ( EqualityComparer.Default.Equals( values[ i ], value ) ) { return true; } } return false; } public static bool ContainsEqual( List values, T value ) { if ( value == null || values == null ) { return false; } return values.Find( v => value.Equals( v ) ) != null; } public static void Sort( List data, Func getValue ) { ValueSorter.SortList( data, getValue ); } public class IndexLerpResult { public int closestIndex = -1; public int secondIndex = -1; public float lerpAmount = 0.5f; } public static List Clone( this List data ) { if ( data == null ) { return null; } var cloned = new List( data.Count ); cloned.AddRange( data ); return cloned; } public static IndexLerpResult LerpIndex( List data, float value, Func getValue, bool sort = false ) { if ( sort ) { Sort( data, getValue ); } var result = new IndexLerpResult(); result.closestIndex = ClosestIndex( data, value, getValue ); result.secondIndex = SecondClosestIndex( data, result.closestIndex, value, getValue ); if ( result.closestIndex == result.secondIndex ) { return result; } var closestValue = getValue( data[ result.closestIndex ] ); var secondValue = getValue( data[ result.secondIndex ] ); var min = closestValue; var max = secondValue; var flip = false; if ( closestValue > secondValue ) { flip = true; min = secondValue; max = closestValue; } result.lerpAmount = MathX.Normalize( value, min, max ); if ( flip ) { result.lerpAmount = 1f - result.lerpAmount; } return result; } public static T GetWithHighestValue( List data, Func getValue ) { var index = IndexOfHighestValue( data, getValue ); return index == -1 ? default(T) : data[ index ] ; } public static T GetWithLowestValue( List data, Func getValue ) { var index = IndexOfLowestValue( data, getValue ); return index == -1 ? default(T) : data[ index ] ; } public static int IndexOfHighestValue( List data, Func getValue ) { var index = -1; var compareValue = -float.MaxValue; for ( int i = 0; i < data.Count; i++ ) { var value = getValue( data[ i ] ); if ( value > compareValue ) { index = i; compareValue = value; } } return index; } public static int IndexOfLowestValue( List data, Func getValue ) { var index = -1; var compareValue = float.MaxValue; for ( int i = 0; i < data.Count; i++ ) { var value = getValue( data[ i ] ); if ( value < compareValue ) { index = i; compareValue = value; } } return index; } public static int SecondClosestIndex( List data, int closest, float compareValue, Func getValue, bool sort = false ) { if ( sort ) { Sort( data, getValue ); } if ( data.Count == 1 ) { return 0; } if ( closest == 0 ) { return closest + 1; } if ( closest == data.Count - 1 ) { return data.Count - 2; } var before = data[ closest - 1 ]; var after = data[ closest + 1 ]; var bD = Mathf.Abs( getValue( before ) - compareValue ); var aD = Mathf.Abs( getValue( after ) - compareValue ); if ( bD < aD ) { return closest - 1 ; } return closest + 1; } public static int ClosestIndex( List data, float compareValue, Func getValue ) { var index = -1; var distance = float.MaxValue; for ( int i = 0 ; i < data.Count; i++ ) { var d = Mathf.Abs( getValue( data[ i ] ) - compareValue ); if ( d < distance ) { index = i; distance = d; } } return index; } public static List CollectIndices( List list, Func evaluator ) { var output = new List(); for ( int i = 0; i < list.Count; i++ ) { if ( evaluator( list[ i ] ) ) { output.Add( i ); } } return output; } public static List CombineAll( params List[] lists ) { var list = new List(); foreach ( var l in lists ) { list.AddRange( l ); } return list; } public static List From( params T[] elements ) { return ToList( elements ); } public static List SubList( T[] elements, int offset, int length ) { var list = new List(); for ( int i = 0; i < length; i++ ) { list.Add( elements[ i + offset ] ); } return list; } public static int Size( List list ) { return list == null ? 0 : list.Count; } public static List Sub( this List elements, int start, int length = 0 ) { var end = length == 0 ? elements.Count : ( start + length ); var list = new List( end - start ); for ( int i = start; i < end; i++ ) { list.Add( elements[ i ] ); } return list; } public static void ShuffleMultiple( this List list, int numShuffles, int step = 2 ) { for ( int i = 0; i < numShuffles; i++ ) { list.Shuffle( step ); } } public static ListView View( this List list, int start = 0, int length = 0 ) { return new ListView( list, start, length == 0 ? ( list.Count - start ) : length); } public static void Shuffle( this List list, int step = 2 ) { var listStart = new List(); var listEnd = new List(); for ( int i = 0; i < list.Count; i++ ) { if ( i % step == 0 ) { listStart.Add( list[ i ] ); } else { listEnd.Add( list[ i ] ); } } list.Clear(); list.Add( listStart ).Add( listEnd ); } public static List Add( this List list, List other ) { list.AddRange( other ); return list; } public static List ToList( T[] array ) { var list = new List(); list.AddRange( array ); return list; } public static bool Has( List list, T item ) { return list.IndexOf( item ) != - 1; } public static T RemoveAt( List list, int index ) { if ( list.Count == 0 || index < 0 || ( index > ( list.Count - 1 ) ) ) { return default(T); } var first = list[ index ]; list.RemoveAt( index ); return first; } public static T RemoveFirst( List list ) { return RemoveAt( list, 0 ); } public static T RemoveLast( List list ) { return RemoveAt( list, list.Count - 1 ); } public static T PopLast( List list ) { if ( list.Count == 0 ){ return default(T); } var element = list[ list.Count - 1 ]; list.RemoveAt( list.Count - 1 ); return element; } public static T Pop( this List list ) { return PopLast( list ); } public static T Shift( this List list ) { if ( list.Count == 0 ){ return default(T); } var element = list[ 0 ]; list.RemoveAt( 0 ); return element; } public static List Create( int size, Func initializer ) { var list = new List(); for ( int i = 0; i < size; i++ ) { list.Add( initializer( i ) ); } return list; } public static T GetLast( List list ) { return list.Count == 0 ? default(T) : list[ list.Count - 1 ]; } public static T Last( this List list ) { return GetLast( list ); } public static void RemoveIncreasingSortedIndices( List list, List increasinglySortedRemovals ) { for ( var i = increasinglySortedRemovals.Count - 1; i >= 0; i-- ) { var index = increasinglySortedRemovals[ i ]; list.RemoveAt( index ); } } public static void RemoveRange( List list, List removals ) { var removalSet = new HashSet(); removalSet.UnionWith( removals ); list.RemoveAll( e => removalSet.Contains( e ) ); } public static int CountItems( List list, Predicate test ) { var result = 0; for ( int i = 0; i < list.Count; i++ ) { if ( test( list[ i ] ) ) { result++; } } return result; } public static int CountItems( T[] list, Predicate test ) { var result = 0; for ( int i = 0; i < list.Length; i++ ) { if ( test( list[ i ] ) ) { result++; } } return result; } public static List FromEnumerable( IEnumerable enumerable ) { var listA = new List(); foreach ( var it in enumerable ) { listA.Add( (T) it ); } return listA; } public static bool AreListsAndEntriesEqual( object objA, object objB ) { if ( ! ( ReflectionHelper.IsList( objA ) && ReflectionHelper.IsList( objB ) ) ) { return false; } return AreEntriesEqual( FromEnumerable( objA as IEnumerable ), FromEnumerable( objB as IEnumerable ) ); } public static bool AreEntriesEqual( List a, List b ) { if ( a.Count != b.Count ) { return false; } for ( int i = 0; i < a.Count; i++ ) { var isEqual = EqualityComparer.Default.Equals( a[ i ], b[ i ]); if ( ! isEqual ) { return false; } } return true; } /*public static string Join( this List list, string seperator = "," ) { var sb = new StringBuilder(); }*/ public static string Join( this List array, string seperator = ", " ) { var sb = new StringBuilder(); for ( var i = 0; i < array.Count; i++ ) { if ( i != 0 ) { sb.Append( seperator ); } var obj = (object) array[ i ]; RJLog.Stringify( array[ i ], sb ); } return sb.ToString(); } public static string Join( List array, string seperator = ", " ) { var sb = new StringBuilder(); for ( var i = 0; i < array.Count; i++ ) { if ( i != 0 ) { sb.Append( seperator ); } sb.Append( RegexUtility.NumberToString( array[ i ] ) ); } return sb.ToString(); } public static List From( List list ) { var copy = new List(); copy.AddRange( list ); return copy; } public static List From<[Godot.MustBeVariant] T>( Godot.Collections.Array list ) { var copy = new List(); copy.AddRange( list ); return copy; } public static bool Has( this List list, Func evaluater ) { foreach ( var t in list ) { if ( evaluater( t ) ) { return true; } } return false; } public static void SwapTowardsBegin( this List list, int index, int steps = 1 ) { list.Swap( index, index - steps ); } public static void SwapTowardsEnd( this List list, int index, int steps = 1 ) { list.Swap( index, index + steps ); } public static void Swap( this List list, int indexA, int indexB ) { if ( list == null || indexA == indexB || indexA < 0 || indexB < 0 || indexA >= list.Count || indexA >= list.Count ) { return; } var buffer = list[ indexA ]; list[ indexA ] = list[ indexB ]; list[ indexB ] = buffer; } public static List FilterAndMap( List list, Func filter, Func map) { var mapped = new List(); for ( int i = 0; i < list.Count; i++ ) { if ( ! filter( list[ i ], i ) ) { continue; } mapped.Add( map( list[ i ] ) ); } return mapped; } public static void Filter( List inputList, List list, Func filter ) { for ( int i = 0; i < inputList.Count; i++ ) { if ( filter( inputList[ i ], i ) ) { list.Add( inputList[ i ] ); } } } public static List Filter( this List list, Func filter ) { var filteredList = new List(); Filter( list, filteredList, filter ); return filteredList; } public static List Filter( this List list, Func filter ) { var filteredList = new List(); Filter( list, filteredList, filter ); return filteredList; } public static List FilterNulls( this List list ) { return Filter( list, e => e != null ); } public static void Filter( List inputList, List list, Func filter ) { for ( int i = 0; i < inputList.Count; i++ ) { if ( filter( inputList[ i ] ) ) { list.Add( inputList[ i ] ); } } } public static List FilterWith( List inputList, Func filter ) { var list = new List(); for ( int i = 0; i < inputList.Count; i++ ) { if ( filter( inputList[ i ] ) ) { list.Add( inputList[ i ] ); } } return list; } public static List FilterType( this List inputList ) where R:T { var list = new List(); inputList.ForEach ( e => { if ( e == null || ! typeof( R ).IsAssignableFrom( e.GetType() ) ) { return; } list.Add( (R) e ); } ); return list; } public static void Add( this List list, params T[] entries ) { list.AddRange( entries ); } public static List Concat( this List list, params T[] entries ) { list.AddRange( entries ); return list; } public static void Insert( List list, T item, int index ) { if ( index >= list.Count ) { list.Add( item ); return; } index = index < 0 ? 0 : index; list.Insert( index, item ); } public static T Find( List list, Func callback ) { for ( int i = 0; i < list.Count; i++ ) { if ( callback( list[ i ] ) ) { return list[ i ]; } } return default( T ); } public static List Map( this List list, Func mapper ) { return Map( list, mapper, new List() ); } public static List Map( this List list, Func mapper ) { return Map( list, mapper, new List() ); } public static List Map( List inputList, Func mapper, List list = null ) { if ( list == null ) { list = new List(); } for ( int i = 0; i < inputList.Count; i++ ) { list.Add( mapper( inputList[ i ], i ) ); } return list; } public static List Map( T[] inputList, Func mapper, List list = null ) { if ( list == null ) { list = new List(); } for ( int i = 0; i < inputList.Length; i++ ) { list.Add( mapper( inputList[ i ], i ) ); } return list; } public static List Map( List inputList, Func mapper, List list = null ) { if ( list == null ) { list = new List(); } for ( int i = 0; i < inputList.Count; i++ ) { list.Add( mapper( inputList[ i ] ) ); } return list; } public static List Map<[Godot.MustBeVariant]T,U>( Godot.Collections.Array inputList, Func mapper, List list = null ) { if ( list == null ) { list = new List(); } for ( int i = 0; i < inputList.Count; i++ ) { list.Add( mapper( inputList[ i ] ) ); } return list; } public static List Map( T[] inputList, Func mapper, List list = null ) { if ( list == null ) { list = new List(); } for ( int i = 0; i < inputList.Length; i++ ) { list.Add( mapper( inputList[ i ] ) ); } return list; } } }