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.
- package/dist/fable.js +471 -371
- package/dist/fable.js.map +1 -1
- package/dist/fable.min.js +2 -2
- package/dist/fable.min.js.map +1 -1
- package/example_applications/mathematical_playground/README.md +27 -0
- package/package.json +2 -2
- package/source/Fable.js +0 -1
- package/source/services/Fable-Service-CSVParser.js +177 -177
- package/source/services/Fable-Service-DataFormat.js +22 -22
- package/source/services/Fable-Service-DataGeneration.js +161 -161
- package/source/services/Fable-Service-DateManipulation.js +209 -209
- package/source/services/Fable-Service-EnvironmentData-Web.js +3 -3
- package/source/services/Fable-Service-EnvironmentData.js +3 -3
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js +136 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js +6 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +39 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js +2 -2
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +9 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js +3 -3
- package/source/services/Fable-Service-ExpressionParser.js +154 -22
- package/source/services/Fable-Service-FilePersistence.js +2 -2
- package/source/services/Fable-Service-Logic.js +1 -1
- package/source/services/Fable-Service-Math.js +293 -57
- package/source/services/Fable-Service-MetaTemplate.js +2 -2
- package/source/services/Fable-Service-Operation.js +7 -7
- package/source/services/Fable-Service-ProgressTime.js +3 -3
- package/source/services/Fable-Service-RestClient.js +2 -2
- package/source/services/Fable-Service-Template.js +4 -4
- package/source/services/Fable-Service-Utility.js +6 -6
- package/test/ExpressionParser_tests.js +67 -0
- package/test/Math_test.js +81 -1
- package/source/services/Fable-Service-ExpressionParser/RNI_Randy.json +0 -1
- 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
|
-
|
|
16
|
+
super(pFable, pOptions, pServiceHash);
|
|
17
17
|
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|