예제 #1
0
 private void Remove(WeightedItem <T> item)
 {
     if (item != null && _pool.Remove(item))
     {
         _totalWeight -= item.Weight;
     }
 }
예제 #2
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);
        }
예제 #3
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));
        }
예제 #4
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;
        }
예제 #5
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);
        }