fable 3.1.33 → 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 +72 -12
- 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/Fable-Service-ExpressionParser-ValueMarshal.js +1 -1
- package/source/services/Fable-Service-ExpressionParser.js +183 -9
- package/source/services/Fable-Service-Math.js +22 -0
- package/source/services/Fable-Service-Utility.js +76 -0
- package/test/ExpressionParser_tests.js +44 -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
|
|
@@ -3683,6 +3683,14 @@ this.LogNoisiness='LogNoisiness'in this.fable?this.fable.LogNoisiness:0;}/**
|
|
|
3683
3683
|
* @param {object} pManifest - The manifest object.
|
|
3684
3684
|
* @returns {any} The result of the solved expression.
|
|
3685
3685
|
*/solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest){return this.Solver.solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest);}/**
|
|
3686
|
+
* Prepares the parameters for a SERIES directive by substituting values and applying defaults.
|
|
3687
|
+
*
|
|
3688
|
+
* @param {Array} pParameters
|
|
3689
|
+
* @param {Array} pDefaults
|
|
3690
|
+
* @param {Object} pResultObject
|
|
3691
|
+
* @param {Object} pDataSourceObject
|
|
3692
|
+
* @param {import('manyfest')} [pManifest]
|
|
3693
|
+
*/_prepareDirectiveParameters(pParameters,pDefaults,pResultObject,pDataSourceObject,pManifest){const tmpResults=[];for(let i=0;i<pParameters.length;i++){const tmpParameter=pParameters[i];let tmpValue=this.fable.Math.parsePrecise(tmpParameter,NaN);if(isNaN(tmpValue)&&typeof tmpParameter==='string'&&tmpParameter.length>0){const tmpToken=this.fable.ExpressionParser.Postfix.getTokenContainerObject(tmpParameter,'Token.Symbol');this.substituteValuesInTokenizedObjects([tmpToken],pDataSourceObject,pResultObject,pManifest);if(tmpToken.Resolved){tmpValue=tmpToken.Value;}}if(isNaN(tmpValue)&&pDefaults.length>i){tmpValue=pDefaults[i];}tmpResults.push(tmpValue);}return tmpResults;}/**
|
|
3686
3694
|
* Solves the given expression using the provided data and manifest.
|
|
3687
3695
|
*
|
|
3688
3696
|
* @param {string} pExpression - The expression to solve.
|
|
@@ -3693,8 +3701,7 @@ this.LogNoisiness='LogNoisiness'in this.fable?this.fable.LogNoisiness:0;}/**
|
|
|
3693
3701
|
* @returns {any} - The result of solving the expression.
|
|
3694
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.
|
|
3695
3703
|
this.tokenize(pExpression,tmpResultsObject);// Lint the tokenized expression to make sure it's valid
|
|
3696
|
-
this.lintTokenizedExpression(tmpResultsObject.RawTokens,tmpResultsObject);this.buildPostfixedSolveList(tmpResultsObject.RawTokens,tmpResultsObject);if(tmpResultsObject.SolverDirectives.Code=='SERIES'){
|
|
3697
|
-
let tmpFrom=this.fable.Math.parsePrecise(tmpResultsObject.SolverDirectives.From,NaN);let tmpTo=this.fable.Math.parsePrecise(tmpResultsObject.SolverDirectives.To,NaN);let tmpStep=this.fable.Math.parsePrecise(tmpResultsObject.SolverDirectives.Step,NaN);if(isNaN(tmpStep)){tmpStep='1';}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
|
|
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,pManifest);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
|
|
3698
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
|
|
3699
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
|
|
3700
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
|
|
@@ -3702,26 +3709,62 @@ if(this.fable.Math.comparePrecise(tmpStep,'0')>0){tmpResultsObject.ExpressionPar
|
|
|
3702
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
|
|
3703
3710
|
// This generates a data source object every time on purpose so we can remarshal in values that changed in the destination
|
|
3704
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
|
|
3705
|
-
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
|
|
3706
3744
|
{// This is where the data from variables gets marshaled into their symbols (from AppData or the like)
|
|
3707
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
|
|
3708
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:
|
|
3709
3747
|
// There is a fifth token type, VirtualSymbol
|
|
3710
3748
|
// This is a value that's added during solve and looked up by address in the VirtualSymbol object.
|
|
3711
|
-
}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.
|
|
3712
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
|
|
3713
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
|
|
3714
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
|
|
3715
3757
|
// FIXME: This is hard coded assignment operators which is bad juju
|
|
3716
3758
|
if(i===0||tmpResults.RawTokens[i-1]==='='||tmpResults.RawTokens[i-1]==='?='){// We have a directive!
|
|
3717
|
-
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
|
|
3718
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
|
|
3719
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
|
|
3720
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
|
|
3721
3764
|
// the colonoscopy if you will
|
|
3722
3765
|
tmpResults.RawTokens.splice(0,tmpDirectiveTokenEndIndex+1);// Further parsing based on directive type could go here
|
|
3723
3766
|
// e.g. parseSeriesDirective for SERIES, etc.
|
|
3724
|
-
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
|
|
3725
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
|
|
3726
3769
|
*
|
|
3727
3770
|
* Current token types:
|
|
@@ -3776,14 +3819,15 @@ tmpCurrentTokenType='Value';tmpCurrentToken+=tmpCharacter;// continue;
|
|
|
3776
3819
|
// tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenize found an unknown character code ${tmpCharCode} character ${tmpCharacter} in the expression: ${pExpression} at index ${i}`);
|
|
3777
3820
|
// this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
|
|
3778
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
|
|
3779
|
-
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
|
|
3780
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
|
|
3781
3824
|
let tmpParenthesisDepth=0;// If it is in a state address, we don't care about the parenthesis
|
|
3782
3825
|
// State addresses are between squiggly brackets
|
|
3783
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?
|
|
3784
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
|
|
3785
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
|
|
3786
|
-
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
|
|
3787
3831
|
// (no, this is not a magical algebraic solver, do your own simplification)
|
|
3788
3832
|
// IF there is only one equality assignment (otherwise we don't even lint this because it's syntax errors all the way down)
|
|
3789
3833
|
if(tmpEqualityAssignmentCount===1){// If there are exactly three tokens, make sure at least one is an assignable-ish address
|
|
@@ -3814,7 +3858,8 @@ if('LeftVirtualSymbolName'in tmpOperation.Operation){tmpOperation.LeftValue=this
|
|
|
3814
3858
|
//if ('LeftVirtualSymbolName' in tmpOperation.RightValue)
|
|
3815
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
|
|
3816
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
|
|
3817
|
-
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.
|
|
3818
3863
|
// That is... the user entered something like "= 5 + 3" so we should just return 8, and use the default Result quietly.
|
|
3819
3864
|
}else{tmpResults.PostfixedAssignmentAddress=pTokenizedExpression[0];}// 2. Categorize tokens in the expression, put them in the "expression list" as a token object
|
|
3820
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
|
|
@@ -3945,7 +3990,7 @@ let tmpValue=tmpManifest.getValueByHash(tmpDataSource,tmpToken.Token);// if (!tm
|
|
|
3945
3990
|
// // If no hash resolves, try by address.
|
|
3946
3991
|
// tmpValue = tmpManifest.getValueAtAddress(tmpToken.Token, tmpDataSource);
|
|
3947
3992
|
// }
|
|
3948
|
-
if(
|
|
3993
|
+
if(tmpValue==null){tmpToken.Value=tmpValue;tmpToken.Resolve=true;tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the symbol hash or address ${tmpToken.Token} at index ${i}`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);if(this.LogNoisiness>1)this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpValue);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){// TODO: Should we allow this to be a function? Good god the complexity and beauty of that...
|
|
3949
3994
|
if(Array.isArray(tmpValue)||typeof tmpValue==='object'){tmpToken.Resolved=true;tmpToken.Value=tmpValue;}else{tmpToken.Resolved=true;tmpToken.Value=tmpValue;tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}; using raw value.`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}}}if(pTokenizedObjects[i].Type==='Token.StateAddress'&&!tmpToken.Resolved){// Symbols are always hashes. This gracefully works for simple shallow objects because hashes default to the address in Manyfest.
|
|
3950
3995
|
let tmpValue=tmpManifest.getValueAtAddress(tmpDataSource,tmpToken.Token);if(!tmpValue){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the state address ${tmpToken.Token} at index ${i}`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{//tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);
|
|
3951
3996
|
this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpValue);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}if(pTokenizedObjects[i].Type==='Token.String'&&!tmpToken.Resolved){tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpToken.Token}] for the string ${tmpToken.Token} at index ${i}`);if(this.LogNoisiness>1)this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=true;// Take the quotes off the string
|
|
@@ -4446,7 +4491,11 @@ const n=pCoefficientMatrix.length;const tmpAugmentedMatrix=pCoefficientMatrix.ma
|
|
|
4446
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
|
|
4447
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
|
|
4448
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
|
|
4449
|
-
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');/**
|
|
4450
4499
|
* Precedent Meta-Templating
|
|
4451
4500
|
* @author Steven Velozo <steven@velozo.com>
|
|
4452
4501
|
* @description Process text stream trie and postfix tree, parsing out meta-template expression functions.
|
|
@@ -4800,6 +4849,17 @@ if(!this.manifest){this.manifest=this.fable.newManyfest();}if(!Array.isArray(pOb
|
|
|
4800
4849
|
* @returns {any} - The value from the object
|
|
4801
4850
|
*/findFirstValueByExactMatchInternal(pFableAddress,pValueToMatchAddress,pValueToMatch,pValueAddress){// Lazily create a manifest if it doesn't exist
|
|
4802
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;}/**
|
|
4803
4863
|
* Flatten an array of solver inputs into a single array
|
|
4804
4864
|
*
|
|
4805
4865
|
* @param {Array<any>} pInputArray - The array of inputs to flatten
|