UNPKG

houser-js-utils

Version:

A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.

1 lines 27.9 kB
{"version":3,"file":"RandomUtils.mjs","sources":["../src/RandomUtils.ts"],"sourcesContent":["/**\n * @module RandomUtils\n * @description A comprehensive collection of utility functions for random number generation.\n * Implements functionality proposed in TC39 Random API proposals including seeded pseudo-random\n * number generation, various distribution methods, and utility functions for common randomness needs.\n * @example\n * ```typescript\n * import { RandomUtils } from 'houser-js-utils';\n *\n * // Generate random integer in range\n * const dice = RandomUtils.int(1, 6);\n *\n * // Create seeded generator for reproducible sequences\n * const seeded = RandomUtils.Seeded.fromFixed(42);\n * const value = seeded.random();\n *\n * // Generate random bytes\n * const bytes = RandomUtils.bytes(16);\n * ```\n */\n\n/**\n * Simple Linear Congruential Generator (LCG) implementation for seeded random numbers.\n * Uses the same constants as Numerical Recipes: a = 1664525, c = 1013904223, m = 2^32\n */\nclass SimpleLCG {\n private state: number;\n\n constructor(seed: number) {\n this.state = seed >>> 0; // Ensure 32-bit unsigned integer\n }\n\n /**\n * Generate next random value and update state\n * @returns Random number between 0 and 1 (exclusive)\n */\n next(): number {\n this.state = (1664525 * this.state + 1013904223) >>> 0;\n return this.state / 0x100000000; // Convert to [0,1)\n }\n\n /**\n * Get current state\n */\n getState(): number {\n return this.state;\n }\n\n /**\n * Set state\n */\n setState(state: number): void {\n this.state = state >>> 0;\n }\n}\n\n/**\n * A seeded pseudo-random number generator that produces reproducible sequences.\n * Based on the TC39 Seeded Random proposal.\n */\nexport class SeededRandom {\n private readonly prng: SimpleLCG;\n\n /**\n * Creates a new seeded random generator\n * @param seed - Seed value or Uint8Array (up to 32 bytes)\n */\n constructor(seed: number | Uint8Array) {\n if (typeof seed === \"number\") {\n this.prng = new SimpleLCG(seed);\n } else if (seed instanceof Uint8Array) {\n if (seed.length > 32) {\n throw new RangeError(\"Seed must be 32 bytes or less\");\n }\n // Convert Uint8Array to number by taking first 4 bytes\n let numSeed = 0;\n for (let i = 0; i < Math.min(4, seed.length); i++) {\n numSeed = (numSeed << 8) | seed[i];\n }\n this.prng = new SimpleLCG(numSeed);\n } else {\n throw new TypeError(\"Seed must be a number or Uint8Array\");\n }\n }\n\n /**\n * Factory method that requires exact 32-byte seed\n * @param seed - Exactly 32 bytes of seed data\n * @returns New SeededRandom instance\n */\n static fromSeed(seed: Uint8Array): SeededRandom {\n if (!(seed instanceof Uint8Array)) {\n throw new TypeError(\"Seed must be a Uint8Array\");\n }\n if (seed.length !== 32) {\n throw new RangeError(\"Seed must be exactly 32 bytes\");\n }\n return new SeededRandom(seed);\n }\n\n /**\n * Factory method that creates generator from state\n * @param state - State data (simplified to number for this implementation)\n * @returns New SeededRandom instance\n */\n static fromState(state: number): SeededRandom {\n const instance = new SeededRandom(0);\n instance.prng.setState(state);\n return instance;\n }\n\n /**\n * Factory method for simple integer seeds\n * @param byte - Integer between 0-255\n * @returns New SeededRandom instance\n */\n static fromFixed(byte: number): SeededRandom {\n if (\n typeof byte !== \"number\" ||\n !Number.isInteger(byte) ||\n byte < 0 ||\n byte > 255\n ) {\n throw new RangeError(\"Byte must be an integer between 0 and 255\");\n }\n return new SeededRandom(byte);\n }\n\n /**\n * Generate a random number between 0 and 1 (exclusive)\n * @returns Random number in [0,1)\n */\n random(): number {\n return this.prng.next();\n }\n\n /**\n * Generate a new seed for creating child PRNGs\n * @returns 32-byte Uint8Array suitable for seeding\n */\n seed(): Uint8Array {\n const seed = new Uint8Array(32);\n for (let i = 0; i < 32; i++) {\n seed[i] = Math.floor(this.random() * 256);\n }\n return seed;\n }\n\n /**\n * Get current generator state\n * @returns Current state as number\n */\n getState(): number {\n return this.prng.getState();\n }\n\n /**\n * Set generator state\n * @param state - State to set\n * @returns This instance for chaining\n */\n setState(state: number): this {\n this.prng.setState(state);\n return this;\n }\n\n /**\n * Generate random number in range\n * @param lo - Lower bound\n * @param hi - Upper bound\n * @param step - Optional step size\n * @returns Random number in specified range\n */\n number(lo: number, hi: number, step?: number): number {\n return RandomUtils.number(lo, hi, step, () => this.random());\n }\n\n /**\n * Generate random integer in range\n * @param lo - Lower bound (inclusive)\n * @param hi - Upper bound (inclusive)\n * @param step - Optional step size\n * @returns Random integer in specified range\n */\n int(lo: number, hi: number, step?: number): number {\n return RandomUtils.int(lo, hi, step, () => this.random());\n }\n\n /**\n * Generate random BigInt in range\n * @param lo - Lower bound (inclusive)\n * @param hi - Upper bound (inclusive)\n * @param step - Optional step size\n * @returns Random BigInt in specified range\n */\n bigint(lo: bigint, hi: bigint, step?: bigint): bigint {\n return RandomUtils.bigint(lo, hi, step, () => this.random());\n }\n\n /**\n * Generate random bytes\n * @param n - Number of bytes to generate\n * @returns Uint8Array of random bytes\n */\n bytes(n: number): Uint8Array {\n return RandomUtils.bytes(n, () => this.random());\n }\n\n /**\n * Fill buffer with random bytes\n * @param buffer - Buffer to fill\n * @param start - Start position (optional)\n * @param end - End position (optional)\n * @returns The filled buffer\n */\n fillBytes<T extends ArrayBuffer | ArrayBufferView>(\n buffer: T,\n start?: number,\n end?: number\n ): T {\n return RandomUtils.fillBytes(buffer, start, end, () => this.random());\n }\n}\n\n/**\n * Collection of random utility functions\n */\nexport const RandomUtils = {\n /**\n * The SeededRandom class for creating reproducible random sequences\n */\n Seeded: SeededRandom,\n\n /**\n * Generate a random number between 0 and 1 (exclusive)\n * @returns Random number in [0,1)\n */\n random(): number {\n return Math.random();\n },\n\n /**\n * Generate a random number in a specified range\n * @param lo - Lower bound\n * @param hi - Upper bound\n * @param step - Optional step size\n * @param randomFn - Optional custom random function\n * @returns Random number in specified range\n */\n number(\n lo: number,\n hi: number,\n step?: number,\n randomFn: () => number = Math.random\n ): number {\n if (typeof lo !== \"number\" || typeof hi !== \"number\") {\n throw new TypeError(\"Lower and upper bounds must be numbers\");\n }\n if (lo >= hi) {\n throw new RangeError(\"Lower bound must be less than upper bound\");\n }\n\n if (step === undefined) {\n // Return random float in range (lo, hi)\n return lo + randomFn() * (hi - lo);\n }\n\n if (typeof step !== \"number\" || step <= 0) {\n throw new RangeError(\"Step must be a positive number\");\n }\n\n // Return random number of form lo + N*step in range [lo, hi]\n const maxN = Math.floor((hi - lo) / step);\n const N = Math.floor(randomFn() * (maxN + 1));\n const result = lo + N * step;\n return result > hi ? hi : result;\n },\n\n /**\n * Generate a random integer in a specified range\n * @param lo - Lower bound (inclusive)\n * @param hi - Upper bound (inclusive)\n * @param step - Optional step size\n * @param randomFn - Optional custom random function\n * @returns Random integer in specified range\n */\n int(\n lo: number,\n hi: number,\n step?: number,\n randomFn: () => number = Math.random\n ): number {\n if (!Number.isInteger(lo) || !Number.isInteger(hi)) {\n throw new TypeError(\"Lower and upper bounds must be integers\");\n }\n if (lo > hi) {\n throw new RangeError(\n \"Lower bound must be less than or equal to upper bound\"\n );\n }\n\n if (step === undefined) {\n // Return random integer in range [lo, hi]\n return Math.floor(randomFn() * (hi - lo + 1)) + lo;\n }\n\n if (!Number.isInteger(step) || step <= 0) {\n throw new RangeError(\"Step must be a positive integer\");\n }\n\n // Return random integer of form lo + N*step in range [lo, hi]\n const maxN = Math.floor((hi - lo) / step);\n const N = Math.floor(randomFn() * (maxN + 1));\n return lo + N * step;\n },\n\n /**\n * Generate a random BigInt in a specified range\n * @param lo - Lower bound (inclusive)\n * @param hi - Upper bound (inclusive)\n * @param step - Optional step size\n * @param randomFn - Optional custom random function\n * @returns Random BigInt in specified range\n */\n bigint(\n lo: bigint,\n hi: bigint,\n step?: bigint,\n randomFn: () => number = Math.random\n ): bigint {\n if (typeof lo !== \"bigint\" || typeof hi !== \"bigint\") {\n throw new TypeError(\"Lower and upper bounds must be BigInts\");\n }\n if (lo > hi) {\n throw new RangeError(\n \"Lower bound must be less than or equal to upper bound\"\n );\n }\n\n const range = hi - lo + 1n;\n\n if (step === undefined) {\n // Generate random BigInt in range [lo, hi]\n const randomValue = BigInt(Math.floor(randomFn() * Number(range)));\n return lo + randomValue;\n }\n\n if (typeof step !== \"bigint\" || step <= 0n) {\n throw new RangeError(\"Step must be a positive BigInt\");\n }\n\n // Return random BigInt of form lo + N*step in range [lo, hi]\n const maxN = (hi - lo) / step;\n const N = BigInt(Math.floor(randomFn() * (Number(maxN) + 1)));\n return lo + N * step;\n },\n\n /**\n * Generate random bytes\n * @param n - Number of bytes to generate\n * @param randomFn - Optional custom random function\n * @returns Uint8Array of random bytes\n */\n bytes(n: number, randomFn: () => number = Math.random): Uint8Array {\n if (!Number.isInteger(n) || n < 0) {\n throw new RangeError(\"Number of bytes must be a non-negative integer\");\n }\n\n const bytes = new Uint8Array(n);\n for (let i = 0; i < n; i++) {\n bytes[i] = Math.floor(randomFn() * 256);\n }\n return bytes;\n },\n\n /**\n * Fill a buffer with random bytes\n * @param buffer - Buffer to fill (ArrayBuffer or TypedArray)\n * @param start - Start position (optional)\n * @param end - End position (optional)\n * @param randomFn - Optional custom random function\n * @returns The filled buffer\n */\n fillBytes<T extends ArrayBuffer | ArrayBufferView>(\n buffer: T,\n start?: number,\n end?: number,\n randomFn: () => number = Math.random\n ): T {\n let view: Uint8Array;\n\n if (buffer instanceof ArrayBuffer) {\n view = new Uint8Array(buffer);\n } else if (ArrayBuffer.isView(buffer)) {\n view = new Uint8Array(\n buffer.buffer,\n buffer.byteOffset,\n buffer.byteLength\n );\n } else {\n throw new TypeError(\"Buffer must be an ArrayBuffer or ArrayBufferView\");\n }\n\n const startPos = start ?? 0;\n const endPos = end ?? view.length;\n\n if (startPos < 0 || endPos > view.length || startPos > endPos) {\n throw new RangeError(\"Invalid start or end position\");\n }\n\n for (let i = startPos; i < endPos; i++) {\n view[i] = Math.floor(randomFn() * 256);\n }\n\n return buffer;\n },\n\n /**\n * Generate a random boolean value\n * @param probability - Probability of returning true (0-1, default: 0.5)\n * @param randomFn - Optional custom random function\n * @returns Random boolean\n */\n boolean(\n probability: number = 0.5,\n randomFn: () => number = Math.random\n ): boolean {\n if (\n typeof probability !== \"number\" ||\n isNaN(probability) ||\n probability < 0 ||\n probability > 1\n ) {\n throw new RangeError(\"Probability must be a number between 0 and 1\");\n }\n return randomFn() < probability;\n },\n\n /**\n * Choose a random element from an array\n * @param array - Array to choose from\n * @param randomFn - Optional custom random function\n * @returns Random element from the array\n */\n choice<T>(array: T[], randomFn: () => number = Math.random): T {\n if (!Array.isArray(array)) {\n throw new TypeError(\"Input must be an array\");\n }\n if (array.length === 0) {\n throw new RangeError(\"Array cannot be empty\");\n }\n\n const index = Math.floor(randomFn() * array.length);\n return array[index];\n },\n\n /**\n * Choose multiple random elements from an array without replacement\n * @param array - Array to choose from\n * @param count - Number of elements to choose\n * @param randomFn - Optional custom random function\n * @returns Array of randomly chosen elements\n */\n sample<T>(\n array: T[],\n count: number,\n randomFn: () => number = Math.random\n ): T[] {\n if (!Array.isArray(array)) {\n throw new TypeError(\"Input must be an array\");\n }\n if (!Number.isInteger(count) || count < 0) {\n throw new RangeError(\"Count must be a non-negative integer\");\n }\n if (count > array.length) {\n throw new RangeError(\"Count cannot be greater than array length\");\n }\n\n const result: T[] = [];\n const indices = new Set<number>();\n\n while (result.length < count) {\n const index = Math.floor(randomFn() * array.length);\n if (!indices.has(index)) {\n indices.add(index);\n result.push(array[index]);\n }\n }\n\n return result;\n },\n\n /**\n * Shuffle an array using Fisher-Yates algorithm\n * @param array - Array to shuffle\n * @param randomFn - Optional custom random function\n * @returns New shuffled array\n */\n shuffle<T>(array: T[], randomFn: () => number = Math.random): T[] {\n if (!Array.isArray(array)) {\n throw new TypeError(\"Input must be an array\");\n }\n\n const result = [...array];\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(randomFn() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n return result;\n },\n\n /**\n * Generate a random string of specified length\n * @param length - Length of the string to generate\n * @param charset - Character set to use (default: alphanumeric)\n * @param randomFn - Optional custom random function\n * @returns Random string\n */\n string(\n length: number,\n charset: string = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\",\n randomFn: () => number = Math.random\n ): string {\n if (!Number.isInteger(length) || length < 0) {\n throw new RangeError(\"Length must be a non-negative integer\");\n }\n if (typeof charset !== \"string\" || charset.length === 0) {\n throw new TypeError(\"Charset must be a non-empty string\");\n }\n\n let result = \"\";\n for (let i = 0; i < length; i++) {\n result += charset[Math.floor(randomFn() * charset.length)];\n }\n return result;\n },\n\n /**\n * Generate a random UUID v4\n * @param randomFn - Optional custom random function\n * @returns Random UUID string\n */\n uuid(randomFn: () => number = Math.random): string {\n const hex = \"0123456789abcdef\";\n let uuid = \"\";\n\n for (let i = 0; i < 36; i++) {\n if (i === 8 || i === 13 || i === 18 || i === 23) {\n uuid += \"-\";\n } else if (i === 14) {\n uuid += \"4\"; // Version 4\n } else if (i === 19) {\n uuid += hex[Math.floor(randomFn() * 4) + 8]; // Variant bits\n } else {\n uuid += hex[Math.floor(randomFn() * 16)];\n }\n }\n\n return uuid;\n },\n\n /**\n * Generate a weighted random choice\n * @param items - Array of items to choose from\n * @param weights - Array of weights corresponding to items\n * @param randomFn - Optional custom random function\n * @returns Randomly chosen item based on weights\n */\n weightedChoice<T>(\n items: T[],\n weights: number[],\n randomFn: () => number = Math.random\n ): T {\n if (!Array.isArray(items) || !Array.isArray(weights)) {\n throw new TypeError(\"Items and weights must be arrays\");\n }\n if (items.length !== weights.length) {\n throw new RangeError(\n \"Items and weights arrays must have the same length\"\n );\n }\n if (items.length === 0) {\n throw new RangeError(\"Arrays cannot be empty\");\n }\n if (weights.some((w) => typeof w !== \"number\" || w < 0)) {\n throw new RangeError(\"All weights must be non-negative numbers\");\n }\n\n const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);\n if (totalWeight === 0) {\n throw new RangeError(\"Total weight must be greater than 0\");\n }\n\n const random = randomFn() * totalWeight;\n let cumulativeWeight = 0;\n\n for (let i = 0; i < items.length; i++) {\n cumulativeWeight += weights[i];\n if (random <= cumulativeWeight) {\n return items[i];\n }\n }\n\n // Fallback (should never reach here)\n return items[items.length - 1];\n },\n\n /**\n * Generate a random number from normal distribution (Box-Muller transform)\n * @param mean - Mean of the distribution (default: 0)\n * @param stdDev - Standard deviation (default: 1)\n * @param randomFn - Optional custom random function\n * @returns Random number from normal distribution\n */\n normal(\n mean: number = 0,\n stdDev: number = 1,\n randomFn: () => number = Math.random\n ): number {\n if (typeof mean !== \"number\" || typeof stdDev !== \"number\") {\n throw new TypeError(\"Mean and standard deviation must be numbers\");\n }\n if (stdDev <= 0) {\n throw new RangeError(\"Standard deviation must be positive\");\n }\n\n // Use a simple implementation without static variables\n const u1 = randomFn();\n const u2 = randomFn();\n\n // Box-Muller transform\n const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n return z0 * stdDev + mean;\n },\n\n /**\n * Generate a random number from exponential distribution\n * @param rate - Rate parameter (lambda)\n * @param randomFn - Optional custom random function\n * @returns Random number from exponential distribution\n */\n exponential(rate: number = 1, randomFn: () => number = Math.random): number {\n if (typeof rate !== \"number\" || rate <= 0) {\n throw new RangeError(\"Rate must be a positive number\");\n }\n\n return -Math.log(1 - randomFn()) / rate;\n },\n\n /**\n * Generate a random seed for seeding PRNGs\n * @returns 32-byte Uint8Array suitable for seeding\n */\n seed(): Uint8Array {\n return this.bytes(32);\n },\n};\n"],"names":[],"mappings":";;;AAyBA,MAAM,UAAU;AAAA,EAGd,YAAY,MAAc;AAFlB;AAGN,SAAK,QAAQ,SAAS;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe;AACb,SAAK,QAAS,UAAU,KAAK,QAAQ,eAAgB;AACrD,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAmB;AACjB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,OAAqB;AAC5B,SAAK,QAAQ,UAAU;AAAA,EACzB;AACF;AAMO,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxB,YAAY,MAA2B;AANtB;AAOf,QAAI,OAAO,SAAS,UAAU;AAC5B,WAAK,OAAO,IAAI,UAAU,IAAI;AAAA,IAChC,WAAW,gBAAgB,YAAY;AACrC,UAAI,KAAK,SAAS,IAAI;AACpB,cAAM,IAAI,WAAW,+BAA+B;AAAA,MACtD;AAEA,UAAI,UAAU;AACd,eAAS,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,GAAG,KAAK;AACjD,kBAAW,WAAW,IAAK,KAAK,CAAC;AAAA,MACnC;AACA,WAAK,OAAO,IAAI,UAAU,OAAO;AAAA,IACnC,OAAO;AACL,YAAM,IAAI,UAAU,qCAAqC;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,SAAS,MAAgC;AAC9C,QAAI,EAAE,gBAAgB,aAAa;AACjC,YAAM,IAAI,UAAU,2BAA2B;AAAA,IACjD;AACA,QAAI,KAAK,WAAW,IAAI;AACtB,YAAM,IAAI,WAAW,+BAA+B;AAAA,IACtD;AACA,WAAO,IAAI,aAAa,IAAI;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,OAA6B;AAC5C,UAAM,WAAW,IAAI,aAAa,CAAC;AACnC,aAAS,KAAK,SAAS,KAAK;AAC5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAA4B;AAC3C,QACE,OAAO,SAAS,YAChB,CAAC,OAAO,UAAU,IAAI,KACtB,OAAO,KACP,OAAO,KACP;AACA,YAAM,IAAI,WAAW,2CAA2C;AAAA,IAClE;AACA,WAAO,IAAI,aAAa,IAAI;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAiB;AACf,WAAO,KAAK,KAAK,KAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAmB;AACjB,UAAM,OAAO,IAAI,WAAW,EAAE;AAC9B,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,WAAK,CAAC,IAAI,KAAK,MAAM,KAAK,OAAA,IAAW,GAAG;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAmB;AACjB,WAAO,KAAK,KAAK,SAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,OAAqB;AAC5B,SAAK,KAAK,SAAS,KAAK;AACxB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,IAAY,IAAY,MAAuB;AACpD,WAAO,YAAY,OAAO,IAAI,IAAI,MAAM,MAAM,KAAK,QAAQ;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,IAAY,IAAY,MAAuB;AACjD,WAAO,YAAY,IAAI,IAAI,IAAI,MAAM,MAAM,KAAK,QAAQ;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,IAAY,IAAY,MAAuB;AACpD,WAAO,YAAY,OAAO,IAAI,IAAI,MAAM,MAAM,KAAK,QAAQ;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,GAAuB;AAC3B,WAAO,YAAY,MAAM,GAAG,MAAM,KAAK,QAAQ;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UACE,QACA,OACA,KACG;AACH,WAAO,YAAY,UAAU,QAAQ,OAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,EACtE;AACF;AAKO,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA,EAIzB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,SAAiB;AACf,WAAO,KAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OACE,IACA,IACA,MACA,WAAyB,KAAK,QACtB;AACR,QAAI,OAAO,OAAO,YAAY,OAAO,OAAO,UAAU;AACpD,YAAM,IAAI,UAAU,wCAAwC;AAAA,IAC9D;AACA,QAAI,MAAM,IAAI;AACZ,YAAM,IAAI,WAAW,2CAA2C;AAAA,IAClE;AAEA,QAAI,SAAS,QAAW;AAEtB,aAAO,KAAK,cAAc,KAAK;AAAA,IACjC;AAEA,QAAI,OAAO,SAAS,YAAY,QAAQ,GAAG;AACzC,YAAM,IAAI,WAAW,gCAAgC;AAAA,IACvD;AAGA,UAAM,OAAO,KAAK,OAAO,KAAK,MAAM,IAAI;AACxC,UAAM,IAAI,KAAK,MAAM,SAAA,KAAc,OAAO,EAAE;AAC5C,UAAM,SAAS,KAAK,IAAI;AACxB,WAAO,SAAS,KAAK,KAAK;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IACE,IACA,IACA,MACA,WAAyB,KAAK,QACtB;AACR,QAAI,CAAC,OAAO,UAAU,EAAE,KAAK,CAAC,OAAO,UAAU,EAAE,GAAG;AAClD,YAAM,IAAI,UAAU,yCAAyC;AAAA,IAC/D;AACA,QAAI,KAAK,IAAI;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAEA,QAAI,SAAS,QAAW;AAEtB,aAAO,KAAK,MAAM,SAAA,KAAc,KAAK,KAAK,EAAE,IAAI;AAAA,IAClD;AAEA,QAAI,CAAC,OAAO,UAAU,IAAI,KAAK,QAAQ,GAAG;AACxC,YAAM,IAAI,WAAW,iCAAiC;AAAA,IACxD;AAGA,UAAM,OAAO,KAAK,OAAO,KAAK,MAAM,IAAI;AACxC,UAAM,IAAI,KAAK,MAAM,SAAA,KAAc,OAAO,EAAE;AAC5C,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OACE,IACA,IACA,MACA,WAAyB,KAAK,QACtB;AACR,QAAI,OAAO,OAAO,YAAY,OAAO,OAAO,UAAU;AACpD,YAAM,IAAI,UAAU,wCAAwC;AAAA,IAC9D;AACA,QAAI,KAAK,IAAI;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAEA,UAAM,QAAQ,KAAK,KAAK;AAExB,QAAI,SAAS,QAAW;AAEtB,YAAM,cAAc,OAAO,KAAK,MAAM,aAAa,OAAO,KAAK,CAAC,CAAC;AACjE,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,OAAO,SAAS,YAAY,QAAQ,IAAI;AAC1C,YAAM,IAAI,WAAW,gCAAgC;AAAA,IACvD;AAGA,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,IAAI,OAAO,KAAK,MAAM,cAAc,OAAO,IAAI,IAAI,EAAE,CAAC;AAC5D,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,GAAW,WAAyB,KAAK,QAAoB;AACjE,QAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,GAAG;AACjC,YAAM,IAAI,WAAW,gDAAgD;AAAA,IACvE;AAEA,UAAM,QAAQ,IAAI,WAAW,CAAC;AAC9B,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,CAAC,IAAI,KAAK,MAAM,SAAA,IAAa,GAAG;AAAA,IACxC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UACE,QACA,OACA,KACA,WAAyB,KAAK,QAC3B;AACH,QAAI;AAEJ,QAAI,kBAAkB,aAAa;AACjC,aAAO,IAAI,WAAW,MAAM;AAAA,IAC9B,WAAW,YAAY,OAAO,MAAM,GAAG;AACrC,aAAO,IAAI;AAAA,QACT,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MAAA;AAAA,IAEX,OAAO;AACL,YAAM,IAAI,UAAU,kDAAkD;AAAA,IACxE;AAEA,UAAM,WAAW,SAAS;AAC1B,UAAM,SAAS,OAAO,KAAK;AAE3B,QAAI,WAAW,KAAK,SAAS,KAAK,UAAU,WAAW,QAAQ;AAC7D,YAAM,IAAI,WAAW,+BAA+B;AAAA,IACtD;AAEA,aAAS,IAAI,UAAU,IAAI,QAAQ,KAAK;AACtC,WAAK,CAAC,IAAI,KAAK,MAAM,SAAA,IAAa,GAAG;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QACE,cAAsB,KACtB,WAAyB,KAAK,QACrB;AACT,QACE,OAAO,gBAAgB,YACvB,MAAM,WAAW,KACjB,cAAc,KACd,cAAc,GACd;AACA,YAAM,IAAI,WAAW,8CAA8C;AAAA,IACrE;AACA,WAAO,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAU,OAAY,WAAyB,KAAK,QAAW;AAC7D,QAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,YAAM,IAAI,UAAU,wBAAwB;AAAA,IAC9C;AACA,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,IAAI,WAAW,uBAAuB;AAAA,IAC9C;AAEA,UAAM,QAAQ,KAAK,MAAM,SAAA,IAAa,MAAM,MAAM;AAClD,WAAO,MAAM,KAAK;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OACE,OACA,OACA,WAAyB,KAAK,QACzB;AACL,QAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,YAAM,IAAI,UAAU,wBAAwB;AAAA,IAC9C;AACA,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,YAAM,IAAI,WAAW,sCAAsC;AAAA,IAC7D;AACA,QAAI,QAAQ,MAAM,QAAQ;AACxB,YAAM,IAAI,WAAW,2CAA2C;AAAA,IAClE;AAEA,UAAM,SAAc,CAAA;AACpB,UAAM,8BAAc,IAAA;AAEpB,WAAO,OAAO,SAAS,OAAO;AAC5B,YAAM,QAAQ,KAAK,MAAM,SAAA,IAAa,MAAM,MAAM;AAClD,UAAI,CAAC,QAAQ,IAAI,KAAK,GAAG;AACvB,gBAAQ,IAAI,KAAK;AACjB,eAAO,KAAK,MAAM,KAAK,CAAC;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAW,OAAY,WAAyB,KAAK,QAAa;AAChE,QAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,YAAM,IAAI,UAAU,wBAAwB;AAAA,IAC9C;AAEA,UAAM,SAAS,CAAC,GAAG,KAAK;AACxB,aAAS,IAAI,OAAO,SAAS,GAAG,IAAI,GAAG,KAAK;AAC1C,YAAM,IAAI,KAAK,MAAM,SAAA,KAAc,IAAI,EAAE;AACzC,OAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OACE,QACA,UAAkB,kEAClB,WAAyB,KAAK,QACtB;AACR,QAAI,CAAC,OAAO,UAAU,MAAM,KAAK,SAAS,GAAG;AAC3C,YAAM,IAAI,WAAW,uCAAuC;AAAA,IAC9D;AACA,QAAI,OAAO,YAAY,YAAY,QAAQ,WAAW,GAAG;AACvD,YAAM,IAAI,UAAU,oCAAoC;AAAA,IAC1D;AAEA,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,gBAAU,QAAQ,KAAK,MAAM,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC3D;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,WAAyB,KAAK,QAAgB;AACjD,UAAM,MAAM;AACZ,QAAI,OAAO;AAEX,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAI,MAAM,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAC/C,gBAAQ;AAAA,MACV,WAAW,MAAM,IAAI;AACnB,gBAAQ;AAAA,MACV,WAAW,MAAM,IAAI;AACnB,gBAAQ,IAAI,KAAK,MAAM,aAAa,CAAC,IAAI,CAAC;AAAA,MAC5C,OAAO;AACL,gBAAQ,IAAI,KAAK,MAAM,SAAA,IAAa,EAAE,CAAC;AAAA,MACzC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eACE,OACA,SACA,WAAyB,KAAK,QAC3B;AACH,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,QAAQ,OAAO,GAAG;AACpD,YAAM,IAAI,UAAU,kCAAkC;AAAA,IACxD;AACA,QAAI,MAAM,WAAW,QAAQ,QAAQ;AACnC,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,IAAI,WAAW,wBAAwB;AAAA,IAC/C;AACA,QAAI,QAAQ,KAAK,CAAC,MAAM,OAAO,MAAM,YAAY,IAAI,CAAC,GAAG;AACvD,YAAM,IAAI,WAAW,0CAA0C;AAAA,IACjE;AAEA,UAAM,cAAc,QAAQ,OAAO,CAAC,KAAK,WAAW,MAAM,QAAQ,CAAC;AACnE,QAAI,gBAAgB,GAAG;AACrB,YAAM,IAAI,WAAW,qCAAqC;AAAA,IAC5D;AAEA,UAAM,SAAS,aAAa;AAC5B,QAAI,mBAAmB;AAEvB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,0BAAoB,QAAQ,CAAC;AAC7B,UAAI,UAAU,kBAAkB;AAC9B,eAAO,MAAM,CAAC;AAAA,MAChB;AAAA,IACF;AAGA,WAAO,MAAM,MAAM,SAAS,CAAC;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OACE,OAAe,GACf,SAAiB,GACjB,WAAyB,KAAK,QACtB;AACR,QAAI,OAAO,SAAS,YAAY,OAAO,WAAW,UAAU;AAC1D,YAAM,IAAI,UAAU,6CAA6C;AAAA,IACnE;AACA,QAAI,UAAU,GAAG;AACf,YAAM,IAAI,WAAW,qCAAqC;AAAA,IAC5D;AAGA,UAAM,KAAK,SAAA;AACX,UAAM,KAAK,SAAA;AAGX,UAAM,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI,EAAE,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;AACnE,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,OAAe,GAAG,WAAyB,KAAK,QAAgB;AAC1E,QAAI,OAAO,SAAS,YAAY,QAAQ,GAAG;AACzC,YAAM,IAAI,WAAW,gCAAgC;AAAA,IACvD;AAEA,WAAO,CAAC,KAAK,IAAI,IAAI,SAAA,CAAU,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAmB;AACjB,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AACF;"}