Improve IK-style artifact scanner pipeline
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { AlertTriangle, Download, Play, Upload, Wrench } from "lucide-react";
|
||||
import { AlertTriangle, BadgeCheck, Camera, ClipboardList, Download, Gauge, Play, Target, Upload, Wrench } from "lucide-react";
|
||||
import type { CaptureResult } from "../../../types/global";
|
||||
import type { ScanViewControllerResult } from "../types";
|
||||
import { FieldConfidenceList } from "./ScanResultCards";
|
||||
@@ -14,6 +14,53 @@ interface DiagnosticsViewProps {
|
||||
canDemoScan?: boolean;
|
||||
}
|
||||
|
||||
const appDiagnosisSections = [
|
||||
{
|
||||
title: "Was die App kann",
|
||||
tone: "ok",
|
||||
icon: BadgeCheck,
|
||||
items: [
|
||||
"Genshin-Fenster erkennen, Smart Capture ausfuehren und fokussierte Artifact-Crops erzeugen.",
|
||||
"Artifact-Felder deterministisch gegen das lokale Genshin-Datenpaket parsen.",
|
||||
"Auto-Scan read-only aus der sichtbaren Inventory-Seite starten, inklusive Grid, Verifikation, Dedupe und Store.",
|
||||
"Review-Samples, lokale Text-Lernregeln, GOOD Import/Export und Lock-Status im Store nutzen.",
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Was noch fehlt",
|
||||
tone: "warn",
|
||||
icon: ClipboardList,
|
||||
items: [
|
||||
"Paimon-Menue-Einstieg ist gebaut, aber live noch nicht mit 2/20/45 Limits validiert.",
|
||||
"Native/IK-Tesseract ist nur als Benchmark-Pfad vorbereitet, noch nicht Standard.",
|
||||
"Positive locked=true Probe an einem sicher gesperrten Artifact fehlt.",
|
||||
"Empfehlungen bleiben Nebenfunktion, bis Scanner-Vertrauen und Review-Rate stabil genug sind.",
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Wo es Probleme macht",
|
||||
tone: "risk",
|
||||
icon: AlertTriangle,
|
||||
items: [
|
||||
"OCR ist weiterhin der Haupt-Risikofaktor; einige Felder landen noch in Fallback, Ableitung oder Review.",
|
||||
"Bild-Preprocessing kann nur an echten Captures bewertet werden, nicht allein mit Text-Eval.",
|
||||
"Auto-Scan braucht bei erhoehtem Genshin auch eine erhoehte App-Laufzeit.",
|
||||
"Groessere Runs brauchen weiter Beobachtung auf Scroll-Uebergaenge, Wiederholseiten und Review-Quote.",
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Naechste Verbesserungen",
|
||||
tone: "next",
|
||||
icon: Target,
|
||||
items: [
|
||||
"Review-Corpus aus echten Samples vergroessern und mit `npm run eval` messbar halten.",
|
||||
"OCR-Benchmark gegen identische Crops fahren und erst danach Engine-Standard wechseln.",
|
||||
"Paimon-Menue-Pfad live pruefen und bei Blockade sichtbar auf visible-inventory zurueckfallen.",
|
||||
"Diagnose weiter als Operator-Cockpit halten: Live-Status, Evidenz und naechster sicherer Schritt.",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// All developer / diagnostic surfaces live here, separated from the Scan
|
||||
// workspace: runtime + rights, grid detection, learning + data-package status,
|
||||
// fingerprint, auto-scan counters, the automation log, and the raw crop/OCR/
|
||||
@@ -39,6 +86,7 @@ export function DiagnosticsView({ controller, latestCapture, captureStatus, onDe
|
||||
playerProgress,
|
||||
reviewStatus,
|
||||
automationLogLines,
|
||||
diagnosticEvents,
|
||||
canSaveReviewSample,
|
||||
handleSaveReviewSample,
|
||||
} = useScanDiagnosticsModalModel({
|
||||
@@ -106,6 +154,37 @@ export function DiagnosticsView({ controller, latestCapture, captureStatus, onDe
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="diagnose-card app-diagnosis-card">
|
||||
<div className="diagnose-card-heading">
|
||||
<div>
|
||||
<p className="eyebrow">Aktueller App-Stand</p>
|
||||
<h3>Scanner zuerst, Empfehlungen danach</h3>
|
||||
</div>
|
||||
<span className="diagnosis-source">
|
||||
<Gauge size={14} />
|
||||
Quelle: Docs + Live-Status
|
||||
</span>
|
||||
</div>
|
||||
<div className="app-diagnosis-grid">
|
||||
{appDiagnosisSections.map((section) => {
|
||||
const Icon = section.icon;
|
||||
return (
|
||||
<article className={`app-diagnosis-section ${section.tone}`} key={section.title}>
|
||||
<div className="app-diagnosis-title">
|
||||
<Icon size={16} />
|
||||
<strong>{section.title}</strong>
|
||||
</div>
|
||||
<ul>
|
||||
{section.items.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="diagnose-grid">
|
||||
<div className="diagnose-card">
|
||||
<p className="eyebrow">Status</p>
|
||||
@@ -196,6 +275,67 @@ export function DiagnosticsView({ controller, latestCapture, captureStatus, onDe
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="diagnose-card">
|
||||
<div className="diagnose-card-heading">
|
||||
<div>
|
||||
<p className="eyebrow">Evidence timeline</p>
|
||||
<h3>Scan-Flugschreiber</h3>
|
||||
</div>
|
||||
<span className="diagnosis-source">
|
||||
<Camera size={14} />
|
||||
letzte {diagnosticEvents.length}
|
||||
</span>
|
||||
</div>
|
||||
{diagnosticEvents.length > 0 ? (
|
||||
<div className="scan-evidence-timeline">
|
||||
{diagnosticEvents.slice().reverse().map((event) => (
|
||||
<article className={`scan-evidence-event ${event.severity}`} key={event.id}>
|
||||
<div className="scan-evidence-header">
|
||||
<span>{new Date(event.at).toLocaleTimeString()}</span>
|
||||
<strong>{event.phase}</strong>
|
||||
<em>{event.severity}</em>
|
||||
</div>
|
||||
<p>{event.message}</p>
|
||||
{event.details && (
|
||||
<div className="scan-evidence-details">
|
||||
{Object.entries(event.details).map(([key, value]) => (
|
||||
<span key={key}>{key}: {String(value ?? "-")}</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{event.capture && (
|
||||
<div className="scan-evidence-capture">
|
||||
<div>
|
||||
<strong>{event.capture.name}</strong>
|
||||
<span>{event.capture.width}x{event.capture.height} · {event.capture.target ?? "capture"} · fp {event.capture.fingerprint}</span>
|
||||
{event.capture.grid && (
|
||||
<span>grid {event.capture.grid.cols}x{event.capture.grid.rows} · {event.capture.grid.targets} targets · {event.capture.grid.confidence}% · {event.capture.grid.source}</span>
|
||||
)}
|
||||
{event.capture.count && (
|
||||
<span>count {event.capture.count.current}/{event.capture.count.total || "?"} · {event.capture.count.confidence}% · {event.capture.count.text || "-"}</span>
|
||||
)}
|
||||
{event.capture.artifactDetail && (
|
||||
<span>detail {event.capture.artifactDetail.present ? "yes" : "no"} · {event.capture.artifactDetail.confidence}% · orange {event.capture.artifactDetail.orangeHits} · text {event.capture.artifactDetail.textHits}</span>
|
||||
)}
|
||||
{event.capture.paimonMenu && (
|
||||
<span>paimon {event.capture.paimonMenu.present ? "yes" : "no"} · {event.capture.paimonMenu.confidence}%</span>
|
||||
)}
|
||||
{event.capture.layoutWarning && <span className="evidence-warning">{event.capture.layoutWarning}</span>}
|
||||
</div>
|
||||
<div className="scan-evidence-images">
|
||||
{event.capture.screenshots?.inventory && <img src={event.capture.screenshots.inventory} alt={`${event.phase} inventory`} />}
|
||||
{event.capture.screenshots?.detail && <img src={event.capture.screenshots.detail} alt={`${event.phase} detail`} />}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="result-empty">Noch keine Evidence-Events. Starte einen Capture oder Auto-Scan, dann erscheinen hier Schritte mit Screenshots.</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="diagnose-card">
|
||||
<div className="diagnose-card-heading">
|
||||
<p className="eyebrow">Crops, OCR & Confidence</p>
|
||||
|
||||
Reference in New Issue
Block a user