Files
fool-cardgame/tests/core/util/Rng.spec.ts
T
ftcandClaude Opus 5 c980440856 M0: план разработки, техническая структура, каркас проекта
- docs/PLAN.md — план по этапам, обновляется по мере работы
- docs/TECHNICAL.md — слои, карта папок, контракты, рабочие процессы
- docs/DECISIONS.md — журнал решений, принятых самостоятельно
- разрешение 1080x1920, fit-width (портрет, 4:3..21:9)
- каркас assets/scripts (core / modules / app / ui)
- headless-тесты на vitest + strict typecheck + защита чистоты core
- Rng: детерминированный генератор и перемешивание

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 10:28:49 +03:00

63 lines
2.1 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { Rng } from '@core/util/Rng';
describe('Rng', () => {
it('is deterministic for a given seed', () => {
const a = Array.from({ length: 20 }, () => new Rng(42).next());
expect(new Set(a).size).toBe(1);
const first = new Rng(7);
const second = new Rng(7);
for (let i = 0; i < 100; i++) {
expect(first.next()).toBe(second.next());
}
});
it('produces different streams for different seeds', () => {
const a = new Rng(1);
const b = new Rng(2);
const differs = Array.from({ length: 10 }, () => a.next() !== b.next());
expect(differs.some(Boolean)).toBe(true);
});
it('resumes from a captured state', () => {
const source = new Rng(123);
for (let i = 0; i < 5; i++) source.next();
const resumed = Rng.fromState(source.state);
for (let i = 0; i < 20; i++) {
expect(resumed.next()).toBe(source.next());
}
});
it('keeps nextInt inside its bound', () => {
const rng = new Rng(99);
for (let i = 0; i < 10000; i++) {
const v = rng.nextInt(36);
expect(v).toBeGreaterThanOrEqual(0);
expect(v).toBeLessThan(36);
}
});
it('rejects a non-positive bound and an empty pick', () => {
const rng = new Rng(1);
expect(() => rng.nextInt(0)).toThrow(RangeError);
expect(() => rng.pick([])).toThrow(RangeError);
});
it('shuffles as a permutation, not a resample', () => {
const rng = new Rng(2024);
const original = Array.from({ length: 36 }, (_, i) => i);
const shuffled = rng.shuffle([...original]);
expect(shuffled).toHaveLength(36);
expect([...shuffled].sort((x, y) => x - y)).toEqual(original);
expect(shuffled).not.toEqual(original);
});
it('shuffles reproducibly', () => {
const deck = () => Array.from({ length: 36 }, (_, i) => i);
expect(new Rng(5).shuffle(deck())).toEqual(new Rng(5).shuffle(deck()));
});
});