v0.1.9: 百年报告 & 发布之窗(报告/迁移/阵型/冬祷/哨兵)
- 百年族史报告:buildReport 纯函数(人口/声望/战力三线、死因榜、突破密度、 大比战绩、代际长度带)+ 春秋原 SVG 折线视图 + 自动措辞结语 - 存档迁移管线 v2:migrate 链(v1→v2)+ 未来版本拒载(TOO_NEW)+ 导出信封 带 appId/schemaVersion + 导入全链路迁移校验;saveState 自动写 CURRENT_SCHEMA - 战斗阵型:锋阵(+10%攻)/雁阵(御5%+溃伤-15%)/蛇阵(溃伤-30%),三处出战接入 (遣队/大比/劫掠)点将面板下拉 + 战报首行标阵 - 冬至岁祷:每年十一月三选(观星+3声望/祈福全族修为/问卜吉凶) - 发布准备:scripts/verify-release.mjs 验收哨兵(npm run verify/verify:package) + README 全面重写(架构/守护/版本沿革);版本号三处归一 - 测试 861→881(报告四例/迁移五链/阵型六则含胜率统计/冬祷四则); 金钟罩三指纹零漂移;typecheck/build 通过
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { GameState, SaveMeta, SnapshotMeta, Id } from '../types/domain'
|
||||
import { CURRENT_SCHEMA, APP_ID, exportEnvelope, parseImportEnvelope, migrateIfNeeded } from './migrate'
|
||||
|
||||
const DB_PREFIX = 'cotyc-save-'
|
||||
let seqCounter = 0
|
||||
@@ -40,6 +41,7 @@ export class SaveSlot {
|
||||
|
||||
async saveState(state: GameState, label: string): Promise<string> {
|
||||
const id = `${state.year}.${state.month}.${Date.now().toString(36)}-${(seqCounter++ % 1296).toString(36)}`
|
||||
state.schemaVersion = CURRENT_SCHEMA
|
||||
const json = JSON.stringify(state)
|
||||
await this.driver.run(
|
||||
`INSERT INTO snapshot (id, year, month, savedAt, label, data) VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
@@ -112,19 +114,23 @@ export class SaveSlot {
|
||||
|
||||
async exportAll(): Promise<string> {
|
||||
const state = await this.loadState()
|
||||
if (!state) throw new Error('无可导出存档')
|
||||
const meta = await this.getMeta()
|
||||
return JSON.stringify({ app: 'cotyc', schemaVersion: 1, meta, state })
|
||||
const envelope = JSON.parse(exportEnvelope(state)) as { schemaVersion: number; payload: GameState }
|
||||
return JSON.stringify({ app: APP_ID, schemaVersion: envelope.schemaVersion, meta, state: envelope.payload })
|
||||
}
|
||||
|
||||
async importAll(data: string): Promise<boolean> {
|
||||
try {
|
||||
const parsed = JSON.parse(data) as { app?: string; schemaVersion?: number; state?: GameState }
|
||||
if (!parsed.state) return false
|
||||
const parsed = parseImportEnvelope(data)
|
||||
if (!parsed.ok) return false
|
||||
const state = parsed.state
|
||||
state.schemaVersion = CURRENT_SCHEMA
|
||||
await this.driver.exec(`DELETE FROM snapshot`)
|
||||
await this.driver.exec(`DELETE FROM meta`)
|
||||
await this.saveState(parsed.state, 'import')
|
||||
const aliveCount = Object.values(parsed.state.members).filter((c) => c.alive).length
|
||||
await this.setMeta(buildSimpleMeta(parsed.state, this.slot, aliveCount))
|
||||
await this.saveState(state, 'import')
|
||||
const aliveCount = Object.values(state.members).filter((c) => c.alive).length
|
||||
await this.setMeta(buildSimpleMeta(state, this.slot, aliveCount))
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user