feat(iace): 50% display threshold — weak matches shown as separate
Matches below 50% are now split: - GT entries → "Fehlend" tab (not matched by engine) - Engine entries → "Engine Findings" tab (additional findings) Only matches >= 50% shown in "Zugeordnet" tab. Coverage score now counts only real matches (>= 50%). "Extra" tab renamed to "Engine Findings" for clarity. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-9
@@ -14,14 +14,21 @@ type TabType = 'matched' | 'missing' | 'extra'
|
|||||||
export function HazardComparisonTable({ matched, missing, extra }: Props) {
|
export function HazardComparisonTable({ matched, missing, extra }: Props) {
|
||||||
const [tab, setTab] = useState<TabType>('matched')
|
const [tab, setTab] = useState<TabType>('matched')
|
||||||
|
|
||||||
// Compute quality levels for matched pairs
|
// Split matches: >= 50% are real matches, < 50% are weak (shown separately)
|
||||||
const greenCount = matched.filter(p => p.match_score >= 0.7).length
|
const realMatched = matched.filter(p => p.match_score >= 0.5)
|
||||||
const yellowCount = matched.filter(p => p.match_score >= 0.4 && p.match_score < 0.7).length
|
const weakMatched = matched.filter(p => p.match_score < 0.5)
|
||||||
|
|
||||||
|
// Weak matches: GT entries go to "missing", engine entries go to "extra"
|
||||||
|
const allMissing = [...missing, ...weakMatched.map(w => w.gt_entry)]
|
||||||
|
const allExtra = [...extra, ...weakMatched.map(w => w.engine_hazard)]
|
||||||
|
|
||||||
|
const greenCount = realMatched.filter(p => p.match_score >= 0.7).length
|
||||||
|
const yellowCount = realMatched.filter(p => p.match_score >= 0.5 && p.match_score < 0.7).length
|
||||||
|
|
||||||
const tabs: { id: TabType; label: string; count: number; color: string }[] = [
|
const tabs: { id: TabType; label: string; count: number; color: string }[] = [
|
||||||
{ id: 'matched', label: `Zugeordnet (${greenCount} exakt, ${yellowCount} aehnlich)`, count: matched.length, color: 'text-green-600' },
|
{ id: 'matched', label: `Zugeordnet (${greenCount} exakt, ${yellowCount} aehnlich)`, count: realMatched.length, color: 'text-green-600' },
|
||||||
{ id: 'missing', label: 'Fehlend', count: missing.length, color: 'text-red-600' },
|
{ id: 'missing', label: 'Fehlend', count: allMissing.length, color: 'text-red-600' },
|
||||||
{ id: 'extra', label: 'Zusaetzlich', count: extra.length, color: 'text-gray-500' },
|
{ id: 'extra', label: 'Engine Findings', count: allExtra.length, color: 'text-blue-500' },
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -44,9 +51,9 @@ export function HazardComparisonTable({ matched, missing, extra }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
{tab === 'matched' && <MatchedTable pairs={matched} />}
|
{tab === 'matched' && <MatchedTable pairs={realMatched} />}
|
||||||
{tab === 'missing' && <MissingTable entries={missing} />}
|
{tab === 'missing' && <MissingTable entries={allMissing} />}
|
||||||
{tab === 'extra' && <ExtraTable entries={extra} />}
|
{tab === 'extra' && <ExtraTable entries={allExtra} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ export default function BenchmarkPage() {
|
|||||||
const { result, gtLoaded, gtEntryCount, loading, error, importGT, runBenchmark } = useBenchmark(projectId)
|
const { result, gtLoaded, gtEntryCount, loading, error, importGT, runBenchmark } = useBenchmark(projectId)
|
||||||
const [gtProjectId, setGtProjectId] = useState('')
|
const [gtProjectId, setGtProjectId] = useState('')
|
||||||
|
|
||||||
const coveragePct = result ? Math.round(result.coverage_score * 100) : 0
|
// Only count matches >= 50% as real coverage
|
||||||
|
const realMatchCount = result ? (result.matched_pairs?.filter(m => m.match_score >= 0.5).length || 0) : 0
|
||||||
|
const coveragePct = result ? Math.round(realMatchCount * 100 / Math.max(result.total_gt, 1)) : 0
|
||||||
const measurePct = result ? Math.round(result.measure_coverage * 100) : 0
|
const measurePct = result ? Math.round(result.measure_coverage * 100) : 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -74,7 +76,7 @@ export default function BenchmarkPage() {
|
|||||||
<ScoreCard
|
<ScoreCard
|
||||||
label="Hazard Coverage"
|
label="Hazard Coverage"
|
||||||
value={`${coveragePct}%`}
|
value={`${coveragePct}%`}
|
||||||
sub={`${result.matched_pairs?.length || 0} / ${result.total_gt} erkannt`}
|
sub={`${realMatchCount} / ${result.total_gt} erkannt (>= 50% Match)`}
|
||||||
color={coveragePct >= 80 ? 'green' : coveragePct >= 50 ? 'yellow' : 'red'}
|
color={coveragePct >= 80 ? 'green' : coveragePct >= 50 ? 'yellow' : 'red'}
|
||||||
/>
|
/>
|
||||||
<ScoreCard
|
<ScoreCard
|
||||||
|
|||||||
Reference in New Issue
Block a user