feat(seed): ~5x richer demo data via deterministic generators
Rewrite scripts/seed-demo.ts as a thin orchestrator over a new scripts/seed/ module (rng, pools, helpers, content, schedule, logs, generators). Scales demo data from 6 users/3 projects to ~30 users/15 projects with ~5-8x per-table content (~6.8x total rows) via a seeded mulberry32 PRNG for full reproducibility (incl. bcrypt salts and file/URL identifiers). FK-safe ordering, real captured IDs for activity logs, enum pools typed against lib/types. Preserves canonical login credentials and projects.
This commit is contained in:
50
scripts/seed/rng.ts
Normal file
50
scripts/seed/rng.ts
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* シードデータ生成用の決定論的乱数ユーティリティ。
|
||||
* mulberry32 を用い、固定シードで再現可能なデータを生成する。
|
||||
*/
|
||||
|
||||
export type Rng = () => number;
|
||||
|
||||
export function createRng(seed: number): Rng {
|
||||
let a = seed >>> 0;
|
||||
return () => {
|
||||
a |= 0;
|
||||
a = (a + 0x6d2b79f5) | 0;
|
||||
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
||||
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
||||
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
||||
};
|
||||
}
|
||||
|
||||
export function pick<T>(rng: Rng, arr: readonly T[]): T {
|
||||
return arr[Math.floor(rng() * arr.length)]!;
|
||||
}
|
||||
|
||||
export function pickN<T>(rng: Rng, arr: readonly T[], n: number): T[] {
|
||||
return shuffle(rng, arr).slice(0, Math.min(n, arr.length));
|
||||
}
|
||||
|
||||
export function randInt(rng: Rng, min: number, max: number): number {
|
||||
return Math.floor(rng() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
export function shuffle<T>(rng: Rng, arr: readonly T[]): T[] {
|
||||
const out = [...arr];
|
||||
for (let i = out.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(rng() * (i + 1));
|
||||
[out[i], out[j]] = [out[j]!, out[i]!];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function chance(rng: Rng, p: number): boolean {
|
||||
return rng() < p;
|
||||
}
|
||||
|
||||
export function seededUuid(rng: Rng): string {
|
||||
const hex = () =>
|
||||
Math.floor(rng() * 0x10000)
|
||||
.toString(16)
|
||||
.padStart(4, '0');
|
||||
return `${hex()}${hex()}-${hex()}-${hex()}-${hex()}-${hex()}${hex()}${hex()}`;
|
||||
}
|
||||
Reference in New Issue
Block a user