feat(iace): benchmark distance panel (Thema 1)
Surface result.distances in the benchmark module: a DistanceComparison panel showing agreement %, covered values (green), GT-only gaps (amber) and engine-only extras — mirroring the RiskComparison panel. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+69
@@ -0,0 +1,69 @@
|
||||
'use client'
|
||||
|
||||
import type { DistanceComparison as DistanceComparisonData, DistanceToken } from '../_hooks/useBenchmark'
|
||||
|
||||
function fmt(t: DistanceToken): string {
|
||||
const v = Number.isInteger(t.value) ? t.value.toString() : t.value.toString().replace('.', ',')
|
||||
return `${v} ${t.unit}`
|
||||
}
|
||||
|
||||
function TokenList({ tokens, tone }: { tokens: DistanceToken[]; tone: 'ok' | 'gap' | 'extra' }) {
|
||||
if (!tokens.length) return <span className="text-xs text-gray-400">—</span>
|
||||
const cls =
|
||||
tone === 'ok'
|
||||
? 'bg-green-100 text-green-700 dark:bg-green-900/40 dark:text-green-300'
|
||||
: tone === 'gap'
|
||||
? 'bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300'
|
||||
: 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400'
|
||||
return (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{tokens.map((t, i) => (
|
||||
<span key={i} className={`inline-block rounded px-1.5 py-0.5 text-[11px] tabular-nums ${cls}`}>
|
||||
{fmt(t)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Distance/speed dimension comparison: do the engine's mm/mm-s values match the
|
||||
* professional's (GT)? Confidence-aware tonality — green = covered, amber = gap.
|
||||
*/
|
||||
export function DistanceComparison({ data }: { data?: DistanceComparisonData }) {
|
||||
if (!data || data.gt_count === 0) return null
|
||||
|
||||
return (
|
||||
<div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4 space-y-3">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-gray-700 dark:text-gray-300">Abstands-/Geschwindigkeits-Vergleich (Fachmann vs. Tool)</h3>
|
||||
<p className="text-xs text-gray-500 mt-0.5">
|
||||
Deckt das Tool die konkreten mm-/mm-s-Werte des Fachmanns ab? Deterministischer Abgleich der
|
||||
Maße aus den GT-Maßnahmen gegen die vom Tool vorgeschlagenen Maßnahmen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-baseline gap-3">
|
||||
<span className="text-2xl font-bold text-purple-600 tabular-nums">{Math.round(data.agreement_pct)}%</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
{data.matched_count} von {data.gt_count} Fachmann-Maßen abgedeckt
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<dl className="grid grid-cols-1 sm:grid-cols-3 gap-3 text-xs">
|
||||
<div>
|
||||
<dt className="text-[10px] uppercase tracking-wide text-gray-400 mb-1">Abgedeckt</dt>
|
||||
<dd><TokenList tokens={data.matched} tone="ok" /></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-[10px] uppercase tracking-wide text-gray-400 mb-1">Lücken (nur Fachmann)</dt>
|
||||
<dd><TokenList tokens={data.gt_only} tone="gap" /></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-[10px] uppercase tracking-wide text-gray-400 mb-1">Nur Tool</dt>
|
||||
<dd><TokenList tokens={data.engine_only} tone="extra" /></dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user