diff --git a/MiraAPI/Modifiers/ModifierManager.cs b/MiraAPI/Modifiers/ModifierManager.cs index 6aed1ac..f34d11f 100644 --- a/MiraAPI/Modifiers/ModifierManager.cs +++ b/MiraAPI/Modifiers/ModifierManager.cs @@ -5,6 +5,7 @@ using System.Runtime.Serialization; using MiraAPI.Modifiers.Types; using MiraAPI.PluginLoading; using MiraAPI.Roles; +using MiraAPI.Utilities; using Reactor.Utilities; using Reactor.Utilities.Extensions; using Random = System.Random; @@ -125,6 +126,7 @@ public static class ModifierManager .Select(x => Activator.CreateInstance(x.Value) as GameModifier) .OfType() .Where(x => x.GetAmountPerGame() > 0 && x.GetAssignmentChance() > 0) + .Shuffle() .OrderByDescending(x => x.Priority()) .ToArray(); diff --git a/MiraAPI/Utilities/EnumerableExtensions.cs b/MiraAPI/Utilities/EnumerableExtensions.cs new file mode 100644 index 0000000..5e0bc35 --- /dev/null +++ b/MiraAPI/Utilities/EnumerableExtensions.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MiraAPI.Utilities; + +/// +/// Extensions for IEnumerable. +/// +public static class EnumerableExtensions +{ + /// + /// Shuffle the elements of the source enumerable using a new instance of Random. + /// + /// The source enumerable. + /// The type of the elements. + /// >The shuffled enumerable. + public static IEnumerable Shuffle(this IEnumerable source) + { + return source.Shuffle(new Random()); + } + + /// + /// Shuffle the elements of the source enumerable using the provided Random instance. + /// + /// The source enumerable. + /// The Random instance to use for shuffling. + /// The type of the elements. + /// >The shuffled enumerable. + public static IEnumerable Shuffle(this IEnumerable source, Random rng) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(rng); + + return source.ShuffleIterator(rng); + } + + private static IEnumerable ShuffleIterator(this IEnumerable source, Random rng) + { + var buffer = source.ToList(); + for (var i = 0; i < buffer.Count; i++) + { + var j = rng.Next(i, buffer.Count); + yield return buffer[j]; + + buffer[j] = buffer[i]; + } + } +}