From 468867ba3df52b695479697594f64ffa50b5581f Mon Sep 17 00:00:00 2001
From: Cj <161484149+CJ-SPT@users.noreply.github.com>
Date: Mon, 6 Jan 2025 06:09:12 -0500
Subject: [PATCH] Start porting RandomUtil.cs, not yet done.
---
Core/Utils/RandomUtil.cs | 169 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 168 insertions(+), 1 deletion(-)
diff --git a/Core/Utils/RandomUtil.cs b/Core/Utils/RandomUtil.cs
index ded07f39..dd8c41e4 100644
--- a/Core/Utils/RandomUtil.cs
+++ b/Core/Utils/RandomUtil.cs
@@ -1,6 +1,173 @@
-namespace Core.Utils;
+using System.Security.Cryptography;
+using Core.Annotations;
+namespace Core.Utils;
+
+// TODO: Finish porting this class
+[Injectable(InjectionType.Singleton)]
public class RandomUtil
{
+ private readonly Random _random = new();
+ ///
+ /// Generates a random integer between the specified minimum and maximum values, inclusive.
+ ///
+ /// The minimum value (inclusive).
+ /// The maximum value (inclusive).
+ /// A random integer between the specified minimum and maximum values.
+ public int GetInt(int min, int max)
+ {
+ // Prevents a potential integer overflow.
+ if (max == int.MaxValue)
+ {
+ max -= 1;
+ }
+
+ // maxVal is exclusive of the passed value, so add 1
+ return max > min ? _random.Next(min, max + 1) : min;
+ }
+
+ ///
+ /// Generates a random integer between 1 (inclusive) and the specified maximum value (exclusive).
+ /// If the maximum value is less than or equal to 1, it returns 1.
+ ///
+ /// The upper bound (exclusive) for the random integer generation.
+ /// A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
+ public int GetIntEx(int max)
+ {
+ return max > 2 ? _random.Next(1, max - 1) : 1;
+ }
+
+ ///
+ /// Generates a random floating-point number within the specified range.
+ ///
+ /// The minimum value of the range (inclusive).
+ /// The maximum value of the range (exclusive).
+ /// A random floating-point number between `min` (inclusive) and `max` (exclusive).
+ public float GetFloat(float min, float max)
+ {
+ return (float)GetSecureRandomNumber() * (max - min) + min;
+ }
+
+ ///
+ /// Generates a random boolean value.
+ ///
+ /// A random boolean value, where the probability of `true` and `false` is approximately equal.
+ public bool GetBool()
+ {
+ return GetSecureRandomNumber() < 0.5;
+ }
+
+ ///
+ /// Calculates the percentage of a given number and returns the result.
+ ///
+ /// The percentage to calculate.
+ /// The number to calculate the percentage of.
+ /// The number of decimal places to round the result to (default is 2).
+ /// The calculated percentage of the given number, rounded to the specified number of decimal places.
+ public float GetPercentOfValue(float percent, float number, int toFixed = 2)
+ {
+ var num = percent * number / 100;
+
+ return (float)Math.Round(num, toFixed);
+ }
+
+ ///
+ /// Reduces a given number by a specified percentage.
+ ///
+ /// The original number to be reduced.
+ /// The percentage by which to reduce the number.
+ /// The reduced number after applying the percentage reduction.
+ public float ReduceValueByPercent(float number, float percentage)
+ {
+ var reductionAmount = number * percentage / 100;
+
+ return number - reductionAmount;
+ }
+
+ ///
+ /// Determines if a random event occurs based on the given chance percentage.
+ ///
+ /// The percentage chance (0-100) that the event will occur.
+ /// `true` if the event occurs, `false` otherwise.
+ public bool GetChance100(float chancePercent)
+ {
+ chancePercent = Math.Clamp(chancePercent, 0f, 100f);
+
+ return GetIntEx(100) <= chancePercent;
+ }
+
+ ///
+ /// Returns a random string from the provided collection of strings.
+ ///
+ /// This method is separate from GetCollectionValue so we can use a generic inference with GetCollectionValue.
+ ///
+ /// The collection of strings to select a random value from.
+ /// A randomly selected string from the array.
+ public string GetStringCollectionValue(IEnumerable collection)
+ {
+ return collection.ElementAt(GetInt(0, collection.Count() - 1));
+ }
+
+ ///
+ /// Returns a random string from the provided collection of strings.
+ ///
+ ///
+ /// The type of elements in the collection.
+ /// A random element from the collection.
+ /// This was formerly getArrayValue() in the node server
+ public T GetCollectionValue(IEnumerable collection)
+ {
+ return collection.ElementAt(GetInt(0, collection.Count() - 1));
+ }
+
+ ///
+ /// Gets a random key from the given dictionary
+ ///
+ /// The dictionary from which to retrieve a key.
+ /// Type of key
+ /// Type of Value
+ /// A random TKey representing one of the keys of the dictionary.
+ public TKey GetKey(Dictionary dictionary) where TKey : notnull
+ {
+ return GetCollectionValue(dictionary.Keys);
+ }
+
+ ///
+ /// Generates a secure random number between 0 (inclusive) and 1 (exclusive).
+ ///
+ /// This method uses the `crypto` module to generate a 48-bit random integer,
+ /// which is then divided by the maximum possible 48-bit integer value to
+ /// produce a floating-point number in the range [0, 1).
+ ///
+ /// A secure random number between 0 (inclusive) and 1 (exclusive).
+ private static double GetSecureRandomNumber()
+ {
+ var buffer = new byte[6];
+
+ using var rng = RandomNumberGenerator.Create();
+
+ // Fill buffer with random bytes
+ rng.GetBytes(buffer);
+
+ var integer = 0;
+ for (var i = 0; i < 6; i++)
+ {
+ integer = (integer << 8) | buffer[i];
+ }
+
+ const ulong maxInt = 1UL << 48;
+
+ return (double)integer / maxInt;
+ }
+
+ ///
+ /// Determines the number of decimal places in a number.
+ ///
+ /// The number to analyze.
+ /// The number of decimal places, or 0 if none exist.
+ private static int GetNumberPrecision(double num)
+ {
+ return num.ToString().Split('.')[1]?.Length ?? 0;
+ }
}
\ No newline at end of file