spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
Formulas.XOR written and tested.
author
Ben Vogt <[email protected]>
date
2017-02-04 22:45:13
stats
4 file(s) changed, 81 insertions(+), 30 deletions(-)
files
src/RawFormulas/Logical.ts
src/RawFormulas/Math.ts
src/RawFormulas/RawFormulas.ts
tests/FormulasTest.ts
  1diff --git a/src/RawFormulas/Logical.ts b/src/RawFormulas/Logical.ts
  2index 72036de..c135483 100644
  3--- a/src/RawFormulas/Logical.ts
  4+++ b/src/RawFormulas/Logical.ts
  5@@ -1,4 +1,4 @@
  6-import { checkArgumentsAtLeastLength, checkArgumentsLength, valueToString } from "./Utils"
  7+import { checkArgumentsAtLeastLength, checkArgumentsLength, valueToString, valueToBoolean } from "./Utils"
  8 import { CellError } from "../Errors"
  9 import * as ERRORS from "../Errors"
 10 
 11@@ -91,9 +91,34 @@ var NOT = function (...values) : boolean {
 12   }
 13 };
 14 
 15+/**
 16+ * Returns true if any of the provided arguments are logically true, and false if all of the provided arguments are logically false.
 17+ * TODO: Should this allow the acceptance of functions that return true or false?
 18+ * @param values An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.
 19+ * @returns {boolean}
 20+ * @constructor
 21+ */
 22+var OR = function (...values) {
 23+  checkArgumentsAtLeastLength(values, 1);
 24+  for (var i = 0; i < values.length; i++) {
 25+    if (values[i] instanceof Array) {
 26+      if (values[i].length === 0) {
 27+        throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
 28+      }
 29+      if (OR.apply(this, values[i])) {
 30+        return true;
 31+      }
 32+    } else if (valueToBoolean(values[i])) {
 33+      return true;
 34+    }
 35+  }
 36+  return false;
 37+};
 38+
 39 export {
 40   AND,
 41   EXACT,
 42   TRUE,
 43-  NOT
 44+  NOT,
 45+  OR
 46 }
 47\ No newline at end of file
 48diff --git a/src/RawFormulas/Math.ts b/src/RawFormulas/Math.ts
 49index 41025c8..3b5c7ad 100644
 50--- a/src/RawFormulas/Math.ts
 51+++ b/src/RawFormulas/Math.ts
 52@@ -672,30 +672,6 @@ var LOG = function (...values) : number {
 53   return ln / lb;
 54 };
 55 
 56-/**
 57- * Returns true if any of the provided arguments are logically true, and false if all of the provided arguments are logically false.
 58- * TODO: Should this allow the acceptance of functions that return true or false?
 59- * @param values An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.
 60- * @returns {boolean}
 61- * @constructor
 62- */
 63-var OR = function (...values) {
 64-  checkArgumentsAtLeastLength(values, 1);
 65-  for (var i = 0; i < values.length; i++) {
 66-    if (values[i] instanceof Array) {
 67-      if (values[i].length === 0) {
 68-        throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
 69-      }
 70-      if (OR.apply(this, values[i])) {
 71-        return true;
 72-      }
 73-    } else if (valueToBoolean(values[i])) {
 74-      return true;
 75-    }
 76-  }
 77-  return false;
 78-};
 79-
 80 /**
 81  * Returns the tangent of an angle provided in radians.
 82  * @param values The angle to find the tangent of, in radians.
 83@@ -755,7 +731,6 @@ export {
 84   SQRT,
 85   PI,
 86   POWER,
 87-  OR,
 88   LOG,
 89   LOG10,
 90   TAN,
 91diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
 92index a072a42..c465157 100644
 93--- a/src/RawFormulas/RawFormulas.ts
 94+++ b/src/RawFormulas/RawFormulas.ts
 95@@ -36,7 +36,6 @@ import {
 96   SQRT,
 97   PI,
 98   POWER,
 99-  OR,
100   LOG,
101   LOG10,
102   TAN,
103@@ -46,7 +45,8 @@ import {
104   AND,
105   EXACT,
106   TRUE,
107-  NOT
108+  NOT,
109+  OR
110 } from "./Logical";
111 import {
112   CHAR,
113@@ -152,7 +152,37 @@ var SUMSQ = Formula["SUMSQ"];
114 var SUMX2MY2 = Formula["SUMX2MY2"];
115 var SUMX2PY2 = Formula["SUMX2PY2"];
116 var TRUNC = Formula["TRUNC"];
117-var XOR = Formula["XOR"];
118+
119+/**
120+ * Exclusive or or exclusive disjunction is a logical operation that outputs true only when inputs differ.
121+ * @param values to check for exclusivity.
122+ * @returns {boolean} returns true if only one input is considered logically true.
123+ * @constructor
124+ */
125+var XOR = function (...values) {
126+  checkArgumentsAtLeastLength(values, 1);
127+  var alreadyTruthy = false;
128+  for (var i = 0; i < values.length; i++) {
129+    if (values[i] instanceof Array) {
130+      if (values[i].length === 0) {
131+        throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
132+      }
133+      if (XOR.apply(this, values[i])) {
134+        if (alreadyTruthy) {
135+          return false;
136+        }
137+        alreadyTruthy = true;
138+      }
139+    } else if (valueToBoolean(values[i])) {
140+      if (alreadyTruthy) {
141+        return false;
142+      }
143+      alreadyTruthy = true;
144+    }
145+  }
146+  return alreadyTruthy;
147+};
148+
149 var YEARFRAC = Formula["YEARFRAC"];
150 
151 export {
152diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
153index 9f4e3bf..1f54db8 100644
154--- a/tests/FormulasTest.ts
155+++ b/tests/FormulasTest.ts
156@@ -1041,11 +1041,32 @@ assertEquals(TANH([1, 44]), 0.7615941559557649);
157 assertEquals(TANH([1, "str"]), 0.7615941559557649);
158 
159 
160+// Test TRUE
161 assertEquals(TRUE(), true);
162 
163 assertEquals(TRUNC(3.1415, 2), 3.14);
164 
165+// Test XOR
166 assertEquals(XOR(1, 1), false);
167+assertEquals(XOR(1, 0), true);
168+assertEquals(XOR(0, 0, 0), false);
169+assertEquals(XOR(0, 0, 1), true);
170+assertEquals(XOR(0, 0, [0, 0, 1]), true);
171+assertEquals(XOR(0, 1, [0, 0, 1]), false);
172+catchAndAssertEquals(function() {
173+  XOR("str");
174+}, ERRORS.VALUE_ERROR);
175+catchAndAssertEquals(function() {
176+  XOR();
177+}, ERRORS.NA_ERROR);
178+catchAndAssertEquals(function() {
179+  XOR(1, []);
180+}, ERRORS.REF_ERROR);
181+catchAndAssertEquals(function() {
182+  XOR([]);
183+}, ERRORS.REF_ERROR);
184+
185+
186 
187 assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 0), 18.994444444444444);
188 // assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 1)', 18.99587544); // This is slightly off