Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using VoidwalkerEngine.Framework.DataTypes;
- using VoidwalkerEngine.Framework.Utilities;
- namespace VoidwalkerEngine.Framework.Collections
- {
- public class Roulette<T>
- {
- private Dictionary<T, Probability> _items;
- private List<KeyValuePair<T, Probability>> _sortedItems;
- private VoidwalkerRandom _random;
- private bool _isRebuildNeeded;
- public double TotalFitness { get; private set; }
- public int Count
- {
- get
- {
- return _items.Count;
- }
- }
- public Roulette()
- {
- _random = new VoidwalkerRandom();
- _items = new Dictionary<T, Probability>();
- }
- public void Add(T item, int numerator, int denominator)
- {
- Add(item, new Probability(numerator, denominator));
- }
- public void Add(T item, Probability probability)
- {
- if (this._items.ContainsKey(item))
- {
- throw new Exception("Roulette Item already exists!");
- }
- this._items.Add(item, probability);
- this._isRebuildNeeded = true;
- }
- public bool IsEmpty
- {
- get
- {
- return this._items.Count == 0;
- }
- }
- public void Clear()
- {
- this._items.Clear();
- _isRebuildNeeded = true;
- }
- public void Remove(T obj)
- {
- if (this._items.ContainsKey(obj))
- {
- this._items.Remove(obj);
- _isRebuildNeeded = true;
- }
- }
- public T Next()
- {
- if (this._items.Count == 0)
- {
- throw new Exception("Roulette items cannot be null or empty!");
- }
- if (_isRebuildNeeded || this._sortedItems == null)
- {
- this.TotalFitness = 0;
- _sortedItems = new List<KeyValuePair<T, Probability>>();
- foreach (KeyValuePair<T, Probability> item in this._items)
- {
- _sortedItems.Add(item);
- TotalFitness += item.Value.ToPercentage();
- }
- _sortedItems.OrderBy(obj => obj.Value.ToPercentage() / this.TotalFitness).Reverse().ToList();
- _isRebuildNeeded = false;
- }
- double sample = _random.NextDouble();
- foreach (KeyValuePair<T, Probability> candidate in this._sortedItems)
- {
- double candidateSpawnChance = candidate.Value.ToPercentage();
- double fitness = candidateSpawnChance / this.TotalFitness;
- if (sample < fitness)
- {
- return candidate.Key;
- }
- sample -= fitness;
- }
- throw new Exception("This shouldn't be happening...");
- }
- public T[] Next(int count)
- {
- T[] results = new T[count];
- for (int i = 0; i < count; i++)
- {
- results[i] = Next();
- }
- return results;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement