Example #1
0
        private WeightedItem <T> ChooseRandomWeightedItem()
        {
            int lookupWeight      = random.Next(1, totalWeight);
            int currentWeight     = 0;
            WeightedItem <T> item = null;

            foreach (WeightedItem <T> weightedItem in pool)
            {
                currentWeight += weightedItem.Weight;

                if (currentWeight >= lookupWeight)
                {
                    item = weightedItem;

                    break;
                }
            }

            if (item == null)
            {
                throw new InvalidOperationException("The random lookup was greater than the total weight");
            }

            return(item);
        }
Example #2
0
 private void Remove(WeightedItem <T> item)
 {
     if (item != null && pool.Remove(item))
     {
         totalWeight -= item.Weight;
     }
 }
Example #3
0
        /// <summary>
        /// Take an item at random from the pool, keeping weights into consideration.
        /// The item will be removed from the pool.
        /// </summary>
        /// <returns>An item of type T from the WeightedPool</returns>
        /// <exception cref="InvalidOperationException">Thrown when the pool is empty</exception>
        /// <exception cref="InvalidOperationException">Thrown when the random lookup is greater than the total weight. Could only happen if a bad implementation of IRandom were provided</exception>
        public T Draw()
        {
            if (Count <= 0 || totalWeight <= 0)
            {
                throw new InvalidOperationException("Add items to the pool before attempting to draw one");
            }

            WeightedItem <T> item = ChooseRandomWeightedItem();

            Remove(item);

            return(item.Item);
        }
Example #4
0
        /// <summary>
        /// Choose an item at random from the pool, keeping weights into consideration.
        /// The item itself will remain in the pool and a clone of the item selected will be returned.
        /// </summary>
        /// <returns>A clone of the item of type T from the WeightedPool</returns>
        /// <exception cref="InvalidOperationException">Thrown when a clone function was not defined when the pool was constructed</exception>
        /// <exception cref="InvalidOperationException">Thrown when the pool is empty</exception>
        /// <exception cref="InvalidOperationException">Thrown when the random lookup is greater than the total weight. Could only happen if a bad implementation of IRandom were provided</exception>
        public T Choose()
        {
            if (cloneFunc == null)
            {
                throw new InvalidOperationException("A clone function was not defined when this pool was constructed");
            }

            if (Count <= 0 || totalWeight <= 0)
            {
                throw new InvalidOperationException("Add items to the pool before attempting to choose one");
            }

            WeightedItem <T> item = ChooseRandomWeightedItem();

            return(cloneFunc(item.Item));
        }
Example #5
0
        /// <summary>
        /// Add an item of type T to the WeightedPool with the given weight
        /// </summary>
        /// <param name="item">The item to add to the WeightedPool</param>
        /// <param name="weight">
        /// The chance that the item will be picked at random from the pool when weighted against all other items.
        /// Higher weights mean it is more likely to be picked.
        /// </param>
        /// <exception cref="ArgumentNullException">Thrown when provided "item" argument is null</exception>
        /// <exception cref="ArgumentException">Thrown when provided "weight" argument is not greater than 0</exception>
        /// <exception cref="OverflowException">Thrown when adding the weight of the new item to the pool exceeds Int32.MaxValue</exception>
        public void Add(T item, int weight)
        {
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item), "Can not add null item to the pool");
            }

            if (weight <= 0)
            {
                throw new ArgumentException("Weight must be greater than 0", nameof(weight));
            }

            WeightedItem <T> weightedItem = new WeightedItem <T>(item, weight);

            pool.Add(weightedItem);

            if (int.MaxValue - weight < totalWeight)
            {
                throw new OverflowException("The weight of items in the pool would be over Int32.MaxValue");
            }

            totalWeight += weight;
        }