feat: toleranter Spec-Vergleich gegen OCR-Verwechslungen

This commit is contained in:
vchuser
2026-07-28 14:16:31 +02:00
parent 3aa54d6c78
commit a7adfeb9da
2 changed files with 117 additions and 0 deletions
+59
View File
@@ -53,3 +53,62 @@ export function fingerprint(spec) {
export function isUsable(spec) {
return typeof spec.capacityGb === 'number' && Number.isFinite(spec.capacityGb);
}
/**
* Zeichen, die OCR auf glaenzenden Etiketten regelmaessig verwechselt,
* werden auf einen gemeinsamen Vertreter abgebildet. D bleibt bewusst
* unangetastet, sonst kollidiert 4DRx4 mit 40Rx4.
*/
const CONFUSIONS = {
O: '0', Q: '0',
I: '1', L: '1',
B: '8',
S: '5',
Z: '2',
G: '6',
};
/** Vergleichsform eines Tokens: normalisiert, ohne Trennzeichen, verwechslungsfrei. */
export function canonical(raw) {
const normalized = normalizeToken(raw).replace(/[^A-Z0-9]/g, '');
let out = '';
for (const char of normalized) {
out += CONFUSIONS[char] ?? char;
}
return out;
}
/**
* Gleicht einen gelesenen Wert gegen eine Liste bekannter Werte ab.
* Erst exakt, dann ueber die Vergleichsform. Mehrdeutigkeit gilt als Treffer-los.
*/
export function matchKnown(raw, list) {
const normalized = normalizeToken(raw);
if (normalized === '') return null;
for (const candidate of list) {
if (normalizeToken(String(candidate)) === normalized) return candidate;
}
const target = canonical(normalized);
const hits = list.filter((candidate) => canonical(String(candidate)) === target);
return hits.length === 1 ? hits[0] : null;
}
/**
* Zwei Specs sind vertraeglich, wenn alle beidseitig gesetzten Felder
* in ihrer Vergleichsform uebereinstimmen. Felder, die auf einer Seite
* fehlen, verhindern die Vertraeglichkeit nicht - die Entscheidung
* darueber faellt in session.js.
*/
export function specsCompatible(a, b) {
const fields = ['capacityGb', 'formFactor', 'rank', 'speed', 'partNumber'];
for (const field of fields) {
const left = a[field];
const right = b[field];
if (left === null || left === undefined) continue;
if (right === null || right === undefined) continue;
if (canonical(String(left)) !== canonical(String(right))) return false;
}
return true;
}