summary refs log tree commit diff
path: root/src/extensions/Random.ts
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2026-06-12 16:27:38 +0200
committerRory& <root@rory.gay>2026-06-12 17:58:18 +0200
commit03ecae4348182885b8aa06d2b42c2e7da88923b2 (patch)
treed6101462a387ff6523fce39fa0bdb58789a797ef /src/extensions/Random.ts
parentMove migrations to database (diff)
downloadserver-ts-03ecae4348182885b8aa06d2b42c2e7da88923b2.tar.xz
Move more extensions to extensions
Diffstat (limited to 'src/extensions/Random.ts')
-rw-r--r--src/extensions/Random.ts92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/extensions/Random.ts b/src/extensions/Random.ts
new file mode 100644

index 00000000..212e1c9a --- /dev/null +++ b/src/extensions/Random.ts
@@ -0,0 +1,92 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +// Inspired by dotnet: https://learn.microsoft.com/en-us/dotnet/api/system.random?view=net-9.0#methods +export class Random { + public static nextInt(min?: number, max?: number): number { + if (min === undefined && max === undefined) { + // Next() + return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); + } else if (max === undefined) { + // Next(Int32) + if (min! <= 0) throw new RangeError("min must be greater than 0"); + return Math.floor(Math.random() * min!); + } else { + // Next(Int32, Int32) + if (min! >= max!) throw new RangeError("min must be less than max"); + return Math.floor(Math.random() * (max! - min!)) + min!; + } + } + + public static nextDouble(min?: number, max?: number): number { + if (min === undefined && max === undefined) { + // NextDouble() + return Math.random(); + } else if (max === undefined) { + // NextDouble(Double) + if (min! <= 0) throw new RangeError("min must be greater than 0"); + return Math.random() * min!; + } else { + // NextDouble(Double, Double) + if (min! >= max!) throw new RangeError("min must be less than max"); + return Math.random() * (max! - min!) + min!; + } + } + + public static nextBytes(count: number): Uint8Array { + if (count <= 0) throw new RangeError("count must be greater than 0"); + const arr = new Uint8Array(count); + for (let i = 0; i < count; i++) { + arr[i] = Math.floor(Math.random() * 256); + } + return arr; + } + + public static nextBytesArray(count: number) { + if (count <= 0) throw new RangeError("count must be greater than 0"); + const arr = []; + for (let i = 0; i < count; i++) { + arr.push(Math.floor(Math.random() * 256)); + } + return arr; + } + + public static getItems<T>(items: T[], count: number): T[] { + if (count <= 0) throw new RangeError("count must be greater than 0"); + if (count >= items.length) return this.shuffle(items); + const usedIndices = new Set<number>(); + const result: T[] = []; + while (result.length < count && usedIndices.size < items.length) { + const index = Math.floor(Math.random() * items.length); + if (!usedIndices.has(index)) { + usedIndices.add(index); + result.push(items[index]); + } + } + return result; + } + + public static shuffle<T>(items: T[]): T[] { + const array = [...items]; + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + } +}