55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
import { content } from "@deadhead/content";
|
||
import { beforeAll, describe, expect, it } from "vitest";
|
||
import { formatFuelShares, fuelShares, type FuelShare } from "../balance/fuel-share";
|
||
import { checkRoute, fuelPriceAt, legFuel, routeDistance } from "../src/index";
|
||
|
||
const loc = (id: string) => content.location(id)!;
|
||
|
||
let rows: FuelShare[];
|
||
beforeAll(() => {
|
||
rows = fuelShares(content);
|
||
});
|
||
|
||
describe("fuel-to-payout check (CR-018 Step 18.1, decision 0.5.110)", () => {
|
||
it("reports every purchasable ship on every route it can fly", () => {
|
||
const models = content.shipModels.filter((m) => m.purchasable);
|
||
expect(new Set(rows.map((r) => r.modelId))).toEqual(new Set(models.map((m) => m.id)));
|
||
for (const row of rows) {
|
||
const model = content.shipModel(row.modelId)!;
|
||
expect(checkRoute(model, loc(row.originId), loc(row.destinationId), content.config).ok).toBe(
|
||
true,
|
||
);
|
||
expect(row.contracts).toBeGreaterThan(0);
|
||
}
|
||
// Every Earth–Moon leg is flown by every purchasable ship, and boards always offer it.
|
||
for (const model of models) {
|
||
expect(
|
||
rows.some(
|
||
(r) => r.modelId === model.id && r.originId === "earth" && r.destinationId === "moon",
|
||
),
|
||
).toBe(true);
|
||
}
|
||
});
|
||
|
||
it("prices a leg's fuel at the origin and divides by the median fitting payout", () => {
|
||
const row = rows.find(
|
||
(r) => r.modelId === "courier" && r.originId === "earth" && r.destinationId === "moon",
|
||
)!;
|
||
const courier = content.shipModel("courier")!;
|
||
const fuel =
|
||
legFuel(courier, loc("earth"), routeDistance(loc("earth"), loc("moon")), content.config) *
|
||
fuelPriceAt(loc("earth"), content.config);
|
||
expect(row.fuelCost).toBeCloseTo(fuel, 9);
|
||
expect(row.share).toBeCloseTo(row.fuelCost / row.medianPayout, 12);
|
||
expect(row.medianPayout).toBeGreaterThan(0);
|
||
});
|
||
|
||
it("reports the share for each ship and route as a table", () => {
|
||
const table = formatFuelShares(rows).split("\n");
|
||
expect(table).toHaveLength(rows.length + 1);
|
||
expect(
|
||
table.find((line) => line.startsWith("courier") && line.includes("earth → moon")),
|
||
).toMatch(/\d+\.\d%$/);
|
||
});
|
||
});
|