import { content } from "@deadhead/content"; import { describe, expect, it } from "vitest"; import { createDispatchRecord, createRepositionRecord, resolveDispatch, type Contract, type PilotState, type ResolveInput, type ShipState, } from "../src/index"; const now = Date.parse("2100-01-01T00:30:00Z"); const contract: Contract = { id: "c1", originId: "earth", destinationId: "moon", cargoTypeId: "standard", tier: 0, massTonnes: 10, payout: 2000, requiredSkill: null, requiredLongHaulLevel: 0, offeredAt: Date.parse("2100-01-01T00:00:00Z"), expiresAt: Date.parse("2100-01-01T01:00:00Z"), firstContact: false, }; const ship: ShipState = { id: "s1", modelId: "courier", locationId: "earth", inFlight: false }; const pilot: PilotState = { id: "p1", isAvatar: false, assignedShipId: "s1", inFlight: false, skills: {}, }; const record = createDispatchRecord( { id: "d1", ship, pilot, contract, tutorial: false, now, worldSeed: 7 }, content, ); const arrived: ResolveInput = { record, pilotIsAvatar: false, discoveredIds: new Set(["earth", "moon"]), now: record.arrivalAt, }; const resolve = (input: ResolveInput) => { const result = resolveDispatch(input, content); if (result.status !== "resolved") throw new Error("expected a resolution"); return result.resolution; }; describe("dispatch resolution", () => { it("reports in flight before arrival", () => { expect(resolveDispatch({ ...arrived, now: record.arrivalAt - 1 }, content)).toEqual({ status: "in-flight", }); }); it("resolves at and after arrival, moving the ship to the destination", () => { expect(resolve(arrived).shipLocationId).toBe("moon"); expect(resolveDispatch({ ...arrived, now: record.arrivalAt + 60_000 }, content).status).toBe( "resolved", ); }); it("deducts pilot pay for a hired pilot and grants XP", () => { const resolution = resolve(arrived); expect(resolution.credits).toBe(2000 - content.config.pilotPayPerDelivery); expect(resolution.pilotXp).toBeGreaterThan(0); }); it("deducts no pilot pay when the avatar flies", () => { expect(resolve({ ...arrived, pilotIsAvatar: true }).credits).toBe(2000); }); it("pays exactly the stored tutorial share on a tutorial run", () => { const tutorialRecord = createDispatchRecord( { id: "t1", ship: { ...ship, id: "loaner" }, pilot: { ...pilot, id: "avatar", isAvatar: true, assignedShipId: null }, contract: { ...contract, payout: 1000 }, tutorial: true, now, worldSeed: 7, }, content, ); const resolution = resolve({ ...arrived, record: tutorialRecord, pilotIsAvatar: true }); expect(resolution.credits).toBe(1000); expect(resolution.shipLocationId).toBe("moon"); }); it("marks an undiscovered destination as discovered", () => { expect(resolve(arrived).discoversDestination).toBe(false); expect(resolve({ ...arrived, discoveredIds: new Set(["earth"]) }).discoversDestination).toBe( true, ); }); it("gives no credits or XP for a reposition", () => { const reposition = createRepositionRecord( { id: "r1", ship, pilot, destinationId: "moon", now, worldSeed: 7 }, content, ); expect(resolve({ ...arrived, record: reposition, now: reposition.arrivalAt })).toEqual({ credits: 0, pilotXp: 0, shipLocationId: "moon", discoversDestination: false, }); }); it("returns identical results when resolving the same dispatch twice", () => { expect(resolveDispatch(arrived, content)).toEqual(resolveDispatch(arrived, content)); }); });