fable 3.0.148 → 3.0.150

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.0.148",
3
+ "version": "3.0.150",
4
4
  "description": "A service dependency injection, configuration and logging library.",
5
5
  "main": "source/Fable.js",
6
6
  "scripts": {
@@ -83,14 +83,47 @@
83
83
  "Name": "Round",
84
84
  "Address": "fable.Math.roundPrecise"
85
85
  },
86
- "countSetElements": {
86
+
87
+ "cumulativesummation": {
88
+ "Name": "Count Set Elements in a Histogram or Value Map",
89
+ "Address": "fable.Math.cumulativeSummation"
90
+ },
91
+
92
+ "countsetelements": {
87
93
  "Name": "Count Set Elements in a Histogram or Value Map",
88
94
  "Address": "fable.Math.countSetElements"
89
95
  },
90
96
 
91
97
  "getvalue": {
92
98
  "Name": "Get Value from Application State or Services (AppData, etc.)",
93
- "Address": "fable.Utility.getValue"
99
+ "Address": "fable.Utility.getInternalValueByHash"
100
+ },
101
+
102
+ "aggregationhistogram": {
103
+ "Name": "Generate a Histogram by Exact Value Aggregation",
104
+ "Address": "fable.Math.histogramAggregationByExactValueFromInternalState"
105
+ },
106
+ "distributionhistogram": {
107
+ "Name": "Generate a Histogram Based on Value Distribution",
108
+ "Address": "fable.Math.histogramDistributionByExactValueFromInternalState"
109
+ },
110
+
111
+ "getvaluearray": {
112
+ "Name": "Get Value Array from Application State or Services (AppData, etc.)",
113
+ "Address": "fable.Utility.createValueArrayByHashParametersFromInternal"
114
+ },
115
+ "getvalueobject": {
116
+ "Name": "Get Value Object from Application State or Services (AppData, etc.)",
117
+ "Address": "fable.Utility.createValueObjectByHashParametersFromInternal"
118
+ },
119
+
120
+ "cleanvaluearray": {
121
+ "Name": "Clean Value Array",
122
+ "Address": "fable.Math.cleanValueArray"
123
+ },
124
+ "cleanvalueobject": {
125
+ "Name": "Clean Value Object",
126
+ "Address": "fable.Math.cleanValueObject"
94
127
  },
95
128
 
96
129
  "randominteger": {
@@ -204,7 +204,11 @@ class ExpressionParserSolver extends libExpressionParserOperationBase
204
204
  delete tmpResults.fable;
205
205
  }
206
206
 
207
- if (typeof(tmpSolverResultValue) !== 'undefined')
207
+ if (typeof(tmpSolverResultValue) === 'object')
208
+ {
209
+ return tmpSolverResultValue;
210
+ }
211
+ else if (typeof(tmpSolverResultValue) !== 'undefined')
208
212
  {
209
213
  return tmpSolverResultValue.toString();
210
214
  }
@@ -582,6 +582,210 @@ class FableServiceMath extends libFableServiceBase
582
582
  return tmpSortedHistogram;
583
583
  }
584
584
 
585
+ cleanValueArray(pValueArray)
586
+ {
587
+ if (!Array.isArray(pValueArray))
588
+ {
589
+ return [];
590
+ }
591
+
592
+ let tmpCleanedArray = [];
593
+ for (let i = 0; i < pValueArray.length; i++)
594
+ {
595
+ let tmpValue = this.parsePrecise(pValueArray[i], NaN);
596
+ if (!isNaN(tmpValue))
597
+ {
598
+ tmpCleanedArray.push(tmpValue);
599
+ }
600
+ }
601
+ return tmpCleanedArray;
602
+ }
603
+
604
+ cleanValueObject(pValueObject)
605
+ {
606
+ if (typeof (pValueObject) !== 'object')
607
+ {
608
+ return {};
609
+ }
610
+
611
+ let tmpCleanedObject = {};
612
+ let tmpKeys = Object.keys(pValueObject);
613
+ for (let i = 0; i < tmpKeys.length; i++)
614
+ {
615
+ let tmpValue = this.parsePrecise(pValueObject[tmpKeys[i]], NaN);
616
+ if (!isNaN(tmpValue))
617
+ {
618
+ tmpCleanedObject[tmpKeys[i]] = tmpValue;
619
+ }
620
+ }
621
+ return tmpCleanedObject;
622
+ }
623
+
624
+ /**
625
+ * Make a histogram of representative counts for exact values (.tostring() is the keys to count)
626
+ * @param {Array} pValueSet
627
+ * @param {string} pValueAddress
628
+ */
629
+ histogramDistributionByExactValue(pValueObjectSet, pValueAddress, pManifest)
630
+ {
631
+ if (!Array.isArray(pValueObjectSet))
632
+ {
633
+ return pValueObjectSet;
634
+ }
635
+
636
+ if (!pValueAddress)
637
+ {
638
+ return {};
639
+ }
640
+
641
+ let tmpHistogram = {};
642
+ for (let i = 0; i < pValueObjectSet.length; i++)
643
+ {
644
+ let tmpValue = this.fable.Utility.getValueByHash(pValueObjectSet[i], pValueAddress, pManifest).toString();
645
+
646
+ if (!(tmpValue in tmpHistogram))
647
+ {
648
+ tmpHistogram[tmpValue] = 0;
649
+ }
650
+ tmpHistogram[tmpValue] = tmpHistogram[tmpValue] + 1;
651
+ }
652
+
653
+ return tmpHistogram;
654
+ }
655
+
656
+ histogramDistributionByExactValueFromInternalState(pValueObjectSetAddress, pValueAddress)
657
+ {
658
+ if (!pValueObjectSetAddress)
659
+ {
660
+ return {};
661
+ }
662
+
663
+ let tmpValueObjectSet = this.fable.Utility.getInternalValueByHash(pValueObjectSetAddress);
664
+ return this.histogramDistributionByExactValue(tmpValueObjectSet, pValueAddress);
665
+ }
666
+
667
+ /**
668
+ * Make a histogram of representative counts for exact values (.tostring() is the keys to count)
669
+ * @param {Array} pValueSet
670
+ * @param {string} pValueAddress
671
+ */
672
+ histogramAggregationByExactValue(pValueObjectSet, pValueAddress, pValueAmountAddress, pManifest)
673
+ {
674
+ if (!Array.isArray(pValueObjectSet))
675
+ {
676
+ return pValueObjectSet;
677
+ }
678
+
679
+ if (!pValueAddress || !pValueAmountAddress)
680
+ {
681
+ return {};
682
+ }
683
+
684
+ let tmpHistogram = {};
685
+ for (let i = 0; i < pValueObjectSet.length; i++)
686
+ {
687
+ let tmpValue = this.fable.Utility.getValueByHash(pValueObjectSet[i], pValueAddress, pManifest).toString();
688
+ let tmpAmount = this.parsePrecise(this.fable.Utility.getValueByHash(pValueObjectSet[i], pValueAmountAddress, pManifest), NaN);
689
+
690
+ if (!(tmpValue in tmpHistogram))
691
+ {
692
+ tmpHistogram[tmpValue] = 0;
693
+ }
694
+
695
+ if (!isNaN(tmpAmount))
696
+ {
697
+ tmpHistogram[tmpValue] = this.addPrecise(tmpHistogram[tmpValue], tmpAmount);
698
+ }
699
+ }
700
+
701
+ return tmpHistogram;
702
+ }
703
+
704
+ histogramAggregationByExactValueFromInternalState(pValueObjectSetAddress, pValueAddress, pValueAmountAddress)
705
+ {
706
+ if (!pValueObjectSetAddress)
707
+ {
708
+ return {};
709
+ }
710
+
711
+ let tmpValueObjectSet = this.fable.Utility.getInternalValueByHash(pValueObjectSetAddress);
712
+ return this.histogramAggregationByExactValue(tmpValueObjectSet, pValueAddress, pValueAmountAddress);
713
+ }
714
+
715
+ /**
716
+ * Given a value object set (an array of objects), find a specific entry when
717
+ * sorted by a specific value address. Supports -1 syntax for last entry.
718
+ * @param {Array} pValueObjectSet
719
+ * @param {string} pValueAddress
720
+ * @param {Object} pManifest
721
+ */
722
+ entryInSet(pValueObjectSet, pValueAddress, pEntryIndex)
723
+ {
724
+ if (!Array.isArray(pValueObjectSet))
725
+ {
726
+ return pValueObjectSet;
727
+ }
728
+
729
+ if (!pValueAddress)
730
+ {
731
+ return false;
732
+ }
733
+
734
+ if (isNaN(pEntryIndex) || pEntryIndex >= pValueObjectSet.length)
735
+ {
736
+ return false;
737
+ }
738
+
739
+ let tmpValueArray = pValueObjectSet.toSorted((pLeft, pRight) => { return this.comparePrecise(pLeft, pRight); });
740
+ let tmpIndex = (pEntryIndex === -1) ? tmpValueArray.length - 1 : pEntryIndex;
741
+ return tmpValueArray[tmpIndex];
742
+ }
743
+
744
+ smallestInSet(pValueObjectSet, pValueAddress)
745
+ {
746
+ return this.entryInSet(pValueObjectSet, pValueAddress, 0);
747
+ }
748
+
749
+ largestInSet(pValueObjectSet, pValueAddress)
750
+ {
751
+ return this.entryInSet(pValueObjectSet, pValueAddress, -1);
752
+ }
753
+
754
+ /**
755
+ * Expects an array of objects, and an address in each object to sum. Expects
756
+ * an address to put the cumulative summation as well.
757
+ * @param {Array} pValueObjectSet
758
+ */
759
+ cumulativeSummation(pValueObjectSet, pValueAddress, pCumulationResultAddress, pManifest)
760
+ {
761
+ if (!Array.isArray(pValueObjectSet))
762
+ {
763
+ return pValueObjectSet;
764
+ }
765
+
766
+ if (!pValueAddress || !pCumulationResultAddress)
767
+ {
768
+ return pValueObjectSet;
769
+ }
770
+
771
+ let tmpSummationValue = '0.0';
772
+ for (let i = 0; i < pValueObjectSet.length; i++)
773
+ {
774
+ let tmpValue = this.parsePrecise(this.fable.Utility.getValueByHash(pValueObjectSet[i], pValueAddress, pManifest));
775
+
776
+ if (isNaN(tmpValue))
777
+ {
778
+ this.fable.Utility.setValueByHash(pValueObjectSet[i], pCumulationResultAddress, tmpSummationValue, pManifest);
779
+ continue;
780
+ }
781
+
782
+ tmpSummationValue = this.addPrecise(tmpValue, tmpSummationValue);
783
+ this.fable.Utility.setValueByHash(pValueObjectSet[i], pCumulationResultAddress, tmpSummationValue, pManifest);
784
+ }
785
+
786
+ return pValueObjectSet;
787
+ }
788
+
585
789
  /**
586
790
  * Finds the maximum value from a set of precise values.
587
791
  *
@@ -97,18 +97,179 @@ class FableServiceUtility extends libFableServiceBase
97
97
  * Get a value from fable/pict by hash/address
98
98
  * @param {string} pValueAddress - The manyfest hash/address of the value to get
99
99
  */
100
- getValue(pValueAddress)
100
+ getInternalValueByHash(pValueAddress)
101
101
  {
102
- // Lazily create a manifest if it doesn't exist
103
- if (!this.manifest)
102
+ // Get the value from the internal manifest and return it
103
+ return this.getValueByHash(this.fable, pValueAddress);
104
+ }
105
+
106
+ /**
107
+ * Get a value from an object by hash/address
108
+ * @param {object} pObject - The object to get the value from
109
+ * @param {string} pValueAddress - The manyfest hash/address of the value to get
110
+ * @param {object} [pManifest] - The manyfest object to use; constructs one inline if not provided
111
+ * @returns {object} - The value from the object
112
+ */
113
+ getValueByHash(pObject, pValueAddress, pManifest)
114
+ {
115
+ let tmpManifest = pManifest;
116
+
117
+ if (typeof(tmpManifest) == 'undefined')
104
118
  {
105
- this.manifest = this.fable.newManyfest();
119
+ // Lazily create a manifest if it doesn't exist
120
+ if (!this.manifest)
121
+ {
122
+ this.manifest = this.fable.newManyfest();
123
+ }
124
+ tmpManifest = this.manifest;
106
125
  }
107
126
 
108
127
  // Get the value from the internal manifest and return it
109
- return this.manifest.getValueByHash(this.fable, pValueAddress);
128
+ return tmpManifest.getValueByHash(pObject, pValueAddress);
110
129
  }
111
-
130
+
131
+ /**
132
+ * Set a value to an object by hash/address
133
+ * @param {object} pObject - The object to get the value from
134
+ * @param {string} pValueAddress - The manyfest hash/address of the value to get
135
+ * @param {object} pValue - The value to set
136
+ * @param {object} [pManifest] - The manyfest object to use; constructs one inline if not provided
137
+ * @returns {object} - The value from the object
138
+ */
139
+ setValueByHash(pObject, pValueAddress, pValue, pManifest)
140
+ {
141
+ let tmpManifest = pManifest;
142
+
143
+ if (typeof(tmpManifest) == 'undefined')
144
+ {
145
+ // Lazily create a manifest if it doesn't exist
146
+ if (!this.manifest)
147
+ {
148
+ this.manifest = this.fable.newManyfest();
149
+ }
150
+ tmpManifest = this.manifest;
151
+ }
152
+
153
+ // Get the value from the internal manifest and return it
154
+ return tmpManifest.setValueByHash(pObject, pValueAddress, pValue);
155
+ }
156
+
157
+ /**
158
+ * Get a value array from an object by hash/address list
159
+ * @param {object} pObject - The object to get the value from
160
+ * @param {string} pValueAddress - The manyfest hash/address of the value to get
161
+ * @param {object} [pManifest] - The manyfest object to use; constructs one inline if not provided
162
+ * @returns {Array} - The value array built from the hash list
163
+ */
164
+ createValueArrayByHashes(pObject, pValueHashes, pManifest)
165
+ {
166
+ let tmpManifest = pManifest;
167
+
168
+ if (typeof(tmpManifest) == 'undefined')
169
+ {
170
+ // Lazily create a manifest if it doesn't exist
171
+ if (!this.manifest)
172
+ {
173
+ this.manifest = this.fable.newManyfest();
174
+ }
175
+ tmpManifest = this.manifest;
176
+ }
177
+
178
+ if (!Array.isArray(pValueHashes))
179
+ {
180
+ return [];
181
+ }
182
+
183
+ let tmpValueArray = [];
184
+ for (let i = 0; i < pValueHashes.length; i++)
185
+ {
186
+ tmpValueArray.push(tmpManifest.getValueByHash(pObject, pValueHashes[i]));
187
+ }
188
+
189
+ // Get the value from the internal manifest and return it
190
+ return tmpValueArray;
191
+ }
192
+
193
+ /**
194
+ * Get a value array by hash/address list from the internal fable/pict state
195
+ * @param {string} pValueAddress - The manyfest hash/address of the value to get
196
+ * @param {object} [pManifest] - The manyfest object to use; constructs one inline if not provided
197
+ * @returns {Array} - The value array built from the hash list
198
+ */
199
+ createValueArrayByHashesFromInternal(pValueHashes, pManifest)
200
+ {
201
+ return this.createValueArrayByHashes(this.fable, pValueHashes, pManifest);
202
+ }
203
+
204
+ createValueArrayByHashParametersFromInternal()
205
+ {
206
+ if (arguments.length < 2)
207
+ {
208
+ return [];
209
+ }
210
+
211
+ let tmpValueHashes = Array.prototype.slice.call(arguments);
212
+ return this.createValueArrayByHashes(this.fable, tmpValueHashes);
213
+ }
214
+
215
+ /**
216
+ * Get a value object from a list of hash/addressese
217
+ * @param {object} pObject - The object to get the value from
218
+ * @param {string} pValueAddress - The manyfest hash/address of the value to get
219
+ * @param {object} [pManifest] - The manyfest object to use; constructs one inline if not provided
220
+ * @returns {Array} - The value object built from the hash list
221
+ */
222
+ createValueObjectByHashes(pObject, pValueHashes, pManifest)
223
+ {
224
+ let tmpManifest = pManifest;
225
+
226
+ if (typeof(tmpManifest) == 'undefined')
227
+ {
228
+ // Lazily create a manifest if it doesn't exist
229
+ if (!this.manifest)
230
+ {
231
+ this.manifest = this.fable.newManyfest();
232
+ }
233
+ tmpManifest = this.manifest;
234
+ }
235
+
236
+ if (!Array.isArray(pValueHashes))
237
+ {
238
+ return {};
239
+ }
240
+
241
+ let tmpValueObject = {};
242
+ for (let i = 0; i < pValueHashes.length; i++)
243
+ {
244
+ tmpValueObject[pValueHashes[i]] = tmpManifest.getValueByHash(pObject, pValueHashes[i]);
245
+ }
246
+
247
+ // Get the value from the internal manifest and return it
248
+ return tmpValueObject;
249
+ }
250
+
251
+ /**
252
+ * Get a value object by hash/address list from the internal fable/pict state
253
+ * @param {string} pValueAddress - The manyfest hash/address of the value to get
254
+ * @param {object} [pManifest] - The manyfest object to use; constructs one inline if not provided
255
+ * @returns {object} - The value object built from the hash list
256
+ */
257
+ createValueObjectByHashesFromInternal(pValueHashes, pManifest)
258
+ {
259
+ return this.createValueObjectByHashes(this.fable, pValueHashes, pManifest);
260
+ }
261
+
262
+ /**
263
+ * Get a value object by hash/address list as parameters from the internal fable/pict state
264
+ * @returns {Array} - The value array built from the hash list
265
+ */
266
+ createValueObjectByHashParametersFromInternal()
267
+ {
268
+ let tmpValueHashes = Array.prototype.slice.call(arguments);
269
+ return this.createValueObjectByHashes(this.fable, tmpValueHashes);
270
+ }
271
+
272
+
112
273
  /**
113
274
  * Check if a value is null or empty
114
275
  * @param {object} pObject - The object to check
@@ -331,6 +331,40 @@ suite
331
331
  Expect(parseFloat(tmpResult)).to.be.at.most(13.78);
332
332
 
333
333
 
334
+ return fDone();
335
+ }
336
+ );
337
+ test
338
+ (
339
+ 'Complex Histogram Arithmatic',
340
+ (fDone)=>
341
+ {
342
+ let testFable = new libFable();
343
+
344
+ let testCityData = require('./data/cities.json');
345
+ testFable.AppData = { Cities: testCityData };
346
+
347
+ // let tmpDistribution = testFable.Math.histogramDistributionByExactValue(testFable.AppData.Cities, 'state');
348
+
349
+ // Expect(tmpDistribution.Alabama).to.equal(12);
350
+ // Expect(tmpDistribution.Colorado).to.equal(21);
351
+ // Expect(tmpDistribution.Florida).to.equal(73);
352
+ // Expect(tmpDistribution.Georgia).to.equal(18);
353
+
354
+ // Now through the solver
355
+
356
+ let _Parser = testFable.instantiateServiceProviderIfNotExists('ExpressionParser');
357
+ let tmpResultsObject = {};
358
+ let tmpDestinationObject = {};
359
+
360
+ _Parser.solve('DistributionResult = distributionhistogram("AppData.Cities", "state")', this.fable, tmpResultsObject, false, tmpDestinationObject);
361
+ _Parser.solve('AggregationResult = aggregationHistogram("AppData.Cities", "state", "population")', this.fable, tmpResultsObject, false, tmpDestinationObject);
362
+
363
+ Expect(tmpDestinationObject.DistributionResult.Alabama).to.equal(12);
364
+ Expect(tmpDestinationObject.DistributionResult.Colorado).to.equal(21);
365
+
366
+ Expect(tmpDestinationObject.AggregationResult.Alabama).to.equal('1279813');
367
+
334
368
  return fDone();
335
369
  }
336
370
  );
package/test/Math_test.js CHANGED
@@ -80,6 +80,37 @@ suite
80
80
  }
81
81
  );
82
82
  test
83
+ (
84
+ 'Cumulative Summation',
85
+ function(fDone)
86
+ {
87
+ let testFable = new libFable();
88
+
89
+ let tmpTestValueSet = (
90
+ [
91
+ { Item: 'Lettuce', Quantity: 2, Price: "7.99" },
92
+ { Item: 'Tomato', Quantity: 3, Price: "3.99" },
93
+ { Item: 'Onion', Quantity: 1, Price: "1.99" },
94
+ { Item: 'Cucumber', Quantity: 4, Price: "2.99" },
95
+ { Item: 'Carrot', Quantity: 3, Price: "1.99" },
96
+ { Item: 'Radish', Quantity: 2, Price: "1.49" },
97
+ { Item: 'Celery', Quantity: 1, Price: "0.99" },
98
+ { Item: 'Parsley', Quantity: 2, Price: "0.49" }
99
+ ]);
100
+
101
+ testFable.Math.cumulativeSummation(tmpTestValueSet, 'Price', 'RunningTotal');
102
+
103
+ Expect(tmpTestValueSet[0].RunningTotal).to.equal('7.99');
104
+ Expect(tmpTestValueSet[1].RunningTotal).to.equal('11.98');
105
+ Expect(tmpTestValueSet[2].RunningTotal).to.equal('13.97');
106
+ Expect(tmpTestValueSet[3].RunningTotal).to.equal('16.96');
107
+ Expect(tmpTestValueSet[4].RunningTotal).to.equal('18.95');
108
+ Expect(tmpTestValueSet[5].RunningTotal).to.equal('20.44');
109
+
110
+ return fDone();
111
+ }
112
+ );
113
+ test
83
114
  (
84
115
  'Parse Numbers',
85
116
  function(fDone)
@@ -95,6 +126,35 @@ suite
95
126
  }
96
127
  );
97
128
 
129
+ test
130
+ (
131
+ 'Histograms by Count',
132
+ function(fDone)
133
+ {
134
+
135
+ let testFable = new libFable();
136
+
137
+ let tmpTestValueSet = (
138
+ [
139
+ { City: 'New York', State: 'NY', GDP: 1000000 },
140
+ { City: 'Seattle', State: 'WA', GDP: 500000 },
141
+ { City: 'Portland', State: 'OR', GDP: 250000 },
142
+ { City: 'San Francisco', State: 'CA', GDP: 750000 },
143
+ { City: 'Los Angeles', State: 'CA', GDP: 500000 },
144
+ { City: 'San Diego', State: 'CA', GDP: 250000 },
145
+ { City: 'Atlanta', State: 'GA', GDP: 100000 },
146
+ { City: 'Savannah', State: 'GA', GDP: 50000 },
147
+ { City: 'Athens', State: 'GA', GDP: 25000 }
148
+ ]);
149
+
150
+ let tmpHistogramByDistribution = testFable.Math.histogramDistributionByExactValue(tmpTestValueSet, 'State');
151
+ Expect(tmpHistogramByDistribution).to.deep.equal({ CA: 3, GA: 3, NY: 1, OR: 1, WA: 1 });
152
+ let tmpHistogramByAggregation = testFable.Math.histogramAggregationByExactValue(tmpTestValueSet, 'State', 'GDP');
153
+ Expect(tmpHistogramByAggregation).to.deep.equal({ CA: "1500000", GA: "175000", NY: "1000000", OR: "250000", WA: "500000" });
154
+ return fDone();
155
+ }
156
+ );
157
+
98
158
  test
99
159
  (
100
160
  'Round Numbers',
@@ -30,6 +30,83 @@ suite
30
30
  'Utility',
31
31
  function()
32
32
  {
33
+ test
34
+ (
35
+ 'Get values and sets by hash from objects or from fable',
36
+ function()
37
+ {
38
+ testFable = new libFable();
39
+ testFable.AppData = {Name:'Thee Tortoise and the Hare'};
40
+ Expect(testFable.services.Utility.getValueByHash(testFable.AppData, 'Name')).to.equal('Thee Tortoise and the Hare');
41
+ Expect(testFable.services.Utility.getInternalValueByHash('AppData.Name')).to.equal('Thee Tortoise and the Hare');
42
+
43
+ let tmpDataObject = (
44
+ {
45
+ Name:'Thee Tortoise and the Hare',
46
+ Age: 100,
47
+ Colors:['Red','Green','Blue'],
48
+ Details:
49
+ {
50
+ ShoeSize: 12,
51
+ Height: 6.75,
52
+ Weight: "180.9"
53
+ }
54
+ });
55
+
56
+ let tmpValueArray = testFable.services.Utility.createValueArrayByHashes(tmpDataObject, ['Name', 'Age', 'Colors[2]', 'Nonce', 'Details.Height']);
57
+ Expect(tmpValueArray[0]).to.equal('Thee Tortoise and the Hare');
58
+ Expect(tmpValueArray[1]).to.equal(100);
59
+ Expect(tmpValueArray[2]).to.equal('Blue');
60
+ Expect(tmpValueArray[3]).to.equal(undefined);
61
+ Expect(tmpValueArray[4]).to.equal(6.75);
62
+
63
+ testFable.CustomDataLocation = tmpDataObject;
64
+ Expect(testFable.services.Utility.getInternalValueByHash('CustomDataLocation.Name')).to.equal('Thee Tortoise and the Hare');
65
+
66
+ let tmpInternalValueArray = testFable.services.Utility.createValueArrayByHashesFromInternal(['CustomDataLocation.Name', 'CustomDataLocation.Age', 'CustomDataLocation.Colors[1]', 'CustomDataLocation.Nonce', 'CustomDataLocation.Details.Height']);
67
+ Expect(tmpInternalValueArray[0]).to.equal('Thee Tortoise and the Hare');
68
+ Expect(tmpInternalValueArray[1]).to.equal(100);
69
+ Expect(tmpInternalValueArray[2]).to.equal('Green');
70
+ Expect(tmpInternalValueArray[3]).to.equal(undefined);
71
+ Expect(tmpInternalValueArray[4]).to.equal(6.75);
72
+
73
+ let tmpValueObject = testFable.services.Utility.createValueObjectByHashes(tmpDataObject, ['Name', 'Age', 'Colors[2]', 'Nonce', 'Details.Height']);
74
+ Expect(tmpValueObject.Name).to.equal('Thee Tortoise and the Hare');
75
+ Expect(tmpValueObject.Age).to.equal(100);
76
+ Expect(tmpValueObject['Colors[2]']).to.equal('Blue');
77
+ Expect(tmpValueObject.Nonce).to.equal(undefined);
78
+ Expect(tmpValueObject['Details.Height']).to.equal(6.75);
79
+
80
+ let tmpInternalValueObject = testFable.services.Utility.createValueObjectByHashesFromInternal(['CustomDataLocation.Name', 'CustomDataLocation.Age', 'CustomDataLocation.Colors[1]', 'CustomDataLocation.Nonce', 'CustomDataLocation.Details.Height']);
81
+ Expect(tmpInternalValueObject['CustomDataLocation.Name']).to.equal('Thee Tortoise and the Hare');
82
+ Expect(tmpInternalValueObject['CustomDataLocation.Age']).to.equal(100);
83
+ Expect(tmpInternalValueObject['CustomDataLocation.Colors[1]']).to.equal('Green');
84
+ Expect(tmpInternalValueObject['CustomDataLocation.Nonce']).to.equal(undefined);
85
+ Expect(tmpInternalValueObject['CustomDataLocation.Details.Height']).to.equal(6.75);
86
+
87
+ let tmpInternalValueArrayImplicit = testFable.services.Utility.createValueArrayByHashParametersFromInternal('CustomDataLocation.Name', 'CustomDataLocation.Age', 'CustomDataLocation.Colors[1]', 'CustomDataLocation.Nonce', 'CustomDataLocation.Details.Height');
88
+ Expect(tmpInternalValueArrayImplicit[0]).to.equal('Thee Tortoise and the Hare');
89
+ Expect(tmpInternalValueArrayImplicit[1]).to.equal(100);
90
+ Expect(tmpInternalValueArrayImplicit[2]).to.equal('Green');
91
+ Expect(tmpInternalValueArrayImplicit[3]).to.equal(undefined);
92
+ Expect(tmpInternalValueArrayImplicit[4]).to.equal(6.75);
93
+
94
+ let tmpInternalValueObjectImplicit = testFable.services.Utility.createValueObjectByHashParametersFromInternal('CustomDataLocation.Name', 'CustomDataLocation.Age', 'CustomDataLocation.Colors[1]', 'CustomDataLocation.Nonce', 'CustomDataLocation.Details.Height');
95
+ Expect(tmpInternalValueObjectImplicit['CustomDataLocation.Name']).to.equal('Thee Tortoise and the Hare');
96
+ Expect(tmpInternalValueObjectImplicit['CustomDataLocation.Age']).to.equal(100);
97
+ Expect(tmpInternalValueObjectImplicit['CustomDataLocation.Colors[1]']).to.equal('Green');
98
+ Expect(tmpInternalValueObjectImplicit['CustomDataLocation.Nonce']).to.equal(undefined);
99
+ Expect(tmpInternalValueObjectImplicit['CustomDataLocation.Details.Height']).to.equal(6.75);
100
+
101
+ let tmpCleanedValueArray = testFable.Math.cleanValueArray(tmpInternalValueArrayImplicit);
102
+ Expect(tmpCleanedValueArray[0]).to.equal('100');
103
+ Expect(tmpCleanedValueArray[1]).to.equal('6.75');
104
+
105
+ let tmpCleanedValueObject = testFable.Math.cleanValueObject(tmpInternalValueObjectImplicit);
106
+ Expect(tmpCleanedValueObject['CustomDataLocation.Age']).to.equal('100');
107
+ Expect(tmpCleanedValueObject['CustomDataLocation.Details.Height']).to.equal('6.75');
108
+ }
109
+ );
33
110
  test
34
111
  (
35
112
  'Process Template like Underscore',