fable 3.1.34 → 3.1.35
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 +62 -9
- package/dist/fable.js.map +1 -1
- package/dist/fable.min.js +2 -2
- 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 +84 -2
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +5 -0
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Linter.js +1 -1
- package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js +1 -1
- package/source/services/Fable-Service-ExpressionParser.js +144 -0
- package/source/services/Fable-Service-Math.js +22 -0
- package/source/services/Fable-Service-Utility.js +76 -0
- package/test/ExpressionParser_tests.js +30 -0
- package/test/Utility_tests.js +40 -1
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.35","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
|
|
@@ -3709,26 +3709,62 @@ if(this.fable.Math.comparePrecise(tmpStep,'0')>0){tmpResultsObject.ExpressionPar
|
|
|
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
3711
|
let tmpSeriesStepDataSourceObject=Object.assign({},tmpDataSourceObject);tmpSeriesStepDataSourceObject.n=tmpCurrentValueOfN;tmpSeriesStepDataSourceObject.stepIndex=i;let tmpMutatedValues=this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpSeriesStepDataSourceObject,tmpResultsObject,pManifest);tmpValueArray.push(this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,pManifest));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];}let tmpManifest=typeof pManifest==='object'?pManifest:this.fable.newManyfest();tmpManifest.setValueByHash(tmpDataDestinationObject,tmpAssignmentManifestHash,tmpValueArray);return tmpValueArray;}else
|
|
3712
|
+
let tmpAssignmentManifestHash=tmpResultsObject.PostfixedAssignmentAddress;if(tmpResultsObject.OriginalRawTokens[1]==='='&&typeof tmpResultsObject.OriginalRawTokens[0]==='string'&&tmpResultsObject.OriginalRawTokens[0].length>0){tmpAssignmentManifestHash=tmpResultsObject.OriginalRawTokens[0];}let tmpManifest=typeof pManifest==='object'?pManifest:this.fable.newManyfest();tmpManifest.setValueByHash(tmpDataDestinationObject,tmpAssignmentManifestHash,tmpValueArray);return tmpValueArray;}else if(tmpResultsObject.SolverDirectives.Code=='MONTECARLO'){const[tmpSampleCount]=this._prepareDirectiveParameters([tmpResultsObject.SolverDirectives.SampleCount],['1'],tmpResultsObject,tmpDataSourceObject,pManifest);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
|
+
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
|
+
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=pManifest.getValueByHash(tmpDataSourceObject,tmpPointToken);if(!tmpPointValue||tmpPointValue==null){//TODO: Warn?
|
|
3716
|
+
}else{tmpResolvedPoints.push(tmpPointValue);}}else{tmpResolvedPoints.push(tmpPointToken);}}// Now sort the resolved points
|
|
3717
|
+
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
|
+
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}`);
|
|
3719
|
+
// // This generation of data based on the resolved points (and easing type) should be abstracted. Most require the same rules.
|
|
3720
|
+
// tmpVariableDescription.ResolvedPointDomainStarts = [];
|
|
3721
|
+
// tmpVariableDescription.DomainTranslationAmount = [];
|
|
3722
|
+
// // Get the length of each domain segment and the multiplier for them
|
|
3723
|
+
// tmpVariableDescription.DomainLength = this.fable.Math.subtractPrecise(tmpVariableDescription.ResolvedPoints[tmpVariableDescription.ResolvedPoints.length - 1], tmpVariableDescription.ResolvedPoints[0]);
|
|
3724
|
+
// tmpVariableDescription.DomainChunkCount = tmpVariableDescription.ResolvedPoints.length;
|
|
3725
|
+
// tmpVariableDescription.DomainStart = tmpVariableDescription.ResolvedPoints[0];
|
|
3726
|
+
// let tmpCurrentDomainPosition = tmpVariableDescription.DomainStart;
|
|
3727
|
+
// let tmpPreviousDomainTranslationAmount = '0';
|
|
3728
|
+
// for (let j = 0; j < tmpVariableDescription.ResolvedPoints.length; j++)
|
|
3729
|
+
// {
|
|
3730
|
+
// let tmpResolvedPointValue = tmpVariableDescription.ResolvedPoints[j];
|
|
3731
|
+
// // Set the resolved point domain start
|
|
3732
|
+
// tmpVariableDescription.DomainTranslationAmount.push(this.fable.Math.dividePrecise(tmpResolvedPointValue, tmpVariableDescription.DomainLength));
|
|
3733
|
+
// // Push the previous translation amount as the start of this domain
|
|
3734
|
+
// tmpVariableDescription.ResolvedPointDomainStarts.push(tmpPreviousDomainTranslationAmount);
|
|
3735
|
+
// // Calculate the translation amount, for the start of the next domain
|
|
3736
|
+
// tmpPreviousDomainTranslationAmount = this.fable.Math.addPrecise(tmpPreviousDomainTranslationAmount, tmpVariableDescription.DomainLength);
|
|
3737
|
+
// }
|
|
3738
|
+
}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
|
+
// This generates a data source object every time on purpose so we can remarshal in values that changed in the destination
|
|
3740
|
+
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];let tmpPointValue=this.fable.Math.generateValueFromEasingDescription(tmpPointManifest);tmpSeriesStepDataSourceObject[tmpVariableKeys[j]]=tmpPointValue;// Log the value out
|
|
3742
|
+
this.fable.log.info(`Monte Carlo variable ${tmpPointManifestHash} generated value ${tmpPointValue}`);if(!(tmpPointValue in tmpPointManifest.Distribution)){tmpPointManifest.Distribution[tmpPointValue]=0;}tmpPointManifest.Distribution[tmpPointValue]++;tmpPointManifest.ValueSequence.push(tmpPointValue);}let tmpMutatedValues=this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpSeriesStepDataSourceObject,tmpResultsObject,pManifest);tmpMonteCarloOutput.Samples.push(this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,pManifest));for(let j=0;j<tmpMutatedValues.length;j++){tmpMutatedValues[j].Resolved=false;}}// Do the assignment
|
|
3743
|
+
let tmpAssignmentManifestHash=tmpResultsObject.PostfixedAssignmentAddress;if(tmpResultsObject.OriginalRawTokens[1]==='='&&typeof tmpResultsObject.OriginalRawTokens[0]==='string'&&tmpResultsObject.OriginalRawTokens[0].length>0){tmpAssignmentManifestHash=tmpResultsObject.OriginalRawTokens[0];}let tmpManifest=typeof pManifest==='object'?pManifest:this.fable.newManyfest();tmpManifest.setValueByHash(tmpDataDestinationObject,tmpAssignmentManifestHash,tmpMonteCarloOutput);return tmpMonteCarloOutput;}else// For 'SOLVE' or anything else that didn't work
|
|
3713
3744
|
{// This is where the data from variables gets marshaled into their symbols (from AppData or the like)
|
|
3714
3745
|
this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpDataSourceObject,tmpResultsObject,pManifest);// Finally this is the expr solving method, which returns a string and also marshals it into tmpDataDestinationObject
|
|
3715
3746
|
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:
|
|
3716
3747
|
// There is a fifth token type, VirtualSymbol
|
|
3717
3748
|
// This is a value that's added during solve and looked up by address in the VirtualSymbol object.
|
|
3718
|
-
}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',Code:'MONTECARLO',
|
|
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.
|
|
3719
3750
|
let tmpNewSeriesDirectiveDescription=Object.assign({},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
|
+
break;}}return tmpNewSeriesDirectiveDescription;}parseMonteCarloDirective(pTokens){// This isn't a fancy real parse it's just taking words and stealing values after them.
|
|
3752
|
+
let tmpNewSeriesDirectiveDescription=Object.assign({},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){tmpNewSeriesDirectiveDescription.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){tmpNewSeriesDirectiveDescription.Values[tmpVariableToken]={Token:tmpVariableToken,Easing:'Linear',// could be parametric, logarithmic, bezier, uniform, normal, etc.
|
|
3753
|
+
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 tmpNewSeriesDirectiveDescription.Values){let tmpVariableValue=this.fable.Math.parsePrecise(pTokens[i+2],NaN);if(!isNaN(tmpVariableValue))tmpNewSeriesDirectiveDescription.Values[tmpVariableToken].Points.push(tmpVariableValue);}i=i+2;break;case'EASING':if(pTokens.length<i+2){continue;}tmpVariableToken=pTokens[i+1];let tmpEasingType=pTokens[i+2].toUpperCase();if(tmpVariableToken in tmpNewSeriesDirectiveDescription.Values){tmpNewSeriesDirectiveDescription.Values[tmpVariableToken].Easing=tmpEasingType;}i=i+2;break;default:// Ignore other tokens
|
|
3720
3755
|
break;}}return tmpNewSeriesDirectiveDescription;}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
|
|
3721
3756
|
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
|
|
3722
3757
|
// FIXME: This is hard coded assignment operators which is bad juju
|
|
3723
3758
|
if(i===0||tmpResults.RawTokens[i-1]==='='||tmpResults.RawTokens[i-1]==='?='){// We have a directive!
|
|
3724
|
-
tmpResults.SolverDirectives.Type=this.directiveTypes[tmpToken];tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation identified solver directive: ${tmpToken}`)
|
|
3759
|
+
tmpResults.SolverDirectives.Type=this.directiveTypes[tmpToken];tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation identified solver directive: ${tmpToken}`);//this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3760
|
+
// Extract the Directive name and everything else from it up until the : token
|
|
3725
3761
|
let tmpDirectiveTokenStartIndex=i;let tmpDirectiveTokenEndIndex=-1;for(let j=tmpDirectiveTokenStartIndex+1;j<tmpResults.RawTokens.length;j++){if(tmpResults.RawTokens[j]===':'){tmpDirectiveTokenEndIndex=j;break;}}// If the directive token end is not in the expression we don't know what to do
|
|
3726
3762
|
if(tmpDirectiveTokenEndIndex===-1){tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenizeDirectiveMutation could not find the end of the directive token set for directive: ${tmpToken}`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}// Set the tmpResults.SolverDirectiveTokens to the slice of tokens that represent the directive
|
|
3727
3763
|
tmpResults.SolverDirectiveTokens=tmpResults.RawTokens.slice(tmpDirectiveTokenStartIndex,tmpDirectiveTokenEndIndex);// Remove the directive tokens and the assignment to the left of it from the array of raw tokens
|
|
3728
3764
|
// the colonoscopy if you will
|
|
3729
3765
|
tmpResults.RawTokens.splice(0,tmpDirectiveTokenEndIndex+1);// Further parsing based on directive type could go here
|
|
3730
3766
|
// e.g. parseSeriesDirective for SERIES, etc.
|
|
3731
|
-
switch(tmpToken){case'SERIES':tmpResults.SolverDirectives=this.parseSeriesDirective(tmpResults.SolverDirectiveTokens);break;default:// No further parsing needed
|
|
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
|
|
3732
3768
|
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
|
|
3733
3769
|
*
|
|
3734
3770
|
* Current token types:
|
|
@@ -3783,14 +3819,15 @@ tmpCurrentTokenType='Value';tmpCurrentToken+=tmpCharacter;// continue;
|
|
|
3783
3819
|
// tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenize found an unknown character code ${tmpCharCode} character ${tmpCharacter} in the expression: ${pExpression} at index ${i}`);
|
|
3784
3820
|
// this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3785
3821
|
}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
|
|
3786
|
-
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"},"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
|
|
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
|
|
3787
3823
|
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
|
|
3788
3824
|
let tmpParenthesisDepth=0;// If it is in a state address, we don't care about the parenthesis
|
|
3789
3825
|
// State addresses are between squiggly brackets
|
|
3790
3826
|
let tmpInStateAddress=false;for(let i=0;i<pTokenizedExpression.length;i++){if(pTokenizedExpression[i]==='('&&!tmpInStateAddress){tmpParenthesisDepth++;}if(pTokenizedExpression[i]===')'&&!tmpInStateAddress){tmpParenthesisDepth--;}if(pTokenizedExpression[i]==='{'){tmpInStateAddress=true;}if(pTokenizedExpression[i]==='}'){tmpInStateAddress=false;}if(tmpParenthesisDepth<0){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.lintTokenizedExpression found an unbalanced parenthesis in the tokenized expression at token index ${i}`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}if(tmpParenthesisDepth>0){// TODO: Should we add the closing parenthesis?
|
|
3791
3827
|
tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.lintTokenizedExpression found an unbalanced parenthesis in the tokenized expression (ended without closing last set of parenthesis) -- appropriate closing parenthesis will be added.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}// 2. Check for balanced squiggly braces
|
|
3792
3828
|
tmpInStateAddress=false;for(let i=0;i<pTokenizedExpression.length;i++){if(pTokenizedExpression[i]==='{'){tmpInStateAddress=true;}if(pTokenizedExpression[i]==='}'&&tmpInStateAddress){tmpInStateAddress=false;}if(pTokenizedExpression[i]==='}'&&!tmpInStateAddress){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.lintTokenizedExpression found an unbalanced closing squiggly brace "}" in the tokenized expression at token index ${i}`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}if(tmpInStateAddress){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.lintTokenizedExpression found an open squiggly brace in the tokenized expression at index ${i}`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}// 3. Check for an equality assignment
|
|
3793
|
-
let tmpEqualityAssignmentCount=0;let tmpEqualityAssignmentIndex=false;for(let i=0;i<pTokenizedExpression.length;i++){if(this.ExpressionParser.tokenMap[pTokenizedExpression[i]]&&this.ExpressionParser.tokenMap[pTokenizedExpression[i]].Type==='Assignment'){tmpEqualityAssignmentCount++;tmpEqualityAssignmentIndex=i;if(tmpEqualityAssignmentCount>1){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.lintTokenizedExpression found multiple equality assignments in the tokenized expression; equality assignment #${tmpEqualityAssignmentCount} operator '${pTokenizedExpression[i]}' at token index ${i}.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}}if(tmpEqualityAssignmentCount<1){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.lintTokenizedExpression found no equality assignment in the tokenized expression. One called Result will be added automatically.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1])
|
|
3829
|
+
let tmpEqualityAssignmentCount=0;let tmpEqualityAssignmentIndex=false;for(let i=0;i<pTokenizedExpression.length;i++){if(this.ExpressionParser.tokenMap[pTokenizedExpression[i]]&&this.ExpressionParser.tokenMap[pTokenizedExpression[i]].Type==='Assignment'){tmpEqualityAssignmentCount++;tmpEqualityAssignmentIndex=i;if(tmpEqualityAssignmentCount>1){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.lintTokenizedExpression found multiple equality assignments in the tokenized expression; equality assignment #${tmpEqualityAssignmentCount} operator '${pTokenizedExpression[i]}' at token index ${i}.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}}if(tmpEqualityAssignmentCount<1){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.lintTokenizedExpression found no equality assignment in the tokenized expression. One called Result will be added automatically.`);tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);//this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3830
|
+
}// 4. Make sure the equality assignment only has a single value on the other side of it
|
|
3794
3831
|
// (no, this is not a magical algebraic solver, do your own simplification)
|
|
3795
3832
|
// IF there is only one equality assignment (otherwise we don't even lint this because it's syntax errors all the way down)
|
|
3796
3833
|
if(tmpEqualityAssignmentCount===1){// If there are exactly three tokens, make sure at least one is an assignable-ish address
|
|
@@ -3821,7 +3858,8 @@ if('LeftVirtualSymbolName'in tmpOperation.Operation){tmpOperation.LeftValue=this
|
|
|
3821
3858
|
//if ('LeftVirtualSymbolName' in tmpOperation.RightValue)
|
|
3822
3859
|
if('RightVirtualSymbolName'in tmpOperation.Operation){tmpOperation.RightValue=this.getTokenContainerObject(tmpOperation.Operation.RightVirtualSymbolName,'Token.VirtualSymbol');}else{tmpOperation.RightValue=this.getTokenContainerObject(tmpOperation.RightValue.VirtualSymbolName,'Token.VirtualSymbol');}}tmpOperation.Operation.Parsed=true;return tmpOperation;}buildPostfixedSolveList(pTokenizedExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.PostfixedAssignmentAddress='Result';tmpResults.PostfixedAssignmentOperator=this.ExpressionParser.tokenMap['='];// This is the default assignment operator
|
|
3823
3860
|
tmpResults.PostfixTokenObjects=[];tmpResults.PostfixSolveList=[];if(pTokenizedExpression.length<3){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.buildPostfixedSolveList was passed a tokenized expression with less than three tokens.`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixTokenObjects;}// 1. Figure out the Equality Assignment
|
|
3824
|
-
let tmpEqualsIndex=-1;for(let i=0;i<pTokenizedExpression.length;i++){if(this.ExpressionParser.tokenMap[pTokenizedExpression[i]]&&this.ExpressionParser.tokenMap[pTokenizedExpression[i]].Type==='Assignment'){if(tmpEqualsIndex<0){tmpEqualsIndex=i;tmpResults.PostfixedAssignmentOperator=this.ExpressionParser.tokenMap[pTokenizedExpression[i]];}else{tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.buildPostfixedSolveList found multiple assignment operators in the tokenized expression; assignment operator '${pTokenizedExpression[i]}' #${tmpEqualsIndex} at token index ${i}.`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixTokenObjects;}}}if(tmpEqualsIndex==-1){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.buildPostfixedSolveList found no equality assignment in the tokenized expression; defaulting to Result`)
|
|
3861
|
+
let tmpEqualsIndex=-1;for(let i=0;i<pTokenizedExpression.length;i++){if(this.ExpressionParser.tokenMap[pTokenizedExpression[i]]&&this.ExpressionParser.tokenMap[pTokenizedExpression[i]].Type==='Assignment'){if(tmpEqualsIndex<0){tmpEqualsIndex=i;tmpResults.PostfixedAssignmentOperator=this.ExpressionParser.tokenMap[pTokenizedExpression[i]];}else{tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.buildPostfixedSolveList found multiple assignment operators in the tokenized expression; assignment operator '${pTokenizedExpression[i]}' #${tmpEqualsIndex} at token index ${i}.`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixTokenObjects;}}}if(tmpEqualsIndex==-1){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.buildPostfixedSolveList found no equality assignment in the tokenized expression; defaulting to Result`);//this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3862
|
+
}else if(tmpEqualsIndex>1){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.buildPostfixedSolveList found an equality assignment in the tokenized expression at an unexpected location (token index ${tmpEqualsIndex}); the expression cannot be parsed.`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}else if(tmpEqualsIndex===0){// This is an implicit function -- just go to result and return the value.
|
|
3825
3863
|
// That is... the user entered something like "= 5 + 3" so we should just return 8, and use the default Result quietly.
|
|
3826
3864
|
}else{tmpResults.PostfixedAssignmentAddress=pTokenizedExpression[0];}// 2. Categorize tokens in the expression, put them in the "expression list" as a token object
|
|
3827
3865
|
for(let i=tmpEqualsIndex+1;i<pTokenizedExpression.length;i++){tmpResults.PostfixTokenObjects.push(this.getTokenContainerObject(pTokenizedExpression[i]));}// 3. Decorate mathematical parsing depth and detect functions at the same time
|
|
@@ -4453,7 +4491,11 @@ const n=pCoefficientMatrix.length;const tmpAugmentedMatrix=pCoefficientMatrix.ma
|
|
|
4453
4491
|
let maxRow=i;for(let k=i+1;k<n;++k){if(this.gtPrecise(this.absPrecise(tmpAugmentedMatrix[k][i]),this.absPrecise(tmpAugmentedMatrix[maxRow][i]))){maxRow=k;}}const tmpSwapValue=tmpAugmentedMatrix[i];tmpAugmentedMatrix[i]=tmpAugmentedMatrix[maxRow];tmpAugmentedMatrix[maxRow]=tmpSwapValue;// Normalize pivot row
|
|
4454
4492
|
const tmpPivotValue=tmpAugmentedMatrix[i][i];if(this.comparePrecise(tmpPivotValue,0)==0){throw new Error('Matrix not invertible');}for(let j=i;j<=n;++j){tmpAugmentedMatrix[i][j]=this.dividePrecise(tmpAugmentedMatrix[i][j],tmpPivotValue);}// Eliminate other rows
|
|
4455
4493
|
for(let k=0;k<n;++k){if(k===i){continue;}const tmpFactor=tmpAugmentedMatrix[k][i];for(let j=i;j<=n;++j){tmpAugmentedMatrix[k][j]=this.subtractPrecise(tmpAugmentedMatrix[k][j],this.multiplyPrecise(tmpFactor,tmpAugmentedMatrix[i][j]));}}}// Extract solution
|
|
4456
|
-
return tmpAugmentedMatrix.map(row=>row[n]);}
|
|
4494
|
+
return tmpAugmentedMatrix.map(row=>row[n]);}generateValueFromEasingDescription(pEasingConfiguration){// Branch based on type
|
|
4495
|
+
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
|
+
let tmpRandomFraction=Math.random();// Scale it to the domain
|
|
4497
|
+
let tmpScaledValue=this.multiplyPrecise(tmpRandomFraction,tmpDomainRange);// Shift it to the range start
|
|
4498
|
+
return this.addPrecise(pEasingConfiguration.DomainRangeStart,tmpScaledValue);}}}module.exports=FableServiceMath;},{"./Fable-SetConcatArray.js":183,"fable-serviceproviderbase":59}],172:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
|
|
4457
4499
|
* Precedent Meta-Templating
|
|
4458
4500
|
* @author Steven Velozo <steven@velozo.com>
|
|
4459
4501
|
* @description Process text stream trie and postfix tree, parsing out meta-template expression functions.
|
|
@@ -4807,6 +4849,17 @@ if(!this.manifest){this.manifest=this.fable.newManyfest();}if(!Array.isArray(pOb
|
|
|
4807
4849
|
* @returns {any} - The value from the object
|
|
4808
4850
|
*/findFirstValueByExactMatchInternal(pFableAddress,pValueToMatchAddress,pValueToMatch,pValueAddress){// Lazily create a manifest if it doesn't exist
|
|
4809
4851
|
if(!this.manifest){this.manifest=this.fable.newManyfest();}if(typeof pFableAddress!='string'){return undefined;}let tmpObjectArray=this.manifest.getValueByHash(this.fable,pFableAddress);return this.findFirstValueByExactMatch(tmpObjectArray,pValueToMatchAddress,pValueToMatch,pValueAddress);}/**
|
|
4852
|
+
* Find the index of a value in an array, using the specified search mode.
|
|
4853
|
+
*
|
|
4854
|
+
* @param {any} pValueToFind - The value to find.
|
|
4855
|
+
* @param {Array<any>|string} pSearchArray - The array to search, or the address of such an array.
|
|
4856
|
+
* @param {string|number} [pSearchMode='1'] - The search mode ('0' for exact match, '1' (or default) for searching sorted sets and finding the first value >= the specifid value. '-1' is the same behavior as '1' but sorted descending.
|
|
4857
|
+
*
|
|
4858
|
+
* @returns {number} - The index of the found value, or -1 if not found.
|
|
4859
|
+
*/findIndexInternal(pValueToFind,pSearchArray){let pSearchMode=arguments.length>2&&arguments[2]!==undefined?arguments[2]:'1';let tmpSearchArray=pSearchArray;if(typeof pSearchArray==='string'){if(!this.manifest){this.manifest=this.fable.newManyfest();}tmpSearchArray=this.manifest.getValueByHash(this.fable,pSearchArray);}if(!Array.isArray(tmpSearchArray)){this.fable.log.error('findIndexInternal called with non-array search array.');return-1;}const tmpIsNumericSearch=this.fable.Math.parsePrecise(pValueToFind,null)!==null;let tmpMatchIndex=-1;let tmpComparisonFunction;if(Number(pSearchMode)===0){// Exact match
|
|
4860
|
+
if(tmpIsNumericSearch){tmpComparisonFunction=pCandidate=>this.fable.Math.comparePrecise(pCandidate,pValueToFind)===0;}else{tmpComparisonFunction=pCandidate=>pCandidate===pValueToFind;}}else if(Number(pSearchMode)===-1){// Sorted descending
|
|
4861
|
+
if(tmpIsNumericSearch){tmpComparisonFunction=pCandidate=>this.fable.Math.ltePrecise(pCandidate,pValueToFind);}else{tmpComparisonFunction=pCandidate=>pCandidate<=pValueToFind;}}else{// Sorted ascending
|
|
4862
|
+
if(tmpIsNumericSearch){tmpComparisonFunction=pCandidate=>this.fable.Math.gtePrecise(pCandidate,pValueToFind);}else{tmpComparisonFunction=pCandidate=>pCandidate>=pValueToFind;}}for(let i=0;i<tmpSearchArray.length;i++){if(tmpComparisonFunction(tmpSearchArray[i])){return i;}}return-1;}/**
|
|
4810
4863
|
* Flatten an array of solver inputs into a single array
|
|
4811
4864
|
*
|
|
4812
4865
|
* @param {Array<any>} pInputArray - The array of inputs to flatten
|