import { useState } from 'react'
import { useGameStore } from '../store'
import { computeLegacy, resolveLegacy } from '../../game/engine/narrative/legacy'
import { ResolveModal } from '../components/ResolveModal'
import { buildBiography } from '../../game/engine/narrative/biography'
import { yearAxis, decadeLabel } from '../../game/engine/narrative/yearaxis'
import { buildReport, verdictLine } from '../../game/engine/narrative/legacyreport'
export default function LegacyPanel() {
const world = useGameStore((s) => s.world)
const revision = useGameStore((s) => s.revision)
void revision
const [showResolve, setShowResolve] = useState(false)
const [view, setView] = useState<'dims' | 'chronicle' | 'report' | 'scroll' | 'axis' | 'legacy'>('dims')
if (!world) return null
const w = world
const s = w.state
const dims = computeLegacy(s)
const arch = resolveLegacy(s)
const resolved = !!s.family.flag['resolved']
const yearly = s.yearlyReports.slice().sort((a, b) => a.year - b.year)
const births = Object.values(s.members).filter((c) => c.bornYear >= 0)
const genMin = Math.min(...Object.values(s.members).map((c) => c.bornYear))
const genMax = Math.max(...Object.values(s.members).map((c) => c.deathYear ?? s.year))
return (
春秋原:家族百年气数之图。望气可预演四维,落印后方入青册(不阻继续行旅)。
当前气数 · 预演称号 {arch.title}
{resolved && 已定局}
存续{s.year}年 · {s.family.generation}代 · 声望峰值{s.stats.repPeak} · 丁口峰值{s.stats.popPeak}
{s.stats.tourneyBest ? ` · 大比最佳第${s.stats.tourneyBest}名` : ''}
{!resolved && (
)}
{view === 'dims' && (
气数四维
{Object.entries(dims)
.filter(([k]) => k !== 'total')
.map(([k, v]) => (
))}
人兴=代数·丁口峰值 · 道兴=最高境界·功法大成 · 威名=声望峰·大比最佳 · 香火=存续·飞升
)}
{view === 'report' && (
岁末族簿汇编(逐年)
| 年 | 灵石盈亏 | 诞辰 | 辞世 | 声望 | 宗族战力 |
{yearly.slice(-20).map((r) => (
| {r.year}年 |
= 0 ? 'good' : 'bad'}>{r.nets >= 0 ? `+${r.nets}` : r.nets} |
+{r.births} |
-{r.deaths} |
{r.rep} |
{r.power} |
))}
共 {yearly.length} 年度账册。
)}
{view === 'legacy' &&
}
{view === 'axis' &&
}
{view === 'scroll' &&
}
{view === 'chronicle' && (
生卒与突破年表
族人生卒带(首倡 {genMin + s.year - s.year} 年 ~ 卒 {genMax} 年,区间 {genMax - genMin} 载)
大比记录:{s.stats.tourneyHistory.length === 0 ? '尚无参赛记录' : s.stats.tourneyHistory.map((t) => `${t.year}年第${t.rank}名`).join('、')}
突破年表(按年份计数):
{breakdown(s).length === 0 ? '暂无' : breakdown(s).map((b) => `${b.year}年×${b.n}`).join(' · ')}
)}
{showResolve &&
setShowResolve(false)} />}
)
}
function LegacyReportView() {
const world = useGameStore((s) => s.world)
if (!world) return null
const r = buildReport(world.state)
const span = r.years.length
return (
百年族史报告
{span < 4 ? (
开卷尚浅,待岁月沉淀后再启此卷。
) : (
<>
死因榜:{Object.entries(r.deathCauses).filter(([k]) => k !== '').sort((a, b) => b[1] - a[1]).slice(0, 4).map(([k, v]) => `${k}×${v}`).join(' · ') || '尚无记录'}
突破之劲:{r.breakthroughs.slice(-6).map((b) => `${b.year}年×${b.count}`).join(' · ')}
{verdictLine(r)}
>
)}
)
}
function Sparklines({ r }: { r: ReturnType }) {
const width = 640
const height = 150
const pts = (seq: number[], color: string) => {
const max = Math.max(...seq, 1)
const step = seq.length > 1 ? width / (seq.length - 1) : width
return seq.map((v, i) => `${(i * step).toFixed(1)},${(height - 20 - (v / max) * (height - 40)).toFixed(1)}`).join(' ')
}
return (
)
}
function AxisView() {
const world = useGameStore((s) => s.world)
if (!world) return null
const cells = yearAxis(world.state)
return (
横轴年表(十年一格)
{cells.map((c) => (
{decadeLabel(c.from, c.to)}
生 {c.births}
殇 {c.deaths}
{c.events.slice(0, 6).map((e, i) => (
{e.kind}·{e.year}年 {e.label}
))}
{c.events.length > 6 && …还有{c.events.length - 6}件}
))}
)
}
function ScrollScroll() {
const world = useGameStore((s) => s.world)
if (!world) return null
const mem = Object.values(world.state.members).sort((a, b) => b.generation - a.generation || b.bornYear - a.bornYear)
return (
列传长卷
{mem.slice(0, 40).map((c) => {
const bio = buildBiography(world.state, c.id)
return (
{c.name}
{bio.map((l) => l.text).join(' ').slice(0, 90)}{bio.map((l) => l.text).join(' ').length > 90 ? '……' : ''}
)
})}
)
}
function dimName(k: string): string {
const map: Record = { renXing: '人兴', daoXing: '道兴', weiMing: '威名', xiangHuo: '香火' }
return map[k] ?? k
}
function breakdown(s: { chronicle: { category: string; year: number }[] }): { year: number; n: number }[] {
const counts = new Map()
for (const e of s.chronicle) {
if (e.category === 'breakthrough') {
const cur = counts.get(e.year) ?? 0
counts.set(e.year, cur + 1)
}
}
return [...counts.entries()].map(([year, n]) => ({ year, n })).sort((a, b) => a.year - b.year)
}