import type { RenderResponse } from '../worker/renderWorker'; export default function DiagnosticsPanel({ result }: { result: RenderResponse }) { const d = result.diag; const modes = Array.from(result.modeF); const shown = modes.slice(0, 8); return (
Strokes {d.strikeCount === 1 ? `single, ${d.meanV.toFixed(2)} m/s` : `${d.strikeCount} · mean ${d.meanV.toFixed(2)} m/s, max ${d.maxV.toFixed(2)} m/s`}
Contact r = {(d.strikeRadiusM * 100).toFixed(1)} cm ({(d.strikeRimM * 100).toFixed(1)} cm in from the rim{d.strikeCount > 1 ? `, alternating with ${(d.roll2RadiusM * 100).toFixed(1)} cm` : ''})
Impact {d.meanTauUs.toFixed(0)} µs mean (Hertz) · peak force {d.peakForceN.toFixed(0)} N
Plate modes {d.modesKept} up to n = {d.maxN} nodal diameters · {d.plateMassKg.toFixed(2)} kg
Lowest {shown.map((f) => f.toFixed(0)).join(', ')} … Hz
Nonlinearity peak wrms {d.peakWrmsUm.toFixed(0)} µm ={' '} {Math.sqrt(d.peakStrength).toFixed(2)} thicknesses ·{' '} {(100 * d.cascadeLostFrac).toFixed(1)}% left the top of the band
Listener {(d.listenerDistM * 100).toFixed(0)} cm from the plate
Peak pressure {d.peakPa.toFixed(3)} Pa ({d.peakSplDb.toFixed(1)} dB SPL) · click{' '} {d.directPeakPa.toFixed(2)} Pa
Length {d.durationS.toFixed(2)} s · {result.quality} · oversample {d.oversample}
eigensolves: {d.solveCached ? 'cached' : `${(d.solveMs / 1000).toFixed(2)} s`} · cascade + radiation: {d.radiateCached ? 'cached' : `${(d.radiateMs / 1000).toFixed(2)} s`}
{d.warnings.map((w, i) => (
⚠ {w}
))}
); }