init
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RPGCoreCommon.Helpers.Exceptions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RPGCoreCommon.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// This utility class basses on Unity's <see cref="UnityEngine.Random"/> which uses:
|
||||
/// <ul>
|
||||
/// <li><see cref="UnityEngine.Random.InitState"/> to manage seed</li>
|
||||
/// <li><see cref="UnityEngine.Random.value"/> to get random value</li>
|
||||
/// </ul>
|
||||
/// </summary>
|
||||
public static class RandomHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="UnityEngine.Random.InitState"/>
|
||||
/// Alias to Unity's <see cref="UnityEngine.Random.InitState"/>.
|
||||
/// </summary>
|
||||
/// <param name="seed"><inheritdoc cref="UnityEngine.Random.InitState" path="/param[@name='seed']"/></param>
|
||||
public static void InitState(int seed)
|
||||
{
|
||||
UnityEngine.Random.InitState(seed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <b>float</b> between min (inclusive) and max (inclusive).
|
||||
/// </summary>
|
||||
public static float RandomFloat(float min = 0f, float max = 1f)
|
||||
{
|
||||
return UnityEngine.Random.value * (max-min) + min;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns integer between minimum (inclusive) and maximum (inclusive).
|
||||
/// </summary>
|
||||
public static int RandomInt(int minInclusive = 0, int maxInclusive = 100)
|
||||
{
|
||||
return Mathf.RoundToInt(UnityEngine.Random.value * (maxInclusive-minInclusive)) + minInclusive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns random key from given list.
|
||||
/// </summary>
|
||||
public static int RandomKey<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
var list = enumerable.ToList();
|
||||
if (!list.Any()) throw new NotEnoughElementsForRandomPickException("List need at least one element.");
|
||||
|
||||
return RandomInt(0, list.Count - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns random element from given list.
|
||||
/// </summary>
|
||||
public static T RandomElement<T>(IEnumerable<T> enumerable)
|
||||
{
|
||||
return RandomElements(enumerable, 1).First();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns new list with randomized elements.<br/>
|
||||
/// List needs to have at least equal or more elements that given count! If repeatable then list needs to have at least 1 element.<br/>
|
||||
/// </summary>
|
||||
/// <exception cref="NotEnoughElementsForRandomPickException">When given list does not have enough elements to choose from.</exception>
|
||||
public static List<T> RandomElements<T>(IEnumerable<T> enumerable, int count, bool repeatable = true)
|
||||
{
|
||||
var list = enumerable.ToList();
|
||||
var neededCount = repeatable ? 1 : list.Count;
|
||||
if (list.Count < neededCount) throw new NotEnoughElementsForRandomPickException($"Not enough elements in list. Need={neededCount}, Provided={list.Count}");
|
||||
|
||||
if (!repeatable) return list.OrderBy(_ => RandomFloat()).Take(count).ToList();
|
||||
|
||||
return new T[count].Select(_ => list[RandomInt(0, list.Count - 1)]).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns keys from given list by its weight.
|
||||
/// </summary>
|
||||
/// <exception cref="NotEnoughElementsForRandomPickException">When given list does not have any elements to choose from.</exception>
|
||||
public static int RandomKeyByWeight<T>(IEnumerable<T> enumerable, Func<T, float> weightGetter)
|
||||
{
|
||||
var list = enumerable.ToList();
|
||||
if (!list.Any()) throw new NotEnoughElementsForRandomPickException("List need at least one element.");
|
||||
var maxWeight = list.Sum(weightGetter.Invoke);
|
||||
var randomWeight = RandomFloat(0, maxWeight);
|
||||
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
randomWeight -= weightGetter.Invoke(list[i]);
|
||||
if (randomWeight <= 0) return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns element from given list by its weight.
|
||||
/// </summary>
|
||||
/// <exception cref="NotEnoughElementsForRandomPickException">When given list does not have any elements to choose from.</exception>
|
||||
public static T RandomElementByWeight<T>(IEnumerable<T> enumerable, Func<T, float> weightGetter)
|
||||
{
|
||||
return RandomElementsByWeight(enumerable, weightGetter, 1).First();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns elements from given list by its weight.
|
||||
/// </summary>
|
||||
/// <exception cref="NotEnoughElementsForRandomPickException">When given list does not have enough elements to choose from.</exception>
|
||||
public static List<T> RandomElementsByWeight<T>(IEnumerable<T> enumerable, Func<T, float> weightGetter, int count, bool repeatable = true)
|
||||
{
|
||||
var list = enumerable.ToList();
|
||||
var listResult = new List<T>();
|
||||
var neededCount = repeatable ? 1 : list.Count;
|
||||
if (list.Count < neededCount) throw new NotEnoughElementsForRandomPickException($"Not enough elements in list. Need={neededCount}, Provided={list.Count}");
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var randomKey = RandomKeyByWeight(list, weightGetter);
|
||||
listResult.Add(list[randomKey]);
|
||||
if (!repeatable) list.RemoveAt(randomKey);
|
||||
}
|
||||
|
||||
return listResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Percentage chance by given float. Simply checks if random float is smaller than given one.
|
||||
/// </summary>
|
||||
/// <param name="chance">Chance to get true. <b>0.0f</b> = 0%, <b>1.0f</b> = 100%</param>
|
||||
public static bool Chance(float chance)
|
||||
{
|
||||
return RandomFloat() < Mathf.Clamp01(chance);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user