Fix part-number and date-code selection in ocr-extract
Part number now picks the longest hyphenated candidate instead of the first one, matching the documented intent and preventing a short unrelated token from being reported as the part number (which feeds the fingerprint used for sorting). Date code now only accepts YYWW candidates with a plausible year (10-39) and valid calendar week (01-53), taking the last match when several qualify; otherwise it stays null instead of guessing wrong, since a wrong value is worse than a missing one. Adds regression tests for both cases plus a no-plausible-candidate case that must yield null.
This commit is contained in:
+22
-5
@@ -42,16 +42,33 @@ export function extractFields(rawText) {
|
|||||||
matchKnown(raw, KNOWN.formFactor),
|
matchKnown(raw, KNOWN.formFactor),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Teilenummer: der laengste Kandidat, der nicht der Seriennummer entspricht.
|
// Teilenummer: unter den Kandidaten mit Bindestrich der laengste;
|
||||||
|
// bei gleicher Laenge der zuerst vorkommende. Echte Hersteller-
|
||||||
|
// Teilenummern sind laenger als die kurzen Codes, die sonst auf
|
||||||
|
// Etiketten stehen.
|
||||||
PART_NUMBER_PATTERN.lastIndex = 0;
|
PART_NUMBER_PATTERN.lastIndex = 0;
|
||||||
const candidates = [...text.matchAll(PART_NUMBER_PATTERN)].map((m) => m[1]);
|
const candidates = [...text.matchAll(PART_NUMBER_PATTERN)].map((m) => m[1]);
|
||||||
const withDash = candidates.filter((c) => c.includes('-'));
|
const withDash = candidates.filter((c) => c.includes('-'));
|
||||||
spec.partNumber = withDash[0] ?? null;
|
spec.partNumber =
|
||||||
|
withDash.length === 0
|
||||||
|
? null
|
||||||
|
: withDash.reduce((longest, current) =>
|
||||||
|
current.length > longest.length ? current : longest,
|
||||||
|
);
|
||||||
|
|
||||||
// Datumscode: vierstellige Zahl, die fuer sich allein steht.
|
// Datumscode: vierstellige Zahl der Form Jahr-Woche (JJWW), die fuer
|
||||||
|
// sich allein steht. Nur Kandidaten mit plausiblem Jahr (10-39) und
|
||||||
|
// gueltiger Kalenderwoche (01-53) kommen infrage; gibt es mehrere,
|
||||||
|
// gewinnt der zuletzt vorkommende, weil der Datumscode auf diesen
|
||||||
|
// Etiketten am Ende steht.
|
||||||
DATE_CODE_PATTERN.lastIndex = 0;
|
DATE_CODE_PATTERN.lastIndex = 0;
|
||||||
const dateMatch = [...text.matchAll(DATE_CODE_PATTERN)].map((m) => m[1]);
|
const dateCandidates = [...text.matchAll(DATE_CODE_PATTERN)].map((m) => m[1]);
|
||||||
spec.dateCode = dateMatch[0] ?? null;
|
const plausibleDates = dateCandidates.filter((raw) => {
|
||||||
|
const year = Number(raw.slice(0, 2));
|
||||||
|
const week = Number(raw.slice(2, 4));
|
||||||
|
return year >= 10 && year <= 39 && week >= 1 && week <= 53;
|
||||||
|
});
|
||||||
|
spec.dateCode = plausibleDates.length === 0 ? null : plausibleDates[plausibleDates.length - 1];
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,3 +52,20 @@ test('leerer Text liefert ein leeres Spec', () => {
|
|||||||
assert.equal(spec.capacityGb, null);
|
assert.equal(spec.capacityGb, null);
|
||||||
assert.equal(spec.partNumber, null);
|
assert.equal(spec.partNumber, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('waehlt bei der Teilenummer den laengsten Bindestrich-Kandidaten, nicht den ersten', () => {
|
||||||
|
const spec = extractFields(
|
||||||
|
'SAMSUNG\nAB1234SN-001\n64GB 4DRx4 PC4-2400\nM386A8K40BM1-CRC4Y\n1908',
|
||||||
|
);
|
||||||
|
assert.equal(spec.partNumber, 'M386A8K40BM1-CRC4Y');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('verwirft den Datumscode, wenn mehrere vierstellige Bloecke vorkommen und nur einer plausibel ist', () => {
|
||||||
|
const spec = extractFields('SAMSUNG\n1234 5678\n64GB 2Rx4 PC4-2666\n9012\n1908');
|
||||||
|
assert.equal(spec.dateCode, '1908');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('laesst den Datumscode null, wenn kein Kandidat als Jahr-Woche plausibel ist', () => {
|
||||||
|
const spec = extractFields('SAMSUNG\n9999 0060\n64GB 2Rx4 PC4-2666');
|
||||||
|
assert.equal(spec.dateCode, null);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user