using System;
using System.Collections.Generic;
using System.Numerics;
using Unity.VisualScripting;
public static class CustomExtension
{
///
/// insert value to list and sort.
///
static public void OrderInsert(this IList arr, T value, Func comparison)
{
arr.Add(value);
for (int i = arr.Count - 1; i > 0; --i)
{
if (comparison(arr[i - 1], arr[i]) > 0)
{
T tmp = arr[i];
arr[i] = arr[i - 1];
arr[i - 1] = tmp;
}
else
{
break;
}
}
}
///
/// sort list.
///
static public void InsertionSort(this IList arr, Func comparison)
{
for (int i = 1; i < arr.Count; ++i)
{
for (int j = i; j > 0; --j)
{
if (comparison(arr[j - 1], arr[j]) > 0)
{
T tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
}
else
{
break;
}
}
}
}
///
/// sort list.
///
static public void InsertionSort(this IList arr, Func comparison)
{
InsertionSort(arr, (a, b) => comparison(a, b) ? 1 : -1);
}
///
/// insert value to dictionary, if key is exist, replace value.
///
static public void SafeInsert(this IDictionary dic, TKey key, TValue value)
{
if (dic.ContainsKey(key)) dic[key] = value;
else dic.Add(key, value);
}
///
/// insert value to dictionary, if key is exist, replace value.
///
static public void SafeInsert(this IDictionary dic, KeyValuePair kvPair)
{
SafeInsert(dic, kvPair.Key, kvPair.Value);
}
///
/// get value from dictionary, if key is not exist, return default value.
///
static public TValue SafeGet(this IDictionary dic, TKey key)
{
if (dic.ContainsKey(key)) return dic[key];
else return default;
}
static public bool TryGetRandomValue(this IDictionary dic, out TValue result)
{
result = default;
int rnd = UnityEngine.Random.Range(0, dic.Count);
foreach (var kv in dic)
{
if (rnd-- == 0)
{
result = kv.Value;
return true;
}
}
return false;
}
///
/// get value from list, if index less than 0, return first value. if index greater than list count, return last value.
///
static public TValue ClampGet(this IList list, int index)
{
if(list.Count == 0)
throw new Exception("list is empty");
if(index < 0) return list[0];
else if (index >= list.Count) return list[list.Count - 1];
else return list[index];
}
///
/// try get value from list, if index is not valid, return false.
///
static public bool TryGetValueAt(this IList list, int index, out TValue result)
{
if(index >= 0 && index < list.Count)
{
result = list[index];
return true;
}
else
{
result = default;
return false;
}
}
static public bool TryFind(this IList list, Predicate match, out TValue result)
{
foreach(var item in list)
{
if(match(item))
{
result = item;
return true;
}
}
result = default;
return false;
}
static public bool TryBinarySearch(this IList list, TValue value, Comparison comparison, out int index) => TryBinarySearch(list, (v) => comparison(v, value), out index);
static public bool TryBinarySearch(this IList list, Func comparison, out int index)
{
int low = 0;
int high = list.Count - 1;
index = -1;
while (low <= high)
{
int mid = (low + high) / 2;
int cmp = comparison(list[mid]);
if (cmp == 0)
{
index = mid;
break;
}
else if (cmp < 0)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
return index != -1;
}
///
/// try get random value from list, if list is empty, return false.
///
static public bool TryGetRandomValue(this IList list, out TValue result)
{
if(list.Count == 0)
{
result = default;
return false;
}
result = list[UnityEngine.Random.Range(0, list.Count)];
return true;
}
///
/// set elements with given range to value.
///
static public void SetElements(this IList list, TValue value, int offset, int count)
{
for(int i = offset; i < offset + count; ++i)
{
if(i < 0 || i >= list.Count) continue;
list[i] = value;
}
}
///
/// set all elements to value.
///
static public void SetElements(this IList list, TValue value)
{
SetElements(list, value, 0, list.Count);
}
///
/// swapping elements with predict
///
static public int SwapElements(this IList list, Func predict)
{
const int needSetFlag = 0;
const int trueFlag = 1;
const int falseFlag = 2;
int ret = -1;
int[] flags = new int[list.Count];
for(int i = 0; i < list.Count; ++i)
{
if (flags[i] == needSetFlag) flags[i] = predict(list[i]) ? trueFlag : falseFlag;
if (flags[i] == trueFlag) continue;
int j;
for(j = i + 1; j < list.Count; ++j)
{
if (flags[j] == needSetFlag) flags[j] = predict(list[j]) ? trueFlag : falseFlag;
if (flags[j] == falseFlag) continue;
TValue tmp = list[i];
list[i] = list[j];
list[j] = tmp;
flags[i] = trueFlag;
flags[j] = falseFlag;
break;
}
ret = i;
if(j == list.Count) break;
}
return ret;
}
static public void Shuffle(this IList list)
{
int n = list.Count;
while (n > 1)
{
n--;
int rndIdx = UnityEngine.Random.Range(0, n + 1);
TValue tmp = list[rndIdx];
list[rndIdx] = list[n];
list[n] = tmp;
}
}
public static bool EqualsUpToSeconds(this DateTime dt1, DateTime dt2)
{
return dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day &&
dt1.Hour == dt2.Hour && dt1.Minute == dt2.Minute && dt1.Second == dt2.Second;
}
public static BigInteger Multiply(this BigInteger a, float b)
{
return (a * (BigInteger)(b * 1000)) / 1000;
}
public static BigInteger Divide(this BigInteger a, float b)
{
return (a * 1000) / (BigInteger)(b * 1000);
}
}