fable 3.1.35 → 3.1.37
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 +39 -21
- package/dist/fable.js.map +1 -1
- package/dist/fable.min.js +1 -1
- package/dist/fable.min.js.map +1 -1
- package/package.json +1 -1
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js +67 -12
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +4 -0
- package/source/services/Fable-Service-ExpressionParser.js +84 -16
- package/source/services/Fable-Service-Math.js +26 -5
- package/test/ExpressionParser_tests.js +331 -1
- package/test/Math_test.js +20 -12
package/dist/fable.js
CHANGED
|
@@ -3062,7 +3062,7 @@ try{if(!global.localStorage)return false;}catch(_){return false;}var val=global.
|
|
|
3062
3062
|
// presumably different callback function.
|
|
3063
3063
|
// This makes sure that own properties are retained, so that
|
|
3064
3064
|
// decorations and such are not lost along the way.
|
|
3065
|
-
module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],148:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],149:[function(require,module,exports){module.exports={"name":"fable","version":"3.1.
|
|
3065
|
+
module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],148:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],149:[function(require,module,exports){module.exports={"name":"fable","version":"3.1.37","description":"A service dependency injection, configuration and logging library.","main":"source/Fable.js","scripts":{"start":"node source/Fable.js","coverage":"./node_modules/.bin/nyc --reporter=lcov --reporter=text-lcov ./node_modules/mocha/bin/_mocha -- -u tdd -R spec","test":"./node_modules/.bin/mocha -u tdd -R spec","build":"npx quack build","docker-dev-build":"docker build ./ -f Dockerfile_LUXURYCode -t fable-image:local","docker-dev-run":"docker run -it -d --name fable-dev -p 30001:8080 -p 38086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/fable\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" fable-image:local","docker-dev-shell":"docker exec -it fable-dev /bin/bash","tests":"./node_modules/mocha/bin/_mocha -u tdd --exit -R spec --grep"},"mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"browser":{"./source/service/Fable-Service-EnvironmentData.js":"./source/service/Fable-Service-EnvironmentData-Web.js","./source/service/Fable-Service-FilePersistence.js":"./source/service/Fable-Service-FilePersistence-Web.js"},"repository":{"type":"git","url":"https://github.com/stevenvelozo/fable.git"},"keywords":["entity","behavior"],"author":"Steven Velozo <steven@velozo.com> (http://velozo.com/)","license":"MIT","bugs":{"url":"https://github.com/stevenvelozo/fable/issues"},"homepage":"https://github.com/stevenvelozo/fable","devDependencies":{"quackage":"^1.0.45"},"dependencies":{"async.eachlimit":"^0.5.2","async.waterfall":"^0.5.2","big.js":"^7.0.1","cachetrax":"^1.0.4","cookie":"^1.0.2","data-arithmatic":"^1.0.7","dayjs":"^1.11.18","fable-log":"^3.0.16","fable-serviceproviderbase":"^3.0.15","fable-settings":"^3.0.12","fable-uuid":"^3.0.11","manyfest":"^1.0.42","simple-get":"^4.0.1"}};},{}],150:[function(require,module,exports){/**
|
|
3066
3066
|
* Fable Application Services Support Library
|
|
3067
3067
|
* @author <steven@velozo.com>
|
|
3068
3068
|
*/// Pre-init services
|
|
@@ -3701,18 +3701,24 @@ this.LogNoisiness='LogNoisiness'in this.fable?this.fable.LogNoisiness:0;}/**
|
|
|
3701
3701
|
* @returns {any} - The result of solving the expression.
|
|
3702
3702
|
*/solve(pExpression,pDataSourceObject,pResultObject,pManifest,pDataDestinationObject){let tmpResultsObject=typeof pResultObject==='object'?pResultObject:{};let tmpDataSourceObject=typeof pDataSourceObject==='object'?pDataSourceObject:{};let tmpDataDestinationObject=typeof pDataDestinationObject==='object'?pDataDestinationObject:{};// This is technically a "pre-compile" and we can keep this Results Object around to reuse for better performance. Not required.
|
|
3703
3703
|
this.tokenize(pExpression,tmpResultsObject);// Lint the tokenized expression to make sure it's valid
|
|
3704
|
-
this.lintTokenizedExpression(tmpResultsObject.RawTokens,tmpResultsObject);this.buildPostfixedSolveList(tmpResultsObject.RawTokens,tmpResultsObject);if(tmpResultsObject.SolverDirectives.Code=='SERIES'){const[tmpStep,tmpFrom,tmpTo]=this._prepareDirectiveParameters([tmpResultsObject.SolverDirectives.Step,tmpResultsObject.SolverDirectives.From,tmpResultsObject.SolverDirectives.To],['1'],tmpResultsObject,tmpDataSourceObject,
|
|
3704
|
+
this.lintTokenizedExpression(tmpResultsObject.RawTokens,tmpResultsObject);this.buildPostfixedSolveList(tmpResultsObject.RawTokens,tmpResultsObject);const tmpManifest=typeof pManifest==='object'?pManifest:this.fable.newManyfest();if(tmpResultsObject.SolverDirectives.Code=='SERIES'){const[tmpStep,tmpFrom,tmpTo]=this._prepareDirectiveParameters([tmpResultsObject.SolverDirectives.Step,tmpResultsObject.SolverDirectives.From,tmpResultsObject.SolverDirectives.To],['1'],tmpResultsObject,tmpDataSourceObject,tmpManifest);if(isNaN(tmpFrom)||isNaN(tmpTo)){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. FROM, TO must be numeric.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return null;}// Make sure from/to are not equal
|
|
3705
3705
|
if(this.fable.Math.comparePrecise(tmpFrom,tmpTo)==0){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. FROM and TO cannot be equal.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return null;}// Make sure that Step is the correct positive/negative based on From and To
|
|
3706
3706
|
if(this.fable.Math.comparePrecise(tmpStep,'0')==0){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. STEP cannot be zero.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return null;}if(this.fable.Math.comparePrecise(tmpFrom,tmpTo)<0){// From < To so Step must be positive
|
|
3707
3707
|
if(this.fable.Math.comparePrecise(tmpStep,'0')<0){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. STEP must be positive when FROM < TO.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return null;}}else{// From >= To so Step must be negative
|
|
3708
3708
|
if(this.fable.Math.comparePrecise(tmpStep,'0')>0){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid SERIES directive parameters. STEP must be negative when FROM >= TO.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return null;}}// Get the number of iterations we need to perform
|
|
3709
3709
|
let tmpIterations=parseInt(this.fable.Math.floorPrecise(this.fable.Math.dividePrecise(this.fable.Math.subtractPrecise(tmpTo,tmpFrom),tmpStep)));let tmpValueArray=[];for(let i=0;i<=tmpIterations;i++){let tmpCurrentValueOfN=this.fable.Math.addPrecise(tmpFrom,this.fable.Math.multiplyPrecise(tmpStep,i.toString()));// Jimmy up the data source with the current N value, stepIndex and all the other data from the source object
|
|
3710
3710
|
// This generates a data source object every time on purpose so we can remarshal in values that changed in the destination
|
|
3711
|
-
let tmpSeriesStepDataSourceObject=Object.assign({},tmpDataSourceObject);tmpSeriesStepDataSourceObject.n=tmpCurrentValueOfN;tmpSeriesStepDataSourceObject.stepIndex=i;let tmpMutatedValues=this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpSeriesStepDataSourceObject,tmpResultsObject,
|
|
3712
|
-
let tmpAssignmentManifestHash=tmpResultsObject.PostfixedAssignmentAddress;if(tmpResultsObject.OriginalRawTokens[1]==='='&&typeof tmpResultsObject.OriginalRawTokens[0]==='string'&&tmpResultsObject.OriginalRawTokens[0].length>0){tmpAssignmentManifestHash=tmpResultsObject.OriginalRawTokens[0];}
|
|
3711
|
+
let tmpSeriesStepDataSourceObject=Object.assign({},tmpDataSourceObject);tmpSeriesStepDataSourceObject.n=tmpCurrentValueOfN;tmpSeriesStepDataSourceObject.stepIndex=i;let tmpMutatedValues=this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpSeriesStepDataSourceObject,tmpResultsObject,tmpManifest);tmpValueArray.push(this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,tmpManifest));for(let j=0;j<tmpMutatedValues.length;j++){tmpMutatedValues[j].Resolved=false;}}// Do the assignment
|
|
3712
|
+
let tmpAssignmentManifestHash=tmpResultsObject.PostfixedAssignmentAddress;if(tmpResultsObject.OriginalRawTokens[1]==='='&&typeof tmpResultsObject.OriginalRawTokens[0]==='string'&&tmpResultsObject.OriginalRawTokens[0].length>0){tmpAssignmentManifestHash=tmpResultsObject.OriginalRawTokens[0];}tmpManifest.setValueByHash(tmpDataDestinationObject,tmpAssignmentManifestHash,tmpValueArray);return tmpValueArray;}else if(tmpResultsObject.SolverDirectives.Code=='MAP'){// The values to pull in -- this could be a map but affords better flexibility broken out like this.
|
|
3713
|
+
const tmpDirectiveValues=tmpResultsObject.SolverDirectives.Values;const tmpDirectiveValueKeys=tmpResultsObject.SolverDirectives.ValueKeys;let tmpValueArray=[];for(let i=0;i<tmpDirectiveValueKeys.length;i++){const tmpVariableKey=tmpDirectiveValueKeys[i];const tmpVariableDescription=tmpDirectiveValues[tmpVariableKey];// Get the actual value for this variable's address
|
|
3714
|
+
tmpVariableDescription.Value=tmpManifest.getValueByHash(tmpDataSourceObject,tmpVariableDescription.Address);}// If the first value doesn't have keys, don't do the map.
|
|
3715
|
+
if(tmpDirectiveValueKeys.length<1||tmpDirectiveValues[tmpDirectiveValueKeys[0]].Value==null||!Array.isArray(tmpDirectiveValues[tmpDirectiveValueKeys[0]].Value)){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid MAP directive parameters. The first variable's address must resolve to an array.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return undefined;}let tmpControllingSet=tmpDirectiveValues[tmpDirectiveValueKeys[0]].Value;for(let i=0;i<tmpControllingSet.length;i++){// Jimmy up the data source with the current N value, stepIndex and all the other data from the source object
|
|
3716
|
+
// This generates a data source object every time on purpose so we can remarshal in values that changed in the destination
|
|
3717
|
+
let tmpSeriesStepDataSourceObject=Object.assign({},tmpDataSourceObject);for(let j=0;j<tmpDirectiveValueKeys.length;j++){const tmpVariableKey=tmpDirectiveValueKeys[j];if(!Array.isArray(tmpDirectiveValues[tmpVariableKey].Value)||tmpDirectiveValues[tmpVariableKey].Value.length<=j){tmpSeriesStepDataSourceObject[tmpVariableKey]=0;}else{tmpSeriesStepDataSourceObject[tmpVariableKey]=tmpDirectiveValues[tmpVariableKey].Value[i];}}let tmpMutatedValues=this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpSeriesStepDataSourceObject,tmpResultsObject,tmpManifest);tmpValueArray.push(this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,tmpManifest));for(let j=0;j<tmpMutatedValues.length;j++){tmpMutatedValues[j].Resolved=false;}}// Do the assignment
|
|
3718
|
+
let tmpAssignmentManifestHash=tmpResultsObject.PostfixedAssignmentAddress;if(tmpResultsObject.OriginalRawTokens[1]==='='&&typeof tmpResultsObject.OriginalRawTokens[0]==='string'&&tmpResultsObject.OriginalRawTokens[0].length>0){tmpAssignmentManifestHash=tmpResultsObject.OriginalRawTokens[0];}tmpManifest.setValueByHash(tmpDataDestinationObject,tmpAssignmentManifestHash,tmpValueArray);return tmpValueArray;}else if(tmpResultsObject.SolverDirectives.Code=='MONTECARLO'){const[tmpSampleCount]=this._prepareDirectiveParameters([tmpResultsObject.SolverDirectives.SampleCount],['1'],tmpResultsObject,tmpDataSourceObject,tmpManifest);if(isNaN(tmpSampleCount)){tmpResultsObject.ExpressionParserLog.push(`ExpressionParser.solve detected invalid MONTECARLO directive parameters. SAMPLECOUNT must be numeric.`);this.log.warn(tmpResultsObject.ExpressionParserLog[tmpResultsObject.ExpressionParserLog.length-1]);return null;}let tmpMonteCarloOutput=JSON.parse(JSON.stringify(tmpResultsObject.SolverDirectives));tmpMonteCarloOutput.Samples=[];// Now go through each variable and prepare its object of values
|
|
3713
3719
|
let tmpVariableKeys=Object.keys(tmpMonteCarloOutput.Values);for(let i=0;i<tmpVariableKeys.length;i++){let tmpVariableKey=tmpVariableKeys[i];let tmpVariableDescription=tmpMonteCarloOutput.Values[tmpVariableKey];// For each variable, generate its array of sampled values
|
|
3714
3720
|
tmpVariableDescription.Distribution={};tmpVariableDescription.ValueSequence=[];// Resolve the points if they are tokenized expressions
|
|
3715
|
-
const tmpResolvedPoints=[];for(let j=0;j<tmpVariableDescription.Points.length;j++){let tmpPointToken=tmpVariableDescription.Points[j];let tmpPointValue=this.fable.Math.parsePrecise(tmpPointToken,NaN);if(isNaN(tmpPointValue)&&typeof tmpPointToken==='string'&&tmpPointToken.length>0){tmpPointValue=
|
|
3721
|
+
const tmpResolvedPoints=[];for(let j=0;j<tmpVariableDescription.Points.length;j++){let tmpPointToken=tmpVariableDescription.Points[j];let tmpPointValue=this.fable.Math.parsePrecise(tmpPointToken,NaN);if(isNaN(tmpPointValue)&&typeof tmpPointToken==='string'&&tmpPointToken.length>0){tmpPointValue=tmpManifest.getValueByHash(tmpDataSourceObject,tmpPointToken);if(!tmpPointValue||tmpPointValue==null){//TODO: Warn?
|
|
3716
3722
|
}else{tmpResolvedPoints.push(tmpPointValue);}}else{tmpResolvedPoints.push(tmpPointToken);}}// Now sort the resolved points
|
|
3717
3723
|
tmpResolvedPoints.sort((a,b)=>this.fable.Math.comparePrecise(a,b));tmpVariableDescription.ResolvedPoints=tmpResolvedPoints;// Just simple linear until we add more easing types in a separate library (refactoring the below out)
|
|
3718
3724
|
tmpVariableDescription.FirstPoint=tmpVariableDescription.ResolvedPoints[0];tmpVariableDescription.DomainRangeStart=tmpVariableDescription.FirstPoint;if(tmpVariableDescription.ResolvedPoints.length<2){tmpVariableDescription.LastPoint=tmpVariableDescription.FirstPoint;}else{tmpVariableDescription.LastPoint=this.fable.Math.parsePrecise(tmpVariableDescription.ResolvedPoints[tmpVariableDescription.ResolvedPoints.length-1],NaN);if(isNaN(tmpVariableDescription.LastPoint)){tmpVariableDescription.LastPoint=tmpVariableDescription.FirstPoint;}}tmpVariableDescription.DomainLength=this.fable.Math.subtractPrecise(tmpVariableDescription.LastPoint,tmpVariableDescription.FirstPoint);//this.fable.log.trace(`Monte Carlo variable ${tmpVariableKey} has first point ${tmpVariableDescription.FirstPoint}, last point ${tmpVariableDescription.LastPoint}, domain length ${tmpVariableDescription.DomainLength}`);
|
|
@@ -3738,21 +3744,26 @@ tmpVariableDescription.FirstPoint=tmpVariableDescription.ResolvedPoints[0];tmpVa
|
|
|
3738
3744
|
}for(let i=0;i<=tmpSampleCount-1;i++){// Jimmy up the data source with the current N value, stepIndex and all the other data from the source object
|
|
3739
3745
|
// This generates a data source object every time on purpose so we can remarshal in values that changed in the destination
|
|
3740
3746
|
let tmpSeriesStepDataSourceObject=Object.assign({},tmpDataSourceObject);tmpSeriesStepDataSourceObject.stepIndex=i;// Generate each value from the array of values
|
|
3741
|
-
for(let j=0;j<tmpVariableKeys.length;j++){let tmpPointManifestHash=tmpVariableKeys[j];let tmpPointManifest=tmpMonteCarloOutput.Values[tmpPointManifestHash]
|
|
3742
|
-
this.fable.
|
|
3743
|
-
let
|
|
3747
|
+
for(let j=0;j<tmpVariableKeys.length;j++){let tmpPointManifestHash=tmpVariableKeys[j];let tmpPointManifest=tmpMonteCarloOutput.Values[tmpPointManifestHash];// Generate the value for this sample variable
|
|
3748
|
+
let tmpPointValue=this.fable.Math.generateValueFromEasingDescription(tmpPointManifest);tmpSeriesStepDataSourceObject[tmpVariableKeys[j]]=tmpPointValue;tmpPointManifest.ValueSequence.push(tmpPointValue);// We keep track of a distribution of generated values here for analysis later
|
|
3749
|
+
let tmpDistributionRoundPrecision=tmpPointManifest.DistributionRoundPrecision||0;// Log the value out
|
|
3750
|
+
//this.fable.log.info(`Monte Carlo variable ${tmpPointManifestHash} generated value ${tmpPointValue}`);
|
|
3751
|
+
let tmpDistributionPointValue=this.fable.Math.roundPrecise(tmpPointValue,tmpDistributionRoundPrecision);if(!(tmpDistributionPointValue in tmpPointManifest.Distribution)){tmpPointManifest.Distribution[tmpDistributionPointValue]=0;}tmpPointManifest.Distribution[tmpDistributionPointValue]=tmpPointManifest.Distribution[tmpDistributionPointValue]+1;}let tmpMutatedValues=this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpSeriesStepDataSourceObject,tmpResultsObject,tmpManifest);tmpMonteCarloOutput.Samples.push(this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,tmpManifest));for(let j=0;j<tmpMutatedValues.length;j++){tmpMutatedValues[j].Resolved=false;}}// Do the assignment
|
|
3752
|
+
let tmpAssignmentManifestHash=tmpResultsObject.PostfixedAssignmentAddress;if(tmpResultsObject.OriginalRawTokens[1]==='='&&typeof tmpResultsObject.OriginalRawTokens[0]==='string'&&tmpResultsObject.OriginalRawTokens[0].length>0){tmpAssignmentManifestHash=tmpResultsObject.OriginalRawTokens[0];}tmpManifest.setValueByHash(tmpDataDestinationObject,tmpAssignmentManifestHash,tmpMonteCarloOutput);return tmpMonteCarloOutput;}else// For 'SOLVE' or anything else that didn't work
|
|
3744
3753
|
{// This is where the data from variables gets marshaled into their symbols (from AppData or the like)
|
|
3745
3754
|
this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpDataSourceObject,tmpResultsObject,pManifest);// Finally this is the expr solving method, which returns a string and also marshals it into tmpDataDestinationObject
|
|
3746
3755
|
return this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,pManifest);}}}module.exports=FableServiceExpressionParser;},{"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer-DirectiveMutation.js":160,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js":161,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json":162,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Linter.js":163,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Messaging.js":164,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js":165,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js":166,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json":167,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js":168,"fable-serviceproviderbase":59}],159:[function(require,module,exports){const libFableServiceProviderBase=require('fable-serviceproviderbase');class ExpressionParserOperationBase extends libFableServiceProviderBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParserOperationBase';this.numberTest=/^-{0,1}\d*\.{0,1}\d+$/;this.ExpressionParser=false;}connectExpressionParser(pExpressionParser){this.ExpressionParser=pExpressionParser;}getTokenType(pToken){if(pToken in this.ExpressionParser.tokenMap){return`Token.${this.ExpressionParser.tokenMap[pToken].Type}`;}else if(pToken.length>2&&pToken[0]==='{'&&pToken[pToken.length-1]==='}'){return'Token.StateAddress';}else if(pToken.length>2&&pToken[0]==='"'&&pToken[pToken.length-1]==='"'){return'Token.String';}else if(this.numberTest.test(pToken)){return'Token.Constant';}else{return'Token.Symbol';}// Just for documentation sake:
|
|
3747
3756
|
// There is a fifth token type, VirtualSymbol
|
|
3748
3757
|
// This is a value that's added during solve and looked up by address in the VirtualSymbol object.
|
|
3749
|
-
}getTokenContainerObject(pToken,pTokenType){return{Token:pToken,Type:typeof pTokenType==='undefined'?this.getTokenType(pToken):pTokenType,Descriptor:pToken in this.ExpressionParser.tokenMap?this.ExpressionParser.tokenMap[pToken]:false};}}module.exports=ExpressionParserOperationBase;},{"fable-serviceproviderbase":59}],160:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionTokenizerDirectiveMutation extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-TokenizerDirectiveMutation';this.directiveTypes={'SOLVE':{Name:'Solve Expression',Code:'SOLVE'},'SERIES':{Name:'Series',Code:'SERIES',From:null,To:null,Step:null},'MONTECARLO':{Name:'Monte Carlo Simulation',SampleCount:'1',Code:'MONTECARLO',Values:{}}};this.defaultDirective=this.directiveTypes.SOLVE;}parseSeriesDirective(pTokens){// This isn't a fancy real parse it's just taking words and stealing values after them.
|
|
3750
|
-
let tmpNewSeriesDirectiveDescription=
|
|
3758
|
+
}getTokenContainerObject(pToken,pTokenType){return{Token:pToken,Type:typeof pTokenType==='undefined'?this.getTokenType(pToken):pTokenType,Descriptor:pToken in this.ExpressionParser.tokenMap?this.ExpressionParser.tokenMap[pToken]:false};}}module.exports=ExpressionParserOperationBase;},{"fable-serviceproviderbase":59}],160:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionTokenizerDirectiveMutation extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-TokenizerDirectiveMutation';this.directiveTypes={'SOLVE':{Name:'Solve Expression',Code:'SOLVE'},'SERIES':{Name:'Series',Code:'SERIES',From:null,To:null,Step:null},'MONTECARLO':{Name:'Monte Carlo Simulation',SampleCount:'1',Code:'MONTECARLO',Values:{}},'MAP':{Name:'Map',Code:'MAP',Values:{},ValueKeys:[]}};this.defaultDirective=this.directiveTypes.SOLVE;}parseSeriesDirective(pTokens){// This isn't a fancy real parse it's just taking words and stealing values after them.
|
|
3759
|
+
let tmpNewSeriesDirectiveDescription=JSON.parse(JSON.stringify(this.directiveTypes.SERIES));for(let i=0;i<pTokens.length;i++){let tmpToken=pTokens[i].toUpperCase();switch(tmpToken){case'FROM':if(i+1<pTokens.length){tmpNewSeriesDirectiveDescription.From=pTokens[i+1];}break;case'TO':if(i+1<pTokens.length){tmpNewSeriesDirectiveDescription.To=pTokens[i+1];}break;case'STEP':if(i+1<pTokens.length){tmpNewSeriesDirectiveDescription.Step=pTokens[i+1];}break;default:// Ignore other tokens
|
|
3751
3760
|
break;}}return tmpNewSeriesDirectiveDescription;}parseMonteCarloDirective(pTokens){// This isn't a fancy real parse it's just taking words and stealing values after them.
|
|
3752
|
-
let
|
|
3761
|
+
let tmpNewMonteCarloDirectiveDescription=JSON.parse(JSON.stringify(this.directiveTypes.MONTECARLO));for(let i=0;i<pTokens.length;i++){let tmpToken=pTokens[i].toUpperCase();switch(tmpToken){case'SAMPLECOUNT':if(i+1<pTokens.length){tmpNewMonteCarloDirectiveDescription.SampleCount=pTokens[i+1];}i=i+1;break;case'VARIABLE':case'VAR':case'V':if(i+1<pTokens.length){let tmpVariableToken=pTokens[i+1];if(typeof tmpVariableToken==='string'&&tmpVariableToken.length>0){tmpNewMonteCarloDirectiveDescription.Values[tmpVariableToken]={Token:tmpVariableToken,Easing:'Linear',// could be parametric, logarithmic, bezier, uniform, normal, etc.
|
|
3753
3762
|
Points:[]// array of values for points to generate between.
|
|
3754
|
-
};}}i=i+1;break;case'POINT':case'PT':case'P':if(pTokens.length<i+2){continue;}let tmpVariableToken=pTokens[i+1];if(tmpVariableToken in
|
|
3755
|
-
break;}}return
|
|
3763
|
+
};}}i=i+1;break;case'POINT':case'PT':case'P':if(pTokens.length<i+2){continue;}let tmpTokenIndexSkip=2;let tmpVariableToken=pTokens[i+1];if(tmpVariableToken in tmpNewMonteCarloDirectiveDescription.Values){let tmpVariableValueString=pTokens[i+2];if(tmpVariableValueString=='-'||tmpVariableValueString=='+'){if(pTokens.length<i+3){continue;}tmpVariableValueString=tmpVariableValueString+pTokens[i+3];tmpTokenIndexSkip=3;}let tmpVariableValue=this.fable.Math.parsePrecise(tmpVariableValueString,NaN);if(!isNaN(tmpVariableValue)){tmpNewMonteCarloDirectiveDescription.Values[tmpVariableToken].Points.push(tmpVariableValue);}}i=i+tmpTokenIndexSkip;break;case'EASING':if(pTokens.length<i+2){continue;}tmpVariableToken=pTokens[i+1];let tmpEasingType=pTokens[i+2].toUpperCase();if(tmpVariableToken in tmpNewMonteCarloDirectiveDescription.Values){tmpNewMonteCarloDirectiveDescription.Values[tmpVariableToken].Easing=tmpEasingType;}i=i+2;break;default:// Ignore other tokens
|
|
3764
|
+
break;}}return tmpNewMonteCarloDirectiveDescription;}parseMapDirective(pTokens){// This isn't a fancy real parse it's just taking words and stealing values after them.
|
|
3765
|
+
let tmpNewMapDirectiveDescription=JSON.parse(JSON.stringify(this.directiveTypes.MAP));for(let i=0;i<pTokens.length;i++){let tmpToken=pTokens[i].toUpperCase();switch(tmpToken){case'VARIABLE':case'VAR':case'V':if(i+3<pTokens.length&&pTokens[i+2].toUpperCase()=='FROM'){let tmpVariableToken=pTokens[i+1];if(typeof tmpVariableToken==='string'&&tmpVariableToken.length>0){tmpNewMapDirectiveDescription.ValueKeys.push(tmpVariableToken);tmpNewMapDirectiveDescription.Values[tmpVariableToken]={Token:tmpVariableToken,Address:pTokens[i+3]};}i=i+3;}break;default:// Ignore other tokens
|
|
3766
|
+
break;}}return tmpNewMapDirectiveDescription;}parseDirectives(pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.SolverDirectives=this.defaultDirective;tmpResults.SolverDirectiveTokens=[];if(tmpResults.RawTokens.length<2){tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation postprocessor received insufficient tokens to process directives.`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.SolverDirectives;}// Enumerate each of the tmpResults.RawTokens to see if one of the values in the directiveTypeMap exists and is either at the beginning or after the assignment (= or ?=) operator
|
|
3756
3767
|
for(let i=0;i<tmpResults.RawTokens.length;i++){let tmpToken=tmpResults.RawTokens[i].toUpperCase();if(tmpToken in this.directiveTypes){// Check if it's at the beginning or after an assignment operator
|
|
3757
3768
|
// FIXME: This is hard coded assignment operators which is bad juju
|
|
3758
3769
|
if(i===0||tmpResults.RawTokens[i-1]==='='||tmpResults.RawTokens[i-1]==='?='){// We have a directive!
|
|
@@ -3764,7 +3775,7 @@ tmpResults.SolverDirectiveTokens=tmpResults.RawTokens.slice(tmpDirectiveTokenSta
|
|
|
3764
3775
|
// the colonoscopy if you will
|
|
3765
3776
|
tmpResults.RawTokens.splice(0,tmpDirectiveTokenEndIndex+1);// Further parsing based on directive type could go here
|
|
3766
3777
|
// e.g. parseSeriesDirective for SERIES, etc.
|
|
3767
|
-
switch(tmpToken){case'SERIES':tmpResults.SolverDirectives=this.parseSeriesDirective(tmpResults.SolverDirectiveTokens);break;case'MONTECARLO':tmpResults.SolverDirectives=this.parseMonteCarloDirective(tmpResults.SolverDirectiveTokens);break;default:// No further parsing needed
|
|
3778
|
+
switch(tmpToken){case'SERIES':tmpResults.SolverDirectives=this.parseSeriesDirective(tmpResults.SolverDirectiveTokens);break;case'MONTECARLO':tmpResults.SolverDirectives=this.parseMonteCarloDirective(tmpResults.SolverDirectiveTokens);break;case'MAP':tmpResults.SolverDirectives=this.parseMapDirective(tmpResults.SolverDirectiveTokens);break;default:// No further parsing needed
|
|
3768
3779
|
break;}}}}return tmpResults.SolverDirectives;}}module.exports=ExpressionTokenizerDirectiveMutation;},{"./Fable-Service-ExpressionParser-Base.js":159}],161:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionTokenizer extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Tokenizer';}tokenize(pExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.RawExpression=pExpression;tmpResults.SolverDirectives={};tmpResults.RawTokens=[];tmpResults.ExpressionParserLog=[];if(typeof pExpression!=='string'){this.log.warn('ExpressionParser.tokenize was passed a non-string expression.');return tmpResults.RawTokens;}/* Tokenize the expression
|
|
3769
3780
|
*
|
|
3770
3781
|
* Current token types:
|
|
@@ -3819,7 +3830,7 @@ tmpCurrentTokenType='Value';tmpCurrentToken+=tmpCharacter;// continue;
|
|
|
3819
3830
|
// tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenize found an unknown character code ${tmpCharCode} character ${tmpCharacter} in the expression: ${pExpression} at index ${i}`);
|
|
3820
3831
|
// this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3821
3832
|
}if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}tmpResults.OriginalRawTokens=Array.from(tmpResults.RawTokens);// Potentially mutate the tokens based on directives in the tokenized expression
|
|
3822
|
-
this.TokenizerDirectiveMutation.parseDirectives(tmpResults);return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":159}],162:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"percent":{"Name":"Compute Percent (in IS over OF format)","Address":"fable.Math.percentagePrecise"},"compare":{"Name":"Compare","Address":"fable.Math.comparePrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"floor":{"Name":"Floor Value","Address":"fable.Math.floorPrecise"},"ceil":{"Name":"Ceiling Value","Address":"fable.Math.ceilPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"euler":{"Name":"Euler","Address":"fable.Math.eulerPrecise"},"log":{"Name":"Logarithm","Address":"fable.Math.logPrecise"},"exp":{"Name":"Eulers Number to the Power Of N","Address":"fable.Math.expPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"},"cos":{"Name":"Cosine","Address":"fable.Math.cos"},"tan":{"Name":"Tangent","Address":"fable.Math.tan"},"count":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"countset":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"sorthistogrambykeys":{"Name":"Sort Histogram by Keys","Address":"fable.Math.sortHistogramByKeys"},"max":{"Name":"Maximum","Address":"fable.Math.maxPrecise"},"min":{"Name":"Minimum","Address":"fable.Math.minPrecise"},"sum":{"Name":"Sum","Address":"fable.Math.sumPrecise"},"avg":{"Name":"Average","Address":"fable.Math.averagePrecise"},"mean":{"Name":"Mean","Address":"fable.Math.meanPrecise"},"median":{"Name":"Median","Address":"fable.Math.medianPrecise"},"mode":{"Name":"Mode","Address":"fable.Math.modePrecise"},"round":{"Name":"Round","Address":"fable.Math.roundPrecise"},"tofixed":{"Name":"To Fixed","Address":"fable.Math.toFixedPrecise"},"cumulativesummation":{"Name":"Sum each value in a Histogram or Value Map cumulatively, creating or setting a property with the result on each row","Address":"fable.Math.cumulativeSummation"},"subtractingsummation":{"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.","Address":"fable.Math.subtractingSummation"},"iterativeseries":{"Name":"Perform an Iterative Series of Mathematical Operations on Set Elements","Address":"fable.Math.iterativeSeries"},"countsetelements":{"Name":"Count Set Elements in a Histogram or Value Map","Address":"fable.Math.countSetElements"},"getvalue":{"Name":"Get Value from Application State or Services (AppData, etc.)","Address":"fable.Utility.getInternalValueByHash"},"objectkeystoarray":{"Name":"Get Array of an Object's keys","Address":"fable.Utility.objectKeysToArray"},"objectvaluestoarray":{"Name":"Get Array of an Object's values","Address":"fable.Utility.objectValuesToArray"},"generatearrayofobjectsfromsets":{"Name":"Generate Array of Objects from Sets","Address":"fable.Utility.generateArrayOfObjectsFromSets"},"objectvaluessortbyexternalobjectarray":{"Name":"Get Array of an Object's values sorted by an external array","Address":"fable.Utility.objectValuesSortByExternalArray"},"setkeystoarray":{"Name":"Get Array of an Object's keys","Address":"fable.Utility.objectKeysToArray"},"setvaluestoarray":{"Name":"Get Array of an Object's values","Address":"fable.Utility.objectValuesToArray"},"histogramkeystoarray":{"Name":"Get Array of an Object's keys","Address":"fable.Utility.objectKeysToArray"},"histogramvaluestoarray":{"Name":"Get Array of an Object's values","Address":"fable.Utility.objectValuesToArray"},"createarrayfromabsolutevalues":{"Name":"Create Array from Absolute Values","Address":"fable.Utility.createArrayFromAbsoluteValues"},"flatten":{"Name":"flatten an array of values","Address":"fable.Utility.flattenArrayOfSolverInputs"},"findfirstvaluebyexactmatch":{"Name":"find + map on array of objects","Address":"fable.Utility.findFirstValueByExactMatchInternal"},"findfirstvaluebystringincludes":{"Name":"find + map on array of objects","Address":"fable.Utility.findFirstValueByStringIncludesInternal"},"match":{"Name":"Implementation of sheets MATCH() function","Address":"fable.Utility.findIndexInternal"},"resolvehtmlentities":{"Name":"resolve HTML entities","Address":"fable.DataFormat.resolveHtmlEntities"},"concat":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsInternal"},"concatraw":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsRawInternal"},"join":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsInternal"},"joinraw":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsRawInternal"},"if":{"Name":"perform a conditional operator on two values, and choose one of two outcomes based on the result","Address":"fable.Logic.checkIf"},"when":{"Name":"perform a 'truthy' check on one value, and return one of two outcomes based on the result","Address":"fable.Logic.when"},"entryinset":{"Name":"Entry in Set","Address":"fable.Math.entryInSet"},"smallestinset":{"Name":"Smallest in Set","Address":"fable.Math.smallestInSet"},"largestinset":{"Name":"Largest in Set","Address":"fable.Math.largestInSet"},"aggregationhistogram":{"Name":"Generate a Histogram by Exact Value Aggregation","Address":"fable.Math.histogramAggregationByExactValueFromInternalState"},"aggregationhistogrambyobject":{"Name":"Generate a Histogram by Exact Value Aggregation from Object Property","Address":"fable.Math.histogramAggregationByExactValue"},"distributionhistogram":{"Name":"Generate a Histogram Based on Value Distribution","Address":"fable.Math.histogramDistributionByExactValueFromInternalState"},"distributionhistogrambyobject":{"Name":"Generate a Histogram Based on Value Distribution from Object Property","Address":"fable.Math.histogramDistributionByExactValue"},"setconcatenate":{"Name":"Set Concatenate","Address":"fable.Math.setConcatenate"},"getvaluearray":{"Name":"Get Value Array from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueArrayByHashParametersFromInternal"},"getvalueobject":{"Name":"Get Value Object from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueObjectByHashParametersFromInternal"},"cleanvaluearray":{"Name":"Clean Value Array","Address":"fable.Math.cleanValueArray"},"cleanvalueobject":{"Name":"Clean Value Object","Address":"fable.Math.cleanValueObject"},"polynomialregression":{"Name":"Perform an nth degree Polynomial Regression on a Set of X and Y Values","Address":"fable.Math.polynomialRegression"},"randominteger":{"Name":"Random Integer","Address":"fable.DataGeneration.randomInteger"},"randomintegerbetween":{"Name":"Random Integer Between Two Numbers","Address":"fable.DataGeneration.randomIntegerBetween"},"randomintegerupto":{"Name":"Random Integer","Address":"fable.DataGeneration.randomIntegerUpTo"},"randomfloat":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloat"},"randomfloatbetween":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatBetween"},"randomfloatupto":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatUpTo"},"datemilliseconddifference":{"Name":"Date Difference in Milliseconds","Address":"fable.Dates.dateMillisecondDifference"},"dateseconddifference":{"Name":"Date Difference in Seconds","Address":"fable.Dates.dateSecondDifference"},"dateminutedifference":{"Name":"Date Difference in Minutes","Address":"fable.Dates.dateMinuteDifference"},"datehourdifference":{"Name":"Date Difference in Hours","Address":"fable.Dates.dateHourDifference"},"datedaydifference":{"Name":"Date Difference in Days","Address":"fable.Dates.dateDayDifference"},"dateweekdifference":{"Name":"Date Difference in Weeks","Address":"fable.Dates.dateWeekDifference"},"datemonthdifference":{"Name":"Date Difference in Months","Address":"fable.Dates.dateMonthDifference"},"dateyeardifference":{"Name":"Date Difference in Years","Address":"fable.Dates.dateYearDifference"},"datemathadd":{"Name":"Date Math Add","Address":"fable.Dates.dateMath"},"dateaddmilliseconds":{"Name":"Date Add Milliseconds","Address":"fable.Dates.dateAddMilliseconds"},"dateaddseconds":{"Name":"Date Add Seconds","Address":"fable.Dates.dateAddSeconds"},"dateaddminutes":{"Name":"Date Add Minutes","Address":"fable.Dates.dateAddMinutes"},"dateaddhours":{"Name":"Date Add Hours","Address":"fable.Dates.dateAddHours"},"dateadddays":{"Name":"Date Add Days","Address":"fable.Dates.dateAddDays"},"dateaddweeks":{"Name":"Date Add Weeks","Address":"fable.Dates.dateAddWeeks"},"dateaddmonths":{"Name":"Date Add Months","Address":"fable.Dates.dateAddMonths"},"dateaddyears":{"Name":"Date Add Years","Address":"fable.Dates.dateAddYears"},"datefromparts":{"Name":"Date From Parts","Address":"fable.Dates.dateFromParts"},"createvalueobjectbyhashes":{"Name":"Create Value Object by Hashes","Address":"fable.Utility.createValueObjectByHashes"},"polynomialregression":{"Name":"Perform an nth degree Polynomial Regression on a Set of X and Y Values","Address":"fable.Math.polynomialRegression"},"leastsquares":{"Name":"Perform a Least Squares Regression on a Set of Independent Variable Vectors and a Dependent Variable Vector","Address":"fable.Math.leastSquares"},"linest":{"Name":"Perform a Least Squares Regression on a Set of Independent Variable Vectors and a Dependent Variable Vector","Address":"fable.Math.leastSquares"},"matrixtranspose":{"Name":"Transpose a Matrix","Address":"fable.Math.matrixTranspose"},"matrixmultiply":{"Name":"Multiply Two Matrices","Address":"fable.Math.matrixMultiply"},"matrixvectormultiply":{"Name":"Multiply a Matrix by a Vector","Address":"fable.Math.matrixVectorMultiply"},"matrixinverse":{"Name":"Inverse a Matrix","Address":"fable.Math.matrixInverse"},"gaussianelimination":{"Name":"Solve a System of Linear Equations using Gaussian Elimination","Address":"fable.Math.gaussianElimination"}};},{}],163:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserLinter extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Linter';}lintTokenizedExpression(pTokenizedExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.LinterResults=[];// Guard against bad data being passed in
|
|
3833
|
+
this.TokenizerDirectiveMutation.parseDirectives(tmpResults);return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":159}],162:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"percent":{"Name":"Compute Percent (in IS over OF format)","Address":"fable.Math.percentagePrecise"},"compare":{"Name":"Compare","Address":"fable.Math.comparePrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"floor":{"Name":"Floor Value","Address":"fable.Math.floorPrecise"},"ceil":{"Name":"Ceiling Value","Address":"fable.Math.ceilPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"euler":{"Name":"Euler","Address":"fable.Math.eulerPrecise"},"log":{"Name":"Logarithm","Address":"fable.Math.logPrecise"},"exp":{"Name":"Eulers Number to the Power Of N","Address":"fable.Math.expPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"},"cos":{"Name":"Cosine","Address":"fable.Math.cos"},"tan":{"Name":"Tangent","Address":"fable.Math.tan"},"count":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"countset":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"sorthistogrambykeys":{"Name":"Sort Histogram by Keys","Address":"fable.Math.sortHistogramByKeys"},"max":{"Name":"Maximum","Address":"fable.Math.maxPrecise"},"min":{"Name":"Minimum","Address":"fable.Math.minPrecise"},"sum":{"Name":"Sum","Address":"fable.Math.sumPrecise"},"avg":{"Name":"Average","Address":"fable.Math.averagePrecise"},"mean":{"Name":"Mean","Address":"fable.Math.meanPrecise"},"median":{"Name":"Median","Address":"fable.Math.medianPrecise"},"mode":{"Name":"Mode","Address":"fable.Math.modePrecise"},"round":{"Name":"Round","Address":"fable.Math.roundPrecise"},"tofixed":{"Name":"To Fixed","Address":"fable.Math.toFixedPrecise"},"cumulativesummation":{"Name":"Sum each value in a Histogram or Value Map cumulatively, creating or setting a property with the result on each row","Address":"fable.Math.cumulativeSummation"},"subtractingsummation":{"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.","Address":"fable.Math.subtractingSummation"},"iterativeseries":{"Name":"Perform an Iterative Series of Mathematical Operations on Set Elements","Address":"fable.Math.iterativeSeries"},"countsetelements":{"Name":"Count Set Elements in a Histogram or Value Map","Address":"fable.Math.countSetElements"},"getvalue":{"Name":"Get Value from Application State or Services (AppData, etc.)","Address":"fable.Utility.getInternalValueByHash"},"objectkeystoarray":{"Name":"Get Array of an Object's keys","Address":"fable.Utility.objectKeysToArray"},"objectvaluestoarray":{"Name":"Get Array of an Object's values","Address":"fable.Utility.objectValuesToArray"},"generatearrayofobjectsfromsets":{"Name":"Generate Array of Objects from Sets","Address":"fable.Utility.generateArrayOfObjectsFromSets"},"objectvaluessortbyexternalobjectarray":{"Name":"Get Array of an Object's values sorted by an external array","Address":"fable.Utility.objectValuesSortByExternalArray"},"setkeystoarray":{"Name":"Get Array of an Object's keys","Address":"fable.Utility.objectKeysToArray"},"setvaluestoarray":{"Name":"Get Array of an Object's values","Address":"fable.Utility.objectValuesToArray"},"histogramkeystoarray":{"Name":"Get Array of an Object's keys","Address":"fable.Utility.objectKeysToArray"},"histogramvaluestoarray":{"Name":"Get Array of an Object's values","Address":"fable.Utility.objectValuesToArray"},"createarrayfromabsolutevalues":{"Name":"Create Array from Absolute Values","Address":"fable.Utility.createArrayFromAbsoluteValues"},"flatten":{"Name":"flatten an array of values","Address":"fable.Utility.flattenArrayOfSolverInputs"},"findfirstvaluebyexactmatch":{"Name":"find + map on array of objects","Address":"fable.Utility.findFirstValueByExactMatchInternal"},"findfirstvaluebystringincludes":{"Name":"find + map on array of objects","Address":"fable.Utility.findFirstValueByStringIncludesInternal"},"match":{"Name":"Implementation of sheets MATCH() function","Address":"fable.Utility.findIndexInternal"},"resolvehtmlentities":{"Name":"resolve HTML entities","Address":"fable.DataFormat.resolveHtmlEntities"},"concat":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsInternal"},"concatraw":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsRawInternal"},"join":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsInternal"},"joinraw":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsRawInternal"},"if":{"Name":"perform a conditional operator on two values, and choose one of two outcomes based on the result","Address":"fable.Logic.checkIf"},"when":{"Name":"perform a 'truthy' check on one value, and return one of two outcomes based on the result","Address":"fable.Logic.when"},"entryinset":{"Name":"Entry in Set","Address":"fable.Math.entryInSet"},"smallestinset":{"Name":"Smallest in Set","Address":"fable.Math.smallestInSet"},"largestinset":{"Name":"Largest in Set","Address":"fable.Math.largestInSet"},"aggregationhistogram":{"Name":"Generate a Histogram by Exact Value Aggregation","Address":"fable.Math.histogramAggregationByExactValueFromInternalState"},"aggregationhistogrambyobject":{"Name":"Generate a Histogram by Exact Value Aggregation from Object Property","Address":"fable.Math.histogramAggregationByExactValue"},"distributionhistogram":{"Name":"Generate a Histogram Based on Value Distribution","Address":"fable.Math.histogramDistributionByExactValueFromInternalState"},"distributionhistogrambyobject":{"Name":"Generate a Histogram Based on Value Distribution from Object Property","Address":"fable.Math.histogramDistributionByExactValue"},"setconcatenate":{"Name":"Set Concatenate","Address":"fable.Math.setConcatenate"},"getvaluearray":{"Name":"Get Value Array from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueArrayByHashParametersFromInternal"},"getvalueobject":{"Name":"Get Value Object from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueObjectByHashParametersFromInternal"},"cleanvaluearray":{"Name":"Clean Value Array","Address":"fable.Math.cleanValueArray"},"cleanvalueobject":{"Name":"Clean Value Object","Address":"fable.Math.cleanValueObject"},"polynomialregression":{"Name":"Perform an nth degree Polynomial Regression on a Set of X and Y Values","Address":"fable.Math.polynomialRegression"},"randominteger":{"Name":"Random Integer","Address":"fable.DataGeneration.randomInteger"},"randomintegerbetween":{"Name":"Random Integer Between Two Numbers","Address":"fable.DataGeneration.randomIntegerBetween"},"randomintegerupto":{"Name":"Random Integer","Address":"fable.DataGeneration.randomIntegerUpTo"},"randomfloat":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloat"},"randomfloatbetween":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatBetween"},"randomfloatupto":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatUpTo"},"datemilliseconddifference":{"Name":"Date Difference in Milliseconds","Address":"fable.Dates.dateMillisecondDifference"},"dateseconddifference":{"Name":"Date Difference in Seconds","Address":"fable.Dates.dateSecondDifference"},"dateminutedifference":{"Name":"Date Difference in Minutes","Address":"fable.Dates.dateMinuteDifference"},"datehourdifference":{"Name":"Date Difference in Hours","Address":"fable.Dates.dateHourDifference"},"datedaydifference":{"Name":"Date Difference in Days","Address":"fable.Dates.dateDayDifference"},"dateweekdifference":{"Name":"Date Difference in Weeks","Address":"fable.Dates.dateWeekDifference"},"datemonthdifference":{"Name":"Date Difference in Months","Address":"fable.Dates.dateMonthDifference"},"dateyeardifference":{"Name":"Date Difference in Years","Address":"fable.Dates.dateYearDifference"},"datemathadd":{"Name":"Date Math Add","Address":"fable.Dates.dateMath"},"dateaddmilliseconds":{"Name":"Date Add Milliseconds","Address":"fable.Dates.dateAddMilliseconds"},"dateaddseconds":{"Name":"Date Add Seconds","Address":"fable.Dates.dateAddSeconds"},"dateaddminutes":{"Name":"Date Add Minutes","Address":"fable.Dates.dateAddMinutes"},"dateaddhours":{"Name":"Date Add Hours","Address":"fable.Dates.dateAddHours"},"dateadddays":{"Name":"Date Add Days","Address":"fable.Dates.dateAddDays"},"dateaddweeks":{"Name":"Date Add Weeks","Address":"fable.Dates.dateAddWeeks"},"dateaddmonths":{"Name":"Date Add Months","Address":"fable.Dates.dateAddMonths"},"dateaddyears":{"Name":"Date Add Years","Address":"fable.Dates.dateAddYears"},"datefromparts":{"Name":"Date From Parts","Address":"fable.Dates.dateFromParts"},"createvalueobjectbyhashes":{"Name":"Create Value Object by Hashes","Address":"fable.Utility.createValueObjectByHashes"},"polynomialregression":{"Name":"Perform an nth degree Polynomial Regression on a Set of X and Y Values","Address":"fable.Math.polynomialRegression"},"leastsquares":{"Name":"Perform a Least Squares Regression on a Set of Independent Variable Vectors and a Dependent Variable Vector","Address":"fable.Math.leastSquares"},"linest":{"Name":"Perform a Least Squares Regression on a Set of Independent Variable Vectors and a Dependent Variable Vector","Address":"fable.Math.leastSquares"},"matrixtranspose":{"Name":"Transpose a Matrix","Address":"fable.Math.matrixTranspose"},"matrixmultiply":{"Name":"Multiply Two Matrices","Address":"fable.Math.matrixMultiply"},"matrixvectormultiply":{"Name":"Multiply a Matrix by a Vector","Address":"fable.Math.matrixVectorMultiply"},"matrixinverse":{"Name":"Inverse a Matrix","Address":"fable.Math.matrixInverse"},"gaussianelimination":{"Name":"Solve a System of Linear Equations using Gaussian Elimination","Address":"fable.Math.gaussianElimination"},"predict":{"Name":"Predict Y Values from X Values using a Regression Model","Address":"fable.Math.predictFromRegressionModel"}};},{}],163:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserLinter extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Linter';}lintTokenizedExpression(pTokenizedExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.LinterResults=[];// Guard against bad data being passed in
|
|
3823
3834
|
if(!Array.isArray(pTokenizedExpression)){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.lintTokenizedExpression was passed a non-array tokenized expression.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return pTokenizedExpression;}if(pTokenizedExpression.length<1){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.lintTokenizedExpression was passed an empty tokenized expression.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return pTokenizedExpression;}// 1. Check for balanced parenthesis
|
|
3824
3835
|
let tmpParenthesisDepth=0;// If it is in a state address, we don't care about the parenthesis
|
|
3825
3836
|
// State addresses are between squiggly brackets
|
|
@@ -4100,14 +4111,14 @@ tmpNumber=typeof pNonNumberValue==='undefined'?"0.0":pNonNumberValue;}return tmp
|
|
|
4100
4111
|
* @returns {string} - The formatted number as a string.
|
|
4101
4112
|
*/toFixedPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:parseInt(pDecimals,10);let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.toFixed(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}/**
|
|
4102
4113
|
* Adds two values precisely.
|
|
4103
|
-
* @param {number} pLeftValue - The left value to be added.
|
|
4104
|
-
* @param {number} pRightValue - The right value to be added.
|
|
4114
|
+
* @param {number|string} pLeftValue - The left value to be added.
|
|
4115
|
+
* @param {number|string} pRightValue - The right value to be added.
|
|
4105
4116
|
* @returns {string} - The result of adding the two values as a string.
|
|
4106
4117
|
*/addPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.plus(tmpRightValue);return tmpResult.toString();}/**
|
|
4107
4118
|
* Subtracts two values precisely.
|
|
4108
4119
|
*
|
|
4109
|
-
* @param {number} pLeftValue - The left value to subtract.
|
|
4110
|
-
* @param {number} pRightValue - The right value to subtract.
|
|
4120
|
+
* @param {number|string} pLeftValue - The left value to subtract.
|
|
4121
|
+
* @param {number|string} pRightValue - The right value to subtract.
|
|
4111
4122
|
* @returns {string} The result of the subtraction as a string.
|
|
4112
4123
|
*/subtractPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.minus(tmpRightValue);return tmpResult.toString();}/**
|
|
4113
4124
|
* Calculates the precise power of two numbers.
|
|
@@ -4454,7 +4465,7 @@ return A.map(row=>row[0]);}/**
|
|
|
4454
4465
|
* @param {Array<number|string>} pDependentVariableVector - array of target values [y1, y2, ...]
|
|
4455
4466
|
*
|
|
4456
4467
|
* @return {Array<number|string>} - linear coefficients [b0, b1, ..., bn] where y = b0 + b1*x1 + b2*x2 + ... + bn*xn
|
|
4457
|
-
*/leastSquares(pIndependentVariableVectors,pDependentVariableVector){const tmpIndependentVariableVectors=Array.isArray(pIndependentVariableVectors[0])?pIndependentVariableVectors:pIndependentVariableVectors.map(value=>[value]);// Add bias term (intercept)
|
|
4468
|
+
*/leastSquares(pIndependentVariableVectors,pDependentVariableVector){const tmpIndependentVariableVectors=Array.isArray(pIndependentVariableVectors[0])?this.matrixTranspose(pIndependentVariableVectors):pIndependentVariableVectors.map(value=>[value]);// Add bias term (intercept)
|
|
4458
4469
|
const tmpIndependentVariableMatrixWithBiasTerm=tmpIndependentVariableVectors.map(row=>[1,...row]);// Compute X^T * X
|
|
4459
4470
|
const tmpIndependentTermTranpose=this.matrixTranspose(tmpIndependentVariableMatrixWithBiasTerm);const tmpDependentTransposeMultiplication=this.matrixMultiply(tmpIndependentTermTranpose,tmpIndependentVariableMatrixWithBiasTerm);// Compute X^T * y
|
|
4460
4471
|
const tmpIndependentTransposeMultiplication=this.matrixVectorMultiply(tmpIndependentTermTranpose,pDependentVariableVector);// Solve (XtX) * beta = Xty
|
|
@@ -4495,7 +4506,14 @@ return tmpAugmentedMatrix.map(row=>row[n]);}generateValueFromEasingDescription(p
|
|
|
4495
4506
|
switch(pEasingConfiguration.Easing){case'LINEAR':default:let tmpDomainRange=pEasingConfiguration.DomainLength;if(this.comparePrecise(tmpDomainRange,0)==0){return this.parsePrecise(pEasingConfiguration.DomainRangeStart);}// Now, generate a random number and then multiply it to fit in the domain length
|
|
4496
4507
|
let tmpRandomFraction=Math.random();// Scale it to the domain
|
|
4497
4508
|
let tmpScaledValue=this.multiplyPrecise(tmpRandomFraction,tmpDomainRange);// Shift it to the range start
|
|
4498
|
-
return this.addPrecise(pEasingConfiguration.DomainRangeStart,tmpScaledValue);}}
|
|
4509
|
+
return this.addPrecise(pEasingConfiguration.DomainRangeStart,tmpScaledValue);}}/**
|
|
4510
|
+
* Predicts the dependent variable using a regression model.
|
|
4511
|
+
*
|
|
4512
|
+
* @param {Array<number|string>} pRegressionCoefficients - The regression coefficients [b0, b1, ..., bn].
|
|
4513
|
+
* @param {Array<number|string>|number|string} pIndependentVariableVector - The independent variable values [x1, x2, ..., xn] or single value for single variable.
|
|
4514
|
+
*
|
|
4515
|
+
* @return {number|string} - The predicted dependent variable value.
|
|
4516
|
+
*/predictFromRegressionModel(pRegressionCoefficients,pIndependentVariableVector){let tmpIndependentVariableVector=pIndependentVariableVector;if(!Array.isArray(pIndependentVariableVector)){tmpIndependentVariableVector=[pIndependentVariableVector];}return pRegressionCoefficients.slice(1).reduce((sum,b,i)=>{return this.addPrecise(sum,this.multiplyPrecise(b,pIndependentVariableVector[i]));},pRegressionCoefficients[0]);}}module.exports=FableServiceMath;},{"./Fable-SetConcatArray.js":183,"fable-serviceproviderbase":59}],172:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
|
|
4499
4517
|
* Precedent Meta-Templating
|
|
4500
4518
|
* @author Steven Velozo <steven@velozo.com>
|
|
4501
4519
|
* @description Process text stream trie and postfix tree, parsing out meta-template expression functions.
|