deadhead-space-freight-tycoon/packages/content/test/upgrades.test.ts

83 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
content,
gameConfig,
shipModels,
upgradeMaxLevel,
upgradePercentPerLevel,
upgradeSchema,
upgrades,
type ShipStat,
} from "../src/index";
const model = (id: string) => shipModels.find((m) => m.id === id)!;
const upgradeFor = (stat: ShipStat) => upgrades.find((u) => u.stat === stat)!;
/** A stat at the upgrade's max level for this model (decision 0.5.63: linear % of base). */
const maxed = (modelId: string, stat: Exclude<ShipStat, "handlingGameHoursPerTonne">) => {
const upgrade = upgradeFor(stat);
const level = upgradeMaxLevel(upgrade, modelId);
return model(modelId)[stat] * (1 + (upgradePercentPerLevel(upgrade, modelId) * level) / 100);
};
describe("ship upgrades content (CR-009)", () => {
it("has the five upgrades, all valid, three levels each", () => {
for (const upgrade of upgrades) expect(upgradeSchema.safeParse(upgrade).success).toBe(true);
expect(upgrades.map((u) => u.id)).toEqual([
"engines",
"cargo-bay",
"fuel-tanks",
"landing-thrusters",
"handling-gear",
]);
for (const upgrade of upgrades) expect(upgrade.maxLevel).toBe(3);
expect(content.upgrade("engines")?.name).toBe("Engine Tuning");
});
it("only changes stats ships have", () => {
for (const upgrade of upgrades) {
if (upgrade.stat === "handlingGameHoursPerTonne") {
// A game-wide base until upgraded.
expect(gameConfig.handlingGameHoursPerTonne).toBeGreaterThan(0);
} else {
for (const m of shipModels)
expect(m, `${m.id}.${upgrade.stat}`).toHaveProperty(upgrade.stat);
}
for (const id of Object.keys(upgrade.modelOverrides ?? {})) {
expect(content.shipModel(id), id).toBeDefined();
}
}
});
it("prices levels at 10/20/35 % of the ship and 10/20/30 minutes in the shop", () => {
expect(gameConfig.upgradeLevels).toEqual([
{ costPercentOfPrice: 10, shopRealMinutes: 10 },
{ costPercentOfPrice: 20, shopRealMinutes: 20 },
{ costPercentOfPrice: 35, shopRealMinutes: 30 },
]);
for (const upgrade of upgrades) {
for (const m of shipModels) {
expect(upgradeMaxLevel(upgrade, m.id)).toBeLessThanOrEqual(gameConfig.upgradeLevels.length);
}
}
});
it("keeps models distinct (decision 0.5.67)", () => {
expect(maxed("courier", "cargoCapacityTonnes")).toBeLessThan(
model("freighter").cargoCapacityTonnes,
);
expect(maxed("bulk-hauler", "cruiseSpeedKmPerGameHour")).toBeLessThan(
model("freighter").cruiseSpeedKmPerGameHour,
);
expect(maxed("freighter", "fuelRangeMillionKm")).toBeLessThan(
model("bulk-hauler").fuelRangeMillionKm,
);
// Amended by CR-012 (the Lighter's Mars cap is a sim test: upgrade-caps.test.ts).
expect(maxed("clipper", "cargoCapacityTonnes")).toBeLessThan(
model("freighter").cargoCapacityTonnes,
);
expect(maxed("courier", "cruiseSpeedKmPerGameHour")).toBeLessThan(
model("clipper").cruiseSpeedKmPerGameHour,
);
});
});