fable 3.0.132 → 3.0.134

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 CHANGED
@@ -1549,7 +1549,7 @@ let tmpDescriptorAddresses=Object.keys(tmpSource);tmpDescriptorAddresses.forEach
1549
1549
  * @class Manyfest
1550
1550
  */class Manyfest extends libFableServiceProviderBase{constructor(pFable,pManifest,pServiceHash){if(pFable===undefined){super({});}else{super(pFable,pManifest,pServiceHash);}this.serviceType='Manifest';// Wire in logging
1551
1551
  this.logInfo=libSimpleLog;this.logError=libSimpleLog;// Create an object address resolver and map in the functions
1552
- this.objectAddressCheckAddressExists=new libObjectAddressCheckAddressExists(this.logInfo,this.logError);this.objectAddressGetValue=new libObjectAddressGetValue(this.logInfo,this.logError);this.objectAddressSetValue=new libObjectAddressSetValue(this.logInfo,this.logError);this.objectAddressDeleteValue=new libObjectAddressDeleteValue(this.logInfo,this.logError);if(!('defaultValues'in this.options)){this.options.defaultValues={"String":"","Number":0,"Float":0.0,"Integer":0,"Boolean":false,"Binary":0,"DateTime":0,"Array":[],"Object":{},"Null":null};}if(!('strict'in this.options)){this.options.strict=false;}this.scope=undefined;this.elementAddresses=undefined;this.elementHashes=undefined;this.elementDescriptors=undefined;this.reset();if(typeof this.options==='object'){this.loadManifest(this.options);}this.schemaManipulations=new libSchemaManipulation(this.logInfo,this.logError);this.objectAddressGeneration=new libObjectAddressGeneration(this.logInfo,this.logError);this.hashTranslations=new libHashTranslation(this.logInfo,this.logError);}/*************************************************************************
1552
+ this.objectAddressCheckAddressExists=new libObjectAddressCheckAddressExists(this.logInfo,this.logError);this.objectAddressGetValue=new libObjectAddressGetValue(this.logInfo,this.logError);this.objectAddressSetValue=new libObjectAddressSetValue(this.logInfo,this.logError);this.objectAddressDeleteValue=new libObjectAddressDeleteValue(this.logInfo,this.logError);if(!('defaultValues'in this.options)){this.options.defaultValues={"String":"","Number":0,"Float":0.0,"Integer":0,"PreciseNumber":"0.0","Boolean":false,"Binary":0,"DateTime":0,"Array":[],"Object":{},"Null":null};}if(!('strict'in this.options)){this.options.strict=false;}this.scope=undefined;this.elementAddresses=undefined;this.elementHashes=undefined;this.elementDescriptors=undefined;this.reset();if(typeof this.options==='object'){this.loadManifest(this.options);}this.schemaManipulations=new libSchemaManipulation(this.logInfo,this.logError);this.objectAddressGeneration=new libObjectAddressGeneration(this.logInfo,this.logError);this.hashTranslations=new libHashTranslation(this.logInfo,this.logError);this.numberRegex=/^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;}/*************************************************************************
1553
1553
  * Schema Manifest Loading, Reading, Manipulation and Serialization Functions
1554
1554
  */ // Reset critical manifest properties
1555
1555
  reset(){this.scope='DEFAULT';this.elementAddresses=[];this.elementHashes={};this.elementDescriptors={};}clone(){// Make a copy of the options in-place
@@ -1589,8 +1589,8 @@ validate(pObject){let tmpValidationData={Error:null,Errors:[],MissingElements:[]
1589
1589
  for(let i=0;i<this.elementAddresses.length;i++){let tmpDescriptor=this.getDescriptor(this.elementAddresses[i]);let tmpValueExists=this.checkAddressExists(pObject,tmpDescriptor.Address);let tmpValue=this.getValueAtAddress(pObject,tmpDescriptor.Address);if(typeof tmpValue=='undefined'||!tmpValueExists){// This will technically mean that `Object.Some.Value = undefined` will end up showing as "missing"
1590
1590
  // TODO: Do we want to do a different message based on if the property exists but is undefined?
1591
1591
  tmpValidationData.MissingElements.push(tmpDescriptor.Address);if(tmpDescriptor.Required||this.options.strict){addValidationError(tmpDescriptor.Address,'is flagged REQUIRED but is not set in the object');}}// Now see if there is a data type specified for this element
1592
- if(tmpDescriptor.DataType){let tmpElementType=typeof tmpValue;switch(tmpDescriptor.DataType.toString().trim().toLowerCase()){case'string':if(tmpElementType!='string'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}break;case'number':if(tmpElementType!='number'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}break;case'integer':if(tmpElementType!='number'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}else{let tmpValueString=tmpValue.toString();if(tmpValueString.indexOf('.')>-1){// TODO: Is this an error?
1593
- addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but has a decimal point in the number."));}}break;case'float':if(tmpElementType!='number'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}break;case'DateTime':let tmpValueDate=new Date(tmpValue);if(tmpValueDate.toString()=='Invalid Date'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is not parsable as a Date by Javascript"));}default:// Check if this is a string, in the default case
1592
+ if(tmpDescriptor.DataType){let tmpElementType=typeof tmpValue;switch(tmpDescriptor.DataType.toString().trim().toLowerCase()){case'string':if(tmpElementType!='string'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}break;case"precisenumber":if(tmpElementType!='string'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}else if(!this.numberRegex.test(tmpValue)){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is not a valid number"));}break;case'number':if(tmpElementType!='number'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}break;case'integer':if(tmpElementType!='number'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}else{let tmpValueString=tmpValue.toString();if(tmpValueString.indexOf('.')>-1){// TODO: Is this an error?
1593
+ addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but has a decimal point in the number."));}}break;case'float':if(tmpElementType!='number'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is of the type ").concat(tmpElementType));}break;case'datetime':let tmpValueDate=new Date(tmpValue);if(tmpValueDate.toString()=='Invalid Date'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," but is not parsable as a Date by Javascript"));}default:// Check if this is a string, in the default case
1594
1594
  // Note this is only when a DataType is specified and it is an unrecognized data type.
1595
1595
  if(tmpElementType!='string'){addValidationError(tmpDescriptor.Address,"has a DataType ".concat(tmpDescriptor.DataType," (which auto-converted to String because it was unrecognized) but is of the type ").concat(tmpElementType));}break;}}}return tmpValidationData;}// Returns a default value, or, the default value for the data type (which is overridable with configuration)
1596
1596
  getDefaultValue(pDescriptor){if(typeof pDescriptor!='object'){return undefined;}if('Default'in pDescriptor){return pDescriptor.Default;}else{// Default to a null if it doesn't have a type specified.
@@ -3376,9 +3376,19 @@ let tmpValue=tmpManifest.getValueByHash(tmpDataSource,tmpToken.Token);// if (!tm
3376
3376
  // // If no hash resolves, try by address.
3377
3377
  // tmpValue = tmpManifest.getValueAtAddress(tmpToken.Token, tmpDataSource);
3378
3378
  // }
3379
- if(!tmpValue){tmpResults.ExpressionParserLog.push("WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the symbol hash or address ".concat(tmpToken.Token," at index ").concat(i));this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{tmpResults.ExpressionParserLog.push("INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [".concat(tmpValue,"] for the state address ").concat(tmpToken.Token," at index ").concat(i));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 ".concat(tmpToken.Token," at index ").concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}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.
3379
+ if(!tmpValue){tmpResults.ExpressionParserLog.push("WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the symbol hash or address ".concat(tmpToken.Token," at index ").concat(i));this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{tmpResults.ExpressionParserLog.push("INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [".concat(tmpValue,"] for the state address ").concat(tmpToken.Token," at index ").concat(i));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...
3380
+ if(Array.isArray(tmpValue)||typeof tmpValue==='object'){tmpToken.Resolved=true;tmpToken.Value=tmpValue;}else{tmpResults.ExpressionParserLog.push("INFO: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric, non-set value for the state address ".concat(tmpToken.Token," at index ").concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}}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.
3380
3381
  let tmpValue=tmpManifest.getValueAtAddress(tmpDataSource,tmpToken.Token);if(!tmpValue){tmpResults.ExpressionParserLog.push("WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the state address ".concat(tmpToken.Token," at index ").concat(i));this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{tmpResults.ExpressionParserLog.push("INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [".concat(tmpValue,"] for the state address ").concat(tmpToken.Token," at index ").concat(i));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 ".concat(tmpToken.Token," at index ").concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}if(pTokenizedObjects[i].Type==='Token.Constant'&&!tmpToken.Resolved){tmpResults.ExpressionParserLog.push("INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [".concat(tmpToken.Token,"] for the constant ").concat(tmpToken.Token," at index ").concat(i));this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpToken.Token);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){// This constant has the right symbols but apparently isn't a parsable number.
3381
- tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ".concat(tmpToken.Token," at index ").concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}return pTokenizedObjects;}tokenize(pExpression,pResultObject){return this.Tokenizer.tokenize(pExpression,pResultObject);}lintTokenizedExpression(pTokenizedExpression,pResultObject){return this.Linter.lintTokenizedExpression(pTokenizedExpression,pResultObject);}buildPostfixedSolveList(pTokenizedExpression,pResultObject){return this.Postfix.buildPostfixedSolveList(pTokenizedExpression,pResultObject);}solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest){return this.Solver.solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest);}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.tokenize(pExpression,tmpResultsObject);this.lintTokenizedExpression(tmpResultsObject.RawTokens,tmpResultsObject);this.buildPostfixedSolveList(tmpResultsObject.RawTokens,tmpResultsObject);this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpDataSourceObject,tmpResultsObject,pManifest);return this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,pManifest);}}module.exports=FableServiceExpressionParser;},{"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js":137,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json":138,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Linter.js":139,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js":140,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js":141,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json":142,"big.js":17,"fable-serviceproviderbase":51}],136:[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.".concat(this.ExpressionParser.tokenMap[pToken].Type);}else if(pToken.length>2&&pToken[0]==='{'&&pToken[pToken.length-1]==='}'){return'Token.StateAddress';}else if(this.numberTest.test(pToken)){return'Token.Constant';}else{return'Token.Symbol';}// Just for documentation sake:
3382
+ tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ".concat(tmpToken.Token," at index ").concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}return pTokenizedObjects;}tokenize(pExpression,pResultObject){return this.Tokenizer.tokenize(pExpression,pResultObject);}lintTokenizedExpression(pTokenizedExpression,pResultObject){return this.Linter.lintTokenizedExpression(pTokenizedExpression,pResultObject);}buildPostfixedSolveList(pTokenizedExpression,pResultObject){return this.Postfix.buildPostfixedSolveList(pTokenizedExpression,pResultObject);}solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest){return this.Solver.solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest);}/**
3383
+ * Solves the given expression using the provided data and manifest.
3384
+ *
3385
+ * @param {string} pExpression - The expression to solve.
3386
+ * @param {object} pDataSourceObject - (optional) The data source object (e.g. AppData).
3387
+ * @param {object} pResultObject - (optional) The result object containing the full postfix expression list, internal variables and solver history.
3388
+ * @param {object} pManifest - (optional) The manifest object for dereferencing variables.
3389
+ * @param {object} pDataDestinationObject - (optional) The data destination object for where to marshal the result into.
3390
+ * @returns {any} - The result of solving the expression.
3391
+ */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.tokenize(pExpression,tmpResultsObject);this.lintTokenizedExpression(tmpResultsObject.RawTokens,tmpResultsObject);this.buildPostfixedSolveList(tmpResultsObject.RawTokens,tmpResultsObject);this.substituteValuesInTokenizedObjects(tmpResultsObject.PostfixTokenObjects,tmpDataSourceObject,tmpResultsObject,pManifest);return this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDestinationObject,tmpResultsObject,pManifest);}}module.exports=FableServiceExpressionParser;},{"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js":137,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json":138,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Linter.js":139,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js":140,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js":141,"./Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json":142,"big.js":17,"fable-serviceproviderbase":51}],136:[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.".concat(this.ExpressionParser.tokenMap[pToken].Type);}else if(pToken.length>2&&pToken[0]==='{'&&pToken[pToken.length-1]==='}'){return'Token.StateAddress';}else if(this.numberTest.test(pToken)){return'Token.Constant';}else{return'Token.Symbol';}// Just for documentation sake:
3382
3392
  // There is a fifth token type, VirtualSymbol
3383
3393
  // This is a value that's added during solve and looked up by address in the VirtualSymbol object.
3384
3394
  }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":51}],137:[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.RawTokens=[];tmpResults.ExpressionParserLog=[];if(typeof pExpression!=='string'){this.log.warn('ExpressionParser.tokenize was passed a non-string expression.');return tmpResults.RawTokens;}/* Tokenize the expression
@@ -3429,7 +3439,7 @@ tmpCurrentTokenType='Value';tmpCurrentToken+=tmpCharacter;// continue;
3429
3439
  // }
3430
3440
  // tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenize found an unknown character code ${tmpCharCode} character ${tmpCharacter} in the expression: ${pExpression} at index ${i}`);
3431
3441
  // this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
3432
- }if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":136}],138:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"}};},{}],139:[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
3442
+ }if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":136}],138:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"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"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"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"}};},{}],139:[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
3433
3443
  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
3434
3444
  let tmpParenthesisDepth=0;// If it is in a state address, we don't care about the parenthesis
3435
3445
  // State addresses are between squiggly brackets
@@ -3448,45 +3458,16 @@ this.getTokenType(pTokenizedExpression[0])==='Token.StateAddress'||this.getToken
3448
3458
  ){tmpResults.ExpressionParserLog.push("WARNING: ExpressionParser.lintTokenizedExpression found a single equality assignment in the tokenized expression with no assignable address on the left side of the assignment.");tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}}// 5. Check that there are no operators adjacent to each other
3449
3459
  // This is a simple lint check, not a full-blown syntax check
3450
3460
  let tmpTokenPrevious=false;for(let i=0;i<pTokenizedExpression.length-1;i++){if(pTokenizedExpression[i]in this.ExpressionParser.tokenMap&&this.ExpressionParser.tokenMap[pTokenizedExpression[i]].Type!='Parenthesis'&&!tmpTokenPrevious){tmpTokenPrevious=true;}else if(pTokenizedExpression[i]in this.ExpressionParser.tokenMap&&this.ExpressionParser.tokenMap[pTokenizedExpression[i]].Type!='Parenthesis'){// If this isn't a + or - positivity/negativity multiplier, it's an error.
3451
- if(pTokenizedExpression[i]!=='+'&&pTokenizedExpression[i]!=='-'){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.lintTokenizedExpression found an ".concat(pTokenizedExpression[i]," operator adjacent to another operator in the tokenized expression at token index ").concat(i));tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}else{tmpTokenPrevious=false;}}return tmpResults.LinterResults;}}module.exports=ExpressionParserLinter;},{"./Fable-Service-ExpressionParser-Base.js":136}],140:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserPostfix extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Postfix';}getPosfixSolveListOperation(pOperation,pLeftValue,pRightValue,pDepthSolveList,pDepthSolveIndex){let tmpOperation={VirtualSymbolName:pOperation.VirtualSymbolName,Operation:pOperation,LeftValue:pLeftValue,RightValue:pRightValue};let tmpDepthSolveList=Array.isArray(pDepthSolveList)?pDepthSolveList:false;// // Although we have a `Token.Type == "Parenthesis"` option to check on, keeping these explicit means the solver won't
3452
- // // allow users to pass in parenthesis in the wrong order.
3453
- // // The linter does blow up as does the postfix, but, just in case we'll leave these explicit.
3454
- // // It really doesn't hurt anything.
3455
- // if (pLeftValue.Token === ')')
3456
- // {
3457
- // // We have found a close parenthesis which needs to pull the proper virtual symbol for the last operation on this stack.
3458
- // // This ensures we are not expressing the parenthesis virtual symbols to the solver.
3459
- // pLeftValue.VirtualSymbolName = pLayerStackMap[pLeftValue.SolveLayerStack];
3460
- // this.log.error(`ERROR: ExpressionParser.getPosfixSolveListOperation found a close parenthesis in the left value of an operation.`);
3461
- // }
3462
- // else if (pRightValue.Token === '(')
3463
- // {
3464
- // // We have found a close parenthesis which needs to pull the proper virtual symbol for the last operation on this stack.
3465
- // // This ensures we are not expressing the parenthesis virtual symbols to the solver.
3466
- // pRightValue.VirtualSymbolName = pLayerStackMap[pRightValue.SolveLayerStack];
3467
- // this.log.error(`ERROR: ExpressionParser.getPosfixSolveListOperation found a close parenthesis in the left value of an operation.`);
3468
- // }
3469
- // // Set the layer stack map virtual symbol name to the last operation performed on this stack.
3470
- // pLayerStackMap[pOperation.SolveLayerStack] = pOperation.VirtualSymbolName;
3471
- /* These two if blocks are very complex -- they basically provide a
3461
+ if(pTokenizedExpression[i]!=='+'&&pTokenizedExpression[i]!=='-'){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.lintTokenizedExpression found an ".concat(pTokenizedExpression[i]," operator adjacent to another operator in the tokenized expression at token index ").concat(i));tmpResults.LinterResults.push(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}else{tmpTokenPrevious=false;}}return tmpResults.LinterResults;}}module.exports=ExpressionParserLinter;},{"./Fable-Service-ExpressionParser-Base.js":136}],140:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserPostfix extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Postfix';}getPosfixSolveListOperation(pOperation,pLeftValue,pRightValue,pDepthSolveList,pDepthSolveIndex){let tmpOperation={VirtualSymbolName:pOperation.VirtualSymbolName,Operation:pOperation,LeftValue:pLeftValue,RightValue:pRightValue};let tmpDepthSolveList=Array.isArray(pDepthSolveList)?pDepthSolveList:false;/* These two if blocks are very complex -- they basically provide a
3472
3462
  * way to deal with recursion that can be expressed to the user in
3473
3463
  * a meaningful way.
3474
3464
  *
3475
3465
  * The reason we are doing it as such is to show exactly how the
3476
3466
  * solver resolves the passed-in tokens into a solvable expression.
3477
3467
  */if(!tmpOperation.LeftValue.VirtualSymbolName){tmpOperation.LeftValue.VirtualSymbolName=tmpOperation.VirtualSymbolName;}else{// We need to set the left value to a virtual symbol instead of the looked up value if it's already used in another operation
3478
- tmpOperation.LeftValue=this.getTokenContainerObject(tmpOperation.LeftValue.VirtualSymbolName,'Token.VirtualSymbol');// Now walk backwards and see if we need to update a previous symbol for a previously unparsed operator
3479
- if(tmpDepthSolveList){for(let i=pDepthSolveIndex-1;i>=0;i--){if(tmpDepthSolveList[i].Type==='Token.Operator'&&!tmpDepthSolveList[i].Parsed&&// When walking backward, we only want to mutate if the .
3480
- 'Descriptor'in tmpDepthSolveList[i]&&'Descriptor'in tmpOperation.Operation&&// Anything >3 does not have commutative properties
3481
- tmpDepthSolveList[i].Descriptor.Precedence>3){// If the symbol to its right is not the same as this operation
3482
- if(tmpDepthSolveList[i+1].VirtualSymbolName!==tmpOperation.VirtualSymbolName){// This is the recursive "shunting" being simulated
3483
- tmpDepthSolveList[i+1].VirtualSymbolName=tmpOperation.VirtualSymbolName;}break;}}}}if(!tmpOperation.RightValue.VirtualSymbolName){tmpOperation.RightValue.VirtualSymbolName=tmpOperation.VirtualSymbolName;}else{// We need to set the right value to a virtual symbol instead of the looked up value if it's already used in another operation
3484
- tmpOperation.RightValue=this.getTokenContainerObject(tmpOperation.RightValue.VirtualSymbolName,'Token.VirtualSymbol');// Now walk forwards and see if we need to update an upcoming symbol for a previously unparsed operator
3485
- if(tmpDepthSolveList){for(let i=pDepthSolveIndex+1;i<tmpDepthSolveList.length;i++){if(tmpDepthSolveList[i].Type==='Token.Operator'&&!tmpDepthSolveList[i].Parsed&&// When walking forward, we only want to mutate if the precedence hasn't been solved.
3486
- 'Descriptor'in tmpDepthSolveList[i]&&'Descriptor'in tmpOperation.Operation&&// Anything >3 does not have commutative properties
3487
- tmpDepthSolveList[i].Descriptor.Precedence>3){// If the symbol to its right is not the same as this operation
3488
- if(tmpDepthSolveList[i-1].VirtualSymbolName!==tmpOperation.VirtualSymbolName){// This is the recursive "shunting" being simulated
3489
- tmpDepthSolveList[i-1].VirtualSymbolName=tmpOperation.VirtualSymbolName;}break;}else if(tmpDepthSolveList[i].Type==='Token.Operator'&&!tmpDepthSolveList[i].Parsed){break;}}}}tmpOperation.Operation.Parsed=true;return tmpOperation;}buildPostfixedSolveList(pTokenizedExpression,pResultObject){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};tmpResults.PostfixedAssignmentAddress='Result';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
3468
+ if('LeftVirtualSymbolName'in tmpOperation.Operation){tmpOperation.LeftValue=this.getTokenContainerObject(tmpOperation.Operation.LeftVirtualSymbolName,'Token.VirtualSymbol');}else{tmpOperation.LeftValue=this.getTokenContainerObject(tmpOperation.LeftValue.VirtualSymbolName,'Token.VirtualSymbol');}}if(!tmpOperation.RightValue.VirtualSymbolName){tmpOperation.RightValue.VirtualSymbolName=tmpOperation.VirtualSymbolName;}else{// We need to set the right value to a virtual symbol instead of the looked up value if it's already used in another operation
3469
+ //if ('LeftVirtualSymbolName' in tmpOperation.RightValue)
3470
+ 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.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
3490
3471
  let tmpEqualsIndex=-1;for(let i=0;i<pTokenizedExpression.length;i++){if(pTokenizedExpression[i]==='='&&tmpEqualsIndex<0){tmpEqualsIndex=i;}// If there are two equality assignments, error and bail out.
3491
3472
  else if(pTokenizedExpression[i]==='='){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.buildPostfixedSolveList found multiple equality assignments in the tokenized expression; equality assignment #".concat(tmpEqualsIndex," at token index ").concat(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]);}else if(tmpEqualsIndex>1){tmpResults.ExpressionParserLog.push("WARNING: ExpressionParser.buildPostfixedSolveList found an equality assignment in the tokenized expression at an unexpected location (token index ".concat(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.
3492
3473
  // That is... the user entered something like "= 5 + 3" so we should just return 8, and use the default Result quietly.
@@ -3502,12 +3483,7 @@ tmpResults.PostfixTokenObjects[i].Depth=tmpDepth;// Generate the virtual symbol
3502
3483
  tmpResults.PostfixTokenObjects[i].VirtualSymbolName="Pr_".concat(tmpVirtualParenthesisIndex,"_D_").concat(tmpDepth);// 1a. Detect if this parenthesis is signaling a function
3503
3484
  // If the previous token is a Symbol (e.g. it say sin(x) or sqrt(3+5) or something) then the parser will interpret it as a function
3504
3485
  if(i>0){if(tmpResults.PostfixTokenObjects[i-1].Type==='Token.Symbol'){// Set the type of this to be a function
3505
- tmpResults.PostfixTokenObjects[i-1].Type='Token.Function';// tmpResults.PostfixTokenObjects[i-1].Descriptor = this.ExpressionParser.tokenMap[pTokenizedExpression[i-1]];
3506
- // Rename the virtual symbol n ame to include the function
3507
- // tmpResults.PostfixTokenObjects[i].VirtualSymbolName = `Fn_${tmpVirtualParenthesisIndex}_D_${tmpDepth}_${this.fable.DataFormat.cleanNonAlphaCharacters(tmpResults.PostfixTokenObjects[i-1].Token)}`;
3508
- // The function and the parenthesis are at the same depth and virtual symbol
3509
- // tmpResults.PostfixTokenObjects[i-1].VirtualSymbolName = tmpResults.PostfixTokenObjects[i].VirtualSymbolName;
3510
- }}// Parenthesis manage the solve layer stack
3486
+ tmpResults.PostfixTokenObjects[i-1].Type='Token.Function';}}// Parenthesis manage the solve layer stack
3511
3487
  // For adding a new parenthesis solve layer, we put the parenthesis in the stack we are in and then make all the contained tokens be within the stack of the parenthesis
3512
3488
  tmpResults.PostfixTokenObjects[i].SolveLayerStack=tmpSolveLayerStack[tmpSolveLayerStack.length-1];tmpSolveLayerStack.push(tmpResults.PostfixTokenObjects[i].VirtualSymbolName);tmpVirtualParenthesisIndex++;tmpDepth++;}// 2. If it's a closed parenthesis, decrease the depth
3513
3489
  else if(tmpResults.PostfixTokenObjects[i].Token===')'){tmpDepth--;tmpResults.PostfixTokenObjects[i].Depth=tmpDepth;// Check to see that the depth of the closed parenthesis is greater than 0
@@ -3515,17 +3491,7 @@ if(tmpDepth<0){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.buil
3515
3491
  // For closing parenthesis solve layer with a close paren, we put it in the same stack as the opening parenthesis.
3516
3492
  // Give the closing parenthesis the same virtual symbol name as the opening parenthesis
3517
3493
  // (do the both above at the same time)
3518
- tmpResults.PostfixTokenObjects[i].VirtualSymbolName=tmpSolveLayerStack.pop();tmpResults.PostfixTokenObjects[i].SolveLayerStack=tmpSolveLayerStack[tmpSolveLayerStack.length-1];}// 3. If it's a state address or Symbol, set depth
3519
- // It was much more complex later on solving these as virtual symbols of their own.
3520
- // We are saving the value resolution for the very end.
3521
- else if(tmpResults.PostfixTokenObjects[i].Type==='Token.Symbol'){// Set the depth of the current solution depth
3522
- tmpResults.PostfixTokenObjects[i].Depth=tmpDepth;tmpResults.PostfixTokenObjects[i].SolveLayerStack=tmpSolveLayerStack[tmpSolveLayerStack.length-1];// Generate a virtual symbol name that's somewhat human readable
3523
- //tmpResults.PostfixTokenObjects[i].VirtualSymbolName = `Sm_${tmpVirtualParenthesisIndex}_D_${tmpDepth}_${this.fable.DataFormat.cleanNonAlphaCharacters(tmpResults.PostfixTokenObjects[i].Token)}`;
3524
- // We've used up this virtual symbol index so increment it
3525
- // The reason we only use these once is to make sure if we use, say, sin(x) twice at the same depth we still have unique names for each virtual solution
3526
- //tmpVirtualParenthesisIndex++;
3527
- }// 4. If it's an operator or constant or comment, just set the depth
3528
- else{tmpResults.PostfixTokenObjects[i].Depth=tmpDepth;tmpResults.PostfixTokenObjects[i].SolveLayerStack=tmpSolveLayerStack[tmpSolveLayerStack.length-1];}}// 4. Walk through the decorated symbols and generate the postfix solve list
3494
+ tmpResults.PostfixTokenObjects[i].VirtualSymbolName=tmpSolveLayerStack.pop();tmpResults.PostfixTokenObjects[i].SolveLayerStack=tmpSolveLayerStack[tmpSolveLayerStack.length-1];}else{tmpResults.PostfixTokenObjects[i].Depth=tmpDepth;tmpResults.PostfixTokenObjects[i].SolveLayerStack=tmpSolveLayerStack[tmpSolveLayerStack.length-1];}}// 4. Walk through the decorated symbols and generate the postfix solve list
3529
3495
  // We are going to start by creating a map of the solve layers:
3530
3496
  let tmpSolveLayerMap={};let tmpSolveLayerMaxDepth=0;for(let i=0;i<tmpResults.PostfixTokenObjects.length;i++){if(!(tmpResults.PostfixTokenObjects[i].SolveLayerStack in tmpSolveLayerMap)){tmpSolveLayerMap[tmpResults.PostfixTokenObjects[i].SolveLayerStack]=[];}tmpSolveLayerMap[tmpResults.PostfixTokenObjects[i].SolveLayerStack].push(tmpResults.PostfixTokenObjects[i]);// See what our max depth is. This is super important to the postfix operation
3531
3497
  // The programmer in me thinks it would be funny to not track this and just use the map key length as the max size, which would work (logically impossible to have a depth > key length) but it would be quite a bit more confusing to grok the algorithm.
@@ -3548,64 +3514,60 @@ if(tmpSolveLayerTokens[i].Type==='Token.Operator'&&tmpSolveLayerTokens[i].Descri
3548
3514
  if(tmpSolveLayerTokens.length===1){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.buildPostfixedSolveList found a single operator in a solve layer expression at token index ".concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixSolveList;}// If the token is at the beginning of the expression and not a number line orientation modifier, it's an error.
3549
3515
  else if(i==0&&(tmpToken.Token!='+'||tmpToken.Token!='-')){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.buildPostfixedSolveList found an operator at the beginning of a solve layer expression at token index ".concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixSolveList;}// If the token is at the end of the expression, it is an error.
3550
3516
  else if(i==tmpSolveLayerTokens.length-1){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.buildPostfixedSolveList found an operator at the end of a solve layer expression at token index ".concat(i));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixSolveList;}// The - at the beginning of an expression is a number line orientation modifier
3551
- else if(i==0&&tmpToken.Token=='-'){tmpToken.VirtualSymbolName="V_".concat(tmpVirtualSymbolIndex);tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}// The - after an operator or an open parenthesis is also a number line orientation modifier
3517
+ else if(i==0&&tmpToken.Token=='-'){tmpToken.VirtualSymbolName="VNLO_".concat(tmpVirtualSymbolIndex);tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}// The - after an operator or an open parenthesis is also a number line orientation modifier
3552
3518
  else if(i>0&&tmpToken.Token=='-'&&(tmpSolveLayerTokens[i-1].Type==='Token.Operator'||tmpSolveLayerTokens[i-1].Token==='(')){// The number line negation operator is a special case that generates a virtual constant (-1.0) and multiplies it by the next token
3553
- tmpToken.VirtualSymbolName="V_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}// The + at the beginning is also a number line orientation modifier ... THAT WE IGNORE
3519
+ tmpToken.VirtualSymbolName="VNLO_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}// The + at the beginning is also a number line orientation modifier ... THAT WE IGNORE
3554
3520
  else if(i==0&&tmpToken.Token=='+'){continue;}// The + after an operator or a parenthesis is also a number line orientation modifier ... THAT WE IGNORE
3555
3521
  else if(i>0&&tmpToken.Token=='+'&&(tmpSolveLayerTokens[i-1].Type==='Token.Operator'||tmpSolveLayerTokens[i-1].Token==='(')){continue;}// If the token is next to another operator it's a parsing error
3556
3522
  else if(tmpSolveLayerTokens[i-1].Type==='Token.Operator'||tmpSolveLayerTokens[i+1].Type==='Token.Operator'){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.buildPostfixedSolveList found an operator at token index ".concat(i," that is not surrounded by two values."));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixSolveList;}// Finally add a virtual symbol name to the dang thing.
3557
- else{tmpToken.VirtualSymbolName="V_".concat(tmpVirtualSymbolIndex);tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}}else if(tmpSolveLayerTokens[i].Type==='Token.Function'&&tmpPrecedence===0){let tmpToken=tmpSolveLayerTokens[i];tmpToken.VirtualSymbolName="V_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;}}}}// 5.2: Decorate the Parenthesis with Virtual Symbol Names
3523
+ else{tmpToken.VirtualSymbolName="V_".concat(tmpVirtualSymbolIndex);tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}}else if(tmpSolveLayerTokens[i].Type==='Token.Function'&&tmpPrecedence===0){let tmpToken=tmpSolveLayerTokens[i];tmpToken.VirtualSymbolName="VFE_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;}}}}// 5.15 Generate Virtual Symbol Clusters for Functions and Parenthesis
3558
3524
  // ... this gets funny because of precedence of operations surrounding them, parenthesis and functions.
3559
- let tmpParenthesisCacheLIFOStack=[];for(let i=0;i<tmpResults.PostfixTokenObjects.length;i++){let tmpPostfixTokenObject=tmpResults.PostfixTokenObjects[i];if(tmpPostfixTokenObject.Type==='Token.Parenthesis'){// This is just to track the parenthesis stack level in User feedback
3560
- tmpPostfixTokenObject.ParenthesisStack=tmpPostfixTokenObject.VirtualSymbolName;if(tmpPostfixTokenObject.Token==='('){// It's an open parenthesis. If the previous token was an operator, get its precedence.
3561
- if(i>0){if(tmpResults.PostfixTokenObjects[i-1].Type==='Token.Operator'){tmpPostfixTokenObject.PreviousPrecedence=tmpResults.PostfixTokenObjects[i-1].Descriptor.Precedence;tmpPostfixTokenObject.IsFunction=false;tmpPostfixTokenObject.PreviousVirtualSymbolName=tmpResults.PostfixTokenObjects[i-1].VirtualSymbolName;tmpPostfixTokenObject.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];}// This is a function, we will create a virtual symbol for the discrete parenthesis
3562
- else if(tmpResults.PostfixTokenObjects[i-1].Type==='Token.Function'){tmpPostfixTokenObject.PreviousPrecedence=0;tmpPostfixTokenObject.IsFunction=true;tmpPostfixTokenObject.PreviousVirtualSymbolName=tmpResults.PostfixTokenObjects[i-1].VirtualSymbolName;let tmpVirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];if(!tmpVirtualSymbolName){// This is a parenthesis group with no operators in it; make a virtual symbol name.
3563
- tmpVirtualSymbolName="V_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;if(i>1){// Todo: This needs to be enhanced to deal with negations
3564
- let tmpTokenBeforeFunction=tmpResults.PostfixTokenObjects[i-2];if(tmpTokenBeforeFunction.Type==='Token.Operator'){tmpPostfixTokenObject.PreviousVirtualSymbolName=tmpResults.PostfixTokenObjects[i-2].VirtualSymbolName;tmpPostfixTokenObject.PreviousPrecedence=tmpResults.PostfixTokenObjects[i-2].Descriptor.Precedence;}}}}else{tmpPostfixTokenObject.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];}tmpParenthesisCacheLIFOStack.push(tmpPostfixTokenObject);}if(tmpPostfixTokenObject.Token===')'){// There are three options for assigning this:
3565
- let tmpOpenParenthesis=tmpParenthesisCacheLIFOStack.pop();// It's at the end of the tokens -- use the stack's identifier
3566
- if(i>=tmpResults.PostfixTokenObjects.length-1){if(tmpOpenParenthesis.IsFunction){tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.PreviousVirtualSymbolName;}else{tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.VirtualSymbolName;}}else{// The next token is an operator and we're a function
3567
- let tmpPeekedNextToken=tmpResults.PostfixTokenObjects[i+1];if(tmpPeekedNextToken.Type=='Token.Operator'&&tmpOpenParenthesis.IsFunction){// This is the most complex case -- the next token is an operator AND this is a function.
3568
- // The following is just pointer math.
3569
- // If the operater is at the same precedence or higher than the open parenthesis previous operator, use the previous operator's identifier
3570
- // NOTE: This line of code is insanely complex
3571
- //tmpPostfixTokenObject.VirtualSymbolName = tmpOpenParenthesis.PreviousVirtualSymbolName;
3572
- // If the next token has higher precedence than what's before the open parenthesis, use it for the open as well
3573
- if(tmpPeekedNextToken.Descriptor.Precedence<tmpOpenParenthesis.PreviousPrecedence){tmpOpenParenthesis.VirtualSymbolName=tmpPeekedNextToken.VirtualSymbolName;tmpPostfixTokenObject.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];}// Otherwise use this one -- it is the higher precedence. And update the previous parenthesis operator's virtual symbol to be the peeked token's virtual symbol.
3574
- else{tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.PreviousVirtualSymbolName;}}// The next token is an operator and it isn't a function
3575
- else if(tmpPeekedNextToken.Type=='Token.Operator'&&'PreviousPrecedence'in tmpOpenParenthesis){// This is the second most complex case -- the next token is an operator.
3576
- // If the operater is at the same precedence or higher than the open parenthesis previous operator, use the previous operator's identifier
3577
- // NOTE: This line of code is insanely complex
3578
- if(tmpPeekedNextToken.Descriptor.Precedence<=tmpOpenParenthesis.PreviousPrecedence){tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.PreviousVirtualSymbolName;}// Otherwise use this one -- it is the higher precedence. And update the previous parenthesis operator's virtual symbol to be the peeked token's virtual symbol.
3579
- else{tmpPostfixTokenObject.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];tmpOpenParenthesis.VirtualSymbolName=tmpPeekedNextToken.VirtualSymbolName;}}else{// If this is a function, dereference the function's previous virtual symbol name
3580
- if(tmpOpenParenthesis.IsFunction){tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.PreviousVirtualSymbolName;}else{tmpPostfixTokenObject.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];}}}// If there isn't an operator in the layer stack, push forward the assignment
3581
- if(!tmpResults.PostfixLayerstackMap[tmpOpenParenthesis.ParenthesisStack]){tmpResults.PostfixLayerstackMap[tmpOpenParenthesis.ParenthesisStack]=tmpOpenParenthesis.VirtualSymbolName;}}}}for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];if(tmpSolveLayerTokens.length===1){// This is just a simple value assignment -- use a simple addition virtual operation.
3582
- // We often see these inside functions.
3583
- let tmpAbstractAddToken=this.getTokenContainerObject('+');//let tmpVirtualSymbolName = tmpResults.PostfixLayerstackMap[tmpSolveLayerTokens[0].SolveLayerStack];
3584
- tmpAbstractAddToken.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpSolveLayerTokens[0].SolveLayerStack];tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpAbstractAddToken,this.getTokenContainerObject('0.0'),tmpSolveLayerTokens[0]));}}// 5.3: Generate the Postfix Solve List
3585
- for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];// For each precedence level in the layer
3525
+ let tmpFunctionCacheLIFOStack=[];for(let i=0;i<tmpResults.PostfixTokenObjects.length;i++){let tmpPostfixTokenObject=tmpResults.PostfixTokenObjects[i];if(tmpPostfixTokenObject.Type==='Token.Parenthesis'){// This is just to track the parenthesis stack level for User feedback
3526
+ tmpPostfixTokenObject.ParenthesisStack=tmpPostfixTokenObject.VirtualSymbolName;// At the beginning of the expression, this must be an open parenthesis to be legal.
3527
+ if(i==0){tmpPostfixTokenObject.IsFunction=false;let tmpVirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];if(!tmpVirtualSymbolName){// ... this parenthesis group has no operators in it; make a virtual symbol name.
3528
+ tmpVirtualSymbolName="VP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;tmpFunctionCacheLIFOStack.push(tmpPostfixTokenObject);}// If it's an open parenthesis
3529
+ else if(tmpPostfixTokenObject.Token==='('){// ... supporting a function
3530
+ if(tmpResults.PostfixTokenObjects[i-1].Type==='Token.Function'){tmpPostfixTokenObject.IsFunction=true;tmpPostfixTokenObject.Function=tmpResults.PostfixTokenObjects[i-1];let tmpVirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];if(!tmpVirtualSymbolName){// ... this parenthesis group has no operators in it; make a virtual symbol name.
3531
+ tmpVirtualSymbolName="VFP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;}else{tmpPostfixTokenObject.IsFunction=false;let tmpVirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpPostfixTokenObject.VirtualSymbolName];if(!tmpVirtualSymbolName){// This is a parenthesis group with no operators in it; make a virtual symbol name.
3532
+ tmpVirtualSymbolName="VP_".concat(tmpVirtualSymbolIndex);tmpVirtualSymbolIndex++;}tmpPostfixTokenObject.VirtualSymbolName=tmpVirtualSymbolName;}tmpFunctionCacheLIFOStack.push(tmpPostfixTokenObject);}if(tmpPostfixTokenObject.Token===')'){let tmpOpenParenthesis=tmpFunctionCacheLIFOStack.pop();if(tmpOpenParenthesis.IsFunction){tmpPostfixTokenObject.IsFunction=true;tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.Function.VirtualSymbolName;}else{tmpPostfixTokenObject.IsFunction=false;tmpPostfixTokenObject.VirtualSymbolName=tmpOpenParenthesis.VirtualSymbolName;}}}}// X. Postprocess the parenthesis groups to ensure they respect the order of operations for their boundaries
3533
+ for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpParenthesisStack=[];let tmpLastOperator=false;let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];for(let i=0;i<tmpSolveLayerTokens.length;i++){let tmpPostfixTokenObject=tmpSolveLayerTokens[i];// Keep track of the last operator
3534
+ if(tmpPostfixTokenObject.Type==='Token.Operator'){tmpLastOperator=tmpPostfixTokenObject;}// This is only important to do at the close parenthesis.
3535
+ if(tmpPostfixTokenObject.Type==='Token.Function'){tmpPostfixTokenObject.PreviousOperator=tmpLastOperator;}else if(tmpPostfixTokenObject.Type==='Token.Parenthesis'&&tmpPostfixTokenObject.Token==='('&&tmpPostfixTokenObject.IsFunction){tmpParenthesisStack.push(tmpPostfixTokenObject);if(tmpPostfixTokenObject.Function.PreviousOperator){tmpPostfixTokenObject.PreviousOperator=tmpPostfixTokenObject.Function.PreviousOperator;}}else if(tmpPostfixTokenObject.Type==='Token.Parenthesis'&&tmpPostfixTokenObject.Token==='('){tmpPostfixTokenObject.PreviousOperator=tmpLastOperator;tmpParenthesisStack.push(tmpPostfixTokenObject);}else if(tmpPostfixTokenObject.Type==='Token.Parenthesis'&&tmpPostfixTokenObject.Token===')'){// This is ultra complex, and binds the order of operations logic to the open parenthesis for the group
3536
+ let tmpOpenParenthesis=tmpParenthesisStack.pop();if(i<tmpSolveLayerTokens.length-1){for(let j=i+1;j<tmpSolveLayerTokens.length;j++){if(tmpSolveLayerTokens[j].Type==='Token.Operator'){tmpOpenParenthesis.NextOperator=tmpSolveLayerTokens[j];break;}}}if(tmpOpenParenthesis.PreviousOperator&&tmpOpenParenthesis.NextOperator){if(tmpOpenParenthesis.PreviousOperator.Descriptor.Precedence<=tmpOpenParenthesis.NextOperator.Descriptor.Precedence){tmpOpenParenthesis.NextOperator.LeftVirtualSymbolName=tmpOpenParenthesis.PreviousOperator.VirtualSymbolName;}else{tmpOpenParenthesis.PreviousOperator.RightVirtualSymbolName=tmpOpenParenthesis.NextOperator.VirtualSymbolName;}}}else{if(!('SolveLayerStack'in tmpPostfixTokenObject)){// Decorate the solve layer stack for the token
3537
+ if(tmpParenthesisStack.length>0){tmpPostfixTokenObject.SolveLayerStack=tmpParenthesisStack[tmpParenthesisStack.length-1].SolveLayerStack;}else{tmpPostfixTokenObject.SolveLayerStack='Expression_Root';}}}}}// 5.2.9: Make sure the affinity of operators is respecting order of operations.
3538
+ // Walk backwards and forwards, hoisting same value precedence backwards/forwards
3539
+ // across each layer... the precedence change needs to be decreasing to matter
3540
+ for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpLastPrecedence=false;let tmpFinalChainToken=false;let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];for(let i=tmpSolveLayerTokens.length-1;i>=0;i--){let tmpToken=tmpSolveLayerTokens[i];if(tmpToken.Type==='Token.Operator'){if(!tmpFinalChainToken){tmpFinalChainToken=tmpToken;}else if(tmpToken.Descriptor.Precedence>tmpLastPrecedence){// This is less imporant than the last precedence, so hoist back the virtual value
3541
+ tmpToken.RightVirtualSymbolName=tmpFinalChainToken.VirtualSymbolName;//console.log(`Hoisting ${tmpToken.Token} back to ${tmpFinalChainToken.Token}`);
3542
+ tmpFinalChainToken=tmpToken;}else if(tmpToken.Descriptor.Precedence<tmpLastPrecedence){tmpFinalChainToken=tmpToken;}tmpLastPrecedence=tmpToken.Descriptor.Precedence;}}let tmpDecreasingPrecedenceStack=[];let tmpLastToken=false;for(let i=tmpSolveLayerTokens.length-1;i>=0;i--){let tmpToken=tmpSolveLayerTokens[i];if(tmpToken.Type==='Token.Operator'){if(!tmpLastToken){tmpLastToken=tmpToken;}else if(tmpToken.Descriptor.Precedence>tmpLastPrecedence){// Check and see if this needs to be resolved in the stack
3543
+ if(tmpDecreasingPrecedenceStack.length>0){for(let j=tmpDecreasingPrecedenceStack.length-1;j>=0;j--){if(tmpDecreasingPrecedenceStack[j].Descriptor.Precedence>=tmpToken.Descriptor.Precedence){//console.log(`Hoisting ${tmpDecreasingPrecedenceStack[j].Token} up to ${tmpToken.Token}`);
3544
+ tmpDecreasingPrecedenceStack[j].LeftVirtualSymbolName=tmpToken.VirtualSymbolName;tmpDecreasingPrecedenceStack.slice(j,1);break;}}}tmpLastToken=tmpToken;}else if(tmpToken.Descriptor.Precedence<tmpLastPrecedence){tmpDecreasingPrecedenceStack.push(tmpLastToken);tmpLastToken=tmpToken;}tmpLastPrecedence=tmpToken.Descriptor.Precedence;}}}// 5.3: Generate the Postfix Solve List
3545
+ for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];// If this is a layer with one value, presume it's an assignment.
3546
+ if(tmpSolveLayerTokens.length===1){let tmpAbstractAssignToken=this.getTokenContainerObject('=');tmpAbstractAssignToken.VirtualSymbolName=tmpResults.PostfixLayerstackMap[tmpSolveLayerTokens[0].SolveLayerStack];// If this doesn't have a matching solvelayerstack, get the virtual symbol name from the parenthesis group it's in
3547
+ if(!tmpAbstractAssignToken.VirtualSymbolName){for(let i=0;i<tmpResults.PostfixTokenObjects.length;i++){if(tmpResults.PostfixTokenObjects[i].ParenthesisStack===tmpSolveLayerTokens[0].SolveLayerStack){tmpAbstractAssignToken.VirtualSymbolName=tmpResults.PostfixTokenObjects[i].VirtualSymbolName;break;}}}tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpAbstractAssignToken,tmpSolveLayerTokens[0],this.getTokenContainerObject('0.0')));continue;}// For each precedence level in the layer
3586
3548
  for(let tmpPrecedence=0;tmpPrecedence<=this.ExpressionParser.tokenMaxPrecedence;tmpPrecedence++){// Enumerate all tokens in a layer's expression.
3587
3549
  // There is a recursive way to do this, but given the short length of even the most complex equations we're favoring readability.
3588
3550
  for(let i=0;i<tmpSolveLayerTokens.length;i++){// If the token is an operator and at the current precedence, add it to the postfix solve list and mutate the array.
3589
3551
  if(tmpSolveLayerTokens[i].Type==='Token.Operator'&&tmpSolveLayerTokens[i].Descriptor.Precedence===tmpPrecedence){let tmpToken=tmpSolveLayerTokens[i];// The - at the beginning of an expression is a number line orientation modifier
3590
3552
  if(i==0&&tmpToken.Token=='-'){// The number line negation operator is a special case that generates a virtual constant (-1.0) and multiplies it by the next token
3591
3553
  // This is an abstract operation that isn't in the expression.
3592
- let tmpAbstractMultiplyToken=this.getTokenContianerObject('*');tmpAbstractMultiplyToken.VirtualSymbolName=tmpToken.VirtualSymbolName;tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpAbstractMultiplyToken,this.getTokenContainerObject('-1.0'),tmpSolveLayerTokens[i+1]));}// The - after an operator or an open parenthesis is also a number line orientation modifier
3554
+ let tmpAbstractMultiplyToken=this.getTokenContainerObject('*');tmpAbstractMultiplyToken.VirtualSymbolName=tmpToken.VirtualSymbolName;tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpAbstractMultiplyToken,this.getTokenContainerObject('-1.0'),tmpSolveLayerTokens[i+1]));}// The - after an operator or an open parenthesis is also a number line orientation modifier
3593
3555
  else if(i>0&&tmpToken.Token=='-'&&(tmpSolveLayerTokens[i-1].Type==='Token.Operator'||tmpSolveLayerTokens[i-1].Token==='(')){// The number line negation operator is a special case that generates a virtual constant (-1.0) and multiplies it by the next token
3594
- let tmpAbstractMultiplyToken=this.getTokenContianerObject('*');tmpAbstractMultiplyToken.VirtualSymbolName=tmpToken.VirtualSymbolName;tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpAbstractMultiplyToken,this.getTokenContainerObject('-1.0'),tmpSolveLayerTokens[i+1]));}// The + at the beginning is also a number line orientation modifier ... THAT WE IGNORE
3556
+ let tmpAbstractMultiplyToken=this.getTokenContainerObject('*');tmpAbstractMultiplyToken.VirtualSymbolName=tmpToken.VirtualSymbolName;tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpAbstractMultiplyToken,this.getTokenContainerObject('-1.0'),tmpSolveLayerTokens[i+1]));}// The + at the beginning is also a number line orientation modifier ... THAT WE IGNORE
3595
3557
  else if(i==0&&tmpToken.Token=='+'){continue;}// The + after an operator or a parenthesis is also a number line orientation modifier ... THAT WE IGNORE
3596
3558
  else if(i>0&&tmpToken.Token=='+'&&(tmpSolveLayerTokens[i-1].Type==='Token.Operator'||tmpSolveLayerTokens[i-1].Token==='(')){continue;}// Finally add the dang thing.
3597
- else{tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpToken,tmpSolveLayerTokens[i-1],tmpSolveLayerTokens[i+1],tmpSolveLayerTokens,i));}}else if(tmpSolveLayerTokens[i].Type==='Token.Function'&&tmpPrecedence===0){let tmpToken=tmpSolveLayerTokens[i];// Not sure what to do with the other token.
3598
- tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpToken,tmpSolveLayerTokens[i+1],this.getTokenContainerObject('0.0')));}}}}// Now set the assignment address.
3559
+ else{tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpToken,tmpSolveLayerTokens[i-1],tmpSolveLayerTokens[i+1],tmpSolveLayerTokens,i));}}else if(tmpSolveLayerTokens[i].Type==='Token.Function'&&tmpPrecedence===0){let tmpToken=tmpSolveLayerTokens[i];tmpResults.PostfixSolveList.push(this.getPosfixSolveListOperation(tmpToken,tmpSolveLayerTokens[i+1],this.getTokenContainerObject('0.0')));}}}}// 7. Lastly set the assignment address.
3599
3560
  let tmpAssignmentInstruction=this.getPosfixSolveListOperation(this.getTokenContainerObject('Assign','Token.SolverInstruction'),this.getTokenContainerObject('DestinationHash','Token.SolverInstruction'),this.getTokenContainerObject('Resulting','Token.SolverInstruction'));tmpAssignmentInstruction.VirtualSymbolName=tmpResults.PostfixedAssignmentAddress;tmpResults.PostfixSolveList.push(tmpAssignmentInstruction);return tmpResults.PostfixSolveList;}}module.exports=ExpressionParserPostfix;},{"./Fable-Service-ExpressionParser-Base.js":136}],141:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserSolver extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Solver';}solvePostfixedExpression(pPostfixedExpression,pDataDestinationObject,pResultObject,pManifest){let tmpResults=typeof pResultObject==='object'?pResultObject:{ExpressionParserLog:[]};let tmpManifest=typeof pManifest==='object'?pManifest:this.fable.newManyfest();let tmpDataDestinationObject=typeof pDataDestinationObject==='object'?pDataDestinationObject:{};// If there was a fable passed in (e.g. the results object was a service or such), we won't decorate
3600
3561
  let tmpPassedInFable=('fable'in tmpResults);if(!tmpPassedInFable){tmpResults.fable=this.fable;}if(!Array.isArray(pPostfixedExpression)){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression was passed a non-array postfixed expression.");this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}if(pPostfixedExpression.length<1){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression was passed an empty postfixed expression.");this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}// This is how the user communication magic happens.
3601
3562
  tmpResults.VirtualSymbols={};for(let i=0;i<pPostfixedExpression.length;i++){if(pPostfixedExpression[i].Operation.Type==='Token.SolverInstruction'){continue;}let tmpStepResultObject={ExpressionStep:pPostfixedExpression[i],ExpressionStepIndex:i,ResultsObject:tmpResults,Manifest:tmpManifest};// Resolve the virtual symbols to their actual values
3602
3563
  if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.VirtualSymbol'){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.LeftValue.Token);}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.VirtualSymbol'){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.RightValue.Token);}// Resolve the parenthesis to their actual values
3603
- if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.Parenthesis'){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.LeftValue.VirtualSymbolName);}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.Parenthesis'){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.RightValue.VirtualSymbolName);}if(tmpStepResultObject.ExpressionStep.Operation.Type='Operator'){// TODO: This can be optimized. A lot. If necessary. Seems pretty fast honestly for even thousands of operations. Slowest part is arbitrary precision.
3564
+ if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.Parenthesis'){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.LeftValue.VirtualSymbolName);}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.Parenthesis'){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.RightValue.VirtualSymbolName);}// Virtual Constants
3565
+ if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.Constant'&&!('Value'in tmpStepResultObject.ExpressionStep.LeftValue)){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpStepResultObject.ExpressionStep.LeftValue.Token;}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.Constant'&&!('Value'in tmpStepResultObject.ExpressionStep.RightValue)){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpStepResultObject.ExpressionStep.RightValue.Token;}if(tmpStepResultObject.ExpressionStep.Operation.Type='Operator'){// TODO: This can be optimized. A lot. If necessary. Seems pretty fast honestly for even thousands of operations. Slowest part is arbitrary precision.
3604
3566
  // An operator always has a left and right value.
3605
- let tmpFunctionAddress=false;if(tmpStepResultObject.ExpressionStep.Operation.Token in this.ExpressionParser.tokenMap){tmpFunctionAddress="ResultsObject.".concat(tmpStepResultObject.ExpressionStep.Operation.Descriptor.Function);}else if(tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()in this.ExpressionParser.functionMap){tmpFunctionAddress="ResultsObject.".concat(this.ExpressionParser.functionMap[tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()].Address);}try{this.log.trace("Solving Step ".concat(i," [").concat(tmpStepResultObject.ExpressionStep.VirtualSymbolName,"] --> [").concat(tmpStepResultObject.ExpressionStep.Operation.Token,"]: ( ").concat(tmpStepResultObject.ExpressionStep.LeftValue.Value," , ").concat(tmpStepResultObject.ExpressionStep.RightValue.Value," )"));tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]=tmpManifest.getValueAtAddress(tmpStepResultObject,"".concat(tmpFunctionAddress,"(ExpressionStep.LeftValue.Value,ExpressionStep.RightValue.Value)"));this.log.trace(" ---> Step ".concat(i,": ").concat(tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]));}catch(pError){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ".concat(i," with function ").concat(tmpStepResultObject.ExpressionStep.Operation.Token,"."));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}// Equations don't always solve in virtual symbol order.
3567
+ let tmpFunctionAddress=false;if(tmpStepResultObject.ExpressionStep.Operation.Token in this.ExpressionParser.tokenMap){tmpFunctionAddress="ResultsObject.".concat(tmpStepResultObject.ExpressionStep.Operation.Descriptor.Function);}else if(tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()in this.ExpressionParser.functionMap){tmpFunctionAddress="ResultsObject.".concat(this.ExpressionParser.functionMap[tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()].Address);}try{this.log.trace("Solving Step ".concat(i," [").concat(tmpStepResultObject.ExpressionStep.VirtualSymbolName,"] --> [").concat(tmpStepResultObject.ExpressionStep.Operation.Token,"]: ( ").concat(tmpStepResultObject.ExpressionStep.LeftValue.Value," , ").concat(tmpStepResultObject.ExpressionStep.RightValue.Value," )"));tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]=tmpManifest.getValueAtAddress(tmpStepResultObject,"".concat(tmpFunctionAddress,"(ExpressionStep.LeftValue.Value,ExpressionStep.RightValue.Value)"));this.log.trace(" ---> Step ".concat(i,": ").concat(tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]));}catch(pError){tmpResults.ExpressionParserLog.push("ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ".concat(i," with function ").concat(tmpStepResultObject.ExpressionStep.Operation.Token,": ").concat(pError));this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}// Equations don't always solve in virtual symbol order.
3606
3568
  tmpResults.SolverFinalVirtualSymbol=tmpStepResultObject.ExpressionStep.VirtualSymbolName;}}let tmpSolverResultValue=tmpManifest.getValueAtAddress(tmpResults,"VirtualSymbols.".concat(tmpResults.SolverFinalVirtualSymbol));// Now deal with final assignment
3607
3569
  for(let i=0;i<pPostfixedExpression.length;i++){if(pPostfixedExpression[i].Operation.Type==='Token.SolverInstruction'&&pPostfixedExpression[i].Operation.Token=='Assign'){tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,pPostfixedExpression[i].VirtualSymbolName,tmpSolverResultValue);tmpManifest.setValueByHash(tmpDataDestinationObject,pPostfixedExpression[i].VirtualSymbolName,tmpSolverResultValue);}}// Clean up the reference if we added it to the object.
3608
- if(!tmpPassedInFable){delete tmpResults.fable;}return tmpSolverResultValue.toString();}}module.exports=ExpressionParserSolver;},{"./Fable-Service-ExpressionParser-Base.js":136}],142:[function(require,module,exports){module.exports={"=":{"Name":"Equals","Token":"=","Precedence":0,"Type":"Assignment"},"(":{"Name":"Left Parenthesis","Token":"(","Precedence":0,"Type":"Parenthesis"},")":{"Name":"Right Parenthesis","Token":")","Precedence":0,"Type":"Parenthesis"},"*":{"Name":"Multiply","Token":"*","Function":"fable.Math.multiplyPrecise","Precedence":3,"Type":"Operator"},"/":{"Name":"Divide","Token":"/","Function":"fable.Math.dividePrecise","Precedence":3,"Type":"Operator"},"^":{"Name":"Exponent","Token":"^","Function":"fable.Math.powerPrecise","Precedence":1,"Type":"Operator"},"%":{"Name":"Modulus","Token":"%","Function":"fable.Math.modPrecise","Precedence":3,"Type":"Operator"},"+":{"Name":"Add","Token":"+","Function":"fable.Math.addPrecise","Precedence":4,"Type":"Operator"},"-":{"Name":"Subtract","Token":"-","Function":"fable.Math.subtractPrecise","Precedence":4,"Type":"Operator"}};},{}],143:[function(require,module,exports){(function(process){(function(){const libFableServiceBase=require('fable-serviceproviderbase');const libFS=require('fs');const libPath=require('path');const libReadline=require('readline');class FableServiceFilePersistence extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='FilePersistence';if(!('Mode'in this.options)){this.options.Mode=parseInt('0777',8)&~process.umask();}this.libFS=libFS;this.libPath=libPath;this.libReadline=libReadline;}joinPath(){return libPath.resolve(...arguments);}existsSync(pPath){return libFS.existsSync(pPath);}exists(pPath,fCallback){let tmpFileExists=this.existsSync(pPath);;return fCallback(null,tmpFileExists);}appendFileSync(pFileName,pAppendContent,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.appendFileSync(pFileName,pAppendContent,tmpOptions);}deleteFileSync(pFileName){return libFS.unlinkSync(pFileName);}deleteFolderSync(pFileName){return libFS.rmdirSync(pFileName);}readFileSync(pFilePath,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.readFileSync(pFilePath,tmpOptions);}readFile(pFilePath,pOptions,fCallback){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.readFile(pFilePath,tmpOptions,fCallback);}writeFileSync(pFileName,pFileContent,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.writeFileSync(pFileName,pFileContent,tmpOptions);}writeFileSyncFromObject(pFileName,pObject){return this.writeFileSync(pFileName,JSON.stringify(pObject,null,4));}writeFileSyncFromArray(pFileName,pFileArray){if(!Array.isArray(pFileArray)){this.log.error("File Persistence Service attempted to write ".concat(pFileName," from array but the expected array was not an array (it was a ").concat(typeof pFileArray,")."));return Error('Attempted to write ${pFileName} from array but the expected array was not an array (it was a ${typeof(pFileArray)}).');}else{for(let i=0;i<pFileArray.length;i++){return this.appendFileSync(pFileName,"".concat(pFileArray[i],"\n"));}}}writeFile(pFileName,pFileContent,pOptions,fCallback){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.writeFile(pFileName,pFileContent,tmpOptions,fCallback);}lineReaderFactory(pFilePath,fOnLine,fOnComplete,fOnError){let tmpLineReader={};if(typeof pFilePath!='string'){return false;}tmpLineReader.filePath=pFilePath;tmpLineReader.fileStream=libFS.createReadStream(tmpLineReader.filePath);tmpLineReader.reader=libReadline.createInterface({input:tmpLineReader.fileStream,crlfDelay:Infinity});if(typeof fOnError==='function'){tmpLineReader.reader.on('error',fOnError);}tmpLineReader.reader.on('line',typeof fOnLine==='function'?fOnLine:()=>{});if(typeof fOnComplete==='function'){tmpLineReader.reader.on('close',fOnComplete);}return tmpLineReader;}// Folder management
3570
+ if(!tmpPassedInFable){delete tmpResults.fable;}return tmpSolverResultValue.toString();}}module.exports=ExpressionParserSolver;},{"./Fable-Service-ExpressionParser-Base.js":136}],142:[function(require,module,exports){module.exports={"=":{"Name":"Equals","Token":"=","Function":"fable.Math.assignValue","Precedence":0,"Type":"Assignment"},"(":{"Name":"Left Parenthesis","Token":"(","Precedence":0,"Type":"Parenthesis"},")":{"Name":"Right Parenthesis","Token":")","Precedence":0,"Type":"Parenthesis"},"*":{"Name":"Multiply","Token":"*","Function":"fable.Math.multiplyPrecise","Precedence":3,"Type":"Operator"},"/":{"Name":"Divide","Token":"/","Function":"fable.Math.dividePrecise","Precedence":3,"Type":"Operator"},"^":{"Name":"Exponent","Token":"^","Function":"fable.Math.powerPrecise","Precedence":1,"Type":"Operator"},"%":{"Name":"Modulus","Token":"%","Function":"fable.Math.modPrecise","Precedence":3,"Type":"Operator"},"+":{"Name":"Add","Token":"+","Function":"fable.Math.addPrecise","Precedence":4,"Type":"Operator"},"-":{"Name":"Subtract","Token":"-","Function":"fable.Math.subtractPrecise","Precedence":4,"Type":"Operator"}};},{}],143:[function(require,module,exports){(function(process){(function(){const libFableServiceBase=require('fable-serviceproviderbase');const libFS=require('fs');const libPath=require('path');const libReadline=require('readline');class FableServiceFilePersistence extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='FilePersistence';if(!('Mode'in this.options)){this.options.Mode=parseInt('0777',8)&~process.umask();}this.libFS=libFS;this.libPath=libPath;this.libReadline=libReadline;}joinPath(){return libPath.resolve(...arguments);}existsSync(pPath){return libFS.existsSync(pPath);}exists(pPath,fCallback){let tmpFileExists=this.existsSync(pPath);;return fCallback(null,tmpFileExists);}appendFileSync(pFileName,pAppendContent,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.appendFileSync(pFileName,pAppendContent,tmpOptions);}deleteFileSync(pFileName){return libFS.unlinkSync(pFileName);}deleteFolderSync(pFileName){return libFS.rmdirSync(pFileName);}readFileSync(pFilePath,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.readFileSync(pFilePath,tmpOptions);}readFile(pFilePath,pOptions,fCallback){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.readFile(pFilePath,tmpOptions,fCallback);}writeFileSync(pFileName,pFileContent,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.writeFileSync(pFileName,pFileContent,tmpOptions);}writeFileSyncFromObject(pFileName,pObject){return this.writeFileSync(pFileName,JSON.stringify(pObject,null,4));}writeFileSyncFromArray(pFileName,pFileArray){if(!Array.isArray(pFileArray)){this.log.error("File Persistence Service attempted to write ".concat(pFileName," from array but the expected array was not an array (it was a ").concat(typeof pFileArray,")."));return Error('Attempted to write ${pFileName} from array but the expected array was not an array (it was a ${typeof(pFileArray)}).');}else{for(let i=0;i<pFileArray.length;i++){return this.appendFileSync(pFileName,"".concat(pFileArray[i],"\n"));}}}writeFile(pFileName,pFileContent,pOptions,fCallback){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.writeFile(pFileName,pFileContent,tmpOptions,fCallback);}lineReaderFactory(pFilePath,fOnLine,fOnComplete,fOnError){let tmpLineReader={};if(typeof pFilePath!='string'){return false;}tmpLineReader.filePath=pFilePath;tmpLineReader.fileStream=libFS.createReadStream(tmpLineReader.filePath);tmpLineReader.reader=libReadline.createInterface({input:tmpLineReader.fileStream,crlfDelay:Infinity});if(typeof fOnError==='function'){tmpLineReader.reader.on('error',fOnError);}tmpLineReader.reader.on('line',typeof fOnLine==='function'?fOnLine:()=>{});if(typeof fOnComplete==='function'){tmpLineReader.reader.on('close',fOnComplete);}return tmpLineReader;}// Folder management
3609
3571
  makeFolderRecursive(pParameters,fCallback){let tmpParameters=pParameters;if(typeof pParameters=='string'){tmpParameters={Path:pParameters};}else if(typeof pParameters!=='object'){fCallback(new Error('Parameters object or string not properly passed to recursive folder create.'));return false;}if(typeof tmpParameters.Path!=='string'){fCallback(new Error('Parameters object needs a path to run the folder create operation.'));return false;}if(!('Mode'in tmpParameters)){tmpParameters.Mode=this.options.Mode;}// Check if we are just starting .. if so, build the initial state for our recursive function
3610
3572
  if(typeof tmpParameters.CurrentPathIndex==='undefined'){// Build the tools to start recursing
3611
3573
  tmpParameters.ActualPath=libPath.normalize(tmpParameters.Path);tmpParameters.ActualPathParts=tmpParameters.ActualPath.split(libPath.sep);tmpParameters.CurrentPathIndex=0;tmpParameters.CurrentPath='';}else{// This is not our first run, so we will continue the recursion.
@@ -3615,24 +3577,233 @@ tmpParameters.CurrentPathIndex++;}// Check if the path is fully complete
3615
3577
  if(tmpParameters.CurrentPathIndex>=tmpParameters.ActualPathParts.length){return fCallback(null);}// Check if the path exists (and is a folder)
3616
3578
  libFS.open(tmpParameters.CurrentPath+libPath.sep+tmpParameters.ActualPathParts[tmpParameters.CurrentPathIndex],'r',(pError,pFileDescriptor)=>{if(pFileDescriptor){libFS.closeSync(pFileDescriptor);}if(pError&&pError.code=='ENOENT'){/* Path doesn't exist, create it */libFS.mkdir(tmpParameters.CurrentPath+libPath.sep+tmpParameters.ActualPathParts[tmpParameters.CurrentPathIndex],tmpParameters.Mode,pCreateError=>{if(!pCreateError){// We have now created our folder and there was no error -- continue.
3617
3579
  return this.makeFolderRecursive(tmpParameters,fCallback);}else if(pCreateError.code=='EEXIST'){// The folder exists -- our dev might be running this in parallel/async/whatnot.
3618
- return this.makeFolderRecursive(tmpParameters,fCallback);}else{console.log(pCreateError.code);return fCallback(pCreateError);}});}else{return this.makeFolderRecursive(tmpParameters,fCallback);}});}}module.exports=FableServiceFilePersistence;}).call(this);}).call(this,require('_process'));},{"_process":87,"fable-serviceproviderbase":51,"fs":19,"path":83,"readline":19}],144:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
3580
+ return this.makeFolderRecursive(tmpParameters,fCallback);}else{console.log(pCreateError.code);return fCallback(pCreateError);}});}else{return this.makeFolderRecursive(tmpParameters,fCallback);}});}}module.exports=FableServiceFilePersistence;}).call(this);}).call(this,require('_process'));},{"_process":87,"fable-serviceproviderbase":51,"fs":19,"path":83,"readline":19}],144:[function(require,module,exports){/**
3581
+ * @file Fable-Service-Math.js
3582
+ * @description This file contains the implementation of the FableServiceMath class, which provides simple functions for performing arbitrary precision math operations.
3583
+ * @module FableServiceMath
3584
+ * @extends libFableServiceBase
3585
+ */const libFableServiceBase=require('fable-serviceproviderbase');/**
3619
3586
  * Arbitrary Precision Math Operations
3620
3587
  * @author Steven Velozo <steven@velozo.com>
3621
3588
  * @description Simple functions that perform arbitrary precision math operations and return string resultant values. Wraps big.js
3622
3589
  * @class FableServiceMath
3623
3590
  * @extends libFableServiceBase
3624
- */class FableServiceMath extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='Math';}/*
3625
- Pass-through Rounding Method Constants
3626
-
3627
- Property Value BigDecimal Equiv Description
3628
- ---------- ----- ---------------- -----------
3629
- roundDown 0 ROUND_DOWN Rounds towards zero. (_I.e. truncate, no rounding._)
3630
- roundHalfUp 1 ROUND_HALF_UP Rounds towards nearest neighbour. (_If equidistant, rounds away from zero._)
3631
- roundHalfEven 2 ROUND_HALF_EVEN Rounds towards nearest neighbour. (_If equidistant, rounds towards even neighbour._)
3632
- roundUp 3 ROUND_UP Rounds positively away from zero. (_Always round up._)
3633
- */get roundDown(){return this.fable.Utility.bigNumber.roundDown;}get roundHalfUp(){return this.fable.Utility.bigNumber.roundHalfUp;}get roundHalfEven(){return this.fable.Utility.bigNumber.roundHalfEven;}get roundUp(){return this.fable.Utility.bigNumber.roundUp;}parsePrecise(pValue,pNonNumberValue){let tmpNumber;try{tmpNumber=new this.fable.Utility.bigNumber(pValue);}catch(pError){this.log.warn("Error parsing number (type ".concat(typeof pValue,"): ").concat(pError));tmpNumber=typeof pNonNumberValue==='undefined'?"0.0":pNonNumberValue;}return tmpNumber.toString();}percentagePrecise(pIs,pOf){let tmpLeftValue=isNaN(pIs)?0:pIs;let tmpRightValue=isNaN(pOf)?0:pOf;if(tmpRightValue==0){return'0';}let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.div(tmpRightValue);tmpResult=tmpResult.times(100);return tmpResult.toString();}roundPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:pDecimals;let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.round(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}toFixedPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:pDecimals;let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.toFixed(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}addPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.plus(tmpRightValue);return tmpResult.toString();}subtractPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.minus(tmpRightValue);return tmpResult.toString();}// Bignumber does not use precision values for power -- only javascript decimals
3634
- powerPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:parseInt(pRightValue);let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.pow(tmpRightValue);return tmpResult.toString();}multiplyPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.times(tmpRightValue);return tmpResult.toString();}dividePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.div(tmpRightValue);return tmpResult.toString();}modPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.mod(tmpRightValue);return tmpResult.toString();}sqrtPrecise(pValue){let tmpValue=isNaN(pValue)?0:pValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpLeftArbitraryValue.sqrt();return tmpResult.toString();}absPrecise(pValue){let tmpValue=isNaN(pValue)?0:pValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpLeftArbitraryValue.abs();return tmpResult.toString();}comparePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.cmp(tmpRightValue);}gtPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.gt(tmpRightValue);}gtePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.gte(tmpRightValue);}ltPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.lt(tmpRightValue);}ltePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.lt(tmpRightValue);}radPrecise(pDegrees){let tmpDegrees=isNaN(pDegrees)?0:pDegrees;let tmpDegreesArbitraryValue=new this.fable.Utility.bigNumber(tmpDegrees);// TODO: Const for pi in arbitrary precision?
3635
- let tmpResult=tmpDegreesArbitraryValue.times(Math.PI).div(180);return tmpResult.toString();}sin(pRadians){let tmpRadians=isNaN(pRadians)?0:pRadians;return Math.sin(tmpRadians);}cos(pRadians){let tmpRadians=isNaN(pRadians)?0:pRadians;return Math.cos(tmpRadians);}tan(pRadians){let tmpRadians=isNaN(pRadians)?0:pRadians;return Math.tan(tmpRadians);}}module.exports=FableServiceMath;},{"fable-serviceproviderbase":51}],145:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
3591
+ */class FableServiceMath extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='Math';this.pi='3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679';}/*
3592
+ Pass-through Rounding Method Constants
3593
+
3594
+ Property Value BigDecimal Equiv Description
3595
+ ---------- ----- ---------------- -----------
3596
+ roundDown 0 ROUND_DOWN Rounds towards zero. (_I.e. truncate, no rounding._)
3597
+ roundHalfUp 1 ROUND_HALF_UP Rounds towards nearest neighbour. (_If equidistant, rounds away from zero._)
3598
+ roundHalfEven 2 ROUND_HALF_EVEN Rounds towards nearest neighbour. (_If equidistant, rounds towards even neighbour._)
3599
+ roundUp 3 ROUND_UP Rounds positively away from zero. (_Always round up._)
3600
+ */get roundDown(){return this.fable.Utility.bigNumber.roundDown;}get roundHalfUp(){return this.fable.Utility.bigNumber.roundHalfUp;}get roundHalfEven(){return this.fable.Utility.bigNumber.roundHalfEven;}get roundUp(){return this.fable.Utility.bigNumber.roundUp;}/**
3601
+ * Parses a precise number value.
3602
+ *
3603
+ * @param {number} pValue - The value to parse.
3604
+ * @param {any} pNonNumberValue - The value to use if parsing fails.
3605
+ * @returns {string} - The parsed number as a string.
3606
+ */parsePrecise(pValue,pNonNumberValue){let tmpNumber;try{tmpNumber=new this.fable.Utility.bigNumber(pValue);}catch(pError){this.log.warn("Error parsing number (type ".concat(typeof pValue,"): ").concat(pError));tmpNumber=typeof pNonNumberValue==='undefined'?"0.0":pNonNumberValue;}return tmpNumber.toString();}/**
3607
+ * Assigns the given value. For equals operations in the solver.
3608
+ * @param {*} pValue - The value to be assigned.
3609
+ * @returns {*} The assigned value.
3610
+ */assignValue(pValue){return pValue;}/**
3611
+ * Calculates the precise percentage of a given value compared to another value.
3612
+ *
3613
+ * @param {number} pIs - The value to calculate the percentage of.
3614
+ * @param {number} pOf - The value to calculate the percentage against.
3615
+ * @returns {string} The precise percentage as a string.
3616
+ */percentagePrecise(pIs,pOf){let tmpLeftValue=isNaN(pIs)?0:pIs;let tmpRightValue=isNaN(pOf)?0:pOf;if(tmpRightValue==0){return'0';}let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.div(tmpRightValue);tmpResult=tmpResult.times(100);return tmpResult.toString();}/**
3617
+ * Rounds a value to a specified number of decimal places using a specified rounding method.
3618
+ *
3619
+ * @param {number} pValue - The value to be rounded.
3620
+ * @param {number} pDecimals - The number of decimal places to round to.
3621
+ * @param {function} [pRoundingMethod] - The rounding method to use. Defaults to `this.roundHalfUp`.
3622
+ * @returns {string} - The rounded value as a string.
3623
+ */roundPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:pDecimals;let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.round(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}/**
3624
+ * Returns a string representation of a number with a specified number of decimals.
3625
+ *
3626
+ * @param {number} pValue - The number to be formatted.
3627
+ * @param {number} pDecimals - The number of decimals to include in the formatted string.
3628
+ * @param {string} [pRoundingMethod] - The rounding method to use. Defaults to 'roundHalfUp'.
3629
+ * @returns {string} - The formatted number as a string.
3630
+ */toFixedPrecise(pValue,pDecimals,pRoundingMethod){let tmpValue=isNaN(pValue)?0:pValue;let tmpDecimals=isNaN(pDecimals)?0:pDecimals;let tmpRoundingMethod=typeof pRoundingMethod==='undefined'?this.roundHalfUp:pRoundingMethod;let tmpArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpArbitraryValue.toFixed(tmpDecimals,tmpRoundingMethod);return tmpResult.toString();}/**
3631
+ * Adds two values precisely.
3632
+ * @param {number} pLeftValue - The left value to be added.
3633
+ * @param {number} pRightValue - The right value to be added.
3634
+ * @returns {string} - The result of adding the two values as a string.
3635
+ */addPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.plus(tmpRightValue);return tmpResult.toString();}/**
3636
+ * Subtracts two values precisely.
3637
+ *
3638
+ * @param {number} pLeftValue - The left value to subtract.
3639
+ * @param {number} pRightValue - The right value to subtract.
3640
+ * @returns {string} The result of the subtraction as a string.
3641
+ */subtractPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.minus(tmpRightValue);return tmpResult.toString();}/**
3642
+ * Calculates the precise power of two numbers.
3643
+ *
3644
+ * @param {number} pLeftValue - The base value.
3645
+ * @param {number} pRightValue - The exponent value.
3646
+ * @returns {string} The result of raising the base value to the exponent value.
3647
+ */powerPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:parseInt(pRightValue);let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.pow(tmpRightValue);return tmpResult.toString();}/**
3648
+ * Multiplies two values precisely.
3649
+ *
3650
+ * @param {number} pLeftValue - The left value to multiply.
3651
+ * @param {number} pRightValue - The right value to multiply.
3652
+ * @returns {string} The result of the multiplication as a string.
3653
+ */multiplyPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.times(tmpRightValue);return tmpResult.toString();}/**
3654
+ * Divides two values precisely.
3655
+ *
3656
+ * @param {number} pLeftValue - The left value to be divided.
3657
+ * @param {number} pRightValue - The right value to divide by.
3658
+ * @returns {string} The result of the division as a string.
3659
+ */dividePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.div(tmpRightValue);return tmpResult.toString();}/**
3660
+ * Calculates the modulus of two values with precision.
3661
+ *
3662
+ * @param {number} pLeftValue - The left value.
3663
+ * @param {number} pRightValue - The right value.
3664
+ * @returns {string} The result of the modulus operation as a string.
3665
+ */modPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);let tmpResult=tmpLeftArbitraryValue.mod(tmpRightValue);return tmpResult.toString();}/**
3666
+ * Calculates the square root of a number with precise decimal places.
3667
+ *
3668
+ * @param {number} pValue - The number to calculate the square root of.
3669
+ * @returns {string} The square root of the input number as a string.
3670
+ */sqrtPrecise(pValue){let tmpValue=isNaN(pValue)?0:pValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpLeftArbitraryValue.sqrt();return tmpResult.toString();}/**
3671
+ * Calculates the absolute value of a number precisely.
3672
+ *
3673
+ * @param {number} pValue - The number to calculate the absolute value of.
3674
+ * @returns {string} The absolute value of the input number as a string.
3675
+ */absPrecise(pValue){let tmpValue=isNaN(pValue)?0:pValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpValue);let tmpResult=tmpLeftArbitraryValue.abs();return tmpResult.toString();}/**
3676
+ * Compares two values precisely.
3677
+ *
3678
+ * @param {number} pLeftValue - The left value to compare.
3679
+ * @param {number} pRightValue - The right value to compare.
3680
+ * @returns {number} - Returns the result of the comparison.
3681
+ */comparePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.cmp(tmpRightValue);}/**
3682
+ * Determines if the left value is greater than the right value precisely.
3683
+ *
3684
+ * @param {number} pLeftValue - The left value to compare.
3685
+ * @param {number} pRightValue - The right value to compare.
3686
+ * @returns {boolean} - Returns true if the left value is greater than the right value, otherwise returns false.
3687
+ */gtPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.gt(tmpRightValue);}/**
3688
+ * Checks if the left value is greater than or equal to the right value.
3689
+ * If either value is not a number, it is treated as 0.
3690
+ *
3691
+ * @param {number} pLeftValue - The left value to compare.
3692
+ * @param {number} pRightValue - The right value to compare.
3693
+ * @returns {boolean} - True if the left value is greater than or equal to the right value, false otherwise.
3694
+ */gtePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.gte(tmpRightValue);}/**
3695
+ * Determines if the left value is less than the right value precisely.
3696
+ *
3697
+ * @param {number} pLeftValue - The left value to compare.
3698
+ * @param {number} pRightValue - The right value to compare.
3699
+ * @returns {boolean} - Returns true if the left value is less than the right value, otherwise returns false.
3700
+ */ltPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.lt(tmpRightValue);}/**
3701
+ * Determines if the left value is less than or equal to the right value.
3702
+ *
3703
+ * @param {number} pLeftValue - The left value to compare.
3704
+ * @param {number} pRightValue - The right value to compare.
3705
+ * @returns {boolean} - Returns true if the left value is less than or equal to the right value, otherwise returns false.
3706
+ */ltePrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);return tmpLeftArbitraryValue.lt(tmpRightValue);}/**
3707
+ * Converts degrees to radians with arbitrary precision.
3708
+ *
3709
+ * @param {number} pDegrees - The degrees to convert to radians.
3710
+ * @returns {string} - The converted radians as a string.
3711
+ */radPrecise(pDegrees){let tmpDegrees=isNaN(pDegrees)?0:pDegrees;let tmpDegreesArbitraryValue=new this.fable.Utility.bigNumber(tmpDegrees);// TODO: Const for pi in arbitrary precision?
3712
+ let tmpResult=tmpDegreesArbitraryValue.times(Math.PI).div(180);return tmpResult.toString();}/**
3713
+ * Calculates the value of pi with the specified precision.
3714
+ * If no precision is provided, returns 100 digits after the decimal.
3715
+ *
3716
+ * @param {number} [pPrecision] - The precision to use for calculating pi.
3717
+ * @returns {number} - The calculated value of pi.
3718
+ */piPrecise(pPrecision){if(typeof pPrecision==='undefined'){return this.pi;}else{return this.roundPrecise(this.pi,pPrecision);}}/**
3719
+ * Calculates the sine of the given angle in radians.
3720
+ *
3721
+ * @param {number} pRadians - The angle in radians.
3722
+ * @returns {number} The sine of the angle.
3723
+ */sin(pRadians){let tmpRadians=isNaN(pRadians)?0:pRadians;return Math.sin(tmpRadians);}/**
3724
+ * Calculates the cosine of the given angle in radians.
3725
+ *
3726
+ * @param {number} pRadians - The angle in radians.
3727
+ * @returns {number} The cosine of the angle.
3728
+ */cos(pRadians){let tmpRadians=isNaN(pRadians)?0:pRadians;return Math.cos(tmpRadians);}/**
3729
+ * Calculates the tangent of an angle in radians.
3730
+ *
3731
+ * @param {number} pRadians - The angle in radians.
3732
+ * @returns {number} The tangent of the angle.
3733
+ */tan(pRadians){let tmpRadians=isNaN(pRadians)?0:pRadians;return Math.tan(tmpRadians);}/* * * * * * * * * * * * * * * *
3734
+ * Set functions
3735
+ * These are meant to work fine with arrays and more complex set descriptions returned by Manyfest.
3736
+ * Manyfest sometimes returns values as arrays and sometimes as a map of addresses with values depending
3737
+ * on what was requested.
3738
+ *
3739
+ * The following functions will likely be broken into their own service.
3740
+ */ /**
3741
+ * Counts the number of elements in a set.
3742
+ *
3743
+ * @param {Array|Object|any} pValueSet - The set to count the elements of.
3744
+ * @returns {number} The number of elements in the set.
3745
+ */countSetElements(pValueSet){if(Array.isArray(pValueSet)){return pValueSet.length;}else if(typeof pValueSet==='object'){return Object.keys(pValueSet).length;}else if(pValueSet){// This is controversial. Discuss with colleagues!
3746
+ return 1;}return 0;}/**
3747
+ * Sorts the elements in the given value set in ascending order using the precise parsing and comparison.
3748
+ *
3749
+ * @param {Array|Object} pValueSet - The value set to be sorted.
3750
+ * @returns {Array} - The sorted value set.
3751
+ */sortSetPrecise(pValueSet){let tmpSortedSet=[];if(Array.isArray(pValueSet)){for(let i=0;i<pValueSet.length;i++){tmpSortedSet.push(this.parsePrecise(pValueSet[i],NaN));}}else if(typeof pValueSet==='object'){let tmpKeys=Object.keys(pValueSet);for(let i=0;i<tmpKeys.length;i++){tmpSortedSet.push(this.parsePrecise(pValueSet[tmpKeys[i]],NaN));}}tmpSortedSet.sort((pLeft,pRight)=>{return this.comparePrecise(pLeft,pRight);});return tmpSortedSet;}/**
3752
+ * Bucketizes a set of values based on a specified bucket size.
3753
+ *
3754
+ * @param {Array|Object} pValueSet - The set of values to be bucketized.
3755
+ * @param {number} pBucketSize - The size of each bucket. Optional - If NaN, the values will be bucketized by their value.
3756
+ * @returns {Object} - The bucketized set of values.
3757
+ */bucketSetPrecise(pValueSet,pBucketSize){let tmpBucketedSet={};let tmpBucketSize=this.parsePrecise(pBucketSize,NaN);if(Array.isArray(pValueSet)){for(let i=0;i<pValueSet.length;i++){let tmpValue=this.parsePrecise(pValueSet[i],NaN);let tmpBucket=tmpValue.toString();if(!isNaN(tmpBucketSize)){tmpBucket=this.dividePrecise(pValueSet[i],tmpBucketSize);}if(!(tmpBucket in tmpBucketedSet)){tmpBucketedSet[tmpBucket]=0;}tmpBucketedSet[tmpBucket]=tmpBucketedSet[tmpBucket]+1;}}else if(typeof pValueSet==='object'){let tmpKeys=Object.keys(pValueSet);for(let i=0;i<tmpKeys.length;i++){let tmpValue=this.parsePrecise(pValueSet[tmpKeys[i]],NaN);let tmpBucket=tmpValue.toString();if(!isNaN(tmpBucketSize)){tmpBucket=this.dividePrecise(pValueSet[i],tmpBucketSize);}if(!(tmpBucket in tmpBucketedSet)){tmpBucketedSet[tmpBucket]=0;}tmpBucketedSet[tmpBucket]=tmpBucketedSet[tmpBucket]+1;}}return tmpBucketedSet;}/**
3758
+ * Calculates the histogram using precise bucket set for the given pValueSet.
3759
+ *
3760
+ * @param {Array<number>} pValueSet - The array of p-values.
3761
+ * @returns {Array<number>} The histogram of the p-values.
3762
+ */histogramPrecise(pValueSet){return this.bucketSetPrecise(pValueSet);}/**
3763
+ * Sorts the histogram object in ascending order based on the frequencies of the buckets.
3764
+ *
3765
+ * @param {Object} pHistogram - The histogram object to be sorted.
3766
+ * @returns {Object} - The sorted histogram object.
3767
+ */sortHistogramPrecise(pHistogram){let tmpSortedHistogram={};let tmpKeys=Object.keys(pHistogram);tmpKeys.sort((pLeft,pRight)=>{return pHistogram[pLeft]-pHistogram[pRight];});for(let i=0;i<tmpKeys.length;i++){tmpSortedHistogram[tmpKeys[i]]=pHistogram[tmpKeys[i]];}return tmpSortedHistogram;}/**
3768
+ * Finds the maximum value from a set of precise values.
3769
+ *
3770
+ * @param {Array|Object} pValueSet - The set of values to find the maximum from.
3771
+ * @returns {number} - The maximum value from the set.
3772
+ */maxPrecise(pValueSet){let tmpMaxValue=NaN;if(Array.isArray(pValueSet)){for(let i=0;i<pValueSet.length;i++){if(!tmpMaxValue){tmpMaxValue=this.parsePrecise(pValueSet[i],NaN);}else{let tmpComparisonValue=this.parsePrecise(pValueSet[i],NaN);if(this.gtPrecise(tmpComparisonValue,tmpMaxValue)){tmpMaxValue=tmpComparisonValue;}}}}else if(typeof pValueSet==='object'){let tmpKeys=Object.keys(pValueSet);for(let i=0;i<tmpKeys.length;i++){if(!tmpMaxValue){tmpMaxValue=this.parsePrecise(pValueSet[tmpKeys[i]],NaN);}else{let tmpComparisonValue=this.parsePrecise(pValueSet[tmpKeys[i]],NaN);if(this.gtPrecise(tmpComparisonValue,tmpMaxValue)){tmpMaxValue=tmpComparisonValue;}}}}return tmpMaxValue;}/**
3773
+ * Finds the minimum value from a set of values.
3774
+ *
3775
+ * @param {Array|Object} pValueSet - The set of values to find the minimum from.
3776
+ * @returns {number} The minimum value from the set.
3777
+ */minPrecise(pValueSet){let tmpMinValue=NaN;if(Array.isArray(pValueSet)){for(let i=0;i<pValueSet.length;i++){if(!tmpMinValue){tmpMinValue=this.parsePrecise(pValueSet[i],NaN);}else{let tmpComparisonValue=this.parsePrecise(pValueSet[i],NaN);if(!isNaN(tmpComparisonValue)&&this.ltPrecise(tmpComparisonValue,tmpMinValue)){tmpMinValue=tmpComparisonValue;}}}}else if(typeof pValueSet==='object'){let tmpKeys=Object.keys(pValueSet);for(let i=0;i<tmpKeys.length;i++){if(!tmpMinValue){tmpMinValue=this.parsePrecise(pValueSet[tmpKeys[i]],NaN);}else{let tmpComparisonValue=this.parsePrecise(pValueSet[tmpKeys[i]],NaN);if(!isNaN(tmpComparisonValue)&&this.ltPrecise(tmpComparisonValue,tmpMinValue)){tmpMinValue=tmpComparisonValue;}}}}return tmpMinValue;}/**
3778
+ * Calculates the precise sum of values in the given value set.
3779
+ *
3780
+ * @param {Array|Object} pValueSet - The value set to calculate the sum from.
3781
+ * @returns {string} The precise sum value as a string.
3782
+ */sumPrecise(pValueSet){let tmpSumValue="0.0";if(Array.isArray(pValueSet)){for(let i=0;i<pValueSet.length;i++){let tmpComparisonValue=this.parsePrecise(pValueSet[i],NaN);if(!isNaN(tmpComparisonValue)){tmpSumValue=this.addPrecise(tmpSumValue,tmpComparisonValue);}}}else if(typeof pValueSet==='object'){let tmpKeys=Object.keys(pValueSet);for(let i=0;i<tmpKeys.length;i++){let tmpComparisonValue=this.parsePrecise(pValueSet[tmpKeys[i]],NaN);if(!isNaN(tmpComparisonValue)){tmpSumValue=this.addPrecise(tmpSumValue,tmpComparisonValue);}}}return tmpSumValue;}/**
3783
+ * Calculates the precise mean of a given value set.
3784
+ *
3785
+ * @param {Array<number>} pValueSet - The array of values to calculate the mean.
3786
+ * @returns {string} The precise mean value as a string.
3787
+ */meanPrecise(pValueSet){let tmpSumValue=this.sumPrecise(pValueSet);let tmpCount=this.countSetElements(pValueSet);if(tmpCount==0){return'0.0';}return this.dividePrecise(tmpSumValue,tmpCount);}/**
3788
+ * Calculates the average of an array of values precisely.
3789
+ *
3790
+ * @param {Array<number>} pValueSet - The array of values to calculate the average of.
3791
+ * @returns {number} The precise average of the values.
3792
+ */averagePrecise(pValueSet){return this.meanPrecise(pValueSet);}/**
3793
+ * Calculates the precise median value of a given value set.
3794
+ *
3795
+ * @param {Array<number>} pValueSet - The array of values to calculate the median from.
3796
+ * @returns {number|string} - The median value of the given value set. If the value set is empty, returns '0.0'.
3797
+ */medianPrecise(pValueSet){let tmpCount=this.countSetElements(pValueSet);// If there are no elements, return 0 ... should this be NaN?
3798
+ if(tmpCount==0){return'0.0';}let tmpSortedValueSet=this.sortSetPrecise(pValueSet);let tmpMiddleElement=Math.floor(tmpCount/2);// If the count is odd, return the middle element
3799
+ if(tmpCount%2==1){return tmpSortedValueSet[tmpMiddleElement];}// If the count is even, return the average of the two middle elements
3800
+ else{let tmpLeftMiddleValue=tmpSortedValueSet[tmpMiddleElement-1];let tmpRightMiddleValue=tmpSortedValueSet[tmpMiddleElement];return this.dividePrecise(this.addPrecise(tmpLeftMiddleValue,tmpRightMiddleValue),2);}}/**
3801
+ * Calculates the mode (most frequently occurring value) of a given value set using precise mode calculation.
3802
+ *
3803
+ * @param {Array} pValueSet - The array of values to calculate the mode from.
3804
+ * @returns {Array} - An array containing the mode value(s) from the given value set.
3805
+ */modePrecise(pValueSet){let tmpHistogram=this.bucketSetPrecise(pValueSet);let tmpMaxCount=0;// Philosophical question about whether the values should be returned sorted.
3806
+ let tmpHistogramValueSet=Object.keys(tmpHistogram);let tmpModeValueSet=[];for(let i=0;i<tmpHistogramValueSet.length;i++){if(tmpHistogram[tmpHistogramValueSet[i]]>tmpMaxCount){tmpMaxCount=tmpHistogram[tmpHistogramValueSet[i]];tmpModeValueSet=[tmpHistogramValueSet[i]];}else if(tmpHistogram[tmpHistogramValueSet[i]]==tmpMaxCount){tmpModeValueSet.push(tmpHistogramValueSet[i]);}}return tmpModeValueSet;}}module.exports=FableServiceMath;},{"fable-serviceproviderbase":51}],145:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
3636
3807
  * Precedent Meta-Templating
3637
3808
  * @author Steven Velozo <steven@velozo.com>
3638
3809
  * @description Process text stream trie and postfix tree, parsing out meta-template expression functions.