import { content } from "@deadhead/content"; import { describe, expect, it } from "vitest"; import { boardPeriodIndex, createRng, dutyAfterTrip, dutyLimit, isResting, needsRest, restEndsAt, tripGameHours, } from "../src/index"; const config = content.config; describe("pilot duty and rest (CR-004)", () => { it("raises the duty limit by the bonus for each Long Haul level", () => { expect(dutyLimit({}, config)).toBe(config.dutyLimitGameHours); for (let level = 1; level <= 5; level++) { expect(dutyLimit({ "long-haul": level }, config)).toBe( config.dutyLimitGameHours + level * config.longHaulDutyBonusGameHours, ); } // Other skills do not count. expect(dutyLimit({ "heavy-cargo": 3 }, config)).toBe(config.dutyLimitGameHours); }); it("is resting until, but not at, rest-ends-at", () => { const ends = Date.parse("2100-01-01T12:00:00Z"); expect(isResting(ends, ends - 1000)).toBe(true); expect(isResting(ends, ends)).toBe(false); expect(isResting(null, ends)).toBe(false); }); it("adds a trip's hours to duty, except for tutorial runs", () => { expect(dutyAfterTrip(3, 4, false)).toBe(7); expect(dutyAfterTrip(3, 4, true)).toBe(3); // One real minute is one game hour at 60× compression. expect(tripGameHours(0, 4 * 60_000, config)).toBeCloseTo(4); }); it("needs rest at or over the limit", () => { expect(needsRest(dutyAfterTrip(10, 4, false), 12)).toBe(true); expect(needsRest(dutyAfterTrip(4, 4, false), 12)).toBe(false); expect(needsRest(12, 12)).toBe(true); }); it("always wakes a rested pilot in a later board period", () => { const rng = createRng(2026); for (let i = 0; i < 2000; i++) { const start = Math.floor(rng.next() * 1e13); expect(boardPeriodIndex(restEndsAt(start, config), config)).toBeGreaterThan( boardPeriodIndex(start, config), ); } }); });