using System; using System.Linq; using System.Collections.Generic; namespace DiIiS_NA.Core.Helpers.Math; public static class RandomHelper { private static readonly Random Random = new(); public static int Next() { return Random.Next(); } public static int Next(int maxValue) { return Random.Next(maxValue); } public static int Next(int minValue, int maxValue) { return Random.Next(minValue, maxValue); } public static void NextBytes(byte[] buffer) { Random.NextBytes(buffer); } public static double NextDouble() { return Random.NextDouble(); } public static T RandomItem(IEnumerable source) { var collection = source as IReadOnlyCollection ?? source?.ToArray(); if (collection == null || collection.Count == 0) { throw new ArgumentException("Cannot be null or empty", nameof(source)); } var randomIndex = Next(collection.Count); return collection.ElementAt(randomIndex); } public static bool TryGetRandomItem(IEnumerable source, out T randomItem) { var collection = source as IReadOnlyCollection ?? source?.ToArray(); if (collection == null) { throw new ArgumentException("Cannot be null", nameof(source)); } if (collection.Count == 0) { randomItem = default; return false; } var randomIndex = Next(collection.Count); randomItem = collection.ElementAt(randomIndex); return true; } /// /// Picks a random item from a list /// /// /// /// A function that assigns each item a probability. If the probabilities dont sum up to 1, they are normalized /// public static T RandomItem(IEnumerable source, Func probability) { var collection = source as IReadOnlyCollection ?? source.ToArray(); int cumulative = (int)collection.Select(probability).Sum(); int randomRoll = Next(cumulative); float cumulativePercentages = 0; foreach (T element in collection) { cumulativePercentages += probability(element); if (cumulativePercentages > randomRoll) return element; } return collection.First(); } } public class ItemRandomHelper { uint _a; uint _b; public ItemRandomHelper(int seed) { _a = (uint)seed; _b = 666; } public void ReinitSeed() { _b = 666; } public uint Next() { ulong temp = 1791398085UL * _a + _b; _a = (uint)temp; _b = (uint)(temp >> 32); return _a; } public float Next(float min, float max) { return min + (Next() % (uint)(max - min + 1)); } }