not-tonight/tests/staff.test.ts

56 lines
1.9 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
BUMP_MOP_CHANCE,
KAYDEN_HOLD_COOLDOWN_MS,
KAYDEN_HOLD_MS,
ORDER_LAG_MS,
RADIO_COOLDOWN_MS,
SHAN_CLEAN_CHANCE,
SHAN_MIN_INTOX,
orderLag,
rollBumpMops,
rollShanClean,
} from '../src/rules/staff';
import { drunkStage } from '../src/rules/drunk';
import { SeededRNG } from '../src/core/SeededRNG';
import { VENUES } from '../src/data/venues';
describe('radio command', () => {
it('is a Head of Security-tier verb: Elevate and ROOM only', () => {
expect(VENUES.map((v) => v.radioCommand === true)).toEqual([false, false, true, true]);
});
it('staff competence is real but imperfect — that IS the staff', () => {
const rng = new SeededRNG(3).stream('s');
let bump = 0;
let shan = 0;
for (let i = 0; i < 2000; i++) {
if (rollBumpMops(rng)) bump++;
if (rollShanClean(rng)) shan++;
}
expect(bump / 2000).toBeGreaterThan(BUMP_MOP_CHANCE - 0.05);
expect(bump / 2000).toBeLessThan(BUMP_MOP_CHANCE + 0.05);
expect(shan / 2000).toBeGreaterThan(SHAN_CLEAN_CHANCE - 0.05);
expect(shan / 2000).toBeLessThan(SHAN_CLEAN_CHANCE + 0.05);
});
it('orders take a real walk and cool down longer than they take', () => {
const rng = new SeededRNG(4).stream('s');
for (let i = 0; i < 100; i++) {
const lag = orderLag(rng);
expect(lag).toBeGreaterThanOrEqual(ORDER_LAG_MS[0]);
expect(lag).toBeLessThanOrEqual(ORDER_LAG_MS[1]);
}
expect(RADIO_COOLDOWN_MS.mess).toBeGreaterThan(ORDER_LAG_MS[1]);
expect(RADIO_COOLDOWN_MS.water).toBeGreaterThan(ORDER_LAG_MS[1]);
});
it("Shan's floor starts at loose — sober people are not a radio matter", () => {
expect(drunkStage(SHAN_MIN_INTOX)).toBe('loose');
});
it('the rope hold ends before it can be re-ordered', () => {
expect(KAYDEN_HOLD_COOLDOWN_MS).toBeGreaterThan(KAYDEN_HOLD_MS);
});
});