fable 3.1.8 → 3.1.9

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.
Files changed (26) hide show
  1. package/dist/fable.js +97 -52
  2. package/dist/fable.js.map +1 -1
  3. package/dist/fable.min.js +2 -2
  4. package/dist/fable.min.js.map +1 -1
  5. package/package.json +1 -1
  6. package/source/Fable.js +1 -0
  7. package/source/services/Fable-Service-DataFormat.js +65 -52
  8. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ExpressionTokenizer.js +2 -2
  9. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-FunctionMap.json +24 -4
  10. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Messaging.js +3 -3
  11. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-Postfix.js +25 -10
  12. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-SolvePostfixedExpression.js +20 -30
  13. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-TokenMap.json +2 -2
  14. package/source/services/Fable-Service-ExpressionParser/Fable-Service-ExpressionParser-ValueMarshal.js +2 -0
  15. package/source/services/Fable-Service-FilePersistence.js +3 -3
  16. package/source/services/Fable-Service-Logic.js +129 -0
  17. package/source/services/Fable-Service-Math.js +49 -11
  18. package/source/services/Fable-Service-Utility.js +35 -1
  19. package/source/services/Fable-SetConcatArray.js +25 -0
  20. package/test/CSVParser_tests.js +2 -2
  21. package/test/DataFormat-StringManipulation_tests.js +17 -1
  22. package/test/ExpressionParser_tests.js +154 -8
  23. package/test/FableOperation_tests.js +2 -2
  24. package/test/FilePersistence_tests.js +2 -2
  25. package/test/Math_test.js +4 -4
  26. package/test/MetaTemplating_tests.js +4 -4
package/dist/fable.js CHANGED
@@ -3020,7 +3020,7 @@ try{if(!global.localStorage)return false;}catch(_){return false;}var val=global.
3020
3020
  // presumably different callback function.
3021
3021
  // This makes sure that own properties are retained, so that
3022
3022
  // decorations and such are not lost along the way.
3023
- module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],148:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],149:[function(require,module,exports){module.exports={"name":"fable","version":"3.1.8","description":"A service dependency injection, configuration and logging library.","main":"source/Fable.js","scripts":{"start":"node source/Fable.js","coverage":"./node_modules/.bin/nyc --reporter=lcov --reporter=text-lcov ./node_modules/mocha/bin/_mocha -- -u tdd -R spec","test":"./node_modules/.bin/mocha -u tdd -R spec","build":"npx quack build","docker-dev-build":"docker build ./ -f Dockerfile_LUXURYCode -t fable-image:local","docker-dev-run":"docker run -it -d --name fable-dev -p 30001:8080 -p 38086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/fable\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" fable-image:local","docker-dev-shell":"docker exec -it fable-dev /bin/bash","tests":"./node_modules/mocha/bin/_mocha -u tdd --exit -R spec --grep"},"mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"browser":{"./source/service/Fable-Service-EnvironmentData.js":"./source/service/Fable-Service-EnvironmentData-Web.js","./source/service/Fable-Service-FilePersistence.js":"./source/service/Fable-Service-FilePersistence-Web.js"},"repository":{"type":"git","url":"https://github.com/stevenvelozo/fable.git"},"keywords":["entity","behavior"],"author":"Steven Velozo <steven@velozo.com> (http://velozo.com/)","license":"MIT","bugs":{"url":"https://github.com/stevenvelozo/fable/issues"},"homepage":"https://github.com/stevenvelozo/fable","devDependencies":{"quackage":"^1.0.41"},"dependencies":{"async.eachlimit":"^0.5.2","async.waterfall":"^0.5.2","big.js":"^6.2.2","cachetrax":"^1.0.4","cookie":"^0.6.0","data-arithmatic":"^1.0.7","dayjs":"^1.11.13","fable-log":"^3.0.16","fable-serviceproviderbase":"^3.0.15","fable-settings":"^3.0.12","fable-uuid":"^3.0.11","http-proxy":"^1.18.1","manyfest":"^1.0.38","simple-get":"^4.0.1"}};},{}],150:[function(require,module,exports){/**
3023
+ module.exports=wrappy;function wrappy(fn,cb){if(fn&&cb)return wrappy(fn)(cb);if(typeof fn!=='function')throw new TypeError('need wrapper function');Object.keys(fn).forEach(function(k){wrapper[k]=fn[k];});return wrapper;function wrapper(){var args=new Array(arguments.length);for(var i=0;i<args.length;i++){args[i]=arguments[i];}var ret=fn.apply(this,args);var cb=args[args.length-1];if(typeof ret==='function'&&ret!==cb){Object.keys(cb).forEach(function(k){ret[k]=cb[k];});}return ret;}}},{}],148:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;}},{}],149:[function(require,module,exports){module.exports={"name":"fable","version":"3.1.9","description":"A service dependency injection, configuration and logging library.","main":"source/Fable.js","scripts":{"start":"node source/Fable.js","coverage":"./node_modules/.bin/nyc --reporter=lcov --reporter=text-lcov ./node_modules/mocha/bin/_mocha -- -u tdd -R spec","test":"./node_modules/.bin/mocha -u tdd -R spec","build":"npx quack build","docker-dev-build":"docker build ./ -f Dockerfile_LUXURYCode -t fable-image:local","docker-dev-run":"docker run -it -d --name fable-dev -p 30001:8080 -p 38086:8086 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/fable\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" fable-image:local","docker-dev-shell":"docker exec -it fable-dev /bin/bash","tests":"./node_modules/mocha/bin/_mocha -u tdd --exit -R spec --grep"},"mocha":{"diff":true,"extension":["js"],"package":"./package.json","reporter":"spec","slow":"75","timeout":"5000","ui":"tdd","watch-files":["source/**/*.js","test/**/*.js"],"watch-ignore":["lib/vendor"]},"browser":{"./source/service/Fable-Service-EnvironmentData.js":"./source/service/Fable-Service-EnvironmentData-Web.js","./source/service/Fable-Service-FilePersistence.js":"./source/service/Fable-Service-FilePersistence-Web.js"},"repository":{"type":"git","url":"https://github.com/stevenvelozo/fable.git"},"keywords":["entity","behavior"],"author":"Steven Velozo <steven@velozo.com> (http://velozo.com/)","license":"MIT","bugs":{"url":"https://github.com/stevenvelozo/fable/issues"},"homepage":"https://github.com/stevenvelozo/fable","devDependencies":{"quackage":"^1.0.41"},"dependencies":{"async.eachlimit":"^0.5.2","async.waterfall":"^0.5.2","big.js":"^6.2.2","cachetrax":"^1.0.4","cookie":"^0.6.0","data-arithmatic":"^1.0.7","dayjs":"^1.11.13","fable-log":"^3.0.16","fable-serviceproviderbase":"^3.0.15","fable-settings":"^3.0.12","fable-uuid":"^3.0.11","manyfest":"^1.0.38","simple-get":"^4.0.1"}};},{}],150:[function(require,module,exports){/**
3024
3024
  * Fable Application Services Support Library
3025
3025
  * @author <steven@velozo.com>
3026
3026
  */// Pre-init services
@@ -3045,7 +3045,7 @@ this.connectFable(this);// --> Bootstrapping of fable into the Service Manager i
3045
3045
  // Initialization Phase 2: Map in the default services.
3046
3046
  // They will then be available in the Default service provider set as well.
3047
3047
  this.connectPreinitServiceProviderInstance(this.UUID);this.connectPreinitServiceProviderInstance(this.Logging);this.connectPreinitServiceProviderInstance(this.SettingsManager);// Initialize and instantiate the default baked-in Data Arithmatic service
3048
- this.addAndInstantiateServiceType('EnvironmentData',require('./services/Fable-Service-EnvironmentData.js'));this.addServiceType('Template',require('./services/Fable-Service-Template.js'));this.addServiceType('MetaTemplate',require('./services/Fable-Service-MetaTemplate.js'));this.addServiceType('Anticipate',require('./services/Fable-Service-Anticipate.js'));this.addAndInstantiateServiceType('Dates',require('./services/Fable-Service-DateManipulation.js'));this.addAndInstantiateServiceType('DataFormat',require('./services/Fable-Service-DataFormat.js'));this.addAndInstantiateServiceType('DataGeneration',require('./services/Fable-Service-DataGeneration.js'));this.addAndInstantiateServiceType('Utility',require('./services/Fable-Service-Utility.js'));this.addAndInstantiateServiceType('Math',require('./services/Fable-Service-Math.js'));this.addServiceType('ExpressionParser',require('./services/Fable-Service-ExpressionParser.js'));this.addServiceType('RestClient',require('./services/Fable-Service-RestClient.js'));this.addServiceType('Manifest',require('manyfest'));this.addServiceType('ObjectCache',require('cachetrax'));this.addAndInstantiateServiceType('ProgressTime',require('./services/Fable-Service-ProgressTime.js'));this.addServiceType('ProgressTrackerSet',require('./services/Fable-Service-ProgressTrackerSet.js'));this.addServiceType('Operation',require('./services/Fable-Service-Operation.js'));this.addServiceType('CSVParser',require('./services/Fable-Service-CSVParser.js'));this.addServiceType('FilePersistence',require('./services/Fable-Service-FilePersistence.js'));}/* State Accessors */get isFable(){return true;}get settings(){return this.SettingsManager.settings;}get settingsManager(){return this.SettingsManager;}// For backwards compatibility
3048
+ this.addAndInstantiateServiceType('EnvironmentData',require('./services/Fable-Service-EnvironmentData.js'));this.addServiceType('Template',require('./services/Fable-Service-Template.js'));this.addServiceType('MetaTemplate',require('./services/Fable-Service-MetaTemplate.js'));this.addServiceType('Anticipate',require('./services/Fable-Service-Anticipate.js'));this.addAndInstantiateServiceType('Dates',require('./services/Fable-Service-DateManipulation.js'));this.addAndInstantiateServiceType('DataFormat',require('./services/Fable-Service-DataFormat.js'));this.addAndInstantiateServiceType('DataGeneration',require('./services/Fable-Service-DataGeneration.js'));this.addAndInstantiateServiceType('Utility',require('./services/Fable-Service-Utility.js'));this.addAndInstantiateServiceType('Logic',require('./services/Fable-Service-Logic.js'));this.addAndInstantiateServiceType('Math',require('./services/Fable-Service-Math.js'));this.addServiceType('ExpressionParser',require('./services/Fable-Service-ExpressionParser.js'));this.addServiceType('RestClient',require('./services/Fable-Service-RestClient.js'));this.addServiceType('Manifest',require('manyfest'));this.addServiceType('ObjectCache',require('cachetrax'));this.addAndInstantiateServiceType('ProgressTime',require('./services/Fable-Service-ProgressTime.js'));this.addServiceType('ProgressTrackerSet',require('./services/Fable-Service-ProgressTrackerSet.js'));this.addServiceType('Operation',require('./services/Fable-Service-Operation.js'));this.addServiceType('CSVParser',require('./services/Fable-Service-CSVParser.js'));this.addServiceType('FilePersistence',require('./services/Fable-Service-FilePersistence.js'));}/* State Accessors */get isFable(){return true;}get settings(){return this.SettingsManager.settings;}get settingsManager(){return this.SettingsManager;}// For backwards compatibility
3049
3049
  getUUID(){return this.UUID.getUUID();}newAnticipate(){return this.instantiateServiceProviderWithoutRegistration('Anticipate');}newManyfest(pManifestDefinition){return this.instantiateServiceProviderWithoutRegistration('Manifest',pManifestDefinition);}/* Service Manager Methods */addServiceType(pServiceType,pServiceClass){if(pServiceType in this.servicesMap){// TODO: Check if any services are running?
3050
3050
  this.log.warn(`Adding a service type [${pServiceType}] that already exists. This will change the default class prototype for this service.`);}else{// Add the container for instantiated services to go in
3051
3051
  this.servicesMap[pServiceType]={};// Add the type to the list of types
@@ -3078,7 +3078,7 @@ if(pServiceHash in this.servicesMap[pServiceType]){if(!(pServiceType in this)||t
3078
3078
  * @param {Date} pDate - An optional javascript Date object to generate a datestamp for.
3079
3079
  * @returns {string} - A string formatted as YYYY-MM-DD-HH-MM-SS
3080
3080
  */static generateFileNameDateStamp(pDate){const tmpDate=pDate||new Date();const tmpYear=tmpDate.getFullYear();const tmpMonth=String(tmpDate.getMonth()+1).padStart(2,'0');const tmpDay=String(tmpDate.getDate()).padStart(2,'0');const tmpHour=String(tmpDate.getHours()).padStart(2,'0');const tmpMinute=String(tmpDate.getMinutes()).padStart(2,'0');const tmpSecond=String(tmpDate.getSeconds()).padStart(2,'0');return`${tmpYear}-${tmpMonth}-${tmpDay}-${tmpHour}-${tmpMinute}-${tmpSecond}`;}}// This is for backwards compatibility
3081
- function autoConstruct(pSettings){return new Fable(pSettings);}module.exports=Fable;module.exports.new=autoConstruct;module.exports.LogProviderBase=libFableLog.LogProviderBase;module.exports.ServiceProviderBase=libFableServiceBase;module.exports.CoreServiceProviderBase=libFableServiceBase.CoreServiceProviderBase;module.exports.precedent=libFableSettings.precedent;},{"../package.json":149,"./services/Fable-Service-Anticipate.js":151,"./services/Fable-Service-CSVParser.js":152,"./services/Fable-Service-DataFormat.js":153,"./services/Fable-Service-DataGeneration.js":155,"./services/Fable-Service-DateManipulation.js":156,"./services/Fable-Service-EnvironmentData.js":157,"./services/Fable-Service-ExpressionParser.js":158,"./services/Fable-Service-FilePersistence.js":168,"./services/Fable-Service-Math.js":169,"./services/Fable-Service-MetaTemplate.js":170,"./services/Fable-Service-Operation.js":174,"./services/Fable-Service-ProgressTime.js":175,"./services/Fable-Service-ProgressTrackerSet.js":177,"./services/Fable-Service-RestClient.js":178,"./services/Fable-Service-Template.js":179,"./services/Fable-Service-Utility.js":180,"cachetrax":22,"fable-log":57,"fable-serviceproviderbase":59,"fable-settings":63,"fable-uuid":66,"manyfest":92}],151:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceAnticipate extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='AsyncAnticipate';// The queue of operations waiting to run.
3081
+ function autoConstruct(pSettings){return new Fable(pSettings);}module.exports=Fable;module.exports.new=autoConstruct;module.exports.LogProviderBase=libFableLog.LogProviderBase;module.exports.ServiceProviderBase=libFableServiceBase;module.exports.CoreServiceProviderBase=libFableServiceBase.CoreServiceProviderBase;module.exports.precedent=libFableSettings.precedent;},{"../package.json":149,"./services/Fable-Service-Anticipate.js":151,"./services/Fable-Service-CSVParser.js":152,"./services/Fable-Service-DataFormat.js":153,"./services/Fable-Service-DataGeneration.js":155,"./services/Fable-Service-DateManipulation.js":156,"./services/Fable-Service-EnvironmentData.js":157,"./services/Fable-Service-ExpressionParser.js":158,"./services/Fable-Service-FilePersistence.js":168,"./services/Fable-Service-Logic.js":169,"./services/Fable-Service-Math.js":170,"./services/Fable-Service-MetaTemplate.js":171,"./services/Fable-Service-Operation.js":175,"./services/Fable-Service-ProgressTime.js":176,"./services/Fable-Service-ProgressTrackerSet.js":178,"./services/Fable-Service-RestClient.js":179,"./services/Fable-Service-Template.js":180,"./services/Fable-Service-Utility.js":181,"cachetrax":22,"fable-log":57,"fable-serviceproviderbase":59,"fable-settings":63,"fable-uuid":66,"manyfest":92}],151:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceAnticipate extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='AsyncAnticipate';// The queue of operations waiting to run.
3082
3082
  this.operationQueue=[];this.erroredOperations=[];this.executingOperationCount=0;this.completedOperationCount=0;this.callDepth=0;this.maxOperations=1;this.lastError=undefined;this.waitingFunctions=[];}checkQueue(){// This could be combined with the last else if stanza but the logic for errors and non-errors would be blended and more complex to follow so keeping it unrolled.
3083
3083
  if(this.lastError){// If there are no operations left, and we have waiting functions, call them.
3084
3084
  for(let i=0;i<this.waitingFunctions.length;i++){//this.log.trace('Calling waiting function.')
@@ -3136,7 +3136,7 @@ if(this.EmitHeader){return this.Header;}else{return false;}}else{return this.emi
3136
3136
  this._Regex_formatterInsertCommas=/.{1,3}/g;// Match Function:
3137
3137
  // function(pMatch, pSign, pZeros, pBefore, pDecimal, pAfter)
3138
3138
  // Thoughts about below: /^([+-]?)(0*)(\d+)(\.(\d+))?$/;
3139
- this._Regex_formatterAddCommasToNumber=/^([-+]?)(0?)(\d+)(.?)(\d+)$/g;this._Regex_formatterDollarsRemoveCommas=/,/gi;this._Regex_formatterCleanNonAlphaChar=/[^a-zA-Z]/gi;this._Regex_formatterCapitalizeEachWord=/([a-zA-Z]+)/g;// TODO: Potentially pull these in from a configuration.
3139
+ this._Regex_formatterAddCommasToNumber=/^([-+]?)(0?)(\d+)(.?)(\d+)$/g;this._Regex_formatterDollarsRemoveCommas=/,/gi;this._Regex_formatterCleanNonAlphaChar=/[^a-zA-Z]/gi;this._Regex_formatterCapitalizeEachWord=/([a-zA-Z]+)/g;this._Regex_matcherHTMLEntities=/&(#?[a-zA-Z0-9]+);/g;// TODO: Potentially pull these in from a configuration.
3140
3140
  // TODO: Use locale data for this if it's defaults all the way down.
3141
3141
  this._Value_MoneySign_Currency='$';this._Value_NaN_Currency='--';this._Value_GroupSeparator_Number=',';this._Value_Prefix_StringHash='HSH';this._Value_Clean_formatterCleanNonAlpha='';this._UseEngineStringStartsWith=typeof String.prototype.startsWith==='function';this._UseEngineStringEndsWith=typeof String.prototype.endsWith==='function';}/*************************************************************************
3142
3142
  * String Manipulation and Comparison Functions
@@ -3182,6 +3182,9 @@ if(!(pEndIndex<this.length)){pEndIndex=this.length;}else{pEndIndex|=0;// round p
3182
3182
  * @param {string} pString
3183
3183
  * @returns {string}
3184
3184
  */insecureStringHash(pString){let tmpHash=0;let tmpStringLength=pString.length;let tmpCharacterIndex=0;while(tmpCharacterIndex<tmpStringLength){tmpHash=(tmpHash<<5)-tmpHash+pString.charCodeAt(tmpCharacterIndex++)|0;}return`${this._Value_Prefix_StringHash}${tmpHash}`;}capitalizeEachWord(pString){return pString.replace(this._Regex_formatterCapitalizeEachWord,pMatch=>{return pMatch.charAt(0).toUpperCase()+pMatch.substr(1);});}/**
3185
+ * @param {string} pString - The string to resolve
3186
+ * @return {string} - The input string with all HTML entities resolved to their character counterparts
3187
+ */resolveHtmlEntities(pString){if(typeof pString!=='string'){return pString;}return pString.replace(this._Regex_matcherHTMLEntities,(pMatch,pEntity)=>{switch(pEntity){case'comma':return',';case'amp':return'&';case'lt':return'<';case'gt':return'>';case'times':return'×';case'divide':return'÷';case'plus':return'+';case'minus':return'-';case'infin':return'∞';case'ang':return'∠';case'quot':return'"';case'apos':return'\'';case'nbsp':return' ';case'copy':return'©';case'reg':return'®';case'trade':return'™';case'euro':return'€';default:if(!pEntity.startsWith('#')){return pMatch;}}const tmpNumericalValue=parseInt(pEntity.substring(1),10);return String.fromCharCode(tmpNumericalValue);});}/**
3185
3188
  * Concatenate a list of strings together. Non-strings are excluded.
3186
3189
  *
3187
3190
  * @param {...string} pStrings - The strings to concatenate
@@ -3191,7 +3194,7 @@ if(!(pEndIndex<this.length)){pEndIndex=this.length;}else{pEndIndex|=0;// round p
3191
3194
  *
3192
3195
  * @param {...any} pParams - Any number of parameters
3193
3196
  * @return {string}
3194
- */concatenateStringsInternal(){const pParams=[...arguments];const tmpArrayFlattener=p=>{if(Array.isArray(p)){return p.flatMap(tmpArrayFlattener);}if(typeof p==='object'){return Object.values(p);}return[p];};const tmpFlattenedArrays=pParams.flatMap(tmpArrayFlattener);return this.concatenateStrings(...tmpFlattenedArrays);}/**
3197
+ */concatenateStringsInternal(){const pParams=[...arguments];const tmpFlattenedArrays=this.fable.Utility.flattenArrayOfSolverInputs(pParams);return this.concatenateStrings(...tmpFlattenedArrays);}/**
3195
3198
  * Join a list of strings together. Non-strings are excluded.
3196
3199
  *
3197
3200
  * @param {string} pJoin - The string to join with
@@ -3203,7 +3206,7 @@ if(!(pEndIndex<this.length)){pEndIndex=this.length;}else{pEndIndex|=0;// round p
3203
3206
  * @param {string} pJoin - The string to join with
3204
3207
  * @param {...any} pParams - Any number of parameters
3205
3208
  * @return {string}
3206
- */joinStringsInternal(){const[pJoinOn,...pParams]=arguments;const tmpArrayFlattener=p=>{if(Array.isArray(p)){return p.flatMap(tmpArrayFlattener);}if(typeof p==='object'){return Object.values(p);}return[p];};const tmpFlattenedArrays=pParams.flatMap(tmpArrayFlattener);return this.joinStrings(pJoinOn,...tmpFlattenedArrays);}/**
3209
+ */joinStringsInternal(){const[pJoinOn,...pParams]=arguments;const tmpFlattenedArrays=this.fable.Utility.flattenArrayOfSolverInputs(pParams);return this.joinStrings(pJoinOn,...tmpFlattenedArrays);}/**
3207
3210
  * Concatenate a list of values together into a string.
3208
3211
  *
3209
3212
  * @param {...any} pValues - The strings to concatenate
@@ -3213,7 +3216,7 @@ if(!(pEndIndex<this.length)){pEndIndex=this.length;}else{pEndIndex|=0;// round p
3213
3216
  *
3214
3217
  * @param {...any} pParams - Any number of parameters
3215
3218
  * @return {string}
3216
- */concatenateStringsRawInternal(pValueObjectSetAddress){const pParams=[...arguments];const tmpArrayFlattener=p=>{if(Array.isArray(p)){return p.flatMap(tmpArrayFlattener);}if(typeof p==='object'){return Object.values(p);}return[p];};const tmpFlattenedArrays=pParams.flatMap(tmpArrayFlattener);return this.concatenateStringsRaw(...tmpFlattenedArrays);}/**
3219
+ */concatenateStringsRawInternal(pValueObjectSetAddress){const pParams=[...arguments];const tmpFlattenedArrays=this.fable.Utility.flattenArrayOfSolverInputs(pParams);return this.concatenateStringsRaw(...tmpFlattenedArrays);}/**
3217
3220
  * Join a list of values together into a string.
3218
3221
  *
3219
3222
  * @param {string} pJoin - The string to join with
@@ -3225,7 +3228,7 @@ if(!(pEndIndex<this.length)){pEndIndex=this.length;}else{pEndIndex|=0;// round p
3225
3228
  * @param {string} pJoin - The string to join with
3226
3229
  * @param {...any} pParams - Any number of parameters
3227
3230
  * @return {string}
3228
- */joinStringsRawInternal(){const[pJoinOn,...pParams]=arguments;const tmpArrayFlattener=p=>{if(Array.isArray(p)){return p.flatMap(tmpArrayFlattener);}if(typeof p==='object'){return Object.values(p);}return[p];};const tmpFlattenedArrays=pParams.flatMap(tmpArrayFlattener);return this.joinStringsRaw(pJoinOn,...tmpFlattenedArrays);}/**
3231
+ */joinStringsRawInternal(){const[pJoinOn,...pParams]=arguments;const tmpFlattenedArrays=this.fable.Utility.flattenArrayOfSolverInputs(pParams);return this.joinStringsRaw(pJoinOn,...tmpFlattenedArrays);}/**
3229
3232
  * Clean wrapping characters if they exist consistently around the string. If they do not, the string is returned unchanged.
3230
3233
  *
3231
3234
  * @param {string} pWrapCharacter - The character expected as the wrapping character
@@ -3615,8 +3618,8 @@ return this.solvePostfixedExpression(tmpResultsObject.PostfixSolveList,tmpDataDe
3615
3618
  * - String
3616
3619
  * : Wrapped in double quotes e.g. "Hello World", "This is a test", etc.
3617
3620
  */let tmpCurrentTokenType=false;let tmpCurrentToken='';for(let i=0;i<pExpression.length;i++){let tmpCharacter=pExpression[i];// [ WHITESPACE ]
3618
- // 1. Space breaks tokens except when we're in an address that's been scoped by a {}
3619
- if(tmpCharacter===' '&&tmpCurrentTokenType!=='StateAddress'&&tmpCurrentTokenType!=='String'){if(tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}tmpCurrentToken='';tmpCurrentTokenType=false;continue;}// [ STATE ADDRESS AND STRING BLOCKS ]
3621
+ // 1. Space breaks tokens except when we're in an address that's been scoped by a {} or ""
3622
+ if((tmpCharacter===' '||tmpCharacter==='\t')&&tmpCurrentTokenType!=='StateAddress'&&tmpCurrentTokenType!=='String'){if(tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}tmpCurrentToken='';tmpCurrentTokenType=false;continue;}// [ STATE ADDRESS AND STRING BLOCKS ]
3620
3623
  // 2. If we're in an address, we keep going until we hit the closing brace
3621
3624
  if(tmpCurrentTokenType==='StateAddress'&&tmpCharacter!=='}'){tmpCurrentToken+=tmpCharacter;continue;}if(tmpCurrentTokenType==='String'&&tmpCharacter!=='"'){tmpCurrentToken+=tmpCharacter;continue;}// 3. If we're in an address and we hit the closing brace, we close the token, push it and reset
3622
3625
  if(tmpCurrentTokenType==='StateAddress'&&tmpCharacter==='}'){tmpCurrentToken+=tmpCharacter;tmpResults.RawTokens.push(tmpCurrentToken);tmpCurrentToken='';tmpCurrentTokenType=false;continue;}if(tmpCurrentTokenType==='String'&&tmpCharacter==='"'){tmpCurrentToken+=tmpCharacter;tmpResults.RawTokens.push(tmpCurrentToken);tmpCurrentToken='';tmpCurrentTokenType=false;continue;}// 4. If we're not in an address and we hit a closing brace it's a problem
@@ -3652,7 +3655,7 @@ tmpCurrentTokenType='Value';tmpCurrentToken+=tmpCharacter;// continue;
3652
3655
  // }
3653
3656
  // tmpResults.ExpressionParserLog.push(`ExpressionParser.tokenize found an unknown character code ${tmpCharCode} character ${tmpCharacter} in the expression: ${pExpression} at index ${i}`);
3654
3657
  // this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);
3655
- }if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":159}],161:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"percent":{"Name":"Compute Percent (in IS over OF format)","Address":"fable.Math.percentagePrecise"},"compare":{"Name":"Compare","Address":"fable.Math.comparePrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"floor":{"Name":"Floor Value","Address":"fable.Math.floorPrecise"},"ceil":{"Name":"Ceiling Value","Address":"fable.Math.ceilPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"euler":{"Name":"Euler","Address":"fable.Math.eulerPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"},"cos":{"Name":"Cosine","Address":"fable.Math.cos"},"tan":{"Name":"Tangent","Address":"fable.Math.tan"},"count":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"countset":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"max":{"Name":"Maximum","Address":"fable.Math.maxPrecise"},"min":{"Name":"Minimum","Address":"fable.Math.minPrecise"},"sum":{"Name":"Sum","Address":"fable.Math.sumPrecise"},"avg":{"Name":"Average","Address":"fable.Math.averagePrecise"},"mean":{"Name":"Mean","Address":"fable.Math.meanPrecise"},"median":{"Name":"Median","Address":"fable.Math.medianPrecise"},"mode":{"Name":"Mode","Address":"fable.Math.modePrecise"},"round":{"Name":"Round","Address":"fable.Math.roundPrecise"},"tofixed":{"Name":"To Fixed","Address":"fable.Math.toFixedPrecise"},"cumulativesummation":{"Name":"Count Set Elements in a Histogram or Value Map","Address":"fable.Math.cumulativeSummation"},"countsetelements":{"Name":"Count Set Elements in a Histogram or Value Map","Address":"fable.Math.countSetElements"},"getvalue":{"Name":"Get Value from Application State or Services (AppData, etc.)","Address":"fable.Utility.getInternalValueByHash"},"findfirstvaluebyexactmatch":{"Name":"find + map on array of objects?","Address":"fable.Utility.findFirstValueByExactMatchInternal"},"findfirstvaluebystringincludes":{"Name":"find + map on array of objects?","Address":"fable.Utility.findFirstValueByStringIncludesInternal"},"concat":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsInternal"},"concatraw":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsRawInternal"},"join":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsInternal"},"joinraw":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsRawInternal"},"entryinset":{"Name":"Entry in Set","Address":"fable.Math.entryInSet"},"smallestInSet":{"Name":"Smallest in Set","Address":"fable.Math.smallestInSet"},"largestInSet":{"Name":"Largest in Set","Address":"fable.Math.largestInSet"},"aggregationhistogram":{"Name":"Generate a Histogram by Exact Value Aggregation","Address":"fable.Math.histogramAggregationByExactValueFromInternalState"},"distributionhistogram":{"Name":"Generate a Histogram Based on Value Distribution","Address":"fable.Math.histogramDistributionByExactValueFromInternalState"},"setconcatenate":{"Name":"Set Concatenate","Address":"fable.Math.setConcatenate"},"getvaluearray":{"Name":"Get Value Array from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueArrayByHashParametersFromInternal"},"getvalueobject":{"Name":"Get Value Object from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueObjectByHashParametersFromInternal"},"cleanvaluearray":{"Name":"Clean Value Array","Address":"fable.Math.cleanValueArray"},"cleanvalueobject":{"Name":"Clean Value Object","Address":"fable.Math.cleanValueObject"},"randominteger":{"Name":"Random Integer","Address":"fable.DataGeneration.randomInteger"},"randomintegerbetween":{"Name":"Random Integer Between Two Numbers","Address":"fable.DataGeneration.randomIntegerBetween"},"randomintegerupto":{"Name":"Random Integer","Address":"fable.DataGeneration.randomIntegerUpTo"},"randomfloat":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloat"},"randomfloatbetween":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatBetween"},"randomfloatupto":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatUpTo"},"datedaydifference":{"Name":"Date Difference in Days","Address":"fable.Dates.dateDayDifference"},"dateweekdifference":{"Name":"Date Difference in Weeks","Address":"fable.Dates.dateWeekDifference"},"datemonthdifference":{"Name":"Date Difference in Months","Address":"fable.Dates.dateMonthDifference"},"dateyeardifference":{"Name":"Date Difference in Years","Address":"fable.Dates.dateYearDifference"},"createValueObjectByHashes":{"Name":"Create Value Object by Hashes","Address":"fable.Utility.createValueObjectByHashes"}};},{}],162:[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
3658
+ }if(tmpCurrentTokenType&&tmpCurrentToken.length>0){tmpResults.RawTokens.push(tmpCurrentToken);}return tmpResults.RawTokens;}}module.exports=ExpressionTokenizer;},{"./Fable-Service-ExpressionParser-Base.js":159}],161:[function(require,module,exports){module.exports={"sqrt":{"Name":"Square Root","Address":"fable.Math.sqrtPrecise"},"percent":{"Name":"Compute Percent (in IS over OF format)","Address":"fable.Math.percentagePrecise"},"compare":{"Name":"Compare","Address":"fable.Math.comparePrecise"},"abs":{"Name":"Absolute Value","Address":"fable.Math.absPrecise"},"floor":{"Name":"Floor Value","Address":"fable.Math.floorPrecise"},"ceil":{"Name":"Ceiling Value","Address":"fable.Math.ceilPrecise"},"rad":{"Name":"Degrees to Radians","Address":"fable.Math.radPrecise"},"pi":{"Name":"Pi","Address":"fable.Math.piPrecise"},"euler":{"Name":"Euler","Address":"fable.Math.eulerPrecise"},"sin":{"Name":"Sine","Address":"fable.Math.sin"},"cos":{"Name":"Cosine","Address":"fable.Math.cos"},"tan":{"Name":"Tangent","Address":"fable.Math.tan"},"count":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"countset":{"Name":"Count Set Elements","Address":"fable.Math.countSetElements"},"sortset":{"Name":"Sort Set","Address":"fable.Math.sortSetPrecise"},"bucketset":{"Name":"Bucket Set","Address":"fable.Math.bucketSetPrecise"},"sorthistogram":{"Name":"Sort Histogram","Address":"fable.Math.sortHistogramPrecise"},"max":{"Name":"Maximum","Address":"fable.Math.maxPrecise"},"min":{"Name":"Minimum","Address":"fable.Math.minPrecise"},"sum":{"Name":"Sum","Address":"fable.Math.sumPrecise"},"avg":{"Name":"Average","Address":"fable.Math.averagePrecise"},"mean":{"Name":"Mean","Address":"fable.Math.meanPrecise"},"median":{"Name":"Median","Address":"fable.Math.medianPrecise"},"mode":{"Name":"Mode","Address":"fable.Math.modePrecise"},"round":{"Name":"Round","Address":"fable.Math.roundPrecise"},"tofixed":{"Name":"To Fixed","Address":"fable.Math.toFixedPrecise"},"cumulativesummation":{"Name":"Count Set Elements in a Histogram or Value Map","Address":"fable.Math.cumulativeSummation"},"countsetelements":{"Name":"Count Set Elements in a Histogram or Value Map","Address":"fable.Math.countSetElements"},"getvalue":{"Name":"Get Value from Application State or Services (AppData, etc.)","Address":"fable.Utility.getInternalValueByHash"},"flatten":{"Name":"flatten an array of values","Address":"fable.Utility.flattenArrayOfSolverInputs"},"findfirstvaluebyexactmatch":{"Name":"find + map on array of objects","Address":"fable.Utility.findFirstValueByExactMatchInternal"},"findfirstvaluebystringincludes":{"Name":"find + map on array of objects","Address":"fable.Utility.findFirstValueByStringIncludesInternal"},"resolvehtmlentities":{"Name":"resolve HTML entities","Address":"fable.Utility.resolveHtmlEntities"},"concat":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsInternal"},"concatraw":{"Name":"concatenate an array of values and output a string","Address":"fable.DataFormat.concatenateStringsRawInternal"},"join":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsInternal"},"joinraw":{"Name":"join an array of values and output a string","Address":"fable.DataFormat.joinStringsRawInternal"},"if":{"Name":"perform a conditional operator on two values, and choose one of two outcomes based on the result","Address":"fable.Logic.checkIf"},"when":{"Name":"perform a 'truthy' check on one value, and return one of two outcomes based on the result","Address":"fable.Logic.when"},"entryinset":{"Name":"Entry in Set","Address":"fable.Math.entryInSet"},"smallestinset":{"Name":"Smallest in Set","Address":"fable.Math.smallestInSet"},"largestinset":{"Name":"Largest in Set","Address":"fable.Math.largestInSet"},"aggregationhistogram":{"Name":"Generate a Histogram by Exact Value Aggregation","Address":"fable.Math.histogramAggregationByExactValueFromInternalState"},"distributionhistogram":{"Name":"Generate a Histogram Based on Value Distribution","Address":"fable.Math.histogramDistributionByExactValueFromInternalState"},"setconcatenate":{"Name":"Set Concatenate","Address":"fable.Math.setConcatenate"},"getvaluearray":{"Name":"Get Value Array from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueArrayByHashParametersFromInternal"},"getvalueobject":{"Name":"Get Value Object from Application State or Services (AppData, etc.)","Address":"fable.Utility.createValueObjectByHashParametersFromInternal"},"cleanvaluearray":{"Name":"Clean Value Array","Address":"fable.Math.cleanValueArray"},"cleanvalueobject":{"Name":"Clean Value Object","Address":"fable.Math.cleanValueObject"},"randominteger":{"Name":"Random Integer","Address":"fable.DataGeneration.randomInteger"},"randomintegerbetween":{"Name":"Random Integer Between Two Numbers","Address":"fable.DataGeneration.randomIntegerBetween"},"randomintegerupto":{"Name":"Random Integer","Address":"fable.DataGeneration.randomIntegerUpTo"},"randomfloat":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloat"},"randomfloatbetween":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatBetween"},"randomfloatupto":{"Name":"Random Float","Address":"fable.DataGeneration.randomFloatUpTo"},"datedaydifference":{"Name":"Date Difference in Days","Address":"fable.Dates.dateDayDifference"},"dateweekdifference":{"Name":"Date Difference in Weeks","Address":"fable.Dates.dateWeekDifference"},"datemonthdifference":{"Name":"Date Difference in Months","Address":"fable.Dates.dateMonthDifference"},"dateyeardifference":{"Name":"Date Difference in Years","Address":"fable.Dates.dateYearDifference"},"createValueObjectByHashes":{"Name":"Create Value Object by Hashes","Address":"fable.Utility.createValueObjectByHashes"}};},{}],162:[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
3656
3659
  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
3657
3660
  let tmpParenthesisDepth=0;// If it is in a state address, we don't care about the parenthesis
3658
3661
  // State addresses are between squiggly brackets
@@ -3675,11 +3678,11 @@ if(pTokenizedExpression[i]!=='+'&&pTokenizedExpression[i]!=='-'){tmpResults.Expr
3675
3678
  * Represents a user-friendly messaging service for the ExpressionParser compiler output.
3676
3679
  * @class ExpressionParserMessaging
3677
3680
  * @extends libExpressionParserOperationBase
3678
- */class ExpressionParserMessaging extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Messaging';}getOperationVirtualSymbolName(pOperationToken){return pOperationToken&&'VirtualSymbolName'in pOperationToken?pOperationToken.VirtualSymbolName:pOperationToken.Type==='Token.VirtualSymbol'?pOperationToken.Token:'NO_VIRTUAL_SYMBOL_NAME_FOUND';}getVirtualTokenValue(pToken,pOperationResults){let tmpVirtualSymbol=this.getOperationVirtualSymbolName(pToken);if(pToken.Type=='Token.Constant'&&pToken.Value){return pToken.Value.toString();}let tmpVirtualSymbolData='VirtualSymbols'in pOperationResults?pOperationResults.VirtualSymbols:{};if(this.ExpressionParser.GenericManifest.checkAddressExists(tmpVirtualSymbolData,tmpVirtualSymbol)){let tmpValue=this.ExpressionParser.GenericManifest.getValueAtAddress(tmpVirtualSymbolData,tmpVirtualSymbol);if(typeof tmpValue==='object'){return`{${Object.keys(tmpValue).length} values}`;}if(Array.isArray(tmpValue)){return`[${Object.keys(tmpValue).length} values]`;}return tmpValue;}return'NO_VALUE_FOUND';}getTokenAddressString(pToken){return pExpression.Token;}getTokenSymbolString(pExpressionToken){return pExpressionToken.Token;}getOperationSymbolMessage(pOperation){if(!pOperation){return'INVALID_OPERATION';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pOperation);let tmpOperationLeftValue=this.getTokenSymbolString(pOperation.LeftValue);let tmpOperationSymbol=this.getTokenSymbolString(pOperation.Operation);let tmpOperationRightValue=this.getTokenSymbolString(pOperation.RightValue);let tmpVirtualSymbolPrefix=tmpOperationVirtualSymbol.substring(0,3);if(tmpOperationSymbol==='='){// Assignment operators are special
3681
+ */class ExpressionParserMessaging extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-Messaging';}getOperationVirtualSymbolName(pOperationToken){return pOperationToken&&'VirtualSymbolName'in pOperationToken?pOperationToken.VirtualSymbolName:pOperationToken.Type==='Token.VirtualSymbol'?pOperationToken.Token:'NO_VIRTUAL_SYMBOL_NAME_FOUND';}getVirtualTokenValue(pToken,pOperationResults){let tmpVirtualSymbol=this.getOperationVirtualSymbolName(pToken);if((pToken.Type=='Token.Symbol'||pToken.Type=='Token.Constant')&&pToken.Value){return pToken.Value.toString();}let tmpVirtualSymbolData='VirtualSymbols'in pOperationResults?pOperationResults.VirtualSymbols:{};if(this.ExpressionParser.GenericManifest.checkAddressExists(tmpVirtualSymbolData,tmpVirtualSymbol)){let tmpValue=this.ExpressionParser.GenericManifest.getValueAtAddress(tmpVirtualSymbolData,tmpVirtualSymbol);if(typeof tmpValue==='object'){return`{${Object.keys(tmpValue).length} values}`;}if(Array.isArray(tmpValue)){return`[${Object.keys(tmpValue).length} values]`;}return tmpValue;}return'NO_VALUE_FOUND';}getTokenAddressString(pToken){return pExpression.Token;}getTokenSymbolString(pExpressionToken){return pExpressionToken.Token;}getOperationSymbolMessage(pOperation){if(!pOperation){return'INVALID_OPERATION';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pOperation);let tmpOperationLeftValue=this.getTokenSymbolString(pOperation.LeftValue);let tmpOperationSymbol=this.getTokenSymbolString(pOperation.Operation);let tmpOperationRightValue=this.getTokenSymbolString(pOperation.RightValue);let tmpVirtualSymbolPrefix=tmpOperationVirtualSymbol.substring(0,3);if(tmpOperationSymbol==='='){// Assignment operators are special
3679
3682
  return`${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue}`;}if(tmpVirtualSymbolPrefix==='VFE'){// Virtual Function Expression
3680
3683
  return`${tmpOperationVirtualSymbol} = ${tmpOperationSymbol}(${tmpOperationLeftValue})`;}return`${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue} ${tmpOperationSymbol} ${tmpOperationRightValue}`;}getOperationValueMessage(pOperation,pResultObject){if(!pOperation){return'INVALID_OPERATION';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pOperation);let tmpOperationLeftValue=this.getVirtualTokenValue(pOperation.LeftValue,pResultObject);let tmpOperationSymbol=this.getTokenSymbolString(pOperation.Operation);let tmpOperationRightValue=this.getVirtualTokenValue(pOperation.RightValue,pResultObject);let tmpVirtualSymbolPrefix=tmpOperationVirtualSymbol.substring(0,3);if(tmpOperationSymbol==='='){// Assignment operators are special
3681
3684
  return`${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue}`;}if(tmpVirtualSymbolPrefix==='VFE'){// Virtual Function Expression
3682
- return`${tmpOperationVirtualSymbol} = ${tmpOperationSymbol}(${tmpOperationLeftValue})`;}return`${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue} ${tmpOperationSymbol} ${tmpOperationRightValue}`;}getOperationOutcomeMessage(pToken,pOperationResults){if(!pToken){return'INVALID_TOKEN';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pToken);let tmpOperationOutcomeValue=this.getVirtualTokenValue(pToken,pOperationResults);return`${tmpOperationVirtualSymbol} = ${tmpOperationOutcomeValue}`;}logFunctionOutcome(pResultObject){if(typeof pResultObject!=='object'){this.log.error(`Solver results object was not an object. Cannot log outcome.`);return;}let tmpAssignmentAddress='PostfixedAssignmentAddress'in pResultObject?pResultObject.PostfixedAssignmentAddress:'NO_ASSIGNMENT_ADDRESS_FOUND';let tmpRawExpression='RawExpression'in pResultObject?pResultObject.RawExpression:'NO_EXPRESSION_FOUND';let tmpRawResult='RawResult'in pResultObject?pResultObject.RawResult:'NO_RESULT_FOUND';this.log.info(`Solved f(${tmpAssignmentAddress}) = {${tmpRawExpression}}`);for(let i=0;i<pResultObject.PostfixSolveList.length;i++){let tmpToken=pResultObject.PostfixSolveList[i];let tmpTokenSymbolMessage=this.getOperationSymbolMessage(tmpToken);this.log.info(`${i} Symbols: ${tmpTokenSymbolMessage}`);let tmpTokenValueMessage=this.getOperationValueMessage(tmpToken,pResultObject);this.log.info(`${i} Values: ${tmpTokenValueMessage}`);let tmpTokenOutcome=this.getOperationOutcomeMessage(tmpToken,pResultObject);this.log.info(`${i} Outcome: ${tmpTokenOutcome}`);}this.log.info(`{${tmpRawExpression}} = ${tmpRawResult}`);}logFunctionSolve(pResultObject){if(typeof pResultObject!=='object'){this.log.error(`Solver results object was not an object. Cannot log the solve.`);return;}if(!('PostfixSolveList'in pResultObject)||!Array.isArray(pResultObject.PostfixSolveList)){this.log.error(`Solver results object did not contain a PostfixSolveList array. Cannot log the solve.`);return;}for(let i=0;i<tmpExpressionParseOutcome.PostfixSolveList.length;i++){let tmpToken=tmpExpressionParseOutcome.PostfixSolveList[i];console.log(`${i}: ${tmpToken.VirtualSymbolName} = (${tmpToken.LeftValue.Token}::${tmpToken.LeftValue.Value}) ${tmpToken.Operation.Token} (${tmpToken.RightValue.Token}::${tmpToken.RightValue.Value}) `);}this.logFunctionOutcome(pResultObject);}}module.exports=ExpressionParserMessaging;},{"./Fable-Service-ExpressionParser-Base.js":159,"big.js":17}],164:[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
3685
+ return`${tmpOperationVirtualSymbol} = ${tmpOperationSymbol}(${tmpOperationLeftValue})`;}return`${tmpOperationVirtualSymbol} = ${tmpOperationLeftValue} ${tmpOperationSymbol} ${tmpOperationRightValue}`;}getOperationOutcomeMessage(pToken,pOperationResults){if(!pToken){return'INVALID_TOKEN';}let tmpOperationVirtualSymbol=this.getOperationVirtualSymbolName(pToken);let tmpOperationOutcomeValue=this.getVirtualTokenValue(pToken,pOperationResults);return`${tmpOperationVirtualSymbol} = ${tmpOperationOutcomeValue}`;}logFunctionOutcome(pResultObject){if(typeof pResultObject!=='object'){this.log.error(`Solver results object was not an object. Cannot log outcome.`);return;}let tmpAssignmentAddress='PostfixedAssignmentAddress'in pResultObject?pResultObject.PostfixedAssignmentAddress:'NO_ASSIGNMENT_ADDRESS_FOUND';let tmpRawExpression='RawExpression'in pResultObject?pResultObject.RawExpression:'NO_EXPRESSION_FOUND';let tmpRawResult='RawResult'in pResultObject?pResultObject.RawResult:'NO_RESULT_FOUND';this.log.info(`Solved f(${tmpAssignmentAddress}) = {${tmpRawExpression}}`);for(let i=0;i<pResultObject.PostfixSolveList.length;i++){let tmpToken=pResultObject.PostfixSolveList[i];let tmpTokenSymbolMessage=this.getOperationSymbolMessage(tmpToken);this.log.info(`${i} Symbols: ${tmpTokenSymbolMessage}`);let tmpTokenValueMessage=this.getOperationValueMessage(tmpToken,pResultObject);this.log.info(`${i} Values: ${tmpTokenValueMessage}`);let tmpTokenOutcome=this.getOperationOutcomeMessage(tmpToken,pResultObject);this.log.info(`${i} Outcome: ${tmpTokenOutcome}`);}this.log.info(`{${tmpRawExpression}} = ${tmpRawResult}`);}logFunctionSolve(pResultObject){if(typeof pResultObject!=='object'){this.log.error(`Solver results object was not an object. Cannot log the solve.`);return;}if(!('PostfixSolveList'in pResultObject)||!Array.isArray(pResultObject.PostfixSolveList)){this.log.error(`Solver results object did not contain a PostfixSolveList array. Cannot log the solve.`);return;}for(let i=0;i<pResultObject.PostfixSolveList.length;i++){let tmpToken=pResultObject.PostfixSolveList[i];console.log(`${i}: ${tmpToken.VirtualSymbolName} = (${tmpToken.LeftValue.Token}::${tmpToken.LeftValue.Value}) ${tmpToken.Operation.Token} (${tmpToken.RightValue.Token}::${tmpToken.RightValue.Value}) `);}this.logFunctionOutcome(pResultObject);}}module.exports=ExpressionParserMessaging;},{"./Fable-Service-ExpressionParser-Base.js":159,"big.js":17}],164:[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
3683
3686
  * way to deal with recursion that can be expressed to the user in
3684
3687
  * a meaningful way.
3685
3688
  *
@@ -3727,20 +3730,26 @@ if(tmpSolveLayerMap[pLeftLayer][0].Depth<tmpSolveLayerMap[pRightLayer][0].Depth)
3727
3730
  // 5.1 Build the Virtual Symbol Names
3728
3731
  // This maps layer stack addresses (which match parenthesis virtual symbol names) to the resultant value for that layer stack.
3729
3732
  // These values change as it solves but the last assignment is the proper assignment because math only reads forward in a line
3730
- tmpResults.PostfixLayerstackMap={};for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];// For each precedence (this isn't strictly required here but makes the outcome for the user more readable)
3733
+ tmpResults.PostfixLayerstackMap={};//FIXME: vet these - do we need a suffix version?
3734
+ const unaryEligibleOperationTokens=['+','-'];const unaryOperationPrefixTriggerTypes=['Token.Operator','Token.Assignment'];for(let tmpSolveLayerIndex=0;tmpSolveLayerIndex<tmpSolveLayerKeys.length;tmpSolveLayerIndex++){let tmpSolveLayerTokens=tmpSolveLayerMap[tmpSolveLayerKeys[tmpSolveLayerIndex]];// For each precedence (this isn't strictly required here but makes the outcome for the user more readable)
3731
3735
  for(let tmpPrecedence=0;tmpPrecedence<=this.ExpressionParser.tokenMaxPrecedence;tmpPrecedence++){// Enumerate all tokens in a layer's expression.
3732
3736
  // There is a recursive way to do this, but given the short length of even the most complex equations we're favoring readability.
3733
- 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.
3734
- if(tmpSolveLayerTokens[i].Type==='Token.Operator'&&tmpSolveLayerTokens[i].Descriptor.Precedence===tmpPrecedence){let tmpToken=tmpSolveLayerTokens[i];// If there is a token and nothing else in this layer, then it's an error.
3735
- if(tmpSolveLayerTokens.length===1){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.buildPostfixedSolveList found a single operator in a solve layer expression at token index ${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.
3737
+ for(let i=0;i<tmpSolveLayerTokens.length;i++){const tmpToken=tmpSolveLayerTokens[i];if(unaryEligibleOperationTokens.includes(tmpToken.Token)&&(// promote to unary if:
3738
+ // 1. we are the first token in our group
3739
+ // 2. we are prefixed by a token type that is incompatible with us being binary
3740
+ i==0||unaryOperationPrefixTriggerTypes.includes(tmpSolveLayerTokens[i-1].Type))){//FIXME: slow, but don't break the static data
3741
+ tmpToken.Descriptor=JSON.parse(JSON.stringify(tmpToken.Descriptor));tmpToken.Descriptor.Precedence=1;}//FIXME: handle operators with dynamic precedence (ex. unary vs. bunary + and -)
3742
+ // If the token is an operator and at the current precedence, add it to the postfix solve list and mutate the array.
3743
+ if(tmpSolveLayerTokens[i].Type==='Token.Operator'&&tmpToken.Descriptor.Precedence===tmpPrecedence){// If there is a token and nothing else in this layer, then it's an error.
3744
+ if(tmpSolveLayerTokens.length===1){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.buildPostfixedSolveList found a single operator in a solve layer expression at token index ${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
3745
+ else if(i==0&&(tmpToken.Token=='-'||tmpToken.Token=='+')){tmpToken.VirtualSymbolName=`VNLO_${tmpVirtualSymbolIndex}`;tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}// If the token is at the beginning of the expression and not a number line orientation modifier, it's an error.
3736
3746
  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 ${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.
3737
- 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 ${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
3738
- else if(i==0&&tmpToken.Token=='-'){tmpToken.VirtualSymbolName=`VNLO_${tmpVirtualSymbolIndex}`;tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}// The - after an operator or an open parenthesis is also a number line orientation modifier
3747
+ 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 ${i}`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return tmpResults.PostfixSolveList;}// The - after an operator or an open parenthesis is also a number line orientation modifier
3739
3748
  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
3740
3749
  tmpToken.VirtualSymbolName=`VNLO_${tmpVirtualSymbolIndex}`;tmpVirtualSymbolIndex++;}// The + at the beginning is also a number line orientation modifier ... THAT WE IGNORE
3741
3750
  else if(i==0&&tmpToken.Token=='+'){continue;}// The + after an operator or a parenthesis is also a number line orientation modifier ... THAT WE IGNORE
3742
3751
  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
3743
- 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 ${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.
3752
+ else if((tmpSolveLayerTokens[i-1].Type==='Token.Operator'||tmpSolveLayerTokens[i+1].Type==='Token.Operator')&&tmpSolveLayerTokens[i+1].Token!='-'&&tmpSolveLayerTokens[i+1].Token!='+'){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.buildPostfixedSolveList found an operator at token index ${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.
3744
3753
  else{tmpToken.VirtualSymbolName=`V_${tmpVirtualSymbolIndex}`;tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;tmpVirtualSymbolIndex++;}}else if(tmpSolveLayerTokens[i].Type==='Token.Function'&&tmpPrecedence===0){let tmpToken=tmpSolveLayerTokens[i];tmpToken.VirtualSymbolName=`VFE_${tmpVirtualSymbolIndex}`;tmpVirtualSymbolIndex++;tmpResults.PostfixLayerstackMap[tmpToken.SolveLayerStack]=tmpToken.VirtualSymbolName;}}}}// 5.15 Generate Virtual Symbol Clusters for Functions and Parenthesis
3745
3754
  // ... this gets funny because of precedence of operations surrounding them, parenthesis and functions.
3746
3755
  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
@@ -3781,19 +3790,15 @@ else if(i>0&&tmpToken.Token=='+'&&(tmpSolveLayerTokens[i-1].Type==='Token.Operat
3781
3790
  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.
3782
3791
  let tmpAbstractAssignToken='PostfixedAssignmentOperator'in tmpResults?this.getTokenContainerObject(tmpResults.PostfixedAssignmentOperator.Token):this.getTokenContainerObject('=');// The address we are assigning to
3783
3792
  tmpAbstractAssignToken.VirtualSymbolName=tmpResults.PostfixedAssignmentAddress;// The address it's coming from
3784
- let tmpSolveResultToken=this.getTokenContainerObject('Result','Token.LastResult');let tmpFinalAssignmentInstruction=this.getPosfixSolveListOperation(tmpAbstractAssignToken,tmpSolveResultToken,this.getTokenContainerObject('SolverMarshal','Token.SolverMarshal'));tmpResults.PostfixSolveList.push(tmpFinalAssignmentInstruction);return tmpResults.PostfixSolveList;}}module.exports=ExpressionParserPostfix;},{"./Fable-Service-ExpressionParser-Base.js":159}],165:[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
3793
+ let tmpSolveResultToken=this.getTokenContainerObject('Result','Token.LastResult');let tmpFinalAssignmentInstruction=this.getPosfixSolveListOperation(tmpAbstractAssignToken,tmpSolveResultToken,this.getTokenContainerObject('SolverMarshal','Token.SolverMarshal'));tmpResults.PostfixSolveList.push(tmpFinalAssignmentInstruction);return tmpResults.PostfixSolveList;}}module.exports=ExpressionParserPostfix;},{"./Fable-Service-ExpressionParser-Base.js":159}],165:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');const libSetConcatArray=require('../Fable-SetConcatArray.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
3785
3794
  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.
3786
- 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};if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.LastResult'){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpResults.LastResult;}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.LastResult'){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpResults.LastResult;}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
3795
+ tmpResults.VirtualSymbols={};for(let i=0;i<pPostfixedExpression.length;i++){// X = SUM(15, SUM(SIN(25), 10), (5 + 2), 3)
3796
+ if(pPostfixedExpression[i].Operation.Type==='Token.SolverInstruction'){continue;}let tmpStepResultObject={ExpressionStep:pPostfixedExpression[i],ExpressionStepIndex:i,ResultsObject:tmpResults,Manifest:tmpManifest};if(tmpStepResultObject.ExpressionStep.LeftValue.Type==='Token.LastResult'){tmpStepResultObject.ExpressionStep.LeftValue.Value=tmpResults.LastResult;}if(tmpStepResultObject.ExpressionStep.RightValue.Type==='Token.LastResult'){tmpStepResultObject.ExpressionStep.RightValue.Value=tmpResults.LastResult;}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
3787
3797
  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
3788
3798
  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.
3789
3799
  // An operator always has a left and right value.
3790
- let tmpFunctionAddress=false;// Note: There are easier, passive ways of managing this state. But this is complex.
3791
- let tmpIsFunction=false;if(tmpStepResultObject.ExpressionStep.Operation.Token in this.ExpressionParser.tokenMap){tmpFunctionAddress=`ResultsObject.${tmpStepResultObject.ExpressionStep.Operation.Descriptor.Function}`;}else if(tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()in this.ExpressionParser.functionMap){tmpIsFunction=true;tmpFunctionAddress=`ResultsObject.${this.ExpressionParser.functionMap[tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()].Address}`;}if(tmpIsFunction){try{//this.log.trace(`Solving Function Step ${i} [${tmpStepResultObject.ExpressionStep.VirtualSymbolName}] --> [${tmpStepResultObject.ExpressionStep.Operation.Token}]: ( ${tmpStepResultObject.ExpressionStep.LeftValue.Value} , ${tmpStepResultObject.ExpressionStep.RightValue.Value} )`);
3792
- // Build the set of arguments to send to the functions.
3793
- tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString='';if(typeof tmpStepResultObject.ExpressionStep.LeftValue.Value==='undefined'){tmpStepResultObject.ExpressionStep.LeftValue.Arguments=[];}else if(Array.isArray(tmpStepResultObject.ExpressionStep.LeftValue.Value)){// Allow for array-based math sets to just be pased through
3794
- tmpStepResultObject.ExpressionStep.LeftValue.Arguments=tmpStepResultObject.ExpressionStep.LeftValue.Value;tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString='ExpressionStep.LeftValue.Arguments';}else if(typeof tmpStepResultObject.ExpressionStep.LeftValue.Value==='object'){// Allow for array-based math sets to just be pased through
3795
- tmpStepResultObject.ExpressionStep.LeftValue.Arguments=tmpStepResultObject.ExpressionStep.LeftValue.Value;tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString='ExpressionStep.LeftValue.Arguments';}else{// Allow for string-based math sets.
3796
- tmpStepResultObject.ExpressionStep.LeftValue.Arguments=tmpStepResultObject.ExpressionStep.LeftValue.Value.toString().split(',');for(let j=0;j<tmpStepResultObject.ExpressionStep.LeftValue.Arguments.length;j++){if(tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString!==''){tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString+=',';}tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString+=`ExpressionStep.LeftValue.Arguments[${j}]`;}}tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName,tmpManifest.getValueAtAddress(tmpStepResultObject,`${tmpFunctionAddress}(${tmpStepResultObject.ExpressionStep.LeftValue.ArgumentString})`));tmpResults.LastResult=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName);//this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
3800
+ let tmpFunctionAddress;// Note: There are easier, passive ways of managing this state. But this is complex.
3801
+ let tmpIsFunction=false;if(tmpStepResultObject.ExpressionStep.Operation.Token in this.ExpressionParser.tokenMap){tmpFunctionAddress=`ResultsObject.${tmpStepResultObject.ExpressionStep.Operation.Descriptor.Function}`;}else if(tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()in this.ExpressionParser.functionMap){tmpIsFunction=true;tmpFunctionAddress=`ResultsObject.${this.ExpressionParser.functionMap[tmpStepResultObject.ExpressionStep.Operation.Token.toLowerCase()].Address}`;}if(tmpIsFunction){try{let tmpResult;const tmpFunction=tmpManifest.getValueAtAddress(tmpStepResultObject,tmpFunctionAddress);if(typeof tmpFunction==='function'){let tmpFunctionBinding=null;if(tmpFunctionAddress.includes('.')){tmpFunctionBinding=tmpManifest.getValueAtAddress(tmpStepResultObject,tmpFunctionAddress.split('.').slice(0,-1).join('.'));}let tmpArguments=tmpStepResultObject.ExpressionStep.LeftValue.Value;if(!(tmpArguments instanceof libSetConcatArray)){tmpArguments=[tmpArguments];}else{tmpArguments=tmpArguments.values;}tmpResult=tmpFunction.apply(tmpFunctionBinding,tmpArguments);}tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName,tmpResult);tmpResults.LastResult=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName);//this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
3797
3802
  }catch(pError){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ${i} with function ${tmpStepResultObject.ExpressionStep.Operation.Token}: ${pError}`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}}else{try{//this.log.trace(`Solving Step ${i} [${tmpStepResultObject.ExpressionStep.VirtualSymbolName}] --> [${tmpStepResultObject.ExpressionStep.Operation.Token}]: ( ${tmpStepResultObject.ExpressionStep.LeftValue.Value} , ${tmpStepResultObject.ExpressionStep.RightValue.Value} )`);
3798
3803
  tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName,tmpManifest.getValueAtAddress(tmpStepResultObject,`${tmpFunctionAddress}(ExpressionStep.LeftValue.Value,ExpressionStep.RightValue.Value)`));tmpResults.LastResult=tmpManifest.getValueAtAddress(tmpResults.VirtualSymbols,tmpStepResultObject.ExpressionStep.VirtualSymbolName);//this.log.trace(` ---> Step ${i}: ${tmpResults.VirtualSymbols[tmpStepResultObject.ExpressionStep.VirtualSymbolName]}`)
3799
3804
  }catch(pError){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.solvePostfixedExpression failed to solve step ${i} with function ${tmpStepResultObject.ExpressionStep.Operation.Token}: ${pError}`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);return false;}}// Equations don't always solve in virtual symbol order.
@@ -3803,7 +3808,7 @@ tmpManifest.setValueAtAddress(tmpResults.VirtualSymbols,pPostfixedExpression[i].
3803
3808
  if(pPostfixedExpression[i].Operation.Descriptor.OnlyEmpty){// If it is only on "empty" values, check if the value is empty before assigning
3804
3809
  if(this.fable.Utility.addressIsNullOrEmpty(tmpDataDestinationObject,pPostfixedExpression[i].VirtualSymbolName)){tmpManifest.setValueByHash(tmpDataDestinationObject,pPostfixedExpression[i].VirtualSymbolName,tmpSolverResultValue);}}else{// Otherwise, just assign it.
3805
3810
  tmpManifest.setValueByHash(tmpDataDestinationObject,pPostfixedExpression[i].VirtualSymbolName,tmpSolverResultValue);}}}tmpResults.RawResult=tmpSolverResultValue;// Clean up the fable reference if we added it to the object.
3806
- if(!tmpPassedInFable){delete tmpResults.fable;}if(typeof tmpSolverResultValue==='object'){return tmpSolverResultValue;}else if(typeof tmpSolverResultValue!=='undefined'){return tmpSolverResultValue.toString();}else{return tmpSolverResultValue;}}}module.exports=ExpressionParserSolver;},{"./Fable-Service-ExpressionParser-Base.js":159}],166:[function(require,module,exports){module.exports={"=":{"Name":"Assign Value","Token":"=","Function":"fable.Math.assignValue","Precedence":0,"Type":"Assignment"},"?=":{"Name":"Null or Empty Coalescing Assign Value","Token":"?=","Function":"fable.Math.assignValue","OnlyEmpty":true,"Precedence":0,"Type":"Assignment"},"(":{"Name":"Left Parenthesis","Token":"(","Precedence":0,"Type":"Parenthesis"},")":{"Name":"Right Parenthesis","Token":")","Precedence":0,"Type":"Parenthesis"},",":{"Name":"Set Concatenate","Token":",","Function":"fable.Math.setConcatenate","Precedence":4,"Type":"Operator"},"*":{"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"}};},{}],167:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserValueMarshal extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-ValueMarshal';}/**
3811
+ if(!tmpPassedInFable){delete tmpResults.fable;}if(typeof tmpSolverResultValue==='object'){return tmpSolverResultValue;}else if(typeof tmpSolverResultValue!=='undefined'){return tmpSolverResultValue.toString();}else{return tmpSolverResultValue;}}}module.exports=ExpressionParserSolver;},{"../Fable-SetConcatArray.js":182,"./Fable-Service-ExpressionParser-Base.js":159}],166:[function(require,module,exports){module.exports={"=":{"Name":"Assign Value","Token":"=","Function":"fable.Math.assignValue","Precedence":0,"Type":"Assignment"},"?=":{"Name":"Null or Empty Coalescing Assign Value","Token":"?=","Function":"fable.Math.assignValue","OnlyEmpty":true,"Precedence":0,"Type":"Assignment"},"(":{"Name":"Left Parenthesis","Token":"(","Precedence":0,"Type":"Parenthesis"},")":{"Name":"Right Parenthesis","Token":")","Precedence":0,"Type":"Parenthesis"},",":{"Name":"Set Concatenate","Token":",","Function":"fable.Math.setConcatenate","Precedence":4,"Type":"Operator"},"*":{"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":2,"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"}};},{}],167:[function(require,module,exports){const libExpressionParserOperationBase=require('./Fable-Service-ExpressionParser-Base.js');class ExpressionParserValueMarshal extends libExpressionParserOperationBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ExpressionParser-ValueMarshal';}/**
3807
3812
  * Substitutes values in tokenized objects based on the provided data source and manifest.
3808
3813
  *
3809
3814
  * TODO: Move this to its own file in the "Fable-Service-ExpressionParser" directory.
@@ -3819,14 +3824,14 @@ let tmpValue=tmpManifest.getValueByHash(tmpDataSource,tmpToken.Token);// if (!tm
3819
3824
  // // If no hash resolves, try by address.
3820
3825
  // tmpValue = tmpManifest.getValueAtAddress(tmpToken.Token, tmpDataSource);
3821
3826
  // }
3822
- if(!tmpValue){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the symbol hash or address ${tmpToken.Token} at index ${i}`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);if(this.LogNoisiness>1)this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpValue);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){// TODO: Should we allow this to be a function? Good god the complexity and beauty of that...
3827
+ if(!tmpValue){tmpToken.Value=tmpValue;tmpToken.Resolve=true;tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the symbol hash or address ${tmpToken.Token} at index ${i}`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);if(this.LogNoisiness>1)this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpValue);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){// TODO: Should we allow this to be a function? Good god the complexity and beauty of that...
3823
3828
  if(Array.isArray(tmpValue)||typeof tmpValue==='object'){tmpToken.Resolved=true;tmpToken.Value=tmpValue;}else{tmpToken.Resolved=true;tmpToken.Value=tmpValue;tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}; using raw value.`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);}}}}if(pTokenizedObjects[i].Type==='Token.StateAddress'&&!tmpToken.Resolved){// Symbols are always hashes. This gracefully works for simple shallow objects because hashes default to the address in Manyfest.
3824
3829
  let tmpValue=tmpManifest.getValueAtAddress(tmpDataSource,tmpToken.Token);if(!tmpValue){tmpResults.ExpressionParserLog.push(`WARNING: ExpressionParser.substituteValuesInTokenizedObjects found no value for the state address ${tmpToken.Token} at index ${i}`);this.log.warn(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);continue;}else{//tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpValue}] for the state address ${tmpToken.Token} at index ${i}`);
3825
3830
  this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpValue);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}if(pTokenizedObjects[i].Type==='Token.String'&&!tmpToken.Resolved){tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpToken.Token}] for the string ${tmpToken.Token} at index ${i}`);if(this.LogNoisiness>1)this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=true;// Take the quotes off the string
3826
3831
  tmpToken.Value=tmpToken.Token.substring(1,tmpToken.Token.length-1);}if(pTokenizedObjects[i].Type==='Token.Constant'&&!tmpToken.Resolved){tmpResults.ExpressionParserLog.push(`INFO: ExpressionParser.substituteValuesInTokenizedObjects found a value [${tmpToken.Token}] for the constant ${tmpToken.Token} at index ${i}`);if(this.LogNoisiness>1)this.log.info(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);try{let tmpValueParsed=new this.fable.Utility.bigNumber(tmpToken.Token);tmpToken.Resolved=true;tmpToken.Value=tmpValueParsed.toString();}catch(pError){// This constant has the right symbols but apparently isn't a parsable number.
3827
3832
  tmpResults.ExpressionParserLog.push(`ERROR: ExpressionParser.substituteValuesInTokenizedObjects found a non-numeric value for the state address ${tmpToken.Token} at index ${i}`);this.log.error(tmpResults.ExpressionParserLog[tmpResults.ExpressionParserLog.length-1]);tmpToken.Resolved=false;}}}return pTokenizedObjects;}}module.exports=ExpressionParserValueMarshal;},{"./Fable-Service-ExpressionParser-Base.js":159}],168:[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(){// TODO: Fix anything that's using this before changing this to the new true node join
3828
3833
  // return libPath.join(...pPathArray);
3829
- return libPath.resolve(...arguments);}resolvePath(){return libPath.resolve(...arguments);}existsSync(pPath){return libFS.existsSync(pPath);}exists(pPath,fCallback){let tmpFileExists=this.existsSync(pPath);return fCallback(null,tmpFileExists);}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);}readFileCSV(pFilePath,pOptions,fRecordFunction,fCompleteFunction,fErrorFunction){let tmpCSVParser=this.fable.instantiateServiceProviderWithoutRegistration('CSVParser',pOptions);let tmpRecordFunction=typeof fRecordFunction==='function'?fRecordFunction:pRecord=>{this.fable.log(`CSV Reader received line ${pRecord}`);};let tmpCompleteFunction=typeof fCompleteFunction==='function'?fCompleteFunction:()=>{this.fable.log(`CSV Read of ${pFilePath} complete.`);};let tmpErrorFunction=typeof fErrorFunction==='function'?fErrorFunction:pError=>{this.fable.log(`CSV Read of ${pFilePath} Error: ${pError}`,pError);};return this.lineReaderFactory(pFilePath,pLine=>{let tmpRecord=tmpCSVParser.parseCSVLine(pLine);if(tmpRecord){tmpRecordFunction(tmpRecord,pLine);}},tmpCompleteFunction,tmpErrorFunction);}appendFileSync(pFileName,pAppendContent,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.appendFileSync(pFileName,pAppendContent,tmpOptions);}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 ${pFileName} from array but the expected array was not an array (it was a ${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,`${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
3834
+ return libPath.resolve(...arguments);}resolvePath(){return libPath.resolve(...arguments);}existsSync(pPath){return libFS.existsSync(pPath);}exists(pPath,fCallback){let tmpFileExists=this.existsSync(pPath);return fCallback(null,tmpFileExists);}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);}readFileCSV(pFilePath,pOptions,fRecordFunction,fCompleteFunction,fErrorFunction){let tmpCSVParser=this.fable.instantiateServiceProviderWithoutRegistration('CSVParser',pOptions);let tmpRecordFunction=typeof fRecordFunction==='function'?fRecordFunction:pRecord=>{this.fable.log.trace(`CSV Reader received line ${pRecord}`);};let tmpCompleteFunction=typeof fCompleteFunction==='function'?fCompleteFunction:()=>{this.fable.log.info(`CSV Read of ${pFilePath} complete.`);};let tmpErrorFunction=typeof fErrorFunction==='function'?fErrorFunction:pError=>{this.fable.log.error(`CSV Read of ${pFilePath} Error: ${pError}`,pError);};return this.lineReaderFactory(pFilePath,pLine=>{let tmpRecord=tmpCSVParser.parseCSVLine(pLine);if(tmpRecord){tmpRecordFunction(tmpRecord,pLine);}},tmpCompleteFunction,tmpErrorFunction);}appendFileSync(pFileName,pAppendContent,pOptions){let tmpOptions=typeof pOptions==='undefined'?'utf8':pOptions;return libFS.appendFileSync(pFileName,pAppendContent,tmpOptions);}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 ${pFileName} from array but the expected array was not an array (it was a ${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,`${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
3830
3835
  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
3831
3836
  if(typeof tmpParameters.CurrentPathIndex==='undefined'){// Build the tools to start recursing
3832
3837
  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.
@@ -3836,12 +3841,34 @@ tmpParameters.CurrentPathIndex++;}// Check if the path is fully complete
3836
3841
  if(tmpParameters.CurrentPathIndex>=tmpParameters.ActualPathParts.length){return fCallback(null);}// Check if the path exists (and is a folder)
3837
3842
  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.
3838
3843
  return this.makeFolderRecursive(tmpParameters,fCallback);}else if(pCreateError.code=='EEXIST'){// The folder exists -- our dev might be running this in parallel/async/whatnot.
3839
- 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":107,"fable-serviceproviderbase":59,"fs":19,"path":103,"readline":19}],169:[function(require,module,exports){/**
3844
+ 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":107,"fable-serviceproviderbase":59,"fs":19,"path":103,"readline":19}],169:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceLogic extends libFableServiceBase{/**
3845
+ * @param {import('../Fable.js')} pFable - The fable object
3846
+ * @param {Record<string, any>} [pOptions] - The options object
3847
+ * @param {string} [pServiceHash] - The hash of the service
3848
+ */constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);}/**
3849
+ * Find the first value in an object that contains a specific value
3850
+ *
3851
+ * @param {string|number} pLeft - The left value to check
3852
+ * @param {string} pComparisonOperator - The comparison operator to use
3853
+ * @param {string|number} pRight - The right value to check
3854
+ * @param {any} pOnTrue - The value to return if the comparison is true
3855
+ * @param {any} [pOnFalse = ''] - The value to return if the comparison is false
3856
+ * @return {any} - The selected value
3857
+ */checkIf(pLeft,pComparisonOperator,pRight,pOnTrue,pOnFalse){// precise numeric
3858
+ // string (non-numeric)
3859
+ let tmpMathLeft=this.fable.Math.parsePrecise(pLeft,null);let tmpMathRight=this.fable.Math.parsePrecise(pRight,null);let tmpCheckResult=false;if(tmpMathLeft===null||tmpMathRight===null){if(typeof pOnFalse==='undefined'){pOnFalse='';}switch(pComparisonOperator){case'<':case'LT':tmpCheckResult=pLeft<pRight;break;case'<=':case'LTE':tmpCheckResult=pLeft<=pRight;break;case'>':case'GT':tmpCheckResult=pLeft>pRight;break;case'>=':case'GTE':tmpCheckResult=pLeft>=pRight;break;case'==':tmpCheckResult=pLeft==pRight;case'===':tmpCheckResult=pLeft===pRight;default:this.fable.log.warn(`[FableServiceLogic.checkIf] Invalid comparison operator: ${pComparisonOperator}`);tmpCheckResult=pLeft==pRight;}}else{if(typeof pOnFalse==='undefined'){pOnFalse='0';}switch(pComparisonOperator){case'<':case'LT':tmpCheckResult=this.fable.Math.ltPrecise(tmpMathLeft,tmpMathRight);break;case'<=':case'LTE':tmpCheckResult=this.fable.Math.ltePrecise(tmpMathLeft,tmpMathRight);break;case'>':case'GT':tmpCheckResult=this.fable.Math.gtPrecise(tmpMathLeft,tmpMathRight);break;case'>=':case'GTE':tmpCheckResult=this.fable.Math.gtePrecise(tmpMathLeft,tmpMathRight);break;case'==':tmpCheckResult=this.fable.Math.comparePreciseWithin(tmpMathLeft,tmpMathRight,'0.000001')==0;break;case'===':tmpCheckResult=this.fable.Math.comparePrecise(tmpMathLeft,tmpMathRight)==0;break;default:this.fable.log.warn(`[FableServiceLogic.checkIf] Invalid comparison operator: ${pComparisonOperator}`);tmpCheckResult=pLeft==pRight?pOnTrue:pOnFalse;}}return tmpCheckResult?pOnTrue:pOnFalse;}/**
3860
+ * Find the first value in an object that contains a specific value
3861
+ *
3862
+ * @param {any} pCheckForTruthy - The object to check
3863
+ * @param {any} pOnTrue - The value to return if the object is truthy
3864
+ * @param {any} [pOnFalse = ''] - The value to return if the object is falsy
3865
+ * @return {any} - The value from the object
3866
+ */when(pCheckForTruthy,pOnTrue){let pOnFalse=arguments.length>2&&arguments[2]!==undefined?arguments[2]:'';if(!pCheckForTruthy){return pOnFalse;}if(Array.isArray(pCheckForTruthy)&&pCheckForTruthy.length<1){return pOnFalse;}if(typeof pCheckForTruthy==='object'&&Object.keys(pCheckForTruthy).length<1){return pOnFalse;}return pOnTrue;}}module.exports=FableServiceLogic;},{"fable-serviceproviderbase":59}],170:[function(require,module,exports){/**
3840
3867
  * @file Fable-Service-Math.js
3841
3868
  * @description This file contains the implementation of the FableServiceMath class, which provides simple functions for performing arbitrary precision math operations.
3842
3869
  * @module FableServiceMath
3843
3870
  * @extends libFableServiceBase
3844
- */const libFableServiceBase=require('fable-serviceproviderbase');/**
3871
+ */const libFableServiceBase=require('fable-serviceproviderbase');const libSetConcatArray=require('./Fable-SetConcatArray.js');/**
3845
3872
  * Arbitrary Precision Math Operations
3846
3873
  * @author Steven Velozo <steven@velozo.com>
3847
3874
  * @description Simple functions that perform arbitrary precision math operations and return string resultant values. Wraps big.js
@@ -3864,7 +3891,7 @@ this.euler='2.718281828459045235360287471352662497757247093699959574966967627724
3864
3891
  * @param {number} pValue - The value to parse.
3865
3892
  * @param {any} pNonNumberValue - The value to use if parsing fails.
3866
3893
  * @returns {string} - The parsed number as a string.
3867
- */parsePrecise(pValue,pNonNumberValue){let tmpNumber;try{tmpNumber=new this.fable.Utility.bigNumber(pValue);}catch(pError){this.log.warn(`Error parsing number (type ${typeof pValue}): ${pError}`);tmpNumber=typeof pNonNumberValue==='undefined'?"0.0":pNonNumberValue;}return tmpNumber.toString();}/**
3894
+ */parsePrecise(pValue,pNonNumberValue){let tmpNumber;try{tmpNumber=new this.fable.Utility.bigNumber(pValue);}catch(pError){this.log.warn(`Error parsing number (type ${typeof pValue}): ${pError}`);tmpNumber=typeof pNonNumberValue==='undefined'?"0.0":pNonNumberValue;}return tmpNumber?tmpNumber.toString():tmpNumber;}/**
3868
3895
  * Assigns the given value. For equals operations in the solver.
3869
3896
  * @param {*} pValue - The value to be assigned.
3870
3897
  * @returns {*} The assigned value.
@@ -3883,8 +3910,8 @@ this.euler='2.718281828459045235360287471352662497757247093699959574966967627724
3883
3910
  *
3884
3911
  * @param {any} pLeftValue - The left value to append.
3885
3912
  * @param {any} pRightValue - The right value to append.
3886
- * @returns {string} The concatenated string of the left and right values.
3887
- */setConcatenate(pLeftValue,pRightValue){return`${pLeftValue},${pRightValue}`;}/**
3913
+ * @returns {InstanceType<libSetConcatArray>} The concatenated string of the left and right values.
3914
+ */setConcatenate(pLeftValue,pRightValue){return new libSetConcatArray(pLeftValue,pRightValue);}/**
3888
3915
  * Rounds a value to a specified number of decimal places using a specified rounding method.
3889
3916
  *
3890
3917
  * @param {number} pValue - The value to be rounded.
@@ -3915,7 +3942,8 @@ this.euler='2.718281828459045235360287471352662497757247093699959574966967627724
3915
3942
  * @param {number} pLeftValue - The base value.
3916
3943
  * @param {number} pRightValue - The exponent value.
3917
3944
  * @returns {string} The result of raising the base value to the exponent value.
3918
- */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();}/**
3945
+ */powerPrecise(pLeftValue,pRightValue){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:parseInt(pRightValue);let tmpResult;if(tmpRightValue==Number(pRightValue)){const tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);tmpResult=tmpLeftArbitraryValue.pow(tmpRightValue);}else{//FIXME: big.js shits itself on non-integer exponents........................
3946
+ tmpResult=Math.pow(tmpLeftValue,Number(pRightValue));}return tmpResult.toString();}/**
3919
3947
  * Multiplies two values precisely.
3920
3948
  *
3921
3949
  * @param {number} pLeftValue - The left value to multiply.
@@ -3956,10 +3984,17 @@ this.euler='2.718281828459045235360287471352662497757247093699959574966967627724
3956
3984
  */ceilPrecise(pValue){let tmpValue=isNaN(pValue)?0:pValue;let tmpResult=Math.ceil(tmpValue);return tmpResult.toString();}/**
3957
3985
  * Compares two values precisely.
3958
3986
  *
3959
- * @param {number} pLeftValue - The left value to compare.
3960
- * @param {number} pRightValue - The right value to compare.
3987
+ * @param {number|string} pLeftValue - The left value to compare.
3988
+ * @param {number|string} pRightValue - The right value to compare.
3961
3989
  * @returns {number} - Returns the result of the comparison.
3962
3990
  */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);}/**
3991
+ * Compares two values precisely within a tolerance.
3992
+ *
3993
+ * @param {number|string} pLeftValue - The left value to compare.
3994
+ * @param {number|string} pRightValue - The right value to compare.
3995
+ * @param {number|string} pEpsilon - The epsilon value for comparison.
3996
+ * @returns {number} - Returns the result of the comparison.
3997
+ */comparePreciseWithin(pLeftValue,pRightValue,pEpsilon){let tmpLeftValue=isNaN(pLeftValue)?0:pLeftValue;let tmpRightValue=isNaN(pRightValue)?0:pRightValue;let tmpLeftArbitraryValue=new this.fable.Utility.bigNumber(tmpLeftValue);const diff=tmpLeftArbitraryValue.minus(tmpRightValue).abs();if(diff.lte(pEpsilon)){return 0;}if(tmpLeftArbitraryValue.lt(tmpRightValue)){return-1;}return 1;}/**
3963
3998
  * Determines if the left value is greater than the right value precisely.
3964
3999
  *
3965
4000
  * @param {number} pLeftValue - The left value to compare.
@@ -4050,7 +4085,8 @@ return 1;}return 0;}/**
4050
4085
  *
4051
4086
  * @param {Object} pHistogram - The histogram object to be sorted.
4052
4087
  * @returns {Object} - The sorted histogram object.
4053
- */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;}cleanValueArray(pValueArray){if(!Array.isArray(pValueArray)){return[];}let tmpCleanedArray=[];for(let i=0;i<pValueArray.length;i++){let tmpValue=this.parsePrecise(pValueArray[i],NaN);if(!isNaN(tmpValue)){tmpCleanedArray.push(tmpValue);}}return tmpCleanedArray;}cleanValueObject(pValueObject){if(typeof pValueObject!=='object'){return{};}let tmpCleanedObject={};let tmpKeys=Object.keys(pValueObject);for(let i=0;i<tmpKeys.length;i++){let tmpValue=this.parsePrecise(pValueObject[tmpKeys[i]],NaN);if(!isNaN(tmpValue)){tmpCleanedObject[tmpKeys[i]]=tmpValue;}}return tmpCleanedObject;}/**
4088
+ */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;}cleanValueArray(pValueArray){if(!Array.isArray(pValueArray)){return[];}let tmpCleanedArray=[];for(let i=0;i<pValueArray.length;i++){let tmpValue=this.parsePrecise(pValueArray[i],NaN);if(!isNaN(tmpValue)){tmpCleanedArray.push(tmpValue);}}return tmpCleanedArray;}cleanValueObject(pValueObject){if(typeof pValueObject!=='object'){return{};}//TODO: is this right?
4089
+ let tmpCleanedObject={};let tmpKeys=Object.keys(pValueObject);for(let i=0;i<tmpKeys.length;i++){let tmpValue=this.parsePrecise(pValueObject[tmpKeys[i]],NaN);if(!isNaN(tmpValue)){tmpCleanedObject[tmpKeys[i]]=tmpValue;}}return tmpCleanedObject;}/**
4054
4090
  * Make a histogram of representative counts for exact values (.tostring() is the keys to count)
4055
4091
  * @param {Array} pValueSet
4056
4092
  * @param {string} pValueAddress
@@ -4071,7 +4107,7 @@ return 1;}return 0;}/**
4071
4107
  * @param {Array} pValueObjectSet
4072
4108
  * @param {string} pValueAddress
4073
4109
  * @param {Object} pManifest
4074
- */entryInSet(pValueObjectSet,pValueAddress,pEntryIndex){if(!Array.isArray(pValueObjectSet)){return pValueObjectSet;}if(!pValueAddress){return false;}if(isNaN(pEntryIndex)||pEntryIndex>=pValueObjectSet.length){return false;}let tmpValueArray=pValueObjectSet.toSorted((pLeft,pRight)=>{return this.comparePrecise(pLeft,pRight);});let tmpIndex=pEntryIndex===-1?tmpValueArray.length-1:pEntryIndex;return tmpValueArray[tmpIndex];}/**
4110
+ */entryInSet(pValueObjectSet,pValueAddress,pEntryIndex){const tmpEntryIndex=typeof pEntryIndex==='number'?pEntryIndex:parseInt(pEntryIndex);if(!Array.isArray(pValueObjectSet)){return pValueObjectSet;}if(!pValueAddress){return false;}if(isNaN(tmpEntryIndex)||tmpEntryIndex>=pValueObjectSet.length){return false;}let tmpValueArray=pValueObjectSet.toSorted((pLeft,pRight)=>{return this.comparePrecise(pLeft[pValueAddress],pRight[pValueAddress]);});let tmpIndex=tmpEntryIndex<0?tmpValueArray.length+tmpEntryIndex:tmpEntryIndex;return tmpValueArray[tmpIndex];}/**
4075
4111
  * Finds the smallest value in a set of objects based on a specified value address.
4076
4112
  *
4077
4113
  * @param {Object[]} pValueObjectSet - An array of objects to search through.
@@ -4126,7 +4162,7 @@ else{let tmpLeftMiddleValue=tmpSortedValueSet[tmpMiddleElement-1];let tmpRightMi
4126
4162
  * @param {Array} pValueSet - The array of values to calculate the mode from.
4127
4163
  * @returns {Array} - An array containing the mode value(s) from the given value set.
4128
4164
  */modePrecise(pValueSet){let tmpHistogram=this.bucketSetPrecise(pValueSet);let tmpMaxCount=0;// Philosophical question about whether the values should be returned sorted.
4129
- 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":59}],170:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
4165
+ 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-SetConcatArray.js":182,"fable-serviceproviderbase":59}],171:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');/**
4130
4166
  * Precedent Meta-Templating
4131
4167
  * @author Steven Velozo <steven@velozo.com>
4132
4168
  * @description Process text stream trie and postfix tree, parsing out meta-template expression functions.
@@ -4138,7 +4174,7 @@ let tmpHistogramValueSet=Object.keys(tmpHistogram);let tmpModeValueSet=[];for(le
4138
4174
  * @param {function} fCallback - The callback function to call when a pattern is matched
4139
4175
  * @param {array} pDataContext - The history of data objects already passed in
4140
4176
  * @return {string} The result from the parser
4141
- */parseString(pString,pData,fCallback,pDataContext){if(this.LogNoisiness>4){this.fable.log.trace(`Metatemplate parsing template string [${pString}] where the callback is a ${typeof fCallback}`,{TemplateData:pData});}return this.StringParser.parseString(pString,this.ParseTree,pData,fCallback,pDataContext);}}module.exports=FableServiceMetaTemplate;},{"./Fable-Service-MetaTemplate/MetaTemplate-StringParser.js":171,"./Fable-Service-MetaTemplate/MetaTemplate-WordTree.js":172,"fable-serviceproviderbase":59}],171:[function(require,module,exports){/**
4177
+ */parseString(pString,pData,fCallback,pDataContext){if(this.LogNoisiness>4){this.fable.log.trace(`Metatemplate parsing template string [${pString}] where the callback is a ${typeof fCallback}`,{TemplateData:pData});}return this.StringParser.parseString(pString,this.ParseTree,pData,fCallback,pDataContext);}}module.exports=FableServiceMetaTemplate;},{"./Fable-Service-MetaTemplate/MetaTemplate-StringParser.js":172,"./Fable-Service-MetaTemplate/MetaTemplate-WordTree.js":173,"fable-serviceproviderbase":59}],172:[function(require,module,exports){/**
4142
4178
  * String Parser
4143
4179
  * @author Steven Velozo <steven@velozo.com>
4144
4180
  * @description Parse a string, properly processing each matched token in the word tree.
@@ -4225,7 +4261,7 @@ return fCallback();}/**
4225
4261
  let tmpPreviousDataContext=Array.isArray(pDataContext)?pDataContext:[];let tmpDataContext=Array.from(tmpPreviousDataContext);tmpDataContext.push(pData);if(typeof fCallback!=='function'){let tmpParserState=this.newParserState(pParseTree);for(var i=0;i<pString.length;i++){// TODO: This is not fast.
4226
4262
  this.parseCharacter(pString[i],tmpParserState,pData,tmpDataContext);}this.flushOutputBuffer(tmpParserState);return tmpParserState.Output;}else{// This is the async mode
4227
4263
  let tmpParserState=this.newParserState(pParseTree);tmpParserState.Asynchronous=true;let tmpAnticipate=this.fable.instantiateServiceProviderWithoutRegistration('Anticipate');for(let i=0;i<pString.length;i++){tmpAnticipate.anticipate(fCallback=>{this.parseCharacterAsync(pString[i],tmpParserState,pData,fCallback,tmpDataContext);});}tmpAnticipate.wait(pError=>{// Flush the remaining data
4228
- this.flushOutputBuffer(tmpParserState);return fCallback(pError,tmpParserState.Output);});}}}module.exports=StringParser;},{}],172:[function(require,module,exports){/**
4264
+ this.flushOutputBuffer(tmpParserState);return fCallback(pError,tmpParserState.Output);});}}}module.exports=StringParser;},{}],173:[function(require,module,exports){/**
4229
4265
  * Word Tree
4230
4266
  * @author Steven Velozo <steven@velozo.com>
4231
4267
  * @description Create a tree (directed graph) of Javascript objects, one character per object.
@@ -4261,7 +4297,7 @@ if(pParserContext){tmpLeaf.ParserContext=pParserContext;}tmpLeaf.isAsync=true;re
4261
4297
  * @param {string} pPatternEnd - The ending string for the pattern (e.g. "}")
4262
4298
  * @param {function} fParser - The function to parse if this is the matched pattern, once the Pattern End is met. If this is a string, a simple replacement occurs.
4263
4299
  * @param {Object} pParserContext - The context to pass to the parser function
4264
- */addPattern(pPatternStart,pPatternEnd,fParser,pParserContext){return this.addPatternBoth(pPatternStart,pPatternEnd,fParser,null,pParserContext);}}module.exports=WordTree;},{}],173:[function(require,module,exports){module.exports={"Metadata":{"UUID":false,"Hash":false,"Name":"","Summary":"","Version":0},"Status":{"Completed":false,"StepCount":1},"Steps":[],"Errors":[],"Log":[]};},{}],174:[function(require,module,exports){const{PE}=require('big.js');const libFableServiceBase=require('fable-serviceproviderbase');const _OperationStatePrototypeString=JSON.stringify(require('./Fable-Service-Operation-DefaultSettings.js'));class FableOperation extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);// Timestamps will just be the long ints
4300
+ */addPattern(pPatternStart,pPatternEnd,fParser,pParserContext){return this.addPatternBoth(pPatternStart,pPatternEnd,fParser,null,pParserContext);}}module.exports=WordTree;},{}],174:[function(require,module,exports){module.exports={"Metadata":{"UUID":false,"Hash":false,"Name":"","Summary":"","Version":0},"Status":{"Completed":false,"StepCount":1},"Steps":[],"Errors":[],"Log":[]};},{}],175:[function(require,module,exports){const{PE}=require('big.js');const libFableServiceBase=require('fable-serviceproviderbase');const _OperationStatePrototypeString=JSON.stringify(require('./Fable-Service-Operation-DefaultSettings.js'));class FableOperation extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);// Timestamps will just be the long ints
4265
4301
  this.timeStamps={};this.serviceType='PhasedOperation';this.state=JSON.parse(_OperationStatePrototypeString);this.stepMap={};this.stepFunctions={};// Match the service instantiation to the operation.
4266
4302
  this.state.Metadata.Hash=this.Hash;this.state.Metadata.UUID=this.UUID;this.state.Metadata.Name=typeof this.options.Name=='string'?this.options.Name:`Unnamed Operation ${this.state.Metadata.UUID}`;this.name=this.state.Metadata.Name;this.progressTrackerSet=this.fable.instantiateServiceProviderWithoutRegistration('ProgressTrackerSet');this.state.OverallProgressTracker=this.progressTrackerSet.createProgressTracker(`Overall-${this.state.Metadata.UUID}`);// This is here to use the pass-through logging functions in the operation itself.
4267
4303
  this.log=this;}execute(fExecutionCompleteCallback){// TODO: Should the same operation be allowed to execute more than one time?
@@ -4276,9 +4312,9 @@ tmpAnticipate.wait(pError=>{if(pError){this.fable.log.error(`Operation [${this.s
4276
4312
  addStep(fStepFunction,pStepMetadata,pStepName,pStepDescription,pGUIDStep){let tmpStep={};// GUID is optional
4277
4313
  tmpStep.GUIDStep=typeof pGUIDStep!=='undefined'?pGUIDStep:`STEP-${this.state.Steps.length}-${this.fable.DataGeneration.randomNumericString()}`;// Name is optional
4278
4314
  tmpStep.Name=typeof pStepName!=='undefined'?pStepName:`Step [${tmpStep.GUIDStep}]`;tmpStep.Description=typeof pStepDescription!=='undefined'?pStepDescription:`Step execution of ${tmpStep.Name}.`;tmpStep.ProgressTracker=this.progressTrackerSet.createProgressTracker(tmpStep.GUIDStep);tmpStep.Metadata=typeof pStepMetadata==='object'?pStepMetadata:{};// There is an array of steps, in the Operation State itself ... push a step there
4279
- this.state.Steps.push(tmpStep);this.stepMap[tmpStep.GUIDStep]=tmpStep;this.stepFunctions[tmpStep.GUIDStep]=typeof fStepFunction=='function'?fStepFunction:function(fDone){return fDone();};this.state.Status.StepCount++;return tmpStep;}setStepTotalOperations(pGUIDStep,pTotalOperationCount){if(!(pGUIDStep in this.stepMap)){return new Error(`Step [${pGUIDStep}] does not exist in operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} when attempting to set total operations to ${pTotalOperationCount}.`);}this.progressTrackerSet.setProgressTrackerTotalOperations(this.stepMap[pGUIDStep].ProgressTracker.Hash,pTotalOperationCount);}writeOperationLog(pLogLevel,pLogText,pLogObject){this.state.Log.push(`[${new Date().toUTCString()}]-[${pLogLevel}]: ${pLogText}`);if(typeof pLogObject=='object'){this.state.Log.push(JSON.stringify(pLogObject));}}writeOperationErrors(pLogText,pLogObject){this.state.Errors.push(`${pLogText}`);if(typeof pLogObject=='object'){this.state.Errors.push(JSON.stringify(pLogObject));}}trace(pLogText,pLogObject){this.writeOperationLog('TRACE',pLogText,pLogObject);this.fable.log.trace(pLogText,pLogObject);}debug(pLogText,pLogObject){this.writeOperationLog('DEBUG',pLogText,pLogObject);this.fable.log.debug(pLogText,pLogObject);}info(pLogText,pLogObject){this.writeOperationLog('INFO',pLogText,pLogObject);this.fable.log.info(pLogText,pLogObject);}warn(pLogText,pLogObject){this.writeOperationLog('WARN',pLogText,pLogObject);this.fable.log.warn(pLogText,pLogObject);}error(pLogText,pLogObject){this.writeOperationLog('ERROR',pLogText,pLogObject);this.writeOperationErrors(pLogText,pLogObject);this.fable.log.error(pLogText,pLogObject);}fatal(pLogText,pLogObject){this.writeOperationLog('FATAL',pLogText,pLogObject);this.writeOperationErrors(pLogText,pLogObject);this.fable.log.fatal(pLogText,pLogObject);}}module.exports=FableOperation;},{"./Fable-Service-Operation-DefaultSettings.js":173,"big.js":17,"fable-serviceproviderbase":59}],175:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceProgressTime extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ProgressTime';this.timeStamps={};}formatTimeDuration(pTimeDurationInMilliseconds){let tmpTimeDuration=typeof pTimeDurationInMilliseconds=='number'?pTimeDurationInMilliseconds:0;if(pTimeDurationInMilliseconds<0){return'unknown';}let tmpTimeDurationString='';if(tmpTimeDuration>3600000){tmpTimeDurationString+=Math.floor(tmpTimeDuration/3600000)+'h ';tmpTimeDuration=tmpTimeDuration%3600000;}if(tmpTimeDuration>60000){tmpTimeDurationString+=Math.floor(tmpTimeDuration/60000)+'m ';tmpTimeDuration=tmpTimeDuration%60000;}if(tmpTimeDuration>1000){tmpTimeDurationString+=Math.floor(tmpTimeDuration/1000)+'s ';tmpTimeDuration=tmpTimeDuration%1000;}tmpTimeDurationString+=Math.round(tmpTimeDuration)+'ms';return tmpTimeDurationString;}createTimeStamp(pTimeStampHash){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';this.timeStamps[tmpTimeStampHash]=+new Date();return this.timeStamps[tmpTimeStampHash];}getTimeStampValue(pTimeStampHash){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';return tmpTimeStampHash in this.timeStamps?this.timeStamps[tmpTimeStampHash]:-1;}updateTimeStampValue(pTimeStampHash,pReferenceTime){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';let tmpReferenceTime=false;// This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
4315
+ this.state.Steps.push(tmpStep);this.stepMap[tmpStep.GUIDStep]=tmpStep;this.stepFunctions[tmpStep.GUIDStep]=typeof fStepFunction=='function'?fStepFunction:function(fDone){return fDone();};this.state.Status.StepCount++;return tmpStep;}setStepTotalOperations(pGUIDStep,pTotalOperationCount){if(!(pGUIDStep in this.stepMap)){return new Error(`Step [${pGUIDStep}] does not exist in operation [${this.state.Metadata.UUID}] ${this.state.Metadata.Name} when attempting to set total operations to ${pTotalOperationCount}.`);}this.progressTrackerSet.setProgressTrackerTotalOperations(this.stepMap[pGUIDStep].ProgressTracker.Hash,pTotalOperationCount);}writeOperationLog(pLogLevel,pLogText,pLogObject){this.state.Log.push(`[${new Date().toUTCString()}]-[${pLogLevel}]: ${pLogText}`);if(typeof pLogObject=='object'){this.state.Log.push(JSON.stringify(pLogObject));}}writeOperationErrors(pLogText,pLogObject){this.state.Errors.push(`${pLogText}`);if(typeof pLogObject=='object'){this.state.Errors.push(JSON.stringify(pLogObject));}}trace(pLogText,pLogObject){this.writeOperationLog('TRACE',pLogText,pLogObject);this.fable.log.trace(pLogText,pLogObject);}debug(pLogText,pLogObject){this.writeOperationLog('DEBUG',pLogText,pLogObject);this.fable.log.debug(pLogText,pLogObject);}info(pLogText,pLogObject){this.writeOperationLog('INFO',pLogText,pLogObject);this.fable.log.info(pLogText,pLogObject);}warn(pLogText,pLogObject){this.writeOperationLog('WARN',pLogText,pLogObject);this.fable.log.warn(pLogText,pLogObject);}error(pLogText,pLogObject){this.writeOperationLog('ERROR',pLogText,pLogObject);this.writeOperationErrors(pLogText,pLogObject);this.fable.log.error(pLogText,pLogObject);}fatal(pLogText,pLogObject){this.writeOperationLog('FATAL',pLogText,pLogObject);this.writeOperationErrors(pLogText,pLogObject);this.fable.log.fatal(pLogText,pLogObject);}}module.exports=FableOperation;},{"./Fable-Service-Operation-DefaultSettings.js":174,"big.js":17,"fable-serviceproviderbase":59}],176:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceProgressTime extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ProgressTime';this.timeStamps={};}formatTimeDuration(pTimeDurationInMilliseconds){let tmpTimeDuration=typeof pTimeDurationInMilliseconds=='number'?pTimeDurationInMilliseconds:0;if(pTimeDurationInMilliseconds<0){return'unknown';}let tmpTimeDurationString='';if(tmpTimeDuration>3600000){tmpTimeDurationString+=Math.floor(tmpTimeDuration/3600000)+'h ';tmpTimeDuration=tmpTimeDuration%3600000;}if(tmpTimeDuration>60000){tmpTimeDurationString+=Math.floor(tmpTimeDuration/60000)+'m ';tmpTimeDuration=tmpTimeDuration%60000;}if(tmpTimeDuration>1000){tmpTimeDurationString+=Math.floor(tmpTimeDuration/1000)+'s ';tmpTimeDuration=tmpTimeDuration%1000;}tmpTimeDurationString+=Math.round(tmpTimeDuration)+'ms';return tmpTimeDurationString;}createTimeStamp(pTimeStampHash){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';this.timeStamps[tmpTimeStampHash]=+new Date();return this.timeStamps[tmpTimeStampHash];}getTimeStampValue(pTimeStampHash){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';return tmpTimeStampHash in this.timeStamps?this.timeStamps[tmpTimeStampHash]:-1;}updateTimeStampValue(pTimeStampHash,pReferenceTime){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';let tmpReferenceTime=false;// This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
4280
4316
  if(typeof pReferenceTime=='string'){tmpReferenceTime=tmpReference in this.timeStamps?this.timeStamps[tmpReference]:false;}else if(typeof pReferenceTime=='number'){tmpReferenceTime=pReferenceTime;}else{tmpReferenceTime=+new Date();}if(tmpTimeStampHash in this.timeStamps&&tmpReferenceTime){this.timeStamps[tmpTimeStampHash]=tmpReferenceTime;return this.timeStamps[tmpTimeStampHash];}else{return-1;}}removeTimeStamp(pTimeStampHash){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';if(tmpTimeStampHash in this.timeStamps){delete this.timeStamps[tmpTimeStampHash];return true;}else{return false;}}getTimeStampDelta(pTimeStampHash,pReferenceTime){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';let tmpReferenceTime=false;// This function allows the user to pass in either a reference time in ms, or, a hash of a timestamp.
4281
- if(typeof pReferenceTime=='string'){tmpReferenceTime=tmpReference in this.timeStamps?this.timeStamps[tmpReference]:false;}else if(typeof pReferenceTime=='number'){tmpReferenceTime=pReferenceTime;}else{tmpReferenceTime=+new Date();}if(tmpTimeStampHash in this.timeStamps&&tmpReferenceTime){return tmpReferenceTime-this.timeStamps[tmpTimeStampHash];}else{return-1;}}getDurationBetweenTimestamps(pTimeStampHashStart,pTimeStampHashEnd){let tmpTimeStampHashStart=typeof pTimeStampHashStart=='string'?pTimeStampHashStart:'Default';let tmpTimeStampHashEnd=typeof pTimeStampHashEnd=='string'?pTimeStampHashEnd:'Default';if(tmpTimeStampHashStart in this.timeStamps&&tmpTimeStampHashEnd in this.timeStamps){return this.timeStamps[tmpTimeStampHashEnd]-this.timeStamps[tmpTimeStampHashStart];}else{return-1;}}getTimeStampDeltaMessage(pTimeStampHash,pMessage,pReferenceTime){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';let tmpMessage=typeof pMessage!=='undefined'?pMessage:`Elapsed for ${tmpTimeStampHash}: `;let tmpOperationTime=this.getTimeStampDelta(tmpTimeStampHash,pReferenceTime);return`${tmpMessage} ${this.formatTimeDuration(tmpOperationTime)}`;}logTimeStampDelta(pTimeStampHash,pMessage,pReferenceTime){this.fable.log.info(this.getTimeStampDeltaMessage(pTimeStampHash,pMessage,pReferenceTime));}}module.exports=FableServiceProgressTime;},{"fable-serviceproviderbase":59}],176:[function(require,module,exports){class ProgressTracker{constructor(pProgressTrackerSet,pProgressTrackerHash){this.progressTrackerSet=pProgressTrackerSet;this.progressTrackerHash=pProgressTrackerHash;this.data=this.progressTrackerSet.getProgressTrackerData(this.progressTrackerHash);}updateProgressTracker(pProgressAmount){return this.progressTrackerSet.updateProgressTracker(this.progressTrackerHash,pProgressAmount);}incrementProgressTracker(pProgressIncrementAmount){return this.progressTrackerSet.incrementProgressTracker(this.progressTrackerHash,pProgressIncrementAmount);}setProgressTrackerTotalOperations(pTotalOperationCount){return this.progressTrackerSet.setProgressTrackerTotalOperations(this.progressTrackerHash,pTotalOperationCount);}getProgressTrackerStatusString(){return this.progressTrackerSet.getProgressTrackerStatusString(this.progressTrackerHash);}}module.exports=ProgressTracker;},{}],177:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');const libProgressTrackerClass=require('./Fable-Service-ProgressTracker/ProgressTracker.js');class FableServiceProgressTrackerSet extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ProgressTrackerSet';this.progressTrackers={};// Create an internal PorgressTime service to track timestamps
4317
+ if(typeof pReferenceTime=='string'){tmpReferenceTime=tmpReference in this.timeStamps?this.timeStamps[tmpReference]:false;}else if(typeof pReferenceTime=='number'){tmpReferenceTime=pReferenceTime;}else{tmpReferenceTime=+new Date();}if(tmpTimeStampHash in this.timeStamps&&tmpReferenceTime){return tmpReferenceTime-this.timeStamps[tmpTimeStampHash];}else{return-1;}}getDurationBetweenTimestamps(pTimeStampHashStart,pTimeStampHashEnd){let tmpTimeStampHashStart=typeof pTimeStampHashStart=='string'?pTimeStampHashStart:'Default';let tmpTimeStampHashEnd=typeof pTimeStampHashEnd=='string'?pTimeStampHashEnd:'Default';if(tmpTimeStampHashStart in this.timeStamps&&tmpTimeStampHashEnd in this.timeStamps){return this.timeStamps[tmpTimeStampHashEnd]-this.timeStamps[tmpTimeStampHashStart];}else{return-1;}}getTimeStampDeltaMessage(pTimeStampHash,pMessage,pReferenceTime){let tmpTimeStampHash=typeof pTimeStampHash=='string'?pTimeStampHash:'Default';let tmpMessage=typeof pMessage!=='undefined'?pMessage:`Elapsed for ${tmpTimeStampHash}: `;let tmpOperationTime=this.getTimeStampDelta(tmpTimeStampHash,pReferenceTime);return`${tmpMessage} ${this.formatTimeDuration(tmpOperationTime)}`;}logTimeStampDelta(pTimeStampHash,pMessage,pReferenceTime){this.fable.log.info(this.getTimeStampDeltaMessage(pTimeStampHash,pMessage,pReferenceTime));}}module.exports=FableServiceProgressTime;},{"fable-serviceproviderbase":59}],177:[function(require,module,exports){class ProgressTracker{constructor(pProgressTrackerSet,pProgressTrackerHash){this.progressTrackerSet=pProgressTrackerSet;this.progressTrackerHash=pProgressTrackerHash;this.data=this.progressTrackerSet.getProgressTrackerData(this.progressTrackerHash);}updateProgressTracker(pProgressAmount){return this.progressTrackerSet.updateProgressTracker(this.progressTrackerHash,pProgressAmount);}incrementProgressTracker(pProgressIncrementAmount){return this.progressTrackerSet.incrementProgressTracker(this.progressTrackerHash,pProgressIncrementAmount);}setProgressTrackerTotalOperations(pTotalOperationCount){return this.progressTrackerSet.setProgressTrackerTotalOperations(this.progressTrackerHash,pTotalOperationCount);}getProgressTrackerStatusString(){return this.progressTrackerSet.getProgressTrackerStatusString(this.progressTrackerHash);}}module.exports=ProgressTracker;},{}],178:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');const libProgressTrackerClass=require('./Fable-Service-ProgressTracker/ProgressTracker.js');class FableServiceProgressTrackerSet extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.serviceType='ProgressTrackerSet';this.progressTrackers={};// Create an internal PorgressTime service to track timestamps
4282
4318
  this.progressTimes=this.fable.instantiateServiceProviderWithoutRegistration('ProgressTime');// This timestamp is used and updated by *all* progress trackers.
4283
4319
  this.progressTimes.createTimeStamp('CurrentTime');}getProgressTracker(pProgressTrackerHash){let tmpProgressTrackerHash=typeof pProgressTrackerHash=='string'?pProgressTrackerHash:'Default';if(!(tmpProgressTrackerHash in this.progressTrackers)){this.fable.log.warn(`ProgressTracker ${tmpProgressTrackerHash} does not exist! Creating a new tracker...`);this.createProgressTracker(tmpProgressTrackerHash,100);}return new libProgressTrackerClass(this,pProgressTrackerHash);}getProgressTrackerData(pProgressTrackerHash){let tmpProgressTrackerHash=typeof pProgressTrackerHash=='string'?pProgressTrackerHash:'Default';if(!(tmpProgressTrackerHash in this.progressTrackers)){this.fable.log.warn(`ProgressTracker ${tmpProgressTrackerHash} does not exist! Creating a new tracker...`);this.createProgressTracker(tmpProgressTrackerHash,100);}return this.progressTrackers[tmpProgressTrackerHash];}createProgressTracker(pProgressTrackerHash,pTotalOperations){let tmpProgressTrackerHash=typeof pProgressTrackerHash=='string'?pProgressTrackerHash:'Default';let tmpTotalOperations=typeof pTotalOperations=='number'?pTotalOperations:100;let tmpProgressTracker={Hash:tmpProgressTrackerHash,StartTimeHash:`${tmpProgressTrackerHash}-Start`,StartTimeStamp:-1,CurrentTimeStamp:-1,EndTimeHash:`${tmpProgressTrackerHash}-End`,EndTimeStamp:-1,PercentComplete:-1,// If this is set to true, PercentComplete will be calculated as CurrentCount / TotalCount even if it goes over 100%
4284
4320
  AllowTruePercentComplete:false,ElapsedTime:-1,AverageOperationTime:-1,EstimatedCompletionTime:-1,TotalCount:tmpTotalOperations,CurrentCount:-1};if(tmpProgressTrackerHash in this.progressTrackers){this.fable.log.warn(`ProgressTracker ${tmpProgressTrackerHash} already exists! Overwriting with a new tracker...`);this.progressTimes.removeTimeStamp(tmpProgressTracker.StartTimeHash);this.progressTimes.removeTimeStamp(tmpProgressTracker.EndTimeHash);}this.progressTrackers[tmpProgressTrackerHash]=tmpProgressTracker;return tmpProgressTracker;}setProgressTrackerTotalOperations(pProgressTrackerHash,pTotalOperations){let tmpProgressTrackerHash=typeof pProgressTrackerHash=='string'?pProgressTrackerHash:'Default';let tmpTotalOperations=typeof pTotalOperations=='number'?pTotalOperations:100;if(!(tmpProgressTrackerHash in this.progressTrackers)){this.fable.log.warn(`Attempted to set the total operations of ProgressTracker ${tmpProgressTrackerHash} but it does not exist! Creating a new tracker...`);this.createProgressTracker(tmpProgressTrackerHash,tmpTotalOperations);}this.progressTrackers[tmpProgressTrackerHash].TotalCount=tmpTotalOperations;return this.progressTrackers[tmpProgressTrackerHash];}startProgressTracker(pProgressTrackerHash){let tmpProgressTrackerHash=typeof pProgressTrackerHash=='string'?pProgressTrackerHash:'Default';// This is the only method to lazily create ProgressTrackers now
@@ -4301,7 +4337,7 @@ this.solveProgressTrackerStatus(tmpProgressTrackerHash);if(!(tmpProgressTrackerH
4301
4337
  if(tmpProgressTracker.StartTimeStamp<1){return`ProgressTracker ${tmpProgressTracker.Hash} has not been started yet.`;}// 2. Started, but no operations completed
4302
4338
  if(tmpProgressTracker.CurrentCount<1&&tmpProgressTracker.EndTimeStamp<1){return`ProgressTracker ${tmpProgressTracker.Hash} has no completed operations. ${this.progressTimes.formatTimeDuration(tmpProgressTracker.ElapsedTime)} have elapsed since it was started.`;}// 3. Started, some operations completed
4303
4339
  else if(tmpProgressTracker.EndTimeStamp<1){return`ProgressTracker ${tmpProgressTracker.Hash} is ${tmpProgressTracker.PercentComplete.toFixed(3)}% completed - ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations over ${this.progressTimes.formatTimeDuration(tmpProgressTracker.ElapsedTime)} (median ${this.progressTimes.formatTimeDuration(tmpProgressTracker.AverageOperationTime)} per). Estimated completion: ${this.progressTimes.formatTimeDuration(tmpProgressTracker.EstimatedCompletionTime)}`;}// 4. Done
4304
- else{return`ProgressTracker ${tmpProgressTracker.Hash} is done. ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations were completed in ${this.progressTimes.formatTimeDuration(tmpProgressTracker.ElapsedTime)} (median ${this.progressTimes.formatTimeDuration(tmpProgressTracker.AverageOperationTime)} per).`;}}}logProgressTrackerStatus(pProgressTrackerHash){this.fable.log.info(this.getProgressTrackerStatusString(pProgressTrackerHash));}}module.exports=FableServiceProgressTrackerSet;},{"./Fable-Service-ProgressTracker/ProgressTracker.js":176,"fable-serviceproviderbase":59}],178:[function(require,module,exports){(function(Buffer){(function(){const libFableServiceBase=require('fable-serviceproviderbase');const libSimpleGet=require('simple-get');const libCookie=require('cookie');class FableServiceRestClient extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.TraceLog=false;if(this.options.TraceLog||this.fable.TraceLog){this.TraceLog=true;}this.dataFormat=this.fable.services.DataFormat;this.serviceType='RestClient';this.cookie=false;// This is a function that can be overridden, to allow the management
4340
+ else{return`ProgressTracker ${tmpProgressTracker.Hash} is done. ${tmpProgressTracker.CurrentCount} / ${tmpProgressTracker.TotalCount} operations were completed in ${this.progressTimes.formatTimeDuration(tmpProgressTracker.ElapsedTime)} (median ${this.progressTimes.formatTimeDuration(tmpProgressTracker.AverageOperationTime)} per).`;}}}logProgressTrackerStatus(pProgressTrackerHash){this.fable.log.info(this.getProgressTrackerStatusString(pProgressTrackerHash));}}module.exports=FableServiceProgressTrackerSet;},{"./Fable-Service-ProgressTracker/ProgressTracker.js":177,"fable-serviceproviderbase":59}],179:[function(require,module,exports){(function(Buffer){(function(){const libFableServiceBase=require('fable-serviceproviderbase');const libSimpleGet=require('simple-get');const libCookie=require('cookie');class FableServiceRestClient extends libFableServiceBase{constructor(pFable,pOptions,pServiceHash){super(pFable,pOptions,pServiceHash);this.TraceLog=false;if(this.options.TraceLog||this.fable.TraceLog){this.TraceLog=true;}this.dataFormat=this.fable.services.DataFormat;this.serviceType='RestClient';this.cookie=false;// This is a function that can be overridden, to allow the management
4305
4341
  // of the request options before they are passed to the request library.
4306
4342
  this.prepareRequestOptions=pOptions=>{return pOptions;};}get simpleGet(){return libSimpleGet;}prepareCookies(pRequestOptions){if(this.cookie){let tmpCookieObject=this.cookie;if(!('headers'in pRequestOptions)){pRequestOptions.headers={};}let tmpCookieKeys=Object.keys(tmpCookieObject);if(tmpCookieKeys.length>0){// Only grab the first for now.
4307
4343
  pRequestOptions.headers.cookie=libCookie.serialize(tmpCookieKeys[0],tmpCookieObject[tmpCookieKeys[0]]);}}return pRequestOptions;}preRequest(pOptions){// Validate the options object
@@ -4314,7 +4350,7 @@ if(!tmpDataBuffer){tmpDataBuffer=Buffer.from(pChunk);}else{tmpDataBuffer=Buffer.
4314
4350
  {
4315
4351
  tmpOptions.headers['Content-Type'] = 'application/json';
4316
4352
  }
4317
- */tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} JSON request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}return libSimpleGet(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpJSONData='';pResponse.on('data',pChunk=>{if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpJSONData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> JSON ${tmpOptions.method} completed - received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}return fCallback(pError,pResponse,JSON.parse(tmpJSONData));});});}getJSON(pOptionsOrURL,fCallback){let tmpRequestOptions=typeof pOptionsOrURL=='object'?pOptionsOrURL:{};if(typeof pOptionsOrURL=='string'){tmpRequestOptions.url=pOptionsOrURL;}tmpRequestOptions.method='GET';return this.executeJSONRequest(tmpRequestOptions,fCallback);}putJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`PUT JSON Error Invalid options object`));}pOptions.method='PUT';return this.executeJSONRequest(pOptions,fCallback);}postJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`POST JSON Error Invalid options object`));}pOptions.method='POST';return this.executeJSONRequest(pOptions,fCallback);}patchJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`PATCH JSON Error Invalid options object`));}pOptions.method='PATCH';return this.executeJSONRequest(pOptions,fCallback);}headJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`HEAD JSON Error Invalid options object`));}pOptions.method='HEAD';return this.executeJSONRequest(pOptions,fCallback);}delJSON(pOptions,fCallback){pOptions.method='DELETE';return this.executeJSONRequest(pOptions,fCallback);}getRawText(pOptionsOrURL,fCallback){let tmpRequestOptions=typeof pOptionsOrURL=='object'?pOptionsOrURL:{};if(typeof pOptionsOrURL=='string'){tmpRequestOptions.url=pOptionsOrURL;}tmpRequestOptions.method='GET';return this.executeChunkedRequest(tmpRequestOptions,fCallback);}}module.exports=FableServiceRestClient;}).call(this);}).call(this,require("buffer").Buffer);},{"buffer":20,"cookie":31,"fable-serviceproviderbase":59,"simple-get":123}],179:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceTemplate extends libFableServiceBase{// Underscore and lodash have a behavior, _.template, which compiles a
4353
+ */tmpOptions.RequestStartTime=this.fable.log.getTimeStamp();if(this.TraceLog){this.fable.log.debug(`Beginning ${tmpOptions.method} JSON request to ${tmpOptions.url} at ${tmpOptions.RequestStartTime}`);}return libSimpleGet(tmpOptions,(pError,pResponse)=>{if(pError){return fCallback(pError,pResponse);}if(this.TraceLog){let tmpConnectTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} connected in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpConnectTime)}ms code ${pResponse.statusCode}`);}let tmpJSONData='';pResponse.on('data',pChunk=>{if(this.TraceLog){let tmpChunkTime=this.fable.log.getTimeStamp();this.fable.log.debug(`--> JSON ${tmpOptions.method} data chunk size ${pChunk.length}b received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpChunkTime)}ms`);}tmpJSONData+=pChunk;});pResponse.on('end',()=>{if(this.TraceLog){let tmpCompletionTime=this.fable.log.getTimeStamp();this.fable.log.debug(`==> JSON ${tmpOptions.method} completed - received in ${this.dataFormat.formatTimeDelta(tmpOptions.RequestStartTime,tmpCompletionTime)}ms`);}return fCallback(pError,pResponse,JSON.parse(tmpJSONData));});});}getJSON(pOptionsOrURL,fCallback){let tmpRequestOptions=typeof pOptionsOrURL=='object'?pOptionsOrURL:{};if(typeof pOptionsOrURL=='string'){tmpRequestOptions.url=pOptionsOrURL;}tmpRequestOptions.method='GET';return this.executeJSONRequest(tmpRequestOptions,fCallback);}putJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`PUT JSON Error Invalid options object`));}pOptions.method='PUT';return this.executeJSONRequest(pOptions,fCallback);}postJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`POST JSON Error Invalid options object`));}pOptions.method='POST';return this.executeJSONRequest(pOptions,fCallback);}patchJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`PATCH JSON Error Invalid options object`));}pOptions.method='PATCH';return this.executeJSONRequest(pOptions,fCallback);}headJSON(pOptions,fCallback){if(typeof pOptions.body!='object'){return fCallback(new Error(`HEAD JSON Error Invalid options object`));}pOptions.method='HEAD';return this.executeJSONRequest(pOptions,fCallback);}delJSON(pOptions,fCallback){pOptions.method='DELETE';return this.executeJSONRequest(pOptions,fCallback);}getRawText(pOptionsOrURL,fCallback){let tmpRequestOptions=typeof pOptionsOrURL=='object'?pOptionsOrURL:{};if(typeof pOptionsOrURL=='string'){tmpRequestOptions.url=pOptionsOrURL;}tmpRequestOptions.method='GET';return this.executeChunkedRequest(tmpRequestOptions,fCallback);}}module.exports=FableServiceRestClient;}).call(this);}).call(this,require("buffer").Buffer);},{"buffer":20,"cookie":31,"fable-serviceproviderbase":59,"simple-get":123}],180:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');class FableServiceTemplate extends libFableServiceBase{// Underscore and lodash have a behavior, _.template, which compiles a
4318
4354
  // string-based template with code snippets into simple executable pieces,
4319
4355
  // with the added twist of returning a precompiled function ready to go.
4320
4356
  //
@@ -4334,7 +4370,7 @@ this.renderFunction=false;this.templateString=false;}renderTemplate(pData){retur
4334
4370
  // underscore code until this is rewritten using precedent.
4335
4371
  this.TemplateSource="__p+='"+pTemplateText.replace(this.Matchers.Escaper,pMatch=>{return`\\${this.templateEscapes[pMatch]}`;}).replace(this.Matchers.Interpolate||this.Matchers.GuaranteedNonMatch,(pMatch,pCode)=>{return`'+\n(${decodeURIComponent(pCode)})+\n'`;}).replace(this.Matchers.Evaluate||this.Matchers.GuaranteedNonMatch,(pMatch,pCode)=>{return`';\n${decodeURIComponent(pCode)}\n;__p+='`;})+`';\n`;this.TemplateSource=`with(pTemplateDataObject||{}){\n${this.TemplateSource}}\n`;this.TemplateSource=`var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n${this.TemplateSource}return __p;\n`;this.renderFunction=new Function('pTemplateDataObject',this.TemplateSource);if(typeof pData!='undefined'){return this.renderFunction(pData);}// Provide the compiled function source as a convenience for build time
4336
4372
  // precompilation.
4337
- this.TemplateSourceCompiled='function(obj){\n'+this.TemplateSource+'}';return this.templateFunction();}}module.exports=FableServiceTemplate;},{"fable-serviceproviderbase":59}],180:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');// TODO: These are still pretty big -- consider the smaller polyfills
4373
+ this.TemplateSourceCompiled='function(obj){\n'+this.TemplateSource+'}';return this.templateFunction();}}module.exports=FableServiceTemplate;},{"fable-serviceproviderbase":59}],181:[function(require,module,exports){const libFableServiceBase=require('fable-serviceproviderbase');// TODO: These are still pretty big -- consider the smaller polyfills
4338
4374
  const libAsyncWaterfall=require('async.waterfall');const libAsyncEachLimit=require('async.eachlimit');const libBigNumber=require('big.js');class FableServiceUtility extends libFableServiceBase{// Underscore and lodash have a behavior, _.template, which compiles a
4339
4375
  // string-based template with code snippets into simple executable pieces,
4340
4376
  // with the added twist of returning a precompiled function ready to go.
@@ -4459,5 +4495,14 @@ if(!this.manifest){this.manifest=this.fable.newManyfest();}if(!Array.isArray(pOb
4459
4495
  * @param {string} pValueAddress - The manyfest hash/address of the value to return
4460
4496
  * @returns {any} - The value from the object
4461
4497
  */findFirstValueByExactMatchInternal(pFableAddress,pValueToMatchAddress,pValueToMatch,pValueAddress){// Lazily create a manifest if it doesn't exist
4462
- if(!this.manifest){this.manifest=this.fable.newManyfest();}if(typeof pFableAddress!='string'){return undefined;}let tmpObjectArray=this.manifest.getValueByHash(this.fable,pFableAddress);return this.findFirstValueByExactMatch(tmpObjectArray,pValueToMatchAddress,pValueToMatch,pValueAddress);}}module.exports=FableServiceUtility;},{"async.eachlimit":1,"async.waterfall":15,"big.js":17,"fable-serviceproviderbase":59}]},{},[150])(150);});
4498
+ if(!this.manifest){this.manifest=this.fable.newManyfest();}if(typeof pFableAddress!='string'){return undefined;}let tmpObjectArray=this.manifest.getValueByHash(this.fable,pFableAddress);return this.findFirstValueByExactMatch(tmpObjectArray,pValueToMatchAddress,pValueToMatch,pValueAddress);}/**
4499
+ * Flatten an array of solver inputs into a single array
4500
+ *
4501
+ * @param {Array<any>} pInputArray - The array of inputs to flatten
4502
+ * @return {Array<any>} - The flattened array
4503
+ */flattenArrayOfSolverInputs(pInputArray){if(!Array.isArray(pInputArray)){if(typeof pInputArray==='object'){pInputArray=Object.values(pInputArray);}if(!pInputArray){return[];}}const tmpArrayFlattener=p=>{if(Array.isArray(p)){return p;// .flatMap(tmpArrayFlattener);
4504
+ }if(typeof p==='object'){return Object.values(p);}return[p];};return pInputArray.flatMap(tmpArrayFlattener);}}module.exports=FableServiceUtility;},{"async.eachlimit":1,"async.waterfall":15,"big.js":17,"fable-serviceproviderbase":59}],182:[function(require,module,exports){class SetConcatArray{/**
4505
+ * @param {Array<any>|SetConcatArray} pLeftValue - The left value to concatenate.
4506
+ * @param {Array<any>|SetConcatArray} pRightValue - The right value to concatenate.
4507
+ */constructor(pLeftValue,pRightValue){if(pLeftValue instanceof SetConcatArray){this.values=pLeftValue.values.concat([pRightValue]);}else if(pRightValue instanceof SetConcatArray){this.values=[pLeftValue].concat(pRightValue.values);}else{this.values=[pLeftValue,pRightValue];}}}module.exports=SetConcatArray;},{}]},{},[150])(150);});
4463
4508
  //# sourceMappingURL=fable.js.map