From 940b56ba5fd9246366ff953082c085ae83decaa9 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Wed, 26 Feb 2020 10:55:15 +0000 Subject: [PATCH] Luhn Checksum Operation Added --- src/core/config/Categories.json | 1 + src/core/operations/LuhnChecksum.mjs | 62 +++++++++++++++++++++++++ tests/operations/index.mjs | 1 + tests/operations/tests/LuhnChecksum.mjs | 44 ++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 src/core/operations/LuhnChecksum.mjs create mode 100644 tests/operations/tests/LuhnChecksum.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 0d68efe8..459b3071 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -332,6 +332,7 @@ "Fletcher-32 Checksum", "Fletcher-64 Checksum", "Adler-32 Checksum", + "Luhn Checksum", "CRC-8 Checksum", "CRC-16 Checksum", "CRC-32 Checksum", diff --git a/src/core/operations/LuhnChecksum.mjs b/src/core/operations/LuhnChecksum.mjs new file mode 100644 index 00000000..24549072 --- /dev/null +++ b/src/core/operations/LuhnChecksum.mjs @@ -0,0 +1,62 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Luhn Checksum operation + */ +class LuhnChecksum extends Operation { + + /** + * LuhnChecksum constructor + */ + constructor() { + super(); + + this.name = "Luhn Checksum"; + this.module = "Crypto"; + 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, Canadian Social Insurance Numbers."; + this.infoURL = "https://wikipedia.org/wiki/Luhn_algorithm"; + this.inputType = "string"; + this.outputType = "number"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + let even = false; + return input.split("").reverse().reduce((acc, elem) => { + + // Convert element to integer. + let temp = parseInt(elem, 10); + + // If element is not an integer. + if (isNaN(temp)) + throw new OperationError("Character: " + elem + " is not a digit."); + + // 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); + } + + even = !even; + return acc + temp; + + }, 0) % 10; + } + +} + +export default LuhnChecksum; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 3257905d..44f57b07 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -97,6 +97,7 @@ import "./tests/DefangIP.mjs"; import "./tests/ParseUDP.mjs"; import "./tests/AvroToJSON.mjs"; import "./tests/Lorenz.mjs"; +import "./tests/LuhnChecksum.mjs"; // Cannot test operations that use the File type yet diff --git a/tests/operations/tests/LuhnChecksum.mjs b/tests/operations/tests/LuhnChecksum.mjs new file mode 100644 index 00000000..28b17854 --- /dev/null +++ b/tests/operations/tests/LuhnChecksum.mjs @@ -0,0 +1,44 @@ +/** + * From Decimal tests + * + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @licence Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Luhn Checksum on standard data", + input: "35641709012469", + expectedOutput: "7", + recipeConfig: [ + { + op: "Luhn Checksum", + args: [] + }, + ], + }, + { + name: "Luhn Checksum on invalid data", + input: "35641709b012469", + expectedOutput: "Character: b is not a digit.", + recipeConfig: [ + { + op: "Luhn Checksum", + args: [] + }, + ], + }, + { + name: "Luhn Checksum on empty data", + input: "", + expectedOutput: "0", + recipeConfig: [ + { + op: "Luhn Checksum", + args: [] + }, + ], + } +]);