db+game: ship_systems table + starting ship seed (new game and v4 backfill step)

This commit is contained in:
2026-09-28 23:32:04 +00:00
parent c7580d92bd
commit 0910891995
5 changed files with 108 additions and 3 deletions
+24 -1
View File
@@ -6,6 +6,7 @@ import { eq } from 'drizzle-orm'
import { openGameDb, type GameDb } from '@/lib/db/client'
import * as schema from '@/lib/db/schema'
import { generateStartingCrew, rollCrewMember, startingCrewRng } from './crew'
import { BASE_CAPACITY, BASE_LEVEL, SHIP_TYPES } from './ship-costs'
import { SCHEMA_VERSION, getCrewState, getSystemState, explorePlanet, getWorldState, jumpToSystem, type WorldState } from './save'
import { bodyRng, explorationRng, generatePlanets, rollExploration } from './world'
@@ -325,10 +326,14 @@ describe('backfill (old saves)', () => {
const crewOf = (rows: { id: number; name: string; role: string; traitGood: string; traitBad: string; origin: string }[]) =>
rows.map((c) => ({ name: c.name, role: c.role, traitGood: c.traitGood, traitBad: c.traitBad, origin: c.origin })) // ids excluded — re-seed moves autoincrement on
const beforeCrew = crewOf(await db.db.select().from(schema.crew))
const shipOf = (rows: { id: number; type: string; level: number; capacity: number }[]) =>
rows.map((s) => ({ type: s.type, level: s.level, capacity: s.capacity })).sort((a, b) => a.type.localeCompare(b.type)) // ids excluded — re-seed moves autoincrement on
const beforeShip = shipOf(await db.db.select().from(schema.shipSystems))
// Simulate a save created by pre-v0.4 code: no bodies, no crew, no version stamp (NULL).
// Simulate a save created by pre-v0.4 code: no bodies, no crew, no ship, no version stamp (NULL).
await db.db.delete(schema.planets)
await db.db.delete(schema.crew)
await db.db.delete(schema.shipSystems)
await db.db.update(schema.saves).set({ schemaVersion: null })
const world = await getWorldState(db) // ensureSave → backfill runs
@@ -339,6 +344,7 @@ describe('backfill (old saves)', () => {
expect(bodyShape(rows.sort((a, b) => a.id - b.id))).toEqual(beforeBodies[s.id]) // identical to fresh generation
}
expect(crewOf(await db.db.select().from(schema.crew))).toEqual(beforeCrew)
expect(shipOf(await db.db.select().from(schema.shipSystems))).toEqual(beforeShip)
const [save] = await db.db.select().from(schema.saves)
expect(save.schemaVersion).toBe(SCHEMA_VERSION)
@@ -348,6 +354,7 @@ describe('backfill (old saves)', () => {
await getWorldState(db)
expect((await db.db.select().from(schema.planets)).length).toBe(planetCount)
expect((await db.db.select().from(schema.crew)).length).toBe(beforeCrew.length)
expect(shipOf(await db.db.select().from(schema.shipSystems))).toEqual(beforeShip)
for (const s of systems) {
const rows = await rowsFor(s.id)
expect(bodyShape(rows.sort((a, b) => a.id - b.id))).toEqual(beforeBodies[s.id])
@@ -364,4 +371,20 @@ describe('backfill (old saves)', () => {
await getWorldState(db) // second read: no backfill work to do
expect((await db.db.select().from(schema.planets)).length).toBe(planetCount)
})
it('seeds the starting ship on a new game: core types built at base values, WEAPONS unbuilt', async () => {
const { db } = await freshFile()
await getWorldState(db)
const rows = (await db.db.select().from(schema.shipSystems)).sort((a, b) => a.type.localeCompare(b.type))
expect(rows).toHaveLength(SHIP_TYPES.length)
for (const def of SHIP_TYPES) {
const row = rows.find((r) => r.type === def.type)!
if (def.builtAtStart) {
expect({ level: row.level, capacity: row.capacity }).toEqual({ level: BASE_LEVEL, capacity: BASE_CAPACITY })
} else {
expect(row.level).toBe(0) // unbuilt until a BUILD action
expect(row.capacity).toBe(0)
}
}
})
})