/** * Normalize collector numbers so "015/208" and "15/208" compare equal. */ export function normalizeCardNumber(value) { if (value == null || value === '') return ''; const trimmed = String(value).trim(); const slashIndex = trimmed.indexOf('/'); if (slashIndex === -1) { return trimmed.toLowerCase(); } const numerator = trimmed.slice(0, slashIndex).trim(); const denominator = trimmed.slice(slashIndex + 1).trim(); const normalizedNumerator = String(parseInt(numerator, 10)); if (normalizedNumerator === 'NaN') { return trimmed.toLowerCase(); } return `${normalizedNumerator}/${denominator}`.toLowerCase(); } export function cardNumbersEquivalent(a, b) { if (a == null || b == null || a === '' || b === '') return false; return normalizeCardNumber(a) === normalizeCardNumber(b); } /** * Pick one catalog row when name+set candidates share an equivalent collector number. */ export function findPrintingByCollectorNumber(candidates, cardNumber) { if (!cardNumber || candidates.length === 0) return null; const matches = candidates.filter((row) => cardNumbersEquivalent(row.card_number, cardNumber)); return matches.length === 1 ? matches[0] : null; }