fable 3.1.32 → 3.1.34

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.
Files changed (33) hide show
  1. package/dist/fable.js +471 -371
  2. package/dist/fable.js.map +1 -1
  3. package/dist/fable.min.js +2 -2
  4. package/dist/fable.min.js.map +1 -1
  5. package/example_applications/mathematical_playground/README.md +27 -0
  6. package/package.json +2 -2
  7. package/source/Fable.js +0 -1
  8. package/source/services/Fable-Service-CSVParser.js +177 -177
  9. package/source/services/Fable-Service-DataFormat.js +22 -22
  10. package/source/services/Fable-Service-DataGeneration.js +161 -161
  11. package/source/services/Fable-Service-DateManipulation.js +209 -209
  12. package/source/services/Fable-Service-EnvironmentData-Web.js +3 -3
  13. package/source/services/Fable-Service-EnvironmentData.js +3 -3
  14. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js +136 -0
  15. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js +6 -0
  16. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +39 -0
  17. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js +2 -2
  18. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +9 -0
  19. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js +3 -3
  20. package/source/services/Fable-Service-ExpressionParser.js +154 -22
  21. package/source/services/Fable-Service-FilePersistence.js +2 -2
  22. package/source/services/Fable-Service-Logic.js +1 -1
  23. package/source/services/Fable-Service-Math.js +293 -57
  24. package/source/services/Fable-Service-MetaTemplate.js +2 -2
  25. package/source/services/Fable-Service-Operation.js +7 -7
  26. package/source/services/Fable-Service-ProgressTime.js +3 -3
  27. package/source/services/Fable-Service-RestClient.js +2 -2
  28. package/source/services/Fable-Service-Template.js +4 -4
  29. package/source/services/Fable-Service-Utility.js +6 -6
  30. package/test/ExpressionParser_tests.js +67 -0
  31. package/test/Math_test.js +81 -1
  32. package/source/services/Fable-Service-ExpressionParser/RNI_Randy.json +0 -1
  33. package/source/services/Fable-Service-ExpressionParser/RNI_Tool.json +0 -1
@@ -58,7 +58,7 @@ class FableServiceProgressTime extends libFableServiceBase
58
58
  {
59
59
  let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
60
60
  let tmpReferenceTime = false;
61
-
61
+
62
62
  // This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
63
63
  if (typeof(pReferenceTime) == 'string')
64
64
  {
@@ -102,7 +102,7 @@ class FableServiceProgressTime extends libFableServiceBase
102
102
  {
103
103
  let tmpTimeStampHash = (typeof(pTimeStampHash) == 'string') ? pTimeStampHash : 'Default';
104
104
  let tmpReferenceTime = false;
105
-
105
+
106
106
  // This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
107
107
  if (typeof(pReferenceTime) == 'string')
108
108
  {
@@ -156,4 +156,4 @@ class FableServiceProgressTime extends libFableServiceBase
156
156
  }
157
157
  }
158
158
 
159
- module.exports = FableServiceProgressTime;
159
+ module.exports = FableServiceProgressTime;
@@ -44,7 +44,7 @@ class FableServiceRestClient extends libFableServiceBase
44
44
  if (tmpCookieKeys.length > 0)
45
45
  {
46
46
  // Only grab the first for now.
47
- pRequestOptions.headers.cookie = libCookie.serialize(tmpCookieKeys[0], tmpCookieObject[tmpCookieKeys[0]]);
47
+ pRequestOptions.headers.cookie = libCookie.serialize(tmpCookieKeys[0], tmpCookieObject[tmpCookieKeys[0]]);
48
48
  }
49
49
  }
50
50
  return pRequestOptions;
@@ -319,4 +319,4 @@ class FableServiceRestClient extends libFableServiceBase
319
319
  }
320
320
  }
321
321
 
322
- module.exports = FableServiceRestClient;
322
+ module.exports = FableServiceRestClient;
@@ -13,9 +13,9 @@ class FableServiceTemplate extends libFableServiceBase
13
13
  // TODO: Make this use precedent, add configuration, add debugging.
14
14
  constructor(pFable, pOptions, pServiceHash)
15
15
  {
16
- super(pFable, pOptions, pServiceHash);
16
+ super(pFable, pOptions, pServiceHash);
17
17
 
18
- this.serviceType = 'Template';
18
+ this.serviceType = 'Template';
19
19
 
20
20
  // These are the exact regex's used in lodash/underscore
21
21
  // TODO: Switch this to precedent
@@ -49,7 +49,7 @@ class FableServiceTemplate extends libFableServiceBase
49
49
  // This is defined as such to underscore that it is a dynamic programming
50
50
  // function on this class.
51
51
  this.renderFunction = false;
52
- this.templateString = false;
52
+ this.templateString = false;
53
53
  }
54
54
 
55
55
  renderTemplate(pData)
@@ -103,4 +103,4 @@ class FableServiceTemplate extends libFableServiceBase
103
103
  }
104
104
  }
105
105
 
106
- module.exports = FableServiceTemplate;
106
+ module.exports = FableServiceTemplate;
@@ -19,7 +19,7 @@ class FableServiceUtility extends libFableServiceBase
19
19
  // TODO: Make this use precedent, add configuration, add debugging.
20
20
  constructor(pFable, pOptions, pServiceHash)
21
21
  {
22
- super(pFable, pOptions, pServiceHash);
22
+ super(pFable, pOptions, pServiceHash);
23
23
 
24
24
  this.templates = {};
25
25
 
@@ -92,7 +92,7 @@ class FableServiceUtility extends libFableServiceBase
92
92
 
93
93
  return tmpChunkCache;
94
94
  }
95
-
95
+
96
96
  /**
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
@@ -207,7 +207,7 @@ class FableServiceUtility extends libFableServiceBase
207
207
  {
208
208
  return [];
209
209
  }
210
-
210
+
211
211
  let tmpValueHashes = Array.prototype.slice.call(arguments);
212
212
  return this.createValueArrayByHashes(this.fable, tmpValueHashes);
213
213
  }
@@ -325,9 +325,9 @@ class FableServiceUtility extends libFableServiceBase
325
325
 
326
326
  objectValuesSortByExternalArray(pArray, pObjectArray, pDescending, pSearchAddress)
327
327
  {
328
- let tmpDescending = (typeof(pDescending) == 'boolean') ? pDescending :
329
- ((typeof(pDescending) == 'number') && (pDescending == 1)) ? true :
330
- ((typeof(pDescending) == 'string') && (pDescending == '1')) ? true :
328
+ let tmpDescending = (typeof(pDescending) == 'boolean') ? pDescending :
329
+ ((typeof(pDescending) == 'number') && (pDescending == 1)) ? true :
330
+ ((typeof(pDescending) == 'string') && (pDescending == '1')) ? true :
331
331
  false;
332
332
  let tmpManifest = this.fable.newManyfest();
333
333
 
@@ -461,6 +461,47 @@ suite
461
461
  Expect(parseFloat(tmpResult)).to.be.at.most(13.78);
462
462
 
463
463
 
464
+ return fDone();
465
+ }
466
+ );
467
+ test
468
+ (
469
+ 'Test integration prepartion..',
470
+ (fDone) =>
471
+ {
472
+ let testFable = new libFable();
473
+ let _Parser = testFable.instantiateServiceProviderIfNotExists('ExpressionParser');
474
+
475
+ let tmpManifest = testFable.newManyfest();
476
+ let tmpDataSourceObject = {};
477
+ let tmpDataDestinationObject = {};
478
+ let tmpParserResultsObject = {};
479
+
480
+ // Approximate an integration of the function 1000 + (n / 2) from 13.2 and 25 every 0.2 values
481
+ let tmpResult = _Parser.solve('IntegrationApproximationResult = SERIES FROM 13.2 TO 25 STEP 0.2 : 1000 + (n / 2)', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
482
+ Expect(tmpDataDestinationObject.IntegrationApproximationResult[0]).to.equal("1006.6");
483
+ Expect(tmpDataDestinationObject.IntegrationApproximationResult[1]).to.equal("1006.7");
484
+ Expect(tmpDataDestinationObject.IntegrationApproximationResult[59]).to.equal("1012.5");
485
+
486
+ let tmpResultWithStep = _Parser.solve('IntegrationApproximationResultWithStep = SERIES FROM 13.2 TO 25 STEP 0.5 : (1000 * stepIndex) + n', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
487
+ Expect(tmpDataDestinationObject.IntegrationApproximationResultWithStep[0]).to.equal("13.2");
488
+ Expect(tmpDataDestinationObject.IntegrationApproximationResultWithStep[1]).to.equal("1013.7");
489
+ Expect(tmpDataDestinationObject.IntegrationApproximationResultWithStep[23]).to.equal("23024.7");
490
+
491
+ testFable.AppData =
492
+ {
493
+ StartValue: 5,
494
+ EndValue: 10,
495
+ StepValue: 0.5,
496
+ BaseValue: 200,
497
+ };
498
+ let tmpResultWithVariables = _Parser.solve('XValues = SERIES FROM StartValue TO EndValue STEP StepValue : (BaseValue * stepIndex) + n',
499
+ testFable.AppData, tmpParserResultsObject, tmpManifest, testFable.AppData);
500
+ Expect(testFable.AppData.XValues.length).to.equal(11);
501
+ Expect(testFable.AppData.XValues[0]).to.equal('5');
502
+ Expect(testFable.AppData.XValues[5]).to.equal('1007.5');
503
+ Expect(testFable.AppData.XValues[10]).to.equal('2010');
504
+
464
505
  return fDone();
465
506
  }
466
507
  );
@@ -702,6 +743,32 @@ suite
702
743
  Expect(tmpDestinationObject.PreciseEquals).to.equal('no');
703
744
  }
704
745
  );
746
+
747
+ test
748
+ (
749
+ 'Series + Regression',
750
+ () =>
751
+ {
752
+ let testFable = new libFable();
753
+
754
+ let testCityData = require('./data/cities.json');
755
+ testFable.AppData =
756
+ {
757
+ Cities: testCityData.slice(0, 4),
758
+ Null: null,
759
+ };
760
+
761
+ // Now through the solver
762
+ let _Parser = testFable.instantiateServiceProviderIfNotExists('ExpressionParser');
763
+
764
+ _Parser.solve('Coefficients = LINEST(FLATTEN(AppData.Cities[].latitude), FLATTEN(AppData.Cities[].population))', testFable, testFable.AppData, false, testFable.AppData);
765
+ testFable.log.info('Regression Coefficients:', testFable.AppData.Coefficients);
766
+ _Parser.solve('SeriesFromCoefficients = SERIES FROM 100 TO 1000 STEP 100 : AppData.Coefficients[0] + n * AppData.Coefficients[1]', testFable, testFable.AppData, false, testFable.AppData);
767
+ testFable.log.info('Series From Coefficients Result:', testFable.AppData.SeriesFromCoefficients);
768
+ _Parser.solve('IntegratedSeries = SUM(FLATTEN(AppData.SeriesFromCoefficients))', testFable, testFable.AppData, false, testFable.AppData);
769
+ testFable.log.info('Integrated Series Result:', testFable.AppData.IntegratedSeries);
770
+ }
771
+ );
705
772
  }
706
773
  );
707
774
  }
package/test/Math_test.js CHANGED
@@ -462,8 +462,88 @@ suite
462
462
 
463
463
  return fDone();
464
464
  }
465
- )
465
+ );
466
+
467
+ test
468
+ (
469
+ 'Least Squares Regression',
470
+ function()
471
+ {
472
+ let testFable = new libFable();
473
+
474
+ const predict = (coeffs, x) => testFable.Math.addPrecise(coeffs[0], coeffs.slice(1).reduce((sum, b, i) =>
475
+ {
476
+ return testFable.Math.addPrecise(sum, testFable.Math.multiplyPrecise(b, x[i]));
477
+ }, 0));
478
+ // Example: predict y from x1 and x2
479
+ const X_1 = [ 1, 2, 3, 4 ];
480
+ const y_1 = [ 3, 2, 1, 0 ];
481
+
482
+ const coeffs_1 = testFable.Math.leastSquares(X_1, y_1);
483
+ testFable.log.info('Coefficients:', coeffs_1);
484
+
485
+
486
+ testFable.log.info('Prediction for [2,1]:', predict(coeffs_1, [2.5]));
487
+
488
+ // Example: predict y from x1 and x2
489
+ const X = [
490
+ [1, 2],
491
+ [2, 0],
492
+ [3, 1],
493
+ [4, 3]
494
+ ];
495
+
496
+ const y = [3, 2, 4, 5];
497
+
498
+ const coeffs = testFable.Math.leastSquares(X, y);
499
+ testFable.log.info('Coefficients:', coeffs);
500
+
501
+ testFable.log.info('Prediction for [1,2] (training value is 3):', predict(coeffs, [1, 2]));
502
+ testFable.log.info('Prediction for [2,0] (training value is 2):', predict(coeffs, [2, 0]));
503
+ testFable.log.info('Prediction for [3,1] (training value is 4):', predict(coeffs, [3, 1]));
504
+ Expect(Number(predict(coeffs, [3, 1]))).to.be.closeTo(4, 0.51);
505
+ testFable.log.info('Prediction for [4,3] (training value is 5):', predict(coeffs, [4, 3]));
506
+ Expect(Number(predict(coeffs, [4, 3]))).to.be.closeTo(5, 0.25);
507
+ testFable.log.info('Prediction for [2,1]:', predict(coeffs, [2, 1]));
508
+ }
509
+ );
510
+
511
+ test
512
+ (
513
+ 'Linear regression',
514
+ function(fDone)
515
+ {
516
+ let testFable = new libFable();
466
517
 
518
+ const x = [0, 1, 2, 3, 4];
519
+ const y = [1, 2.2, 2.9, 3.7, 4.1];
520
+
521
+ for (let degree = 1; degree < 5; degree++)
522
+ {
523
+ const coeffs = testFable.Math.polynomialRegression(x, y, degree);
524
+
525
+ function predict(x, coeffs)
526
+ {
527
+ return coeffs.reduce((sum, a, i) => sum + a * Math.pow(x, i), 0);
528
+ }
529
+
530
+ testFable.log.info(`degree ${degree} coefficients:`, coeffs);
531
+
532
+ Expect(coeffs.length).to.equal(degree + 1); // quadratic
533
+ for (let i = 0; i < x.length; i++)
534
+ {
535
+ const tmpPrediction = predict(x[i], coeffs);
536
+ testFable.log.info(`x: ${x[i]}, predicted: ${tmpPrediction}, actual: ${y[i]}`);
537
+ if (i === 0 || i === x.length - 1)
538
+ {
539
+ Expect(tmpPrediction).to.be.closeTo(y[i], 1 / degree);
540
+ }
541
+ }
542
+ }
543
+
544
+ return fDone();
545
+ }
546
+ );
467
547
  }
468
548
  );
469
549
  }