forked from Yara724/api
87 lines
2.9 KiB
JavaScript
87 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* Quick manual verification for plate normalization.
|
||
*
|
||
* Usage: node scripts/verify-plate-normalization.mjs
|
||
*
|
||
* Demonstrates that:
|
||
* 339ه77 (ه + U+200D) -> 339ه77 -> letter ه -> code 15
|
||
* 339ي77 (Arabic ي) -> 339ی77 -> letter ی -> code 16
|
||
*/
|
||
|
||
// ---------- paste the pure function here so no build needed ----------
|
||
function normalizePlateText(text) {
|
||
if (!text) return text;
|
||
let result = String(text);
|
||
result = result.normalize("NFKC");
|
||
result = result.replace(/[\u200C\u200D\u200E\u200F\uFEFF]/g, "");
|
||
result = result.replace(/\u064A/g, "\u06CC"); // Arabic ي → Persian ی
|
||
result = result.trim();
|
||
return result;
|
||
}
|
||
|
||
// ---------- the canonical plate-letter → code mapping ----------
|
||
const PLATE_LETTER_MAP = {
|
||
الف: 1, ب: 2, پ: 3, ج: 4, د: 5,
|
||
س: 6, ص: 7, ط: 8, ع: 9, ق: 10,
|
||
ل: 11, م: 12, ن: 13, و: 14, ه: 15,
|
||
ی: 16, ک: 17, ژ: 18, ت: 19, ث: 20,
|
||
ز: 21, ش: 22, ف: 23, گ: 24,
|
||
};
|
||
|
||
function extractAndMap(plateString) {
|
||
const normalized = normalizePlateText(plateString);
|
||
|
||
// Simple parser: digits | letter | digits (left+right digits, 1 letter)
|
||
const match = normalized.match(/^(\d+)([^\d]+)(\d+)$/);
|
||
if (!match) return { input: plateString, normalized, error: "no match" };
|
||
|
||
const [, leftDigits, letterRaw, rightDigits] = match;
|
||
const letter = normalizePlateText(letterRaw);
|
||
const code = PLATE_LETTER_MAP[letter];
|
||
|
||
return {
|
||
input: plateString,
|
||
normalized,
|
||
leftDigits,
|
||
letter,
|
||
rightDigits,
|
||
code,
|
||
ok: code !== undefined,
|
||
};
|
||
}
|
||
|
||
// ---------- test cases ----------
|
||
const cases = [
|
||
{ desc: "ه + ZWJ (the original bug)", plate: "339ه\u200D77" },
|
||
{ desc: "Arabic ي → Persian ی", plate: "339ي77" },
|
||
{ desc: "ه + ZWNJ", plate: "339ه\u200C77" },
|
||
{ desc: "RTL mark around letter", plate: "339\u200Fه\u200E77" },
|
||
{ desc: "BOM + ZWJ combined", plate: "\uFEFF339ه\u200D77" },
|
||
{ desc: "clean letter (no junk)", plate: "339ه77" },
|
||
{ desc: "full plate: الف", plate: "11الف22" },
|
||
{ desc: "full plate: ی", plate: "55ی99" },
|
||
];
|
||
|
||
console.log("Plate Normalization Verification\n");
|
||
console.log("=".repeat(72));
|
||
|
||
let allPassed = true;
|
||
for (const { desc, plate } of cases) {
|
||
const r = extractAndMap(plate);
|
||
const status = r.ok ? "PASS" : "FAIL";
|
||
if (!r.ok) allPassed = false;
|
||
|
||
console.log(`\n[${status}] ${desc}`);
|
||
console.log(` Input: ${JSON.stringify(plate)}`);
|
||
console.log(` Normalized: ${JSON.stringify(r.normalized)}`);
|
||
if (r.letter) {
|
||
console.log(` Letter: ${r.letter} (U+${r.letter.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0")})`);
|
||
}
|
||
console.log(` Code: ${r.code ?? "undefined"}`);
|
||
}
|
||
|
||
console.log("\n" + "=".repeat(72));
|
||
console.log(allPassed ? "\n All tests PASSED ✓" : "\n Some tests FAILED ✗");
|
||
process.exit(allPassed ? 0 : 1);
|