const METRIC_FIELDS = [ { key: 'progress', label: 'progress', color: 'var(--progress)', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'delta', label: 'delta', color: '#6ec6ff', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? (v >= 0 ? '+' : '') + v.toFixed(3) : '—'), }, { key: 'kawasaki', label: 'kawasaki', color: 'var(--validity)', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'maekawa', label: 'maekawa', color: 'var(--validity)', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'blb', label: 'blb', color: 'var(--validity)', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'assignment_accuracy', label: 'assign acc', color: '#ffb74d', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'economy', label: 'economy', color: '#81c784', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'degree_sanity', label: 'deg sanity', color: 'var(--validity)', normalize: (v) => Math.min(Math.max(v || 0, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, { key: 'total', label: 'total', color: '#e0e0e0', normalize: (v) => Math.min(Math.max((v || 0) / 1.5, 0), 1), format: (v) => (v != null ? v.toFixed(3) : '—'), }, ]; function RewardRow({ label, color, pct, formattedValue, isDash, inverted }) { const barColor = inverted && pct > 0 ? 'var(--validity)' : color; return (
{label}
{formattedValue}
); } export default function RewardPanel({ metrics }) { return (
{METRIC_FIELDS.map(({ key, label, color, normalize, format, inverted }) => { const raw = metrics ? metrics[key] : undefined; const isDash = raw === null || raw === undefined; const pct = isDash ? 0 : normalize(raw) * 100; return ( ); })}
); }