import { useState } from 'react' import { useGameStore } from '../store' import { computeLegacy, resolveLegacy } from '../../game/core/legacy' import { resolveLegacy as doesIt } from '../../game/core/legacy' import { ResolveModal } from '../components/ResolveModal' import { buildBiography } from '../../game/core/biography' import { yearAxis, decadeLabel } from '../../game/core/yearaxis' import { buildReport, verdictLine } from '../../game/core/legacyreport' void doesIt 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]) => (
{dimName(k)}
{v}
))}
总评
{dims.total}
人兴=代数·丁口峰值 · 道兴=最高境界·功法大成 · 威名=声望峰·大比最佳 · 香火=存续·飞升
)} {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) }