diff --git a/books.html b/books.html
index 860b8c5..09b6314 100644
--- a/books.html
+++ b/books.html
@@ -55,33 +55,52 @@
}
// Helper: Convert ISBN-10 to ISBN-13 (prefix 978)
+ // ISBN-13 is the modern standard that replaced ISBN-10. All ISBN-10s can be converted
+ // to ISBN-13 by prepending '978' (the bookland EAN prefix) to the first 9 digits,
+ // then recalculating the check digit using the EAN-13 algorithm.
function isbn10to13(isbn10) {
const clean = normalizeIsbn(isbn10);
if (clean.length !== 10) return null;
+
+ // Take first 9 digits of ISBN-10 and prepend '978' to create 12-digit base
const core = '978' + clean.slice(0, 9);
- // EAN-13 check digit
+
+ // Calculate EAN-13 check digit using the standard algorithm:
+ // Sum all digits, alternating between weight 1 (even positions) and weight 3 (odd positions)
+ // The check digit is the number needed to make the total sum a multiple of 10
let sum = 0;
for (let i = 0; i < 12; i++) {
const d = parseInt(core[i], 10);
- sum += (i % 2 === 0) ? d : d * 3;
+ sum += (i % 2 === 0) ? d : d * 3; // Even index = weight 1, odd index = weight 3
}
const check = (10 - (sum % 10)) % 10;
return core + String(check);
}
// Helper: Convert ISBN-13 to ISBN-10 (only for 978 prefix)
+ // Only ISBN-13s with '978' prefix (bookland) can be converted back to ISBN-10.
+ // ISBN-13s with '979' prefix have no ISBN-10 equivalent as they were issued after
+ // the ISBN-10 system was deprecated.
function isbn13to10(isbn13) {
const clean = normalizeIsbn(isbn13);
if (clean.length !== 13 || !clean.startsWith('978')) return null;
+
+ // Extract the 9 core digits (removing '978' prefix and check digit)
const core9 = clean.slice(3, 12);
+
+ // Calculate ISBN-10 check digit using modulo 11 algorithm:
+ // Each digit is multiplied by its position weight (10 down to 2)
+ // The check digit makes the weighted sum divisible by 11
let sum = 0;
for (let i = 0; i < 9; i++) {
- sum += (10 - i) * parseInt(core9[i], 10);
+ sum += (10 - i) * parseInt(core9[i], 10); // Weights: 10, 9, 8, 7, 6, 5, 4, 3, 2
}
+
+ // Calculate what's needed to reach next multiple of 11
let remainder = 11 - (sum % 11);
let check;
- if (remainder === 10) check = 'X';
- else if (remainder === 11) check = '0';
+ if (remainder === 10) check = 'X'; // 'X' represents 10 in ISBN-10
+ else if (remainder === 11) check = '0'; // Remainder 11 means already divisible, use 0
else check = String(remainder);
return core9 + check;
}