104 lines
4.1 KiB
TypeScript
104 lines
4.1 KiB
TypeScript
import { content } from "@deadhead/content";
|
||
import { boardPeriodMs } from "@deadhead/sim";
|
||
import { describe, expect, it } from "vitest";
|
||
import { encodeSave } from "../src/index";
|
||
import {
|
||
addPilot,
|
||
addShip,
|
||
readSave,
|
||
setCredits,
|
||
signUpOwner,
|
||
TEST_NOW,
|
||
useTestApp,
|
||
} from "./support";
|
||
|
||
const testApp = useTestApp();
|
||
const COURIER_HOLD = content.shipModel("courier")!.cargoCapacityTonnes;
|
||
const PERIOD = boardPeriodMs(content.config);
|
||
|
||
describe("completable boards in the engine (Step 19.3, decisions 0.5.114–0.5.117)", () => {
|
||
it("hides a heavy job once the only ship that could take it has left", async () => {
|
||
const { app, clock } = testApp();
|
||
await signUpOwner(app);
|
||
await addShip(app, { id: "f1", modelId: "freighter", name: "Big Wren" });
|
||
await addPilot(app, { id: "p1", name: "Ada", assignedShipId: "f1" });
|
||
|
||
const before = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
|
||
const heavy = before.filter((c) => c.massTonnes > COURIER_HOLD);
|
||
expect(heavy.length).toBeGreaterThan(0);
|
||
|
||
// The Freighter flies empty to the Moon; the Courier is still at Earth.
|
||
await app.call("createDispatch", {
|
||
kind: "reposition",
|
||
shipId: "f1",
|
||
pilotId: "p1",
|
||
destinationId: "moon",
|
||
});
|
||
clock.now += 1_000;
|
||
const after = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
|
||
expect(after.filter((c) => c.massTonnes > COURIER_HOLD)).toEqual([]);
|
||
// What the Courier can take is still there, unchanged.
|
||
expect(after).toEqual(before.filter((c) => c.massTonnes <= COURIER_HOLD));
|
||
});
|
||
|
||
it("adds a bigger ship's jobs at the next board period, not mid-period", async () => {
|
||
const { app, clock } = testApp();
|
||
const owner = await signUpOwner(app);
|
||
const first = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
|
||
expect(first.every((c) => c.massTonnes <= COURIER_HOLD)).toBe(true);
|
||
|
||
await setCredits(app, content.shipModel("freighter")!.price);
|
||
const { ship } = await app.call("buyShip", { modelId: "freighter", bayId: owner.earthBayId });
|
||
await addPilot(app, { id: "p1", name: "Ada", assignedShipId: ship.id });
|
||
clock.now += 1_000;
|
||
expect((await app.call("getContractBoard", { locationId: "earth" })).contracts).toEqual(first);
|
||
|
||
// Next period: the board is made for the Courier and the Freighter.
|
||
clock.now = (Math.floor(TEST_NOW / PERIOD) + 1) * PERIOD + 1_000;
|
||
let heavy = 0;
|
||
for (let period = 0; period < 5; period++, clock.now += PERIOD) {
|
||
const board = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
|
||
heavy += board.filter((c) => c.massTonnes > COURIER_HOLD).length;
|
||
}
|
||
expect(heavy).toBeGreaterThan(0);
|
||
});
|
||
|
||
it("stores the qualifying fleet with each board it generates", async () => {
|
||
const { app } = testApp();
|
||
await signUpOwner(app);
|
||
await app.call("getContractBoard", { locationId: "earth" });
|
||
const [board] = (await readSave(app)).contractBoards.filter((b) => b.kind === "location");
|
||
expect(board!.fleet).toEqual([
|
||
{
|
||
modelId: "courier",
|
||
skills: {},
|
||
upgrades: {},
|
||
fuelFu: content.shipModel("courier")!.tankCapacityFu,
|
||
},
|
||
]);
|
||
});
|
||
|
||
it("opens an older save with no stored boards, and regenerates them on view", async () => {
|
||
const { app } = testApp();
|
||
await signUpOwner(app);
|
||
const before = (await app.call("getContractBoard", { locationId: "earth" })).contracts;
|
||
const old = await readSave(app);
|
||
expect(old.contractBoards.length).toBeGreaterThan(0);
|
||
// As version 3 wrote it: boards without a fleet snapshot.
|
||
const v3 = {
|
||
...old,
|
||
saveVersion: 3,
|
||
contractBoards: old.contractBoards.map(({ fleet: _fleet, ...rest }) => rest),
|
||
};
|
||
|
||
const device = testApp().app;
|
||
await device.call("importSave", { code: await encodeSave(v3 as never) });
|
||
expect((await readSave(device)).contractBoards).toEqual([]);
|
||
// The same inputs regenerate the same board.
|
||
expect((await device.call("getContractBoard", { locationId: "earth" })).contracts).toEqual(
|
||
before,
|
||
);
|
||
expect((await readSave(device)).contractBoards).toHaveLength(1);
|
||
});
|
||
});
|