81 lines
2.8 KiB
TypeScript
81 lines
2.8 KiB
TypeScript
import { content } from "@deadhead/content";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
createRepositionRecord,
|
|
validateReposition,
|
|
type PilotState,
|
|
type RepositionProposal,
|
|
type ShipState,
|
|
} from "../src/index";
|
|
|
|
const now = Date.parse("2100-01-01T00:30:00Z");
|
|
const atEarth: ShipState = { id: "s1", modelId: "courier", locationId: "earth", inFlight: false };
|
|
const pilot: PilotState = {
|
|
id: "p1",
|
|
isAvatar: false,
|
|
assignedShipId: "s1",
|
|
inFlight: false,
|
|
skills: {},
|
|
};
|
|
/** No bays anywhere: deadheads depend only on discovery, range and landing (CR-002). */
|
|
const valid: RepositionProposal = {
|
|
ship: atEarth,
|
|
pilot,
|
|
destinationId: "moon",
|
|
discoveredIds: new Set(["earth", "moon"]),
|
|
credits: 10_000,
|
|
now,
|
|
};
|
|
|
|
const reason = (proposal: RepositionProposal) => {
|
|
const result = validateReposition(proposal, content);
|
|
return result.ok ? "valid" : result.reason;
|
|
};
|
|
|
|
describe("deadhead (fly empty)", () => {
|
|
it("lets a Courier idle at the Moon, with no Moon bay, deadhead to Earth", () => {
|
|
const atMoon = { ...atEarth, locationId: "moon" };
|
|
expect(reason({ ...valid, ship: atMoon, destinationId: "earth" })).toBe("valid");
|
|
});
|
|
|
|
it("needs no skills", () => {
|
|
expect(reason(valid)).toBe("valid");
|
|
});
|
|
|
|
it("refuses an undiscovered destination with location-undiscovered", () => {
|
|
expect(reason({ ...valid, destinationId: "mars" })).toBe("location-undiscovered");
|
|
});
|
|
|
|
it("refuses the ship's own location", () => {
|
|
expect(reason({ ...valid, destinationId: "earth" })).toBe("already-there");
|
|
});
|
|
|
|
it("refuses an out-of-range destination with the out-of-range reason", () => {
|
|
const discovered = new Set(["earth", "moon", "mars"]);
|
|
expect(reason({ ...valid, destinationId: "mars", discoveredIds: discovered })).toBe(
|
|
"out-of-range",
|
|
);
|
|
});
|
|
|
|
it("still needs fuel credits, an idle crew and an assigned pilot", () => {
|
|
expect(reason({ ...valid, credits: 0 })).toBe("insufficient-credits");
|
|
expect(reason({ ...valid, ship: { ...atEarth, inFlight: true } })).toBe("ship-not-idle");
|
|
expect(reason({ ...valid, pilot: { ...pilot, inFlight: true } })).toBe("pilot-not-idle");
|
|
expect(reason({ ...valid, pilot: { ...pilot, assignedShipId: null } })).toBe(
|
|
"pilot-not-assigned",
|
|
);
|
|
});
|
|
|
|
it("creates a record with no contract, zero payout and a fuel charge", () => {
|
|
const record = createRepositionRecord(
|
|
{ id: "r1", ship: atEarth, pilot, destinationId: "moon", now, worldSeed: 7 },
|
|
content,
|
|
);
|
|
expect(record.contract).toBeNull();
|
|
expect(record.expectedPayout).toBe(0);
|
|
expect(record.fuelCost).toBeGreaterThan(0);
|
|
expect([record.originId, record.destinationId]).toEqual(["earth", "moon"]);
|
|
expect(record.arrivalAt).toBeGreaterThan(record.departureAt);
|
|
});
|
|
});
|