Step 2.6: export a single content bundle
CI / check (push) Successful in 24s
Details
CI / check (push) Successful in 24s
Details
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2c211524d3
commit
241e2613f4
|
|
@ -72,3 +72,8 @@ Implementation decisions not spelled out in `memory-bank/implementation-plan.md`
|
|||
- **Starting credits are 0.** The company pays fuel during the tutorial, and the ~21-run target already assumes the player starts with nothing.
|
||||
- **Other defaults:** board size 8, tutorial board 40 (more than the ~30 runs that fit in a 60-minute period), first contact 10% at ×2 pay, contract mass 5–400 t, Long Haul cut-offs 100/250/400/600/800M km, ten pilot levels at 2 skill points each (enough to max all four skills), hire cost 2,000, pilot pay 100 per delivery.
|
||||
- **Known balance issue for Phase 12:** pay is linear in distance, but every trip pays a fixed overhead, so short Earth–Moon runs earn far less per real hour than long runs (a Freighter on Mars earns roughly 50× a Courier on the Moon).
|
||||
|
||||
## Step 2.6
|
||||
|
||||
- **Lookups return `undefined`** for an unknown id ("not found" without throwing). Callers decide whether a missing id is an error.
|
||||
- **The package also exports each data list and schema individually**, alongside the `content` bundle, so tests and the server can validate data with the schemas.
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@
|
|||
- [x] **Step 2.3 — The three ship models.** `src/data/ships.ts`: Courier, Freighter, Bulk Hauler, all atmospheric. Speed, capacity and price orderings tested; range rules are checked in Step 3.7.
|
||||
- [x] **Step 2.4 — Cargo types and skills.** `src/data/cargo.ts`: Standard, Heavy, High-Value, Dangerous; skills Long Haul, Heavy Cargo, Expensive Cargo, Dangerous Cargo (max level 5). The location test now checks cargo ids against the real data.
|
||||
- [x] **Step 2.5 — Default game config.** `src/data/config.ts`. Courier + Earth bay ≈ 21 tutorial runs with the placeholder average payout. Money values rescaled ×10 so tutorial runs pay meaningful amounts; epoch moved from `.env.example` into GameConfig.
|
||||
- [ ] Step 2.6 — Single content bundle
|
||||
- [x] **Step 2.6 — Single content bundle.** `content` in `src/bundle.ts` holds all data plus `location`, `shipModel`, `cargoType` and `skill` lookups that return `undefined` for unknown ids.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { cargoTypes, skills } from "./data/cargo";
|
||||
import { gameConfig } from "./data/config";
|
||||
import { locations } from "./data/locations";
|
||||
import { shipModels } from "./data/ships";
|
||||
|
||||
/** Returns a lookup that gives `undefined` for an unknown id instead of throwing. */
|
||||
function byId<T extends { id: string }>(items: readonly T[]): (id: string) => T | undefined {
|
||||
const map = new Map(items.map((item) => [item.id, item]));
|
||||
return (id) => map.get(id);
|
||||
}
|
||||
|
||||
/** All static game data in one object, with lookups by id. */
|
||||
export const content = {
|
||||
locations,
|
||||
shipModels,
|
||||
cargoTypes,
|
||||
skills,
|
||||
config: gameConfig,
|
||||
location: byId(locations),
|
||||
shipModel: byId(shipModels),
|
||||
cargoType: byId(cargoTypes),
|
||||
skill: byId(skills),
|
||||
};
|
||||
export type Content = typeof content;
|
||||
|
|
@ -3,3 +3,4 @@ export * from "./data/locations";
|
|||
export * from "./data/ships";
|
||||
export * from "./data/cargo";
|
||||
export * from "./data/config";
|
||||
export * from "./bundle";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { content } from "../src/index";
|
||||
|
||||
describe("content bundle", () => {
|
||||
it("contains every kind of content", () => {
|
||||
expect(content.locations).toHaveLength(5);
|
||||
expect(content.shipModels).toHaveLength(3);
|
||||
expect(content.cargoTypes).toHaveLength(4);
|
||||
expect(content.skills).toHaveLength(4);
|
||||
expect(content.config.timeCompression).toBe(60);
|
||||
});
|
||||
|
||||
it("looks up one item of each kind by id", () => {
|
||||
expect(content.location("mars")?.name).toBe("Mars");
|
||||
expect(content.shipModel("freighter")?.name).toBe("Freighter");
|
||||
expect(content.cargoType("dangerous")?.name).toBe("Dangerous");
|
||||
expect(content.skill("long-haul")?.name).toBe("Long Haul");
|
||||
});
|
||||
|
||||
it("returns undefined for an unknown id without throwing", () => {
|
||||
expect(content.location("pluto")).toBeUndefined();
|
||||
expect(content.shipModel("x-wing")).toBeUndefined();
|
||||
expect(content.cargoType("cheese")).toBeUndefined();
|
||||
expect(content.skill("juggling")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue