const formatMoney = (n) => n >= 1e6 ? `$${(n / 1e6).toFixed(2)}M` : n >= 1e3 ? `$${(n / 1e3).toFixed(1)}K` : `$${Math.abs(n).toFixed(0)}` const formatPct = (v) => `${(v * 100).toFixed(0)}%` const fmtDelta = (key, d) => { if (key === 'revenue' || key === 'burn_rate') return formatMoney(Math.abs(d)) if (key === 'runway_months') return `${Math.abs(d).toFixed(1)}mo` if (key === 'profitability_score') return Math.abs(d).toFixed(1) return formatPct(Math.abs(d)) } // ASCII progress bar — no chart.js, pure terminal function AsciiBar({ value, max = 1, width = 8 }) { const filled = Math.round((value / max) * width) const empty = width - filled return ( [ {'█'.repeat(Math.max(0, filled))} {'░'.repeat(Math.max(0, empty))}] ) } const TILES = [ { key: 'profitability_score', label: 'SCORE', fmt: (v) => v.toFixed(1), max: 100 }, { key: 'revenue', label: 'REVENUE', fmt: formatMoney, max: null }, { key: 'burn_rate', label: 'BURN', fmt: formatMoney, max: null }, { key: 'runway_months', label: 'RUNWAY', fmt: (v) => `${v.toFixed(1)}mo`, max: 24 }, { key: 'product_readiness', label: 'PRODUCT', fmt: formatPct, max: 1 }, { key: 'market_share', label: 'MARKET', fmt: formatPct, max: 1 }, { key: 'team_morale', label: 'MORALE', fmt: formatPct, max: 1 }, { key: 'investor_confidence', label: 'INVEST', fmt: formatPct, max: 1 }, { key: 'regulatory_risk', label: 'REG_RSK', fmt: formatPct, max: 1 }, ] function scoreTile(key, val) { if (key === 'regulatory_risk') return val > 0.65 ? 'bad' : val > 0.35 ? 'warn' : 'good' if (key === 'runway_months') return val > 12 ? 'good' : val > 6 ? 'warn' : 'bad' if (key === 'profitability_score') return val >= 60 ? 'good' : val >= 35 ? 'warn' : 'bad' if (key === 'burn_rate') return '' return val > 0.65 ? 'good' : val > 0.35 ? 'warn' : 'bad' } export default function MetricsPanel({ state, prevState }) { if (!state) return null return (
{TILES.map(({ key, label, fmt, max }) => { const val = state[key] ?? 0 const prev = prevState?.[key] const delta = prev !== undefined ? val - prev : null const cls = scoreTile(key, val) const barVal = max ? Math.min(val, max) : null return (
{label}
{fmt(val)} {delta !== null && Math.abs(delta) > 0.001 && ( 0 ? 'pos' : 'neg'}`}> {delta > 0 ? '+' : '−'}{fmtDelta(key, delta)} )}
{barVal !== null && (
)}
) })}
) }