import { describe, expect, it } from 'vitest';
import { Rng } from '../rng';

describe('Rng (mulberry32)', () => {
    it('детерминирован: один сид — одна последовательность', () => {
        const a = new Rng(42);
        const b = new Rng(42);
        const seqA = Array.from({ length: 20 }, () => a.nextUint());
        const seqB = Array.from({ length: 20 }, () => b.nextUint());
        expect(seqA).toEqual(seqB);
    });

    it('разные сиды — разные последовательности', () => {
        const a = new Rng(1);
        const b = new Rng(2);
        const seqA = Array.from({ length: 20 }, () => a.nextUint());
        const seqB = Array.from({ length: 20 }, () => b.nextUint());
        expect(seqA).not.toEqual(seqB);
    });

    it('next() в [0, 1) на большой выборке', () => {
        const r = new Rng(7);
        for (let i = 0; i < 10000; i++) {
            const v = r.next();
            expect(v).toBeGreaterThanOrEqual(0);
            expect(v).toBeLessThan(1);
        }
    });

    it('range() в границах включительно', () => {
        const r = new Rng(9);
        for (let i = 0; i < 2000; i++) {
            const v = r.range(-2, 3);
            expect(v).toBeGreaterThanOrEqual(-2);
            expect(v).toBeLessThanOrEqual(3);
            expect(Number.isInteger(v)).toBe(true);
        }
    });

    it('range(5,5) всегда 5; int(1) всегда 0', () => {
        const r = new Rng(3);
        for (let i = 0; i < 10; i++) {
            expect(r.range(5, 5)).toBe(5);
            expect(r.int(1)).toBe(0);
        }
    });

    it('pick() выдаёт только элементы массива', () => {
        const r = new Rng(11);
        const items = ['a', 'b', 'c'] as const;
        for (let i = 0; i < 100; i++) expect(items).toContain(r.pick(items));
    });

    it('невалидный сид бросает', () => {
        expect(() => new Rng(-1)).toThrow();
        expect(() => new Rng(1.5)).toThrow();
    });
});