class/RandomSeed.js

/**
 * @description 带缓存的随机数种子。
 * @example
 * const seed = new RandomSeed(5, 10, [6])
 * seed.do()
 * // 5 or 7 or 8 or 9 or 10
 */

export class RandomSeed {
    /**
     * @param {Number} lower - 下限(包含)。
     * @param {Number} upper - 上限(包含)。
     * @param {Array} initCache - 初始缓存数组。
     * @param {Boolean} loop - 如果是,当缓存满时,清空缓存。默认 true。
    */

    constructor (lower, upper, initCache, loop = true) {
        if (upper < lower) {
            throw new Error('params error')
        }
        this.lower = lower
        this.upper = upper
        this.loop = loop
        // 在随机范围内 数的个数
        this.length = this.upper - this.lower + 1
        this.setCache(initCache || [])
    }
    setCache (cache) {
        this.initCache = cache
        this.cache = cache.concat()
        // 缓存中界限外的数个数
        this.outBoundsNum = this.initCache.reduce((total, val) => {
            if (val < this.lower || val > this.upper) {
                return total + 1
            }
            return total
        }, 0)
        // cache 能放入的元素个数是
        // cache 的长度加 cache中 超出界限的数的个数
        this.cacheLimitLength = this.length + this.outBoundsNum
    }
    do () {
        if (!this.loop && this.cache.length === this.cacheLimitLength) {
            return
        }

        if (this.upper - this.lower === 0) {
            return this.lower
        }

        const random = Math.floor(Math.random() * this.length + this.lower)

        if (this.cache.length === this.cacheLimitLength) {
            const lastValue = this.cache[this.cache.length - 1]

            if (random === lastValue) {
                return this.do()
            }
            this.cache = this.initCache.concat() || []
        }

        if (this.cache.some(number => number === random)) {
            return this.do()
        }
        this.cache.push(random)
        return random
    }
}