diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js
index 8b828bc0..e2ee57cf 100755
--- a/src/core/config/Categories.js
+++ b/src/core/config/Categories.js
@@ -113,7 +113,7 @@ const Categories = [
]
},
{
- name: "Logical operations",
+ name: "Arithmetic / Logic",
ops: [
"XOR",
"XOR Brute Force",
@@ -122,6 +122,13 @@ const Categories = [
"AND",
"ADD",
"SUB",
+ "Sum",
+ "Subtract",
+ "Multiply",
+ "Divide",
+ "Mean",
+ "Median",
+ "Standard Deviation",
"Bit shift left",
"Bit shift right",
"Rotate left",
diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js
index 1e975118..2f1d6781 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";
@@ -519,6 +520,97 @@ const OperationConfig = {
}
]
},
+ "Sum": {
+ module: "Default",
+ description: "Adds together a list of numbers. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 .5
becomes 18.5
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
+ "Subtract": {
+ module: "Default",
+ description: "Subtracts a list of numbers. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 .5
becomes 1.5
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
+ "Multiply": {
+ module: "Default",
+ description: "Multiplies a list of numbers. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 .5
becomes 40
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
+ "Divide": {
+ module: "Default",
+ description: "Divides a list of numbers. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 .5
becomes 2.5
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
+ "Mean": {
+ module: "Default",
+ description: "Computes the mean (average) of a number list. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 .5 .5
becomes 4.75
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
+ "Median": {
+ module: "Default",
+ description: "Computes the median of a number list. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 1 .5
becomes 4.5
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
+ "Standard Deviation": {
+ module: "Default",
+ description: "Computes the standard deviation of a number list. If an item in the string is not a number it is excluded from the list.
e.g. 0x0a 8 .5
becomes 4.089281382128433
",
+ inputType: "string",
+ outputType: "number",
+ args: [
+ {
+ name: "Delimiter",
+ type: "option",
+ value: Arithmetic.DELIM_OPTIONS
+ }
+ ]
+ },
"From Hex": {
module: "Default",
description: "Converts a hexadecimal byte string back into its raw value.
e.g. ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a
becomes the UTF-8 encoded string Γειά σου
",
diff --git a/src/core/config/modules/Default.js b/src/core/config/modules/Default.js
index a0e8bd23..4fb76887 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";
@@ -159,6 +160,13 @@ OpModules.Default = {
"Return": FlowControl.runReturn,
"Comment": FlowControl.runComment,
"PHP Deserialize": PHP.runDeserialize,
+ "Sum": Arithmetic.runSum,
+ "Subtract": Arithmetic.runSub,
+ "Multiply": Arithmetic.runMulti,
+ "Divide": Arithmetic.runDiv,
+ "Mean": Arithmetic.runMean,
+ "Median": Arithmetic.runMedian,
+ "Standard Deviation": Arithmetic.runStdDev,
/*
diff --git a/src/core/operations/Arithmetic.js b/src/core/operations/Arithmetic.js
new file mode 100644
index 00000000..1fe73ac1
--- /dev/null
+++ b/src/core/operations/Arithmetic.js
@@ -0,0 +1,252 @@
+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: ["Line feed", "Space", "Comma", "Semi-colon", "Colon", "CRLF"],
+
+
+ /**
+ * Splits a string based on a delimiter and calculates the sum of numbers.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runSum: function(input, args) {
+ const val = Arithmetic._sum(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * Splits a string based on a delimiter and subtracts all the numbers.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runSub: function(input, args) {
+ let val = Arithmetic._sub(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * Splits a string based on a delimiter and multiplies the numbers.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runMulti: function(input, args) {
+ let val = Arithmetic._multi(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * Splits a string based on a delimiter and divides the numbers.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runDiv: function(input, args) {
+ let val = Arithmetic._div(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * Splits a string based on a delimiter and computes the mean (average).
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runMean: function(input, args) {
+ let val = Arithmetic._mean(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * Splits a string based on a delimiter and finds the median.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runMedian: function(input, args) {
+ let val = Arithmetic._median(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * splits a string based on a delimiter and computes the standard deviation.
+ *
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {number}
+ */
+ runStdDev: function(input, args) {
+ let val = Arithmetic._stdDev(Arithmetic._createNumArray(input, args[0]));
+ return typeof(val) === "number" ? val : NaN;
+ },
+
+
+ /**
+ * Converts a string array to a number array.
+ *
+ * @private
+ * @param {string[]} input
+ * @param {string} delim
+ * @returns {number[]}
+ */
+ _createNumArray: function(input, delim) {
+ delim = Utils.charRep[delim || "Space"];
+ let splitNumbers = input.split(delim),
+ numbers = [],
+ 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(), 0);
+ }
+ if (!isNaN(num)) {
+ numbers.push(num);
+ }
+ }
+ return numbers;
+ },
+
+
+ /**
+ * Adds an array of numbers and returns the value.
+ *
+ * @private
+ * @param {number[]} data
+ * @returns {number}
+ */
+ _sum: function(data) {
+ if (data.length > 0) {
+ return data.reduce((acc, curr) => acc + curr);
+ }
+ },
+
+
+ /**
+ * Subtracts an array of numbers and returns the value.
+ *
+ * @private
+ * @param {number[]} data
+ * @returns {number}
+ */
+ _sub: function(data) {
+ if (data.length > 0) {
+ return data.reduce((acc, curr) => acc - curr);
+ }
+ },
+
+
+ /**
+ * Multiplies an array of numbers and returns the value.
+ *
+ * @private
+ * @param {number[]} data
+ * @returns {number}
+ */
+ _multi: function(data) {
+ if (data.length > 0) {
+ return data.reduce((acc, curr) => acc * curr);
+ }
+ },
+
+
+ /**
+ * Divides an array of numbers and returns the value.
+ *
+ * @private
+ * @param {number[]} data
+ * @returns {number}
+ */
+ _div: function(data) {
+ if (data.length > 0) {
+ return data.reduce((acc, curr) => acc / curr);
+ }
+ },
+
+
+ /**
+ * Computes mean of a number array and returns the value.
+ *
+ * @private
+ * @param {number[]} data
+ * @returns {number}
+ */
+ _mean: function(data) {
+ if (data.length > 0) {
+ return Arithmetic._sum(data) / data.length;
+ }
+ },
+
+
+ /**
+ * Computes 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)];
+ }
+ },
+
+
+ /**
+ * Computes 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);
+ }
+ },
+};
+
+export default Arithmetic;