{"version":3,"sources":["../src/UniqueRandomGenerator.ts"],"names":["UniqueRandomGenerator","bufferSize","min","max","bitSize","byteSize","randomBytes","randomNumber","i"],"mappings":"AAiBO,IAAMA,CAAAA,CAAN,KAA4B,CAA5B,WAAA,EAAA,CACL,IAAA,CAAQ,GAAA,CAAqB,IAAA,CAC7B,IAAA,CAAQ,GAAA,CAAqB,IAAA,CAC7B,IAAA,CAAQ,MAAA,CAAmB,GAC3B,IAAA,CAAQ,UAAA,CAAqB,CAAA,CAC7B,IAAA,CAAQ,aAAA,CAAyB,KAAA,CACjC,IAAA,CAAQ,KAAA,CAAgB,EAAA,CAaxB,aAAA,CAAcC,CAAAA,CAA0B,CACtC,OAAI,IAAA,CAAK,aAAeA,CAAAA,GACtB,IAAA,CAAK,UAAA,CAAaA,CAAAA,CAClB,IAAA,CAAK,aAAA,CAAgB,IAAA,CAAA,CAEhB,IACT,CAaA,MAAA,CAAOC,CAAAA,CAAmB,CACxB,OAAI,IAAA,CAAK,MAAQA,CAAAA,GACf,IAAA,CAAK,GAAA,CAAMA,CAAAA,CACX,IAAA,CAAK,WAAA,EAAY,CAAA,CAEZ,IACT,CAaA,MAAA,CAAOC,CAAAA,CAAmB,CACxB,OAAI,IAAA,CAAK,MAAQA,CAAAA,GACf,IAAA,CAAK,GAAA,CAAMA,CAAAA,CACX,IAAA,CAAK,WAAA,EAAY,CAAA,CAEZ,IACT,CAcA,SAAA,CAAUD,CAAAA,CAAaC,CAAAA,CAAmB,CACxC,OAAA,IAAA,CAAK,OAAOD,CAAG,CAAA,CACf,IAAA,CAAK,MAAA,CAAOC,CAAG,CAAA,CACR,IACT,CAOQ,WAAA,EAAoB,CACtB,IAAA,CAAK,GAAA,GAAQ,IAAA,EAAQ,IAAA,CAAK,MAAQ,IAAA,GACpC,IAAA,CAAK,KAAA,CAAQ,IAAA,CAAK,GAAA,CAAM,IAAA,CAAK,GAAA,CAAM,CAAA,CAC9B,IAAA,CAAK,aAAA,GACR,IAAA,CAAK,gBAAA,EAAiB,CACtB,IAAA,CAAK,aAAA,CAAgB,IAAA,CAAA,EAG3B,CAQQ,gBAAA,EAAyB,CAC/B,IAAA,CAAK,UAAA,CAAa,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAA,EAAO,EAAK,IAAA,CAAK,KAAA,CAAQ,CAAA,CAAE,EAC/D,CAsBA,uBAAA,CAAwBD,CAAAA,CAAcC,CAAAA,CAAsB,CAS1D,GAPID,CAAAA,GAAQ,MAAA,EAAaC,CAAAA,GAAQ,MAAA,GAC/B,IAAA,CAAK,GAAA,CAAMD,CAAAA,CACX,IAAA,CAAK,GAAA,CAAMC,EACX,IAAA,CAAK,WAAA,EAAY,CAAA,CAIf,IAAA,CAAK,GAAA,GAAQ,IAAA,EAAQ,IAAA,CAAK,GAAA,GAAQ,IAAA,CACpC,MAAM,IAAI,KAAA,CACR,kEACF,CAAA,CAGF,GAAI,IAAA,CAAK,GAAA,GAAQ,IAAA,CAAK,GAAA,CACpB,OAAO,IAAA,CAAK,GAAA,CAGd,IAAMC,CAAAA,CAAU,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,KAAK,CAAC,CAAA,CACzCC,CAAAA,CAAW,IAAA,CAAK,IAAA,CAAKD,CAAAA,CAAU,CAAC,CAAA,CAClCE,CAAAA,CACAC,CAAAA,CAEJ,EAAG,CACDD,CAAAA,CAAc,IAAI,WAAWD,CAAQ,CAAA,CAErC,MAAA,CAAO,eAAA,CAAgBC,CAAW,CAAA,CAClCC,CAAAA,CAAe,CAAA,CACf,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIH,CAAAA,CAAUG,CAAAA,EAAAA,CAC5BD,GAAgBD,CAAAA,CAAYE,CAAC,CAAA,EAAM,CAAA,CAAIA,CAAAA,CAEzCD,CAAAA,CAAgBA,CAAAA,CAAe,IAAA,CAAK,KAAA,CAAS,IAAA,CAAK,IACpD,CAAA,MACE,IAAA,CAAK,MAAA,CAAO,SAASA,CAAY,CAAA,EACjC,IAAA,CAAK,MAAA,CAAO,MAAA,CAAS,IAAA,CAAK,KAAA,EAG5B,OAAI,IAAA,CAAK,MAAA,CAAO,MAAA,EAAU,IAAA,CAAK,UAAA,GAC7B,IAAA,CAAK,MAAA,CAAO,KAAA,EAAM,CAEb,IAAA,CAAK,aAAA,EACR,IAAA,CAAK,gBAAA,EAAiB,CAAA,CAG1B,IAAA,CAAK,MAAA,CAAO,IAAA,CAAKA,CAAY,CAAA,CAEtBA,CACT,CACF","file":"index.mjs","sourcesContent":["/**\n * UniqueRandomGenerator is a class that generates random integers in a range,\n * excluding the numbers that have been generated before, while in the randomized buffer.\n *\n * @remarks\n * This class uses cryptographically secure random number generation via the Web Crypto API,\n * which is available in both modern browsers and Node.js 18+.\n *\n * @example\n * ```typescript\n * const generator = new UniqueRandomGenerator()\n *   .setMinMax(1, 10)\n *   .setBufferSize(3);\n *\n * const num = generator.getRandomIntegerInRange(); // Won't repeat last 3 values\n * ```\n */\nexport class UniqueRandomGenerator {\n  private min: number | null = null;\n  private max: number | null = null;\n  private buffer: number[] = [];\n  private bufferSize: number = 0;\n  private bufferSizeSet: boolean = false;\n  private range: number = 0;\n\n  /**\n   * Sets the buffer size for the generator.\n   *\n   * @param bufferSize - The size of the buffer. Determines how many recent values to avoid.\n   * @returns The instance of UniqueRandomGenerator for method chaining.\n   *\n   * @example\n   * ```typescript\n   * generator.setBufferSize(5); // Avoid repeating the last 5 generated numbers\n   * ```\n   */\n  setBufferSize(bufferSize: number): this {\n    if (this.bufferSize !== bufferSize) {\n      this.bufferSize = bufferSize;\n      this.bufferSizeSet = true;\n    }\n    return this;\n  }\n\n  /**\n   * Sets the minimum value for the range.\n   *\n   * @param min - The minimum value (inclusive).\n   * @returns The instance of UniqueRandomGenerator for method chaining.\n   *\n   * @example\n   * ```typescript\n   * generator.setMin(1); // Range starts at 1\n   * ```\n   */\n  setMin(min: number): this {\n    if (this.min !== min) {\n      this.min = min;\n      this.updateRange();\n    }\n    return this;\n  }\n\n  /**\n   * Sets the maximum value for the range.\n   *\n   * @param max - The maximum value (inclusive).\n   * @returns The instance of UniqueRandomGenerator for method chaining.\n   *\n   * @example\n   * ```typescript\n   * generator.setMax(10); // Range ends at 10\n   * ```\n   */\n  setMax(max: number): this {\n    if (this.max !== max) {\n      this.max = max;\n      this.updateRange();\n    }\n    return this;\n  }\n\n  /**\n   * Sets both the minimum and maximum values for the range.\n   *\n   * @param min - The minimum value (inclusive).\n   * @param max - The maximum value (inclusive).\n   * @returns The instance of UniqueRandomGenerator for method chaining.\n   *\n   * @example\n   * ```typescript\n   * generator.setMinMax(1, 100); // Range from 1 to 100\n   * ```\n   */\n  setMinMax(min: number, max: number): this {\n    this.setMin(min);\n    this.setMax(max);\n    return this;\n  }\n\n  /**\n   * Updates the range based on the current min and max values.\n   *\n   * @private\n   */\n  private updateRange(): void {\n    if (this.min !== null && this.max !== null) {\n      this.range = this.max - this.min + 1;\n      if (!this.bufferSizeSet) {\n        this.updateBufferSize();\n        this.bufferSizeSet = true;\n      }\n    }\n  }\n\n  /**\n   * Set the buffer size to a random number between 0 and this.range - 1,\n   * so that the buffer size changes every time it's exhausted.\n   *\n   * @private\n   */\n  private updateBufferSize(): void {\n    this.bufferSize = Math.floor(Math.random() * (this.range - 1));\n  }\n\n  /**\n   * Generates a cryptographically secure random integer within the specified range.\n   * This function ensures that the generated number hasn't been recently produced\n   * by maintaining a buffer of previously generated numbers.\n   *\n   * @param min - Optional minimum value to override the configured min (inclusive).\n   * @param max - Optional maximum value to override the configured max (inclusive).\n   * @returns A random integer between min (inclusive) and max (inclusive).\n   * @throws {Error} If min or max are not set (either via setMinMax or parameters).\n   *\n   * @example\n   * ```typescript\n   * // Using pre-configured range\n   * generator.setMinMax(1, 10);\n   * const num = generator.getRandomIntegerInRange();\n   *\n   * // Override range for this call\n   * const num2 = generator.getRandomIntegerInRange(50, 100);\n   * ```\n   */\n  getRandomIntegerInRange(min?: number, max?: number): number {\n    // If min and max are provided, use them\n    if (min !== undefined && max !== undefined) {\n      this.min = min;\n      this.max = max;\n      this.updateRange();\n    }\n\n    // Check if min/max are set\n    if (this.min === null || this.max === null) {\n      throw new Error(\n        'Min and max values must be set before generating random numbers.'\n      );\n    }\n\n    if (this.min === this.max) {\n      return this.min; // Return the min value if the range is a single number\n    }\n\n    const bitSize = Math.ceil(Math.log2(this.range));\n    const byteSize = Math.ceil(bitSize / 8);\n    let randomBytes: Uint8Array;\n    let randomNumber: number;\n\n    do {\n      randomBytes = new Uint8Array(byteSize);\n      // Use global crypto (works in Node 18+ and all modern browsers)\n      crypto.getRandomValues(randomBytes);\n      randomNumber = 0;\n      for (let i = 0; i < byteSize; i++) {\n        randomNumber |= randomBytes[i] << (8 * i);\n      }\n      randomNumber = (randomNumber % this.range) + this.min;\n    } while (\n      this.buffer.includes(randomNumber) &&\n      this.buffer.length < this.range\n    );\n\n    if (this.buffer.length >= this.bufferSize) {\n      this.buffer.shift();\n      // Update bufferSize after the buffer is reset, but only if not explicitly set\n      if (!this.bufferSizeSet) {\n        this.updateBufferSize();\n      }\n    }\n    this.buffer.push(randomNumber);\n\n    return randomNumber;\n  }\n}\n"]}