import { content } from "@deadhead/content"; import { describe, expect, it } from "vitest"; import { boardPeriodIndex, boardPeriodMs, generateContractBoard, requiredLongHaulLevel, type BoardInput, } from "../src/index"; const earth = content.location("earth")!; const discoveredIds = new Set(["earth", "moon"]); const periodIndex = boardPeriodIndex(Date.parse("2100-01-01T00:00:00Z"), content.config); const input: BoardInput = { origin: earth, discoveredIds, periodIndex, worldSeed: 12345 }; describe("contract board generation", () => { it("produces an identical board from the same inputs", () => { expect(generateContractBoard(input, content)).toEqual(generateContractBoard(input, content)); }); it("produces a different board for a different period", () => { const next = generateContractBoard({ ...input, periodIndex: periodIndex + 1 }, content); expect(next).not.toEqual(generateContractBoard(input, content)); }); it("has the configured number of contracts, none to its own origin", () => { const board = generateContractBoard(input, content); expect(board).toHaveLength(content.config.contractBoardSize); for (const contract of board) { expect(contract.originId).toBe("earth"); expect(contract.destinationId).not.toBe("earth"); } }); it("expires every contract at the end of its board period", () => { const periodEnd = (periodIndex + 1) * boardPeriodMs(content.config); for (const contract of generateContractBoard(input, content)) { expect(contract.expiresAt).toBe(periodEnd); } }); it("ties tier to skill: Standard is tier 0 with no skill, others 1–5 matching the skill level", () => { const moon = content.location("moon")!; for (let p = 0; p < 50; p++) { for (const c of generateContractBoard({ ...input, origin: moon, periodIndex: p }, content)) { if (c.cargoTypeId === "standard") { expect(c.tier).toBe(0); expect(c.requiredSkill).toBeNull(); } else { expect(c.tier).toBeGreaterThanOrEqual(1); expect(c.tier).toBeLessThanOrEqual(5); expect(c.requiredSkill?.level).toBe(c.tier); } expect(c.massTonnes).toBeGreaterThanOrEqual(content.config.contractMassTonnes.min); expect(c.massTonnes).toBeLessThanOrEqual(content.config.contractMassTonnes.max); } } }); it("makes 5–15% of contracts first contact over 1,000 boards, all to undiscovered places", () => { let total = 0; let firstContact = 0; for (let p = 0; p < 1000; p++) { for (const contract of generateContractBoard({ ...input, periodIndex: p }, content)) { total++; if (contract.firstContact) { firstContact++; expect(discoveredIds.has(contract.destinationId)).toBe(false); } else { expect(discoveredIds.has(contract.destinationId)).toBe(true); } } } const share = firstContact / total; expect(share).toBeGreaterThanOrEqual(0.05); expect(share).toBeLessThanOrEqual(0.15); }); }); describe("required Long Haul level", () => { it("counts the cut-offs a distance exceeds", () => { expect(requiredLongHaulLevel(0.4, content.config)).toBe(0); expect(requiredLongHaulLevel(100, content.config)).toBe(0); expect(requiredLongHaulLevel(101, content.config)).toBe(1); expect(requiredLongHaulLevel(900, content.config)).toBe(5); }); });