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
|
@@ -125,10 +125,20 @@
|
|
|
125
125
|
},
|
|
126
126
|
|
|
127
127
|
"cumulativesummation": {
|
|
128
|
-
"Name": "
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|