/// <summary>
        /// Re/Builds internal CDL (Cummulative Distribution List)
        /// Must be called after modifying (calling Add or Remove), or it will break.
        /// Switches between linear or binary search, depending on which one will be faster.
        /// Might generate some garbage (list resize) on first few builds.
        /// </summary>
        /// <param name="seed">You can specify seed for internal random gen or leave it alone</param>
        /// <returns>Returns itself</returns>
        public IRandomSelector <T> Build(Int32 seed = -1)
        {
            if (_items.Count == 0)
            {
                throw new Exception("Cannot build with no items.");
            }

            // clear list and then transfer weights
            _cdl.Clear();
            foreach (Double weight in _weights)
            {
                _cdl.Add(weight);
            }

            RandomMath.BuildCumulativeDistribution(_cdl);

            // default behavior
            // if seed wasn't specified (it is seed==-1), keep same seed - avoids garbage collection from making new random
            if (seed != -1)
            {
                // input -2 if you want to randomize seed
                if (seed == -2)
                {
                    seed = _random.Next();
                }

                _random = RandomUtils.Create(seed);
            }

            // RandomMath.ListBreakpoint decides where to use Linear or Binary search, based on internal buffer size
            // if CDL list is smaller than breakpoint, then pick linear search random selector, else pick binary search selector
            if (_cdl.Count < RandomMath.ListBreakpoint)
            {
                _select = RandomMath.SelectIndexLinearSearch;
            }
            else
            {
                _select = RandomMath.SelectIndexBinarySearch;
            }

            return(this);
        }
Exemple #2
0
        /// <summary>
        /// Builds StaticRandomSelector & clears internal buffers. Must be called after you finish Add-ing items.
        /// </summary>
        /// <param name="seed">Seed for random selector. If you leave it -1, the internal random will generate one.</param>
        /// <returns>Returns IRandomSelector, underlying objects are either StaticRandomSelectorLinear or StaticRandomSelectorBinary. Both are non-mutable.</returns>
        public IRandomSelector <T> Build(Int32 seed = -1)
        {
            T[]      items = _items.ToArray();
            Double[] cda   = _weights.ToArray();

            _items.Clear();
            _weights.Clear();

            RandomMath.BuildCumulativeDistribution(cda);

            if (seed == -1)
            {
                seed = _random.Next();
            }

            // RandomMath.ArrayBreakpoint decides where to use Linear or Binary search, based on internal buffer size
            // if CDA array is smaller than breakpoint, then pick linear search random selector, else pick binary search selector
            if (cda.Length < RandomMath.ArrayBreakpoint)
            {
                return(new StaticRandomSelectorLinear <T>(items, cda, seed));
            }

            return(new StaticRandomSelectorBinary <T>(items, cda, seed));
        }