import { GameState } from '../../types/domain' export interface AxisEvent { year: number kind: '突破' | '大比' | '渡劫' | '婚' | '殇' | '战' | '飞升' label: string } export interface AxisCell { from: number to: number events: AxisEvent[] births: number deaths: number } /** 横轴年表:十年一格,把族簿大事压缩进一根时间轴 */ export function yearAxis(s: GameState, decadeSize = 10): AxisCell[] { const startYear = Math.max(1, Math.min(...s.chronicle.map((e) => e.year).concat(1))) const endYear = Math.max(startYear, s.year) const cells = new Map() const cellOf = (year: number): AxisCell => { const from = Math.floor((year - 1) / decadeSize) * decadeSize + 1 if (!cells.has(from)) cells.set(from, { from, to: Math.min(from + decadeSize - 1, endYear), events: [], births: 0, deaths: 0 }) return cells.get(from)! } for (const e of s.chronicle) { if (e.year < startYear) continue const cell = cellOf(e.year) const kind: AxisEvent['kind'] | null = e.category === 'breakthrough' ? /渡劫|天劫/.test(e.text) ? '渡劫' : '突破' : e.category === 'birth' ? null : e.category === 'death' ? /飞升/.test(e.text) ? '飞升' : '殇' : e.category === 'marriage' ? '婚' : e.category === 'battle' ? '战' : null if (kind) cell.events.push({ year: e.year, kind, label: e.text.slice(0, 26) }) if (e.category === 'birth') cell.births++ if (e.category === 'death') cell.deaths++ } return [...cells.entries()].sort((a, b) => a[0] - b[0]).map(([, c]) => c) } export function decadeLabel(from: number, to: number): string { return from === to ? `${from}年` : `${from}-${to}年` }