mirror of
https://github.com/Dadechin/Unity-WebSocket.git
synced 2025-07-04 12:24:34 +00:00
96 lines
3.4 KiB
C#
96 lines
3.4 KiB
C#
using GameKit.Dependencies.Utilities.Types;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace GameKit.Dependencies.Utilities
|
|
{
|
|
public interface IWeighted
|
|
{
|
|
float GetWeight();
|
|
ByteRange GetQuantity();
|
|
}
|
|
|
|
public static class WeightedRandom
|
|
{
|
|
/// <summary>
|
|
/// Gets random entries by weight.
|
|
/// </summary>
|
|
/// <param name="source">Entries to pull from.</param>
|
|
/// <param name="countRange">Number of entries to get.</param>
|
|
/// <param name="results">Results of entries. Key is the entry, Value is the number of drops.</param>
|
|
/// <param name="allowRepeatingDrops">True to allow the same entry to be included within results more than once.</param>
|
|
public static void GetEntries<T>(List<T> source, IntRange countRange, ref Dictionary<T, uint> results, bool allowRepeatingDrops = false) where T : IWeighted
|
|
{
|
|
if (source == null || source.Count == 0)
|
|
{
|
|
Debug.Log($"Source list of type {typeof(T).Name} cannot be null or empty.");
|
|
return;
|
|
}
|
|
|
|
int count = Ints.RandomInclusiveRange(countRange.Minimum, countRange.Maximum);
|
|
//If to not return any then exit early.
|
|
if (count == 0)
|
|
return;
|
|
|
|
//Number of times each item has dropped.
|
|
Dictionary<T, byte> dropCount = CollectionCaches<T, byte>.RetrieveDictionary();
|
|
|
|
//Get the total weight.
|
|
float totalWeight = 0f;
|
|
for (int i = 0; i < source.Count; i++)
|
|
totalWeight += source[i].GetWeight();
|
|
|
|
//Make a copy of source to not modify source.
|
|
List<T> sourceCopy = CollectionCaches<T>.RetrieveList();
|
|
foreach (T item in source)
|
|
sourceCopy.Add(item);
|
|
|
|
while (results.Count < count)
|
|
{
|
|
int startCount = results.Count;
|
|
/* Reset copy to totalWeight.
|
|
* totalWeight will be modified if
|
|
* a non-repeatable item is pulled. */
|
|
float tWeightCopy = totalWeight;
|
|
float rnd = UnityEngine.Random.Range(0f, totalWeight);
|
|
|
|
for (int i = 0; i < sourceCopy.Count; i++)
|
|
{
|
|
T item = sourceCopy[i];
|
|
float weight = item.GetWeight();
|
|
|
|
if (rnd <= weight)
|
|
{
|
|
//Try to get current count.
|
|
results.TryGetValueIL2CPP(item, out uint currentCount);
|
|
//Set new vlaue.
|
|
results[item] = (currentCount + 1);
|
|
/* If cannot stay in collection then remove it
|
|
* from copy and remove its weight
|
|
* from total. */
|
|
if (!allowRepeatingDrops)
|
|
{
|
|
sourceCopy.RemoveAt(i);
|
|
totalWeight -= weight;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
tWeightCopy -= weight;
|
|
}
|
|
}
|
|
|
|
/* If nothing was added to results then
|
|
* something went wrong. */
|
|
if (results.Count == startCount)
|
|
break;
|
|
}
|
|
|
|
CollectionCaches<T, byte>.Store(dropCount);
|
|
|
|
}
|
|
}
|
|
|
|
}
|