using System;
namespace Games.Common.Randomness;
///
/// Provides extension methods to providing random numbers in a given range.
///
///
public static class IRandomExtensions
{
///
/// Gets a random such that 0 <= n < exclusiveMaximum.
///
/// The random number.
public static float NextFloat(this IRandom random, float exclusiveMaximum) =>
Scale(random.NextFloat(), exclusiveMaximum);
///
/// Gets a random such that inclusiveMinimum <= n < exclusiveMaximum.
///
/// The random number.
public static float NextFloat(this IRandom random, float inclusiveMinimum, float exclusiveMaximum) =>
Scale(random.NextFloat(), inclusiveMinimum, exclusiveMaximum);
///
/// Gets a random such that 0 <= n < exclusiveMaximum.
///
/// The random number.
public static int Next(this IRandom random, int exclusiveMaximum) => ToInt(random.NextFloat(exclusiveMaximum));
///
/// Gets a random such that inclusiveMinimum <= n < exclusiveMaximum.
///
/// The random number.
public static int Next(this IRandom random, int inclusiveMinimum, int exclusiveMaximum) =>
ToInt(random.NextFloat(inclusiveMinimum, exclusiveMaximum));
///
/// Gets the previous unscaled (between 0 and 1) scaled to a new range:
/// 0 <= x < .
///
/// The random number.
public static float PreviousFloat(this IRandom random, float exclusiveMaximum) =>
Scale(random.PreviousFloat(), exclusiveMaximum);
///
/// Gets the previous unscaled (between 0 and 1) scaled to a new range:
/// <= n < .
///
/// The random number.
public static float PreviousFloat(this IRandom random, float inclusiveMinimum, float exclusiveMaximum) =>
Scale(random.PreviousFloat(), inclusiveMinimum, exclusiveMaximum);
///
/// Gets the previous unscaled (between 0 and 1) scaled to an in a new
/// range: 0 <= n < .
///
/// The random number.
public static int Previous(this IRandom random, int exclusiveMaximum) =>
ToInt(random.PreviousFloat(exclusiveMaximum));
///
/// Gets the previous unscaled (between 0 and 1) scaled to an in a new
/// range: <= n < .
/// The random number.
public static int Previous(this IRandom random, int inclusiveMinimum, int exclusiveMaximum) =>
ToInt(random.PreviousFloat(inclusiveMinimum, exclusiveMaximum));
private static float Scale(float zeroToOne, float exclusiveMaximum)
{
if (exclusiveMaximum <= 0)
{
throw new ArgumentOutOfRangeException(nameof(exclusiveMaximum), "Must be greater than 0.");
}
return Scale(zeroToOne, 0, exclusiveMaximum);
}
private static float Scale(float zeroToOne, float inclusiveMinimum, float exclusiveMaximum)
{
if (exclusiveMaximum <= inclusiveMinimum)
{
throw new ArgumentOutOfRangeException(nameof(exclusiveMaximum), "Must be greater than inclusiveMinimum.");
}
var range = exclusiveMaximum - inclusiveMinimum;
return zeroToOne * range + inclusiveMinimum;
}
private static int ToInt(float value) => (int)Math.Floor(value);
}