102 lines
4.0 KiB
TypeScript
102 lines
4.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
||
import { content, type FixedPosition } from "../src/index";
|
||
import { offsetPosition } from "../src/data/locations";
|
||
// Vite reads the lockfile as text at test time.
|
||
import lockfile from "../../../pnpm-lock.yaml?raw";
|
||
|
||
function point(p: FixedPosition) {
|
||
const a = (p.angleDegrees * Math.PI) / 180;
|
||
return { x: p.radiusMillionKm * Math.cos(a), y: p.radiusMillionKm * Math.sin(a) };
|
||
}
|
||
function distance(fromId: string, toId: string): number {
|
||
const a = point(content.location(fromId)!.position);
|
||
const b = point(content.location(toId)!.position);
|
||
return Math.hypot(b.x - a.x, b.y - a.y);
|
||
}
|
||
|
||
describe("fixed map (Step 15.1, decision 0.5.93)", () => {
|
||
it("gives every location a fixed position", () => {
|
||
for (const location of content.locations) {
|
||
expect(location.position.radiusMillionKm, location.id).toBeGreaterThan(0);
|
||
expect(Number.isFinite(location.position.angleDegrees), location.id).toBe(true);
|
||
}
|
||
});
|
||
|
||
it("defines the Moon as an offset from Earth", () => {
|
||
const moon = content.location("moon")!;
|
||
expect(moon.orbitParent).toEqual({ locationId: "earth", offsetMillionKm: 0.384 });
|
||
expect(moon.position).toEqual(offsetPosition(content.location("earth")!.position, 0.384));
|
||
expect(distance("earth", "moon")).toBeCloseTo(0.384, 6);
|
||
});
|
||
|
||
it("puts every child body at its parent plus its offset", () => {
|
||
for (const location of content.locations.filter((l) => l.orbitParent)) {
|
||
const { locationId, offsetMillionKm } = location.orbitParent!;
|
||
const parent = content.location(locationId)!;
|
||
expect(location.position, location.id).toEqual(
|
||
offsetPosition(parent.position, offsetMillionKm),
|
||
);
|
||
}
|
||
});
|
||
|
||
it.each([
|
||
["earth", "mars", 201],
|
||
["mars", "ceres-station", 202],
|
||
["earth", "ceres-station", 402],
|
||
["ceres-station", "jupiter-cloud-platform", 393],
|
||
["mars", "jupiter-cloud-platform", 592],
|
||
["earth", "jupiter-cloud-platform", 792],
|
||
])("puts %s–%s at about %i M km (CR-015 §2, within 2 %)", (from, to, expected) => {
|
||
const d = distance(from, to);
|
||
expect(Math.abs(d - expected) / expected).toBeLessThan(0.02);
|
||
expect(distance(to, from)).toBeCloseTo(d, 9);
|
||
});
|
||
|
||
it("no longer depends on astronomy-engine", () => {
|
||
expect(lockfile).not.toContain("astronomy-engine");
|
||
});
|
||
});
|
||
|
||
describe("new locations (Step 16.1, decision 0.5.100)", () => {
|
||
it.each([
|
||
["earth", "venus-cloud-city", 200],
|
||
["moon", "venus-cloud-city", 200],
|
||
["venus-cloud-city", "mars", 332],
|
||
["venus-cloud-city", "ceres-station", 520],
|
||
["venus-cloud-city", "jupiter-cloud-platform", 885],
|
||
["ceres-station", "io-sulfur-works", 393],
|
||
["ceres-station", "europa-ice-station", 393],
|
||
])("puts %s–%s at about %i M km (CR-016 §2, within 2 %)", (from, to, expected) => {
|
||
expect(Math.abs(distance(from, to) - expected) / expected).toBeLessThan(0.02);
|
||
});
|
||
|
||
it("keeps the Jupiter system within 1.1M km of the platform", () => {
|
||
const system = ["jupiter-cloud-platform", "io-sulfur-works", "europa-ice-station"];
|
||
for (const a of system) for (const b of system) expect(distance(a, b)).toBeLessThan(1.1);
|
||
});
|
||
|
||
it("rides Io and Europa with Jupiter, at their offsets", () => {
|
||
expect(content.location("io-sulfur-works")!.orbitParent).toEqual({
|
||
locationId: "jupiter-cloud-platform",
|
||
offsetMillionKm: 0.42,
|
||
});
|
||
expect(content.location("europa-ice-station")!.orbitParent).toEqual({
|
||
locationId: "jupiter-cloud-platform",
|
||
offsetMillionKm: 0.67,
|
||
});
|
||
});
|
||
|
||
it("starts all three undiscovered, selling fuel, landable without Hardened ships", () => {
|
||
for (const id of ["venus-cloud-city", "io-sulfur-works", "europa-ice-station"]) {
|
||
const location = content.location(id)!;
|
||
expect(location.startsDiscovered, id).toBe(false);
|
||
expect(location.sellsFuel, id).toBe(true);
|
||
expect(location.landingRequirement, id).not.toBe("hardened");
|
||
}
|
||
expect(content.locations.filter((l) => l.startsDiscovered).map((l) => l.id)).toEqual([
|
||
"earth",
|
||
"moon",
|
||
]);
|
||
});
|
||
});
|