Doku: Codeabgleich nur innerhalb vertraeglicher Angaben, Grenze ergaenzt

README beschreibt jetzt, dass ein Codetreffer einen Widerspruch der
technischen Angaben nicht mehr ueberstimmt (Fehler 1) und dass die
Codemenge eines Stapels ein abgeleiteter statt angesammelter Wert ist
(Fehler 2). Neue Grenze dokumentiert: ein gelesener Barcode-Inhalt ist exakt
gelesen, aber nicht garantiert eine Teilenummer - eine geteilte Los- oder
Wiederverkaeufer-Kennung kann zwei verschiedene Module verbinden, wogegen
die neue Widerspruchspruefung schuetzt. Testanzahl auf 124 aktualisiert.
This commit is contained in:
vchuser
2026-07-29 09:22:11 +02:00
parent 266babc8bf
commit b679df6fd3
+41 -15
View File
@@ -7,16 +7,28 @@ App nennt den Stapel.
Zwei Module gelten als zusammengehörig, wenn sie denselben Barcode-Inhalt
tragen — ein Barcode ist exakt gelesen, das ist der zuverlässigste Maßstab.
Jeder Stapel führt dafür die Menge der Barcode-Zeichenketten, die bei seinen
Modulen gelesen wurden (`stack.codes`); trägt ein neu gescanntes Modul einen
Code, den ein Stapel bereits kennt, gehört es dorthin — das hat Vorrang vor
allem Weiteren, auch wenn die technischen Angaben unvollständig sind
(`proposeAssignment` in `src/session.js`). Auf Etiketten stehen oft zwei
Codes, von denen einer die Seriennummer ist, die bei jedem Modul anders ist:
Sie läuft beim Codeabgleich einfach ins Leere, während die danebenstehende
Teilenummer trägt — kein Sonderfall, nur eine Konsequenz des Mengenvergleichs.
*aktuell* ihm zugeordneten Modulen gelesen wurden (`stack.codes`); diese Menge
wird nicht angesammelt, sondern aus den Codes der zugeordneten Einträge
(`entry.codes`) abgeleitet — genau wie der Stapelzähler (siehe „Sitzungssicherung
im Detail" unten). Sortiert der Nutzer ein Modul um oder entfernt es, verliert
der alte Stapel dessen Codes deshalb sofort wieder; ein bereinigter Fehler
zieht kein weiteres Modul mehr fälschlich an. Trägt ein neu gescanntes Modul
einen Code, den ein Stapel bereits kennt, ist dieser Stapel Kandidat — aber
nur, wenn die technischen Angaben beider Seiten sich dabei nicht widersprechen
(`specsCompatible` in `src/spec.js`, siehe unten); ein Codetreffer allein
genügt nicht, sonst könnte ein Code, der gar keine Teilenummer ist, zwei
technisch verschiedene Module zusammenführen (siehe „Grenzen"). Genau ein
solcher Kandidat gehört dorthin, auch wenn die technischen Angaben
unvollständig sind (`proposeAssignment` in `src/session.js`). Auf Etiketten
stehen oft zwei Codes, von denen einer die Seriennummer ist, die bei jedem
Modul anders ist: Sie läuft beim Codeabgleich einfach ins Leere, während die
danebenstehende Teilenummer trägt — kein Sonderfall, nur eine Konsequenz des
Mengenvergleichs.
Kennt kein Stapel einen der gelesenen Codes (typischerweise beim ersten Modul
eines neuen Stapels), vergleicht die App stattdessen über alle Merkmale, die
Kennt kein Stapel einen der gelesenen Codes ohne Widerspruch (typischerweise
beim ersten Modul eines neuen Stapels, aber auch dann, wenn ein Codetreffer an
der Widerspruchsprüfung scheitert), vergleicht die App stattdessen über alle
Merkmale, die
bei Modul und Stapel bekannt sind — Kapazität, Bauform, Rank, Geschwindigkeit
und, sofern gelesen, Hersteller-Teilenummer (`specsCompatible` in
`src/spec.js`); ein auf einer Seite fehlendes Merkmal wird dabei übersprungen,
@@ -121,7 +133,7 @@ korrekt funktioniert.
npm test
```
121 Tests, alle grün (Stand dieses Dokuments). Getestet werden ausschließlich
124 Tests, alle grün (Stand dieses Dokuments). Getestet werden ausschließlich
die reinen Module ohne Browser-Zugriff: Teilenummer-Decoder, Spec-Normalisierung
und toleranter Vergleich, OCR-Bildaufbereitung (Otsu-Schwellwert) und
-Feldextraktion, Stapel-Zuweisung, die Erkennungs-Pipeline samt Zeitgrenzen
@@ -156,7 +168,7 @@ nicht gesetzt ist).
| `src/pn-tables.js` | Herstellertabellen für den Teilenummer-Decoder |
| `src/pn-decoder.js` | Teilenummer → Spec-Felder |
| `src/ocr-extract.js` | OCR-Rohtext → Spec-Felder |
| `src/session.js` | Stapel halten, vorschlagen, buchen, umsortieren, zurücknehmen — inklusive der je Stapel gesammelten Barcode-Inhalte (`stack.codes`), die vor dem Vergleich der technischen Angaben über die Zuordnung entscheiden |
| `src/session.js` | Stapel halten, vorschlagen, buchen, umsortieren, zurücknehmen — inklusive der aus den Einträgen abgeleiteten, je Stapel bekannten Barcode-Inhalte (`stack.codes`), die vor dem Vergleich der technischen Angaben über die Zuordnung entscheiden, sofern diese Angaben nicht widersprechen |
| `src/pipeline.js` | Barcode → Teilenummer → OCR → Ampelfarbe, inkl. Zeitgrenzen, Mehrdeutigkeitsbehandlung und Kurzschluss über einen bereits bekannten Barcode-Inhalt (`deps.isKnownCode`) |
| `src/storage.js` | Absturzschutz der laufenden Sitzung: sichert und lädt aus `localStorage`, verwirft beim Laden jeden in sich unstimmigen Zustand vollständig (siehe unten) |
| `src/camera.js` | Kamerastart, Einzelbildaufnahme, Bilddatei-Ersatzweg |
@@ -188,11 +200,15 @@ auch nur eine dieser Bedingungen nicht zu, wird die gesamte gespeicherte
Sitzung verworfen (die App startet leer), statt mit einem halb kaputten
Zustand lautlos weiterzuarbeiten. Der gespeicherte Stapelzähler selbst wird
nie übernommen, sondern beim Laden immer neu aus der tatsächlichen Zahl der
zugeordneten Einträge berechnet. Die je Stapel gesicherten Barcode-Inhalte
(`stack.codes`) werden, sofern vorhanden, ebenso streng geprüft (Liste von
zugeordneten Einträge berechnet — genauso die Codemenge eines Stapels
(`stack.codes`): Sie wird nie aus dem gesicherten Wert übernommen, sondern
stets aus den Codes der ihm tatsächlich zugeordneten Einträge (`entry.codes`)
neu zusammengesetzt, dieselbe Ableitung, die `session.js` nach jedem
Umsortieren oder Entfernen eines Eintrags vornimmt. Sind `stack.codes` bzw.
`entry.codes` vorhanden, werden sie streng geprüft (Liste von
Zeichenketten); ein gesicherter Stand aus einer Fassung vor dieser Erweiterung
ohne dieses Feld gilt dagegen nicht als unstimmig, sondern wird beim Laden als
Stapel ohne bekannte Codes wiederhergestellt.
ohne diese Felder gilt dagegen nicht als unstimmig, sondern wird beim Laden
als Stapel bzw. Eintrag ohne bekannte Codes wiederhergestellt.
## Grenzen
@@ -201,6 +217,16 @@ Stapel ohne bekannte Codes wiederhergestellt.
Sitzung, keine dauerhafte Datenhaltung.
- Das Laden der Seite braucht eine Verbindung; das Sortieren selbst nicht
(nach dem Laden läuft alles lokal im Browser).
- Der Codeabgleich (siehe oben) weiß nicht, ob ein gelesener Barcode-Inhalt
tatsächlich eine Teilenummer ist. Trägt ein Etikett daneben noch eine
Los- oder Wiederverkäufer-Kennung und teilen zwei technisch verschiedene
Module dieselbe, würde ein reiner Codetreffer sie fälschlich zusammenführen.
Dagegen schützt, dass ein Codetreffer allein nie genügt: Ein Stapel ist über
einen Code nur dann Kandidat, wenn die technischen Angaben ihm zusätzlich
nicht widersprechen (`specsCompatible`, siehe `proposeAssignment` in
`src/session.js`) — widerspricht der Stapel trotz passendem Code, fällt das
Modul auf einen eigenen Stapel zurück, statt lautlos falsch einsortiert zu
werden.
- Der Teilenummer-Decoder kennt bisher nur das Samsung-DDR4-Schema. Unbekannte
Schemata sind kein Fehler — sie führen automatisch zum OCR-Weg, und selbst
wenn dieser keine Kapazität findet, genügt die exakt gelesene Teilenummer