fable 3.1.23 → 3.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fable",
3
- "version": "3.1.23",
3
+ "version": "3.1.24",
4
4
  "description": "A service dependency injection, configuration and logging library.",
5
5
  "main": "source/Fable.js",
6
6
  "scripts": {
@@ -125,10 +125,20 @@
125
125
  },
126
126
 
127
127
  "cumulativesummation": {
128
- "Name": "Count Set Elements in a Histogram or Value Map",
128
+ "Name": "Sum each value in a Histogram or Value Map cumulatively, creating or setting a property with the result on each row",
129
129
  "Address": "fable.Math.cumulativeSummation"
130
130
  },
131
131
 
132
+ "subtractingSummation": {
133
+ "Name": "Subtract each subsequent value in a Histogram or Value Map cumulatively (by default from the first row), creating or setting a property with the result on each row.",
134
+ "Address": "fable.Math.subtractingSummation"
135
+ },
136
+
137
+ "iterativeseries": {
138
+ "Name": "Perform an Iterative Series of Mathematical Operations on Set Elements",
139
+ "Address": "fable.Math.iterativeSeries"
140
+ },
141
+
132
142
  "countsetelements": {
133
143
  "Name": "Count Set Elements in a Histogram or Value Map",
134
144
  "Address": "fable.Math.countSetElements"
@@ -1101,9 +1101,54 @@ class FableServiceMath extends libFableServiceBase
1101
1101
  /**
1102
1102
  * Expects an array of objects, and an address in each object to sum. Expects
1103
1103
  * an address to put the cumulative summation as well.
1104
- * @param {Array} pValueObjectSet
1104
+ *
1105
+ * @param {Array} pValueObjectSet - The array of objects to perform a cumulative summation on
1106
+ * @param {string} pValueAddress - The address of the column in each object to sum
1107
+ * @param {string} pCumulationResultAddress - The address in each object to put the cumulative summation result
1108
+ * @param {Object} pManifest - The manifest to use for value retrieval and setting
1109
+ * @returns {Array} The updated value object set with cumulative summation results.
1105
1110
  */
1106
1111
  cumulativeSummation(pValueObjectSet, pValueAddress, pCumulationResultAddress, pManifest)
1112
+ {
1113
+ return this.iterativeSeries(pValueObjectSet, pValueAddress, pCumulationResultAddress, "1.0", "add", "0.0", true, pManifest);
1114
+ }
1115
+
1116
+ /**
1117
+ * Expects an array of objects, and an address in each object to sum. Expects
1118
+ * an address to put the cumulative summation as well.
1119
+ *
1120
+ * @param {Array} pValueObjectSet - The array of objects to perform a cumulative summation on
1121
+ * @param {string} pValueAddress - The address of the column in each object to sum
1122
+ * @param {string} pCumulationResultAddress - The address in each object to put the cumulative summation result
1123
+ * @param {string} pStartingValue - The (optional) address of the value to start with
1124
+ * @param {Object} pManifest - The manifest to use for value retrieval and setting
1125
+ * @returns {Array} The updated value object set with cumulative summation results.
1126
+ */
1127
+ subtractingSummation(pValueObjectSet, pValueAddress, pCumulationResultAddress, pStartingValue, pManifest)
1128
+ {
1129
+ let tmpProcessFirstRow = true;
1130
+ // If the starting value comes from somewhere else, we want to subtract the first row from it.
1131
+ if (typeof (pStartingValue) === 'undefined' || pStartingValue === null)
1132
+ {
1133
+ tmpProcessFirstRow = false;
1134
+ }
1135
+ return this.iterativeSeries(pValueObjectSet, pValueAddress, pCumulationResultAddress, "1.0", "subtract", pStartingValue, tmpProcessFirstRow, pManifest);
1136
+ }
1137
+
1138
+ /**
1139
+ * Expects an array of objects, and an address in each object to perform an iterative mathematical operation on.
1140
+
1141
+ * @param {Array} pValueObjectSet - The array of objects to perform a cumulative summation on
1142
+ * @param {string} pValueAddress - The address of the column in each object to sum
1143
+ * @param {string} pValueMultiplier - The multiplier to apply to each value before summation
1144
+ * @param {string} pSummationOperation - The operation to perform for summation: +, -, *, / (and some textual equivalents)
1145
+ * @param {string} pCumulationResultAddress - The address in each object to put the cumulative summation result
1146
+ * @param {string} pStartingValue - The address of the value to process from; defaults to the first row
1147
+ * @param {boolean} pProcessFirstRowWithAValue - Whether to process the first row's value from all subsequent rows
1148
+ * @param {Object} pManifest - The manifest to
1149
+ * @returns {Array} The updated value object set with cumulative summation results.
1150
+ */
1151
+ iterativeSeries(pValueObjectSet, pValueAddress, pCumulationResultAddress, pValueMultiplier, pSummationOperation, pStartingValue, pProcessFirstRowWithAValue, pManifest)
1107
1152
  {
1108
1153
  if (!Array.isArray(pValueObjectSet))
1109
1154
  {
@@ -1115,18 +1160,86 @@ class FableServiceMath extends libFableServiceBase
1115
1160
  return pValueObjectSet;
1116
1161
  }
1117
1162
 
1118
- let tmpSummationValue = '0.0';
1163
+ // By default don't subtract the first row from the value
1164
+ let tmpProcessFirstRow = (typeof(pProcessFirstRowWithAValue) === 'undefined') ? false : pProcessFirstRowWithAValue;
1165
+
1166
+ let tmpValueMultiplier;
1167
+ if (pValueMultiplier && pValueMultiplier !== '')
1168
+ {
1169
+ tmpValueMultiplier = this.parsePrecise(pValueMultiplier);
1170
+ }
1171
+ if (isNaN(tmpValueMultiplier))
1172
+ {
1173
+ tmpValueMultiplier = this.parsePrecise("1.0");
1174
+ }
1175
+
1176
+ // Default to start from the current value address
1177
+ let tmpSummationValue;
1178
+ // This logic ensures we don't default to 0 when pStartingValue is an empty string
1179
+ if (pStartingValue || (pStartingValue !== ''))
1180
+ {
1181
+ tmpSummationValue = this.parsePrecise(pStartingValue);
1182
+ }
1183
+ if (isNaN(tmpSummationValue) || typeof(pStartingValue) === 'undefined' || pStartingValue === null)
1184
+ {
1185
+ tmpSummationValue = '';
1186
+ }
1187
+
1119
1188
  for (let i = 0; i < pValueObjectSet.length; i++)
1120
1189
  {
1121
1190
  let tmpValue = this.parsePrecise(this.fable.Utility.getValueByHash(pValueObjectSet[i], pValueAddress, pManifest));
1191
+ // Since summation might start on a row after the first,
1192
+ let tmpFirstRowWithValue = false;
1193
+ if ((tmpSummationValue === '') && tmpValue && !isNaN(tmpSummationValue))
1194
+ {
1195
+ // Try to grab the summation value from the first row with a value
1196
+ tmpSummationValue = tmpValue;
1197
+ tmpFirstRowWithValue = true;
1198
+ }
1122
1199
 
1200
+ // Continue on with the values as they are if the current row doesn't have a change
1123
1201
  if (isNaN(tmpValue))
1124
1202
  {
1125
1203
  this.fable.Utility.setValueByHash(pValueObjectSet[i], pCumulationResultAddress, tmpSummationValue, pManifest);
1126
1204
  continue;
1127
1205
  }
1128
1206
 
1129
- tmpSummationValue = this.addPrecise(tmpValue, tmpSummationValue);
1207
+ tmpValue = this.multiplyPrecise(tmpValue, tmpValueMultiplier);
1208
+
1209
+ // Now perform the operation
1210
+ if (!tmpFirstRowWithValue || tmpProcessFirstRow)
1211
+ {
1212
+ switch (pSummationOperation)
1213
+ {
1214
+ case '+':
1215
+ case 'add':
1216
+ case 'plus':
1217
+ case 'addition':
1218
+ tmpSummationValue = this.addPrecise(tmpSummationValue, tmpValue);
1219
+ break;
1220
+
1221
+ case '-':
1222
+ case 'sub':
1223
+ case 'minus':
1224
+ case 'subtract':
1225
+ tmpSummationValue = this.subtractPrecise(tmpSummationValue, tmpValue);
1226
+ break;
1227
+
1228
+ case '*':
1229
+ case 'mul':
1230
+ case 'times':
1231
+ case 'multiply':
1232
+ tmpSummationValue = this.multiplyPrecise(tmpSummationValue, tmpValue);
1233
+ break;
1234
+
1235
+ case '-':
1236
+ case 'div':
1237
+ case 'over':
1238
+ case 'divide':
1239
+ tmpSummationValue = this.dividePrecise(tmpSummationValue, tmpValue);
1240
+ break;
1241
+ }
1242
+ }
1130
1243
  this.fable.Utility.setValueByHash(pValueObjectSet[i], pCumulationResultAddress, tmpSummationValue, pManifest);
1131
1244
  }
1132
1245
 
@@ -177,6 +177,30 @@ suite
177
177
  }
178
178
  );
179
179
  test
180
+ (
181
+ 'Test iterative series',
182
+ (fDone)=>
183
+ {
184
+ let testFable = new libFable();
185
+ let _Parser = testFable.instantiateServiceProviderIfNotExists('ExpressionParser');
186
+
187
+ let tmpResult = _Parser.solve('Result = ITERATIVESERIES(Values, "Value", "Resultant", 1, "add")',
188
+ {
189
+ Values: [
190
+ {Value: 10},
191
+ {Value: 20},
192
+ {Value: 5}
193
+ ]
194
+ });
195
+
196
+ Expect(tmpResult[0].Resultant).to.equal("10");
197
+ Expect(tmpResult[1].Resultant).to.equal("30");
198
+ Expect(tmpResult[2].Resultant).to.equal("35");
199
+
200
+ return fDone();
201
+ }
202
+ )
203
+ test
180
204
  (
181
205
  'Exercise End-to-End Expression Parsing',
182
206
  (fDone)=>
package/test/Math_test.js CHANGED
@@ -113,6 +113,100 @@ suite
113
113
  Expect(tmpTestValueSet[4].RunningTotal).to.equal('18.95');
114
114
  Expect(tmpTestValueSet[5].RunningTotal).to.equal('20.44');
115
115
 
116
+ tmpTestValueSet = (
117
+ [
118
+ { Item: 'NoCost', Quantity: 2 },
119
+ ...tmpTestValueSet
120
+ ]);
121
+
122
+ testFable.Math.cumulativeSummation(tmpTestValueSet, 'Price', 'RunningTotal');
123
+
124
+ Expect(tmpTestValueSet[0].RunningTotal).to.equal('0');
125
+ Expect(tmpTestValueSet[1].RunningTotal).to.equal('7.99');
126
+ Expect(tmpTestValueSet[2].RunningTotal).to.equal('11.98');
127
+ Expect(tmpTestValueSet[3].RunningTotal).to.equal('13.97');
128
+ Expect(tmpTestValueSet[4].RunningTotal).to.equal('16.96');
129
+ Expect(tmpTestValueSet[5].RunningTotal).to.equal('18.95');
130
+ Expect(tmpTestValueSet[6].RunningTotal).to.equal('20.44');
131
+
132
+ return fDone();
133
+ }
134
+ );
135
+
136
+ test
137
+ (
138
+ 'Subtractive Summation',
139
+ function(fDone)
140
+ {
141
+ let testFable = new libFable();
142
+
143
+ let tmpTestValueSet = (
144
+ [
145
+ { Item: 'GroceryBag', Volume: '150.00' },
146
+
147
+ { Item: 'Lettuce', Volume: '80' },
148
+ { Item: 'Tomato', Volume: '30.17' },
149
+ { Item: 'Onion', Volume: '10.9' },
150
+ { Item: 'Cucumber', Volume: '15.032' }
151
+ ]);
152
+
153
+ testFable.Math.subtractingSummation(tmpTestValueSet, 'Volume', 'SpaceLeftInBag');
154
+
155
+ Expect(tmpTestValueSet[0].SpaceLeftInBag).to.equal('150');
156
+ Expect(tmpTestValueSet[1].SpaceLeftInBag).to.equal('70');
157
+ Expect(tmpTestValueSet[2].SpaceLeftInBag).to.equal('39.83');
158
+ Expect(tmpTestValueSet[3].SpaceLeftInBag).to.equal('28.93');
159
+ Expect(tmpTestValueSet[4].SpaceLeftInBag).to.equal('13.898');
160
+
161
+ return fDone();
162
+ }
163
+ );
164
+
165
+ test
166
+ (
167
+ 'Iterative Series Operations',
168
+ function(fDone)
169
+ {
170
+ let testFable = new libFable();
171
+
172
+ let tmpTestValueSet = (
173
+ [
174
+ { Item: 'FirstSplit', Amount: '8' },
175
+ { Item: 'SecondSplit', Amount: '2' },
176
+ { Item: 'ThirdSplit', Amount: '4' },
177
+ { Item: 'FourthSplit', Amount: '2' }
178
+ ]);
179
+
180
+ testFable.Math.iterativeSeries(tmpTestValueSet, 'Amount', 'RAMLeft', '1.25', 'divide', '1024', true);
181
+ Expect(tmpTestValueSet[0].RAMLeft).to.equal('102.4');
182
+ Expect(tmpTestValueSet[1].RAMLeft).to.equal('40.96');
183
+ Expect(tmpTestValueSet[2].RAMLeft).to.equal('8.192');
184
+ Expect(tmpTestValueSet[3].RAMLeft).to.equal('3.2768');
185
+
186
+ testFable.Math.iterativeSeries(tmpTestValueSet, 'Amount', 'RAMLeft', '1.0', 'divide', '1024', true);
187
+ Expect(tmpTestValueSet[0].RAMLeft).to.equal('128');
188
+ Expect(tmpTestValueSet[1].RAMLeft).to.equal('64');
189
+ Expect(tmpTestValueSet[2].RAMLeft).to.equal('16');
190
+ Expect(tmpTestValueSet[3].RAMLeft).to.equal('8');
191
+
192
+ testFable.Math.iterativeSeries(tmpTestValueSet, 'Amount', 'RAMLeft', '0.7512', 'mul', '1024', true);
193
+ Expect(tmpTestValueSet[0].RAMLeft).to.equal('6153.8304');
194
+ Expect(tmpTestValueSet[1].RAMLeft).to.equal('9245.51479296');
195
+ Expect(tmpTestValueSet[2].RAMLeft).to.equal('27780.922849886208');
196
+ Expect(tmpTestValueSet[3].RAMLeft).to.equal('41738.0584896690388992');
197
+
198
+ testFable.Math.iterativeSeries(tmpTestValueSet, 'Amount', 'RAMLeft', null, 'sub');
199
+ Expect(tmpTestValueSet[0].RAMLeft).to.equal('8');
200
+ Expect(tmpTestValueSet[1].RAMLeft).to.equal('6');
201
+ Expect(tmpTestValueSet[2].RAMLeft).to.equal('2');
202
+ Expect(tmpTestValueSet[3].RAMLeft).to.equal('0');
203
+
204
+ testFable.Math.iterativeSeries(tmpTestValueSet, 'Amount', 'RAMLeft', undefined, 'sub', 1100);
205
+ Expect(tmpTestValueSet[0].RAMLeft).to.equal('1092');
206
+ Expect(tmpTestValueSet[1].RAMLeft).to.equal('1090');
207
+ Expect(tmpTestValueSet[2].RAMLeft).to.equal('1086');
208
+ Expect(tmpTestValueSet[3].RAMLeft).to.equal('1084');
209
+
116
210
  return fDone();
117
211
  }
118
212
  );
@@ -128,6 +222,7 @@ suite
128
222
  // 3.3333333333333333333333333333333 in the current node.js implementation collapses to 3.3333333333333335
129
223
  Expect(testFable.Math.parsePrecise('4.3333333333333333333333333333333')).to.equal('4.3333333333333333333333333333333');
130
224
  Expect(testFable.Math.parsePrecise(undefined)).to.equal('0.0');
225
+ Expect(testFable.Math.parsePrecise('')).to.equal('0.0');
131
226
 
132
227
  return fDone();
133
228
  }