84 lines
3.3 KiB
TypeScript
84 lines
3.3 KiB
TypeScript
import { content, type ShipModel } from "@deadhead/content";
|
|
import { describe, expect, it } from "vitest";
|
|
import { checkRoute, routeDistance } from "../src/index";
|
|
|
|
const earth = content.location("earth")!;
|
|
const moon = content.location("moon")!;
|
|
const mars = content.location("mars")!;
|
|
const ceres = content.location("ceres-station")!;
|
|
const jupiter = content.location("jupiter-cloud-platform")!;
|
|
const courier = content.shipModel("courier")!;
|
|
const freighter = content.shipModel("freighter")!;
|
|
const bulkHauler = content.shipModel("bulk-hauler")!;
|
|
|
|
/** Test-only ship that cannot land on atmospheric worlds. */
|
|
const vacuumShip: ShipModel = { ...courier, id: "test-vacuum", landingClass: "vacuum" };
|
|
|
|
// Every 4 days across 12 years (one Jupiter orbit).
|
|
const start = Date.parse("2100-01-01T00:00:00Z");
|
|
const samples = Array.from({ length: 1096 }, (_, i) => start + i * 4 * 86_400_000);
|
|
|
|
/** The sampled time when `to` is closest to (or farthest from) Earth. */
|
|
function extremeTime(to: typeof mars, pick: "closest" | "farthest"): number {
|
|
let best = samples[0]!;
|
|
let bestDistance = routeDistance(earth, to, best);
|
|
for (const t of samples) {
|
|
const d = routeDistance(earth, to, t);
|
|
if (pick === "closest" ? d < bestDistance : d > bestDistance) {
|
|
best = t;
|
|
bestDistance = d;
|
|
}
|
|
}
|
|
return best;
|
|
}
|
|
|
|
// Origins are named in every test (decision 0.5.77: range is per leg, from its origin).
|
|
describe("route eligibility", () => {
|
|
it("lets a Courier fly Earth→Moon and Moon→Earth", () => {
|
|
expect(checkRoute(courier, earth, moon, start)).toEqual({ ok: true });
|
|
expect(checkRoute(courier, moon, earth, start)).toEqual({ ok: true });
|
|
});
|
|
|
|
it("keeps a Courier from Earth out of range of Mars, Ceres and Jupiter even at their closest", () => {
|
|
for (const to of [mars, ceres, jupiter]) {
|
|
expect(checkRoute(courier, earth, to, extremeTime(to, "closest"))).toEqual({
|
|
ok: false,
|
|
reason: "out-of-range",
|
|
});
|
|
}
|
|
});
|
|
|
|
it("rejects a vacuum-only ship at Earth because it cannot land", () => {
|
|
expect(checkRoute(vacuumShip, moon, earth, start)).toEqual({
|
|
ok: false,
|
|
reason: "cannot-land",
|
|
});
|
|
expect(checkRoute(vacuumShip, earth, moon, start)).toEqual({ ok: true });
|
|
});
|
|
|
|
it("lets a Freighter from Earth reach Mars even at its farthest", () => {
|
|
expect(checkRoute(freighter, earth, mars, extremeTime(mars, "farthest"))).toEqual({ ok: true });
|
|
});
|
|
|
|
it("lets a Freighter from Earth reach Ceres at its closest but not its farthest (CR-012)", () => {
|
|
expect(checkRoute(freighter, earth, ceres, extremeTime(ceres, "closest"))).toEqual({
|
|
ok: true,
|
|
});
|
|
expect(checkRoute(freighter, earth, ceres, extremeTime(ceres, "farthest")).ok).toBe(false);
|
|
});
|
|
|
|
it("lets only the Bulk Hauler reach Jupiter from Earth at its farthest", () => {
|
|
const t = extremeTime(jupiter, "farthest");
|
|
expect(checkRoute(bulkHauler, earth, jupiter, t)).toEqual({ ok: true });
|
|
expect(checkRoute(freighter, earth, jupiter, t).ok).toBe(false);
|
|
expect(checkRoute(courier, earth, jupiter, t).ok).toBe(false);
|
|
});
|
|
|
|
it("keeps a Freighter from Earth out of Jupiter's range even at its closest (CR-012 amends 0.5.25)", () => {
|
|
expect(checkRoute(freighter, earth, jupiter, extremeTime(jupiter, "closest"))).toEqual({
|
|
ok: false,
|
|
reason: "out-of-range",
|
|
});
|
|
});
|
|
});
|