deadhead-space-freight-tycoon/packages/sim/test/reach-table.test.ts

92 lines
4.0 KiB
TypeScript

import { content } from "@deadhead/content";
import { describe, expect, it } from "vitest";
import { checkRoute, realToGame } from "../src/index";
/** CR-012 §3: reach targets for base ships, monthly over 16 game years (decision 0.5.81). */
const start = realToGame(Date.parse(content.config.epoch.realStart), content.config);
const MONTH = 30.44 * 24 * 3_600_000;
const samples = Array.from({ length: 16 * 12 + 1 }, (_, i) => start + i * MONTH);
const ids = content.locations.map((l) => l.id);
/** Share of sampled dates on which the leg is in range for the base ship. */
function share(modelId: string, fromId: string, toId: string): number {
const ship = content.shipModel(modelId)!;
const from = content.location(fromId)!;
const to = content.location(toId)!;
return samples.filter((t) => checkRoute(ship, from, to, t).ok).length / samples.length;
}
const always = (m: string, from: string, to: string) => expect(share(m, from, to)).toBe(1);
const never = (m: string, from: string, to: string) => expect(share(m, from, to)).toBe(0);
const some = (m: string, from: string, to: string) => {
const s = share(m, from, to);
expect(s).toBeGreaterThan(0);
expect(s).toBeLessThan(1);
return s;
};
describe("reach table (Step 10L.4)", () => {
for (const model of ["courier", "lighter"]) {
describe(model, () => {
it("flies Earth↔Moon always", () => {
always(model, "earth", "moon");
always(model, "moon", "earth");
});
it("never reaches Mars from Earth", () => never(model, "earth", "mars"));
it("never reaches Mars from the Moon", () => never(model, "moon", "mars"));
});
}
describe("clipper", () => {
it("reaches Mars from Earth on some dates, at least 30 %", () => {
expect(some("clipper", "earth", "mars")).toBeGreaterThanOrEqual(0.3);
});
it("reaches Mars from the Moon on some dates, more than from Earth", () => {
expect(some("clipper", "moon", "mars")).toBeGreaterThan(share("clipper", "earth", "mars"));
});
it("reaches Ceres from Mars on some dates", () => some("clipper", "mars", "ceres-station"));
it("never reaches Ceres from Earth", () => never("clipper", "earth", "ceres-station"));
it("never reaches Ceres from the Moon", () => never("clipper", "moon", "ceres-station"));
it("never reaches Jupiter from anywhere", () => {
for (const from of ids)
if (from !== "jupiter-cloud-platform") {
never("clipper", from, "jupiter-cloud-platform");
}
});
});
describe("freighter", () => {
it("reaches Mars from Earth always", () => always("freighter", "earth", "mars"));
it("reaches Ceres from Earth on most dates", () => {
expect(some("freighter", "earth", "ceres-station")).toBeGreaterThan(0.5);
});
it("reaches Jupiter from Ceres on some dates", () =>
some("freighter", "ceres-station", "jupiter-cloud-platform"));
it("never reaches Jupiter from Earth", () =>
never("freighter", "earth", "jupiter-cloud-platform"));
it("never reaches Jupiter from the Moon", () =>
never("freighter", "moon", "jupiter-cloud-platform"));
it("never reaches Jupiter from Mars", () =>
never("freighter", "mars", "jupiter-cloud-platform"));
});
describe("bulk-hauler", () => {
it("reaches Jupiter from Earth always", () =>
always("bulk-hauler", "earth", "jupiter-cloud-platform"));
it("flies every other leg between the five locations always", () => {
for (const from of ids)
for (const to of ids) if (from !== to) always("bulk-hauler", from, to);
});
});
describe("hops", () => {
it("a Clipper can't reach Ceres from Earth on any date but can from Mars on some", () => {
never("clipper", "earth", "ceres-station");
some("clipper", "mars", "ceres-station");
});
it("a Freighter can reach Jupiter from Ceres on some dates but never directly from Earth", () => {
some("freighter", "ceres-station", "jupiter-cloud-platform");
never("freighter", "earth", "jupiter-cloud-platform");
});
});
});