-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1933 from k3ach/master
Updated luhn checksum operation to work with different bases
- Loading branch information
Showing
2 changed files
with
422 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/** | ||
* @author n1073645 [[email protected]] | ||
* @author k3ach [[email protected]] | ||
* @copyright Crown Copyright 2020 | ||
* @license Apache-2.0 | ||
*/ | ||
|
@@ -20,39 +21,46 @@ class LuhnChecksum extends Operation { | |
|
||
this.name = "Luhn Checksum"; | ||
this.module = "Default"; | ||
this.description = "The Luhn algorithm, also known as the modulus 10 or mod 10 algorithm, is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers and Canadian Social Insurance Numbers."; | ||
this.infoURL = "https://wikipedia.org/wiki/Luhn_algorithm"; | ||
this.description = "The Luhn mod N algorithm using the english alphabet. The Luhn mod N algorithm is an extension to the Luhn algorithm (also known as mod 10 algorithm) that allows it to work with sequences of values in any even-numbered base. This can be useful when a check digit is required to validate an identification string composed of letters, a combination of letters and digits or any arbitrary set of N characters where N is divisible by 2."; | ||
this.infoURL = "https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm"; | ||
this.inputType = "string"; | ||
this.outputType = "string"; | ||
this.args = []; | ||
this.args = [ | ||
{ | ||
"name": "Radix", | ||
"type": "number", | ||
"value": 10 | ||
} | ||
]; | ||
} | ||
|
||
/** | ||
* Generates the Luhn Checksum from the input. | ||
* Generates the Luhn checksum from the input. | ||
* | ||
* @param {string} inputStr | ||
* @returns {number} | ||
*/ | ||
checksum(inputStr) { | ||
checksum(inputStr, radix = 10) { | ||
let even = false; | ||
return inputStr.split("").reverse().reduce((acc, elem) => { | ||
// Convert element to integer. | ||
let temp = parseInt(elem, 10); | ||
// Convert element to an integer based on the provided radix. | ||
let temp = parseInt(elem, radix); | ||
|
||
// If element is not an integer. | ||
if (isNaN(temp)) | ||
throw new OperationError("Character: " + elem + " is not a digit."); | ||
// If element is not a valid number in the given radix. | ||
if (isNaN(temp)) { | ||
throw new Error("Character: " + elem + " is not valid in radix " + radix + "."); | ||
} | ||
|
||
// If element is in an even position | ||
if (even) { | ||
// Double the element and add the quotient and remainder together. | ||
temp = 2 * elem; | ||
temp = Math.floor(temp/10) + (temp % 10); | ||
// Double the element and sum the quotient and remainder. | ||
temp = 2 * temp; | ||
temp = Math.floor(temp / radix) + (temp % radix); | ||
} | ||
|
||
even = !even; | ||
return acc + temp; | ||
}, 0) % 10; | ||
}, 0) % radix; // Use radix as the modulus base | ||
} | ||
|
||
/** | ||
|
@@ -63,9 +71,20 @@ class LuhnChecksum extends Operation { | |
run(input, args) { | ||
if (!input) return ""; | ||
|
||
const checkSum = this.checksum(input); | ||
let checkDigit = this.checksum(input + "0"); | ||
checkDigit = checkDigit === 0 ? 0 : (10-checkDigit); | ||
const radix = args[0]; | ||
|
||
if (radix < 2 || radix > 36) { | ||
throw new OperationError("Error: Radix argument must be between 2 and 36"); | ||
} | ||
|
||
if (radix % 2 !== 0) { | ||
throw new OperationError("Error: Radix argument must be divisible by 2"); | ||
} | ||
|
||
const checkSum = this.checksum(input, radix).toString(radix); | ||
let checkDigit = this.checksum(input + "0", radix); | ||
checkDigit = checkDigit === 0 ? 0 : (radix - checkDigit); | ||
checkDigit = checkDigit.toString(radix); | ||
|
||
return `Checksum: ${checkSum} | ||
Checkdigit: ${checkDigit} | ||
|
Oops, something went wrong.