From ae8d1f21786a5fe2216bb6ebf9d22ff0dd57ce98 Mon Sep 17 00:00:00 2001 From: bwhitn Date: Sun, 17 Dec 2017 15:19:10 -0500 Subject: [PATCH 1/5] start of math operations --- src/core/config/OperationConfig.js | 19 +++++ src/core/operations/Arithmetic.js | 130 +++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 src/core/operations/Arithmetic.js diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 9caa4f91..81444880 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -1,3 +1,4 @@ +import Arithmetic from "../operations/Arithmetic.js"; import Base from "../operations/Base.js"; import Base58 from "../operations/Base58.js"; import Base64 from "../operations/Base64.js"; @@ -656,6 +657,24 @@ const OperationConfig = { } ] }, + "Arithmetic": { + module: "Default", + description: "Conducts mathamatical operations on a list of numbers", + inputType: "string" + outputType: "string" + args: [ + { + name: "Delimiter", + type: "option", + value: Arithmetic.DELIM_OPTIONS + }, + { + name: "Operation" + type: "option", + value: Arithmetic.OPERATIONS + } + ] + }, "From Hexdump": { module: "Default", description: "Attempts to convert a hexdump back into raw data. This operation supports many different hexdump variations, but probably not all. Make sure you verify that the data it gives you is correct before continuing analysis.", diff --git a/src/core/operations/Arithmetic.js b/src/core/operations/Arithmetic.js new file mode 100644 index 00000000..8a840a29 --- /dev/null +++ b/src/core/operations/Arithmetic.js @@ -0,0 +1,130 @@ +import Utils from "../Utils.js"; + +/** + * Math operations on numbers. + * + * @author bwhitn [brian.m.whitney@outlook.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @namespace + */ +const Arithmetic = { + + /** + * @constant + * @default + */ + DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF"], + + /** + * @constant + * @default + */ + OPERATIONS: ["Sum", "Sub", "Multiply", "Divide", "Mean", "Median", "Mode"], + + /** + * A mapping of operation names to their function. + * @constant + */ + opMap: { + "Sub": _sub, + "Sum": _sum, + "Multiply": _multiply, + "Divide": _divide, + "Mean": _mean, + "Median": _median, + "Mode": _mode, + }, + + /** + * + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runOp: function(input, args) { + const delim = Utils.charRep[args[0] || "Space"]; + let splitNumbers = input.split(delim), + numbers = [], + num, + retVal; + for (i = 0; i < splitNumbers.length; i++) { + if splitNumbers[i].indexOf(".") { + num = parseFloat(splitNumbers[i].trim()); + } else { + num = parseInt(splitNumbers[i].trim()); + } + if (num !== "NaN") { + numbers.append(num); + } + } + num = Arithmetic.opMap[args[1] || "Sum"](numbers); + if (num !== null) { + return "The values " + args[1] + "equal: " + num; + } + throw "Error with Arithmetic Operation: " + args[1]; + }, + + + _sum: function(data) { + let total = 0; + for (i = 0; i < data.length; i++) { + total += data[i]; + } + return total; + }, + + _sub: function(data) { + let total = 0; + if (data.length > 1) { + total = data[0]; + for (i = 1; i < data.length; i++) { + total -= data[i]; + } + } else { + total = null; + } + return total; + }, + + _multiply: function(data) { + let total = 0; + if (data.length > 1) { + total = data[0]; + for (i = 1; i < data.length; i++) { + total *= data[i]; + } + } else { + total = null; + } + return total; + }, + + _divide: function(data) { + let total = 0; + if (data.length > 1) { + total = data[0]; + for (i = 1; i < data.length; i++) { + total /= data[i] + } + } else { + total = null; + } + return total; + }, + + _mean: function(data) { + let total = 0; + if (data.length > 1) { + total = Arithmetic._sum(data) / data.length; + } else { + total = null; + } + return total; + }, + +}; + +export default Arithmetic; From 772f9a806e8136ac235a7614136a647151afa1b8 Mon Sep 17 00:00:00 2001 From: bwhitn Date: Sun, 17 Dec 2017 15:20:58 -0500 Subject: [PATCH 2/5] Added additional arithmetic source --- src/core/config/Categories.js | 1 + src/core/config/OperationConfig.js | 6 +-- src/core/config/modules/Default.js | 2 + src/core/operations/Arithmetic.js | 80 +++++++++++++++++++++--------- 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js index f04b5fd9..7faa75f2 100755 --- a/src/core/config/Categories.js +++ b/src/core/config/Categories.js @@ -159,6 +159,7 @@ const Categories = [ { name: "Utils", ops: [ + "Arithmetic", "Diff", "Remove whitespace", "Remove null bytes", diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 81444880..65d1d065 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -660,8 +660,8 @@ const OperationConfig = { "Arithmetic": { module: "Default", description: "Conducts mathamatical operations on a list of numbers", - inputType: "string" - outputType: "string" + inputType: "string", + outputType: "string", args: [ { name: "Delimiter", @@ -669,7 +669,7 @@ const OperationConfig = { value: Arithmetic.DELIM_OPTIONS }, { - name: "Operation" + name: "Operation", type: "option", value: Arithmetic.OPERATIONS } diff --git a/src/core/config/modules/Default.js b/src/core/config/modules/Default.js index 682db223..5f049ac7 100644 --- a/src/core/config/modules/Default.js +++ b/src/core/config/modules/Default.js @@ -1,4 +1,5 @@ import FlowControl from "../../FlowControl.js"; +import Arithmetic from "../../operations/Arithmetic.js"; import Base from "../../operations/Base.js"; import Base58 from "../../operations/Base58.js"; import Base64 from "../../operations/Base64.js"; @@ -155,6 +156,7 @@ OpModules.Default = { "Conditional Jump": FlowControl.runCondJump, "Return": FlowControl.runReturn, "Comment": FlowControl.runComment, + "Arithmetic": Arithmetic.runOp, /* diff --git a/src/core/operations/Arithmetic.js b/src/core/operations/Arithmetic.js index 8a840a29..ef6643e4 100644 --- a/src/core/operations/Arithmetic.js +++ b/src/core/operations/Arithmetic.js @@ -23,20 +23,6 @@ const Arithmetic = { */ OPERATIONS: ["Sum", "Sub", "Multiply", "Divide", "Mean", "Median", "Mode"], - /** - * A mapping of operation names to their function. - * @constant - */ - opMap: { - "Sub": _sub, - "Sum": _sum, - "Multiply": _multiply, - "Divide": _divide, - "Mean": _mean, - "Median": _median, - "Mode": _mode, - }, - /** * * @@ -48,13 +34,12 @@ const Arithmetic = { const delim = Utils.charRep[args[0] || "Space"]; let splitNumbers = input.split(delim), numbers = [], - num, - retVal; - for (i = 0; i < splitNumbers.length; i++) { - if splitNumbers[i].indexOf(".") { + num; + for (let i = 0; i < splitNumbers.length; i++) { + if (splitNumbers[i].indexOf(".") >= 0) { num = parseFloat(splitNumbers[i].trim()); } else { - num = parseInt(splitNumbers[i].trim()); + num = parseInt(splitNumbers[i].trim(), 10); } if (num !== "NaN") { numbers.append(num); @@ -68,19 +53,33 @@ const Arithmetic = { }, + /** + * Adds an array of numbers and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ _sum: function(data) { let total = 0; - for (i = 0; i < data.length; i++) { + for (let i = 0; i < data.length; i++) { total += data[i]; } return total; }, + /** + * Subtracts an array of numbers and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ _sub: function(data) { let total = 0; if (data.length > 1) { total = data[0]; - for (i = 1; i < data.length; i++) { + for (let i = 1; i < data.length; i++) { total -= data[i]; } } else { @@ -89,11 +88,18 @@ const Arithmetic = { return total; }, + /** + * Multiplies an array of numbers and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ _multiply: function(data) { let total = 0; if (data.length > 1) { total = data[0]; - for (i = 1; i < data.length; i++) { + for (let i = 1; i < data.length; i++) { total *= data[i]; } } else { @@ -102,12 +108,19 @@ const Arithmetic = { return total; }, + /** + * Divides an array of numbers and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ _divide: function(data) { let total = 0; if (data.length > 1) { total = data[0]; - for (i = 1; i < data.length; i++) { - total /= data[i] + for (let i = 1; i < data.length; i++) { + total /= data[i]; } } else { total = null; @@ -115,6 +128,13 @@ const Arithmetic = { return total; }, + /** + * Finds the mean of a number array and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ _mean: function(data) { let total = 0; if (data.length > 1) { @@ -125,6 +145,18 @@ const Arithmetic = { return total; }, + /** + * A mapping of operation names to their function. + * @constant + */ + opMap: { + "Sub": Arithmetic._sum, + "Sum": Arithmetic._sub, + "Multiply": Arithmetic._multiply, + "Divide": Arithmetic._divide, + "Mean": Arithmetic._mean, + }, + }; export default Arithmetic; From 6ad3728314dcfb7caae95cab81b2a4d0a1536b0f Mon Sep 17 00:00:00 2001 From: bwhitn Date: Sun, 17 Dec 2017 15:29:31 -0500 Subject: [PATCH 3/5] changed op array --- src/core/operations/Arithmetic.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/operations/Arithmetic.js b/src/core/operations/Arithmetic.js index ef6643e4..1278ac3b 100644 --- a/src/core/operations/Arithmetic.js +++ b/src/core/operations/Arithmetic.js @@ -150,11 +150,11 @@ const Arithmetic = { * @constant */ opMap: { - "Sub": Arithmetic._sum, - "Sum": Arithmetic._sub, - "Multiply": Arithmetic._multiply, - "Divide": Arithmetic._divide, - "Mean": Arithmetic._mean, + "Sum": function(numArray) { return Arithmetic._sum(numArray); }, + "Sub": function(numArray) { return Arithmetic._sub(numArray); }, + "Multiply": function(numArray) { return Arithmetic._multiply(numArray); }, + "Divide": function(numArray) { return Arithmetic._divide(numArray); }, + "Mean": function(numArray) { return Arithmetic._mean(numArray); }, }, }; From 298e8e849199bd8c4d22b5625abac9a3c1d8184a Mon Sep 17 00:00:00 2001 From: bwhitn Date: Sun, 17 Dec 2017 21:57:09 -0500 Subject: [PATCH 4/5] Inital commit for pull --- src/core/operations/Arithmetic.js | 140 ++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 46 deletions(-) diff --git a/src/core/operations/Arithmetic.js b/src/core/operations/Arithmetic.js index 1278ac3b..ffcb6c86 100644 --- a/src/core/operations/Arithmetic.js +++ b/src/core/operations/Arithmetic.js @@ -21,7 +21,15 @@ const Arithmetic = { * @constant * @default */ - OPERATIONS: ["Sum", "Sub", "Multiply", "Divide", "Mean", "Median", "Mode"], + OPERATIONS: [ + "Sum", + "Sub", + "Multiply", + "Divide", + "Mean", + "Median", + "Standard Deviation" + ], /** * @@ -39,17 +47,17 @@ const Arithmetic = { if (splitNumbers[i].indexOf(".") >= 0) { num = parseFloat(splitNumbers[i].trim()); } else { - num = parseInt(splitNumbers[i].trim(), 10); + num = parseInt(splitNumbers[i].trim(), 0); } - if (num !== "NaN") { - numbers.append(num); + if (!isNaN(num)) { + numbers.push(num); } } num = Arithmetic.opMap[args[1] || "Sum"](numbers); - if (num !== null) { - return "The values " + args[1] + "equal: " + num; + if (num === null) { + return ""; } - throw "Error with Arithmetic Operation: " + args[1]; + return num; }, @@ -61,11 +69,11 @@ const Arithmetic = { * @returns {number} */ _sum: function(data) { - let total = 0; - for (let i = 0; i < data.length; i++) { - total += data[i]; + if (data.length > 0) { + return data.reduce((acc, curr) => acc + curr); + } else { + return null; } - return total; }, /** @@ -76,16 +84,11 @@ const Arithmetic = { * @returns {number} */ _sub: function(data) { - let total = 0; - if (data.length > 1) { - total = data[0]; - for (let i = 1; i < data.length; i++) { - total -= data[i]; - } + if (data.length > 0) { + return data.reduce((acc, curr) => acc - curr); } else { - total = null; + return null; } - return total; }, /** @@ -96,16 +99,11 @@ const Arithmetic = { * @returns {number} */ _multiply: function(data) { - let total = 0; - if (data.length > 1) { - total = data[0]; - for (let i = 1; i < data.length; i++) { - total *= data[i]; - } + if (data.length > 0) { + return data.reduce((acc, curr) => acc * curr); } else { - total = null; + return null; } - return total; }, /** @@ -116,16 +114,11 @@ const Arithmetic = { * @returns {number} */ _divide: function(data) { - let total = 0; - if (data.length > 1) { - total = data[0]; - for (let i = 1; i < data.length; i++) { - total /= data[i]; - } + if (data.length > 0) { + return data.reduce((acc, curr) => acc / curr); } else { - total = null; + return null; } - return total; }, /** @@ -136,27 +129,82 @@ const Arithmetic = { * @returns {number} */ _mean: function(data) { - let total = 0; - if (data.length > 1) { - total = Arithmetic._sum(data) / data.length; + if (data.length > 0) { + return Arithmetic._sum(data) / data.length; } else { - total = null; + return null; + } + }, + + /** + * Finds the median of a number array and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ + _median: function (data) { + if ((data.length % 2) === 0) { + let first, second; + data.sort(function(a, b){ + return a - b; + }); + first = data[Math.floor(data.length / 2)]; + second = data[Math.floor(data.length / 2) - 1]; + return Arithmetic._mean([first, second]); + } else { + return data[Math.floor(data.length / 2)]; + } + }, + + /** + * Finds the standard deviation of a number array and returns the value. + * + * @private + * @param {number[]} data + * @returns {number} + */ + _stdDev: function (data) { + if (data.length > 0) { + let avg = Arithmetic._mean(data); + let devSum = 0; + for (let i = 0; i < data.length; i++) { + devSum += (data[i] - avg) ** 2; + } + return Math.sqrt(devSum / data.length); + } else { + return null; } - return total; }, /** * A mapping of operation names to their function. + * * @constant */ opMap: { - "Sum": function(numArray) { return Arithmetic._sum(numArray); }, - "Sub": function(numArray) { return Arithmetic._sub(numArray); }, - "Multiply": function(numArray) { return Arithmetic._multiply(numArray); }, - "Divide": function(numArray) { return Arithmetic._divide(numArray); }, - "Mean": function(numArray) { return Arithmetic._mean(numArray); }, + "Sum": function(numArray) { + return Arithmetic._sum(numArray); + }, + "Sub": function(numArray) { + return Arithmetic._sub(numArray); + }, + "Multiply": function(numArray) { + return Arithmetic._multiply(numArray); + }, + "Divide": function(numArray) { + return Arithmetic._divide(numArray); + }, + "Mean": function(numArray) { + return Arithmetic._mean(numArray); + }, + "Median": function(numArray) { + return Arithmetic._median(numArray); + }, + "Standard Deviation": function (numArray) { + return Arithmetic._stdDev(numArray); + }, }, - }; export default Arithmetic; From 2b47631f4d9c1174ca841005f4cc04c12df7225c Mon Sep 17 00:00:00 2001 From: bwhitn Date: Sun, 17 Dec 2017 22:15:13 -0500 Subject: [PATCH 5/5] minor fix --- src/core/operations/Arithmetic.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/Arithmetic.js b/src/core/operations/Arithmetic.js index ffcb6c86..1151c28f 100644 --- a/src/core/operations/Arithmetic.js +++ b/src/core/operations/Arithmetic.js @@ -57,7 +57,7 @@ const Arithmetic = { if (num === null) { return ""; } - return num; + return num.toString(); },