/** * Player-name normalization for cross-source matching. * * ParlayAPI emits "Brunson, Jalen"; ESPN emits "Jalen Brunson"; nba_api * sometimes attaches a jersey number. Normalize aggressively so equality * comparisons just work. * * Pipeline: * NFD unicode → strip accents → lowercase → drop suffixes (jr/sr/ii/iii/ * iv/v) → strip punctuation → collapse whitespace → trim. * * `keepDigits` (default false) controls whether digits survive the * punctuation strip. The trap detector matches names only and wants * digits gone; the player-ID population script keeps them because some * legacy roster fields encode jersey numbers inline. */ function normalizeName(name, { keepDigits = false } = {}) { if (!name) return ''; const punctClass = keepDigits ? '[^a-z0-9\\s]' : '[^a-z\\s]'; return String(name) .normalize('NFD') .replace(/[̀-ͯ]/g, '') .toLowerCase() .replace(/\b(jr|sr|ii|iii|iv|v)\.?\b/g, '') .replace(new RegExp(punctClass, 'g'), ' ') .replace(/\s+/g, ' ') .trim(); } module.exports = { normalizeName };