{"version":3,"file":"gp-advanced-calculations.js","mappings":"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","sources":["webpack:///./js/src/frontend.ts"],"sourcesContent":["/* eslint-disable vars-on-top, no-shadow, @typescript-eslint/no-shadow */\nconst shorthandVariableRegex = /F(\\d+(?:\\.\\d+)?)/gm;\n\ninterface GPAdvancedCalculationsConfig {\n\tformId: string;\n}\n\ninterface FormulaField {\n\tfield_id: number;\n\tformula: string;\n\trounding: string | number;\n}\n\ntype ParsedFormulaItem = (\n\t| ParsedFormulaOperatorItem\n\t| ParsedFormulaSepItem\n\t| ParsedFormulaFunctionItem\n\t| ParsedFormulaValueItem\n\t| ParsedFormulaComparisonOpItem\n\t| ParsedFormulaLogicalOpItem\n) & {\n\tdepth: number;\n\tprocessedAtDepth?: number;\n\tnonFunctionItem?: boolean;\n};\n\ninterface ParsedFormulaSepItem {\n\ttype: 'sep';\n\tvalue: ',';\n}\n\ntype Operator = '*' | '-' | '+' | '/' | '^' | '%';\n\ninterface ParsedFormulaOperatorItem {\n\ttype: 'operator';\n\tvalue: Operator;\n}\n\ninterface ParsedFormulaFunctionItem {\n\ttype: 'function';\n\tvalue: string;\n}\n\ninterface ParsedFormulaValueItem {\n\ttype: 'value';\n\tvalue: number | string; // String for merge tags\n}\n\ninterface ParsedFormulaComparisonOpItem {\n\ttype: 'comparisonOp';\n\tvalue: string;\n}\n\ninterface ParsedFormulaLogicalOpItem {\n\ttype: 'logicalOp';\n\tvalue: string;\n}\n\ntype ParsedFormula = ParsedFormulaItem[];\n\nclass GPAdvancedCalculations {\n\tpublic formId: number;\n\n\t/* Used over Math.PI to keep precision consistent between PHP and JS. */\n\treadonly pi20DecimalPlaces = 3.14159265358979323846;\n\n\tconstructor({ formId }: GPAdvancedCalculationsConfig) {\n\t\tthis.formId = parseInt(formId);\n\n\t\tthis.init();\n\t}\n\n\tinit = () => {\n\t\twindow.gform.addFilter(\n\t\t\t'gform_calculation_formula',\n\t\t\t(\n\t\t\t\tformula: string,\n\t\t\t\tformulaField: FormulaField,\n\t\t\t\tformId: string,\n\t\t\t\tcalcObj: any\n\t\t\t) => {\n\t\t\t\tif (parseInt(formId) !== this.formId) {\n\t\t\t\t\treturn formula;\n\t\t\t\t}\n\n\t\t\t\tformula = this.replaceShorthandVariables(\n\t\t\t\t\tformula,\n\t\t\t\t\tformulaField,\n\t\t\t\t\tthis.formId\n\t\t\t\t);\n\t\t\t\tformula = this.processConditionals(\n\t\t\t\t\tformula,\n\t\t\t\t\tformulaField,\n\t\t\t\t\tthis.formId,\n\t\t\t\t\tcalcObj\n\t\t\t\t);\n\t\t\t\tformula = this.processExponents(\n\t\t\t\t\tformula,\n\t\t\t\t\tformulaField,\n\t\t\t\t\tthis.formId,\n\t\t\t\t\tcalcObj\n\t\t\t\t);\n\t\t\t\tformula = this.processFunctions(\n\t\t\t\t\tformula,\n\t\t\t\t\tformulaField,\n\t\t\t\t\tthis.formId,\n\t\t\t\t\tcalcObj\n\t\t\t\t);\n\n\t\t\t\treturn formula;\n\t\t\t},\n\t\t\t15\n\t\t);\n\n\t\tjQuery(document).trigger('gform_post_conditional_logic');\n\n\t\tthis.bindShorthandCalcEvents();\n\t\tthis.addGPPAListener();\n\t};\n\n\t/**\n\t * Used for binding the calculation events on fields referenced in formulas using shorthand variables.\n\t *\n\t * Loosely based on GFCalc.bindCalcEvents\n\t */\n\tbindShorthandCalcEvents = () => {\n\t\tconst calcObj = window.gf_global.gfcalc[this.formId];\n\t\tconst { formulaFields, formId } = calcObj;\n\n\t\tfor (let i = 0; i < formulaFields.length; i++) {\n\t\t\tconst formulaField: FormulaField = jQuery.extend(\n\t\t\t\t{},\n\t\t\t\tformulaFields[i]\n\t\t\t);\n\t\t\tconst formulaFieldId = formulaField.field_id;\n\n\t\t\tconst matches = formulaField.formula.match(shorthandVariableRegex);\n\n\t\t\tcalcObj.isCalculating[formulaFieldId] = false;\n\n\t\t\tfor (const i in matches) {\n\t\t\t\tif (!matches.hasOwnProperty(i)) continue;\n\n\t\t\t\t// @ts-ignore\n\t\t\t\tconst inputId = matches[i].replace(/^F/, '');\n\t\t\t\tconst fieldId = parseInt(inputId, 10);\n\t\t\t\tconst input = jQuery('#field_' + formId + '_' + fieldId).find(\n\t\t\t\t\t'input[name=\"input_' +\n\t\t\t\t\t\tinputId +\n\t\t\t\t\t\t'\"], select[name=\"input_' +\n\t\t\t\t\t\tinputId +\n\t\t\t\t\t\t'\"]'\n\t\t\t\t);\n\n\t\t\t\tconst eventNamespace = `gpacShorthand_${formulaFieldId}`;\n\n\t\t\t\t// Prevent double-binding\n\t\t\t\tjQuery(input).off(`.${eventNamespace}`);\n\n\t\t\t\tif (\n\t\t\t\t\tinput.prop('type') === 'checkbox' ||\n\t\t\t\t\tinput.prop('type') === 'radio'\n\t\t\t\t) {\n\t\t\t\t\tjQuery(input).on(`click.${eventNamespace}`, function() {\n\t\t\t\t\t\tcalcObj.bindCalcEvent(inputId, formulaField, formId, 0);\n\t\t\t\t\t});\n\t\t\t\t} else if (\n\t\t\t\t\tinput.is('select') ||\n\t\t\t\t\tinput.prop('type') === 'hidden'\n\t\t\t\t) {\n\t\t\t\t\tjQuery(input).on(`change.${eventNamespace}`, function() {\n\t\t\t\t\t\tcalcObj.bindCalcEvent(inputId, formulaField, formId, 0);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tjQuery(input).on(\n\t\t\t\t\t\t`change.${eventNamespace} keydown.${eventNamespace}`,\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\tcalcObj.bindCalcEvent(\n\t\t\t\t\t\t\t\tinputId,\n\t\t\t\t\t\t\t\tformulaField,\n\t\t\t\t\t\t\t\tformId,\n\t\t\t\t\t\t\t\t0\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// allow users to add custom methods for triggering calculations\n\t\t\t\twindow.gform.doAction(\n\t\t\t\t\t'gform_post_calculation_events',\n\t\t\t\t\t// @ts-ignore\n\t\t\t\t\t[matches[i], inputId],\n\t\t\t\t\tformulaField,\n\t\t\t\t\tformId,\n\t\t\t\t\tcalcObj\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Listen for field's being refreshed by GPPA and rebind as needed.\n\t */\n\taddGPPAListener = () => {\n\t\tjQuery(document).on('gppa_updated_batch_fields', (event, formId) => {\n\t\t\t// eslint-disable-next-line eqeqeq\n\t\t\tif (this.formId != formId) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.bindShorthandCalcEvents();\n\t\t});\n\t};\n\n\tprocessConditionals = (\n\t\tformula: string,\n\t\tformulaField: FormulaField,\n\t\tformId: number,\n\t\tcalcObj: any\n\t) => {\n\t\t// eslint-disable-line no-unused-vars\n\t\tlet match;\n\n\t\tconst regex = /^if\\s*\\((.+)\\)\\s*:[\\s]+(.+)[\\s]+((?:elseif\\s*\\(.+\\)\\s*:[\\s]+.+[\\s]+)*?)else\\s*:[\\s]+(.+)[\\s]+endif\\s*;/g,\n\t\t\telseIfRegex = /(?:elseif\\s*\\((.+)\\)\\s*:[\\s]+(.+))+/g;\n\n\t\tlet modified = formula;\n\n\t\twhile ((match = regex.exec(formula)) !== null) {\n\t\t\tlet elseIfMatch;\n\n\t\t\tconst fullMatch = match[0],\n\t\t\t\telseIfs = match[3],\n\t\t\t\tstatements = [];\n\n\t\t\tstatements.push({\n\t\t\t\ttag: 'if',\n\t\t\t\tcondition: this.replaceMergeTags(\n\t\t\t\t\tmatch[1],\n\t\t\t\t\tformulaField,\n\t\t\t\t\tformId\n\t\t\t\t),\n\t\t\t\tformula: match[2],\n\t\t\t});\n\n\t\t\tif (elseIfs) {\n\t\t\t\twhile ((elseIfMatch = elseIfRegex.exec(elseIfs)) !== null) {\n\t\t\t\t\tstatements.push({\n\t\t\t\t\t\ttag: 'elseif',\n\t\t\t\t\t\tcondition: this.replaceMergeTags(\n\t\t\t\t\t\t\telseIfMatch[1],\n\t\t\t\t\t\t\tformulaField,\n\t\t\t\t\t\t\tformId\n\t\t\t\t\t\t),\n\t\t\t\t\t\tformula: elseIfMatch[2],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstatements.push({\n\t\t\t\ttag: 'else',\n\t\t\t\tcondition: null,\n\t\t\t\tformula: match[4],\n\t\t\t});\n\n\t\t\t// @ts-ignore\n\t\t\tjQuery.each(statements, (i, statement) => {\n\t\t\t\tlet condition: string | null = statement.condition;\n\n\t\t\t\tif (condition) {\n\t\t\t\t\tcondition = this.processExponents(\n\t\t\t\t\t\tcondition,\n\t\t\t\t\t\tformulaField,\n\t\t\t\t\t\tthis.formId,\n\t\t\t\t\t\tcalcObj\n\t\t\t\t\t);\n\n\t\t\t\t\tcondition = this.processFunctions(\n\t\t\t\t\t\tcondition,\n\t\t\t\t\t\tformulaField,\n\t\t\t\t\t\tthis.formId,\n\t\t\t\t\t\tcalcObj\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t(statement.tag === 'else' &&\n\t\t\t\t\t\tstatement.condition === null) ||\n\t\t\t\t\t!!this.evalFormula(condition!, formulaField.field_id)\n\t\t\t\t) {\n\t\t\t\t\tmodified = modified.replace(fullMatch, statement.formula);\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn modified;\n\t};\n\n\treplaceShorthandVariables = (\n\t\tformula: string,\n\t\tformulaField: FormulaField,\n\t\tformId: number\n\t) => {\n\t\t// Shorthand Field Variables\n\t\tlet shorthandVariableMatch;\n\n\t\twhile (\n\t\t\t(shorthandVariableMatch = new RegExp(shorthandVariableRegex).exec(\n\t\t\t\tformula\n\t\t\t)) !== null\n\t\t) {\n\t\t\tconst [fullMatch, inputId] = shorthandVariableMatch;\n\n\t\t\tformula = formula.replace(\n\t\t\t\t/* Use negative lookahead to prevent partial matches. e.g. if replacing F4, don't replace F43. */\n\t\t\t\tnew RegExp(`${fullMatch}(?!\\d)`),\n\t\t\t\tthis.replaceMergeTag(inputId, undefined, formulaField, formId)\n\t\t\t);\n\t\t}\n\n\t\treturn formula;\n\t};\n\n\treplaceMergeTags = (\n\t\tformula: string,\n\t\tformulaField: FormulaField,\n\t\tformId: number\n\t) => {\n\t\t// Regular Field Variable Merge Tags\n\t\tconst matches = window.GFMergeTag.parseMergeTags(formula);\n\n\t\tfor (const i in matches) {\n\t\t\tif (!matches.hasOwnProperty(i)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tformula = formula.replace(\n\t\t\t\tmatches[i][0],\n\t\t\t\tthis.replaceMergeTag(\n\t\t\t\t\tmatches[i][1],\n\t\t\t\t\tmatches[i][3],\n\t\t\t\t\tformulaField,\n\t\t\t\t\tformId\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn this.replaceShorthandVariables(formula, formulaField, formId);\n\t};\n\n\treplaceMergeTag = (\n\t\tinputId: string,\n\t\tmodifier: string = 'value',\n\t\tformulaField: FormulaField,\n\t\tformId: number\n\t) => {\n\t\tconst fieldId = parseInt(inputId, 10);\n\n\t\tif (!modifier) {\n\t\t\tconst isProductRadio = jQuery(\n\t\t\t\t'.gfield_price input[name=input_' + fieldId + ']'\n\t\t\t).is('input[type=radio]');\n\t\t\tconst isProductDropdown =\n\t\t\t\tjQuery('.gfield_price select[name=input_' + fieldId + ']')\n\t\t\t\t\t.length > 0;\n\t\t\tconst isOptionCheckbox = jQuery(\n\t\t\t\t'.gfield_price input[name=\"input_' + inputId + '\"]'\n\t\t\t).is('input[type=checkbox]');\n\n\t\t\tif (isProductDropdown || isProductRadio || isOptionCheckbox) {\n\t\t\t\tmodifier = 'price';\n\t\t\t}\n\t\t}\n\n\t\tconst isVisible = window.gf_check_field_rule\n\t\t\t? window.gf_check_field_rule(formId, fieldId, true, '') === 'show'\n\t\t\t: true;\n\n\t\tlet value = isVisible\n\t\t\t? window.GFMergeTag.getMergeTagValue(formId, inputId, modifier)\n\t\t\t: 0;\n\n\t\tif (\n\t\t\t/**\n\t\t\t * Filter whether a number from a merge tag replacement should be cleaned (e.g. commas and currency removed).\n\t\t\t *\n\t\t\t * @since 1.0.2\n\t\t\t *\n\t\t\t * @param boolean shouldClean \tWhether the number should be cleaned.\n\t\t\t * @param string value \t\t\tThe value from the merge tag replacement.\n\t\t\t * @param number formId \t\t\tThe current form ID.\n\t\t\t * @param number fieldId \t\tThe field that the value is being pulled from.\n\t\t\t * @param object formulaField \tThe current field having its formula evaluated. Contains properties such as `field_id`, `formula`, and `rounding`.\n\t\t\t */\n\t\t\twindow.gform.applyFilters(\n\t\t\t\t'gpac_should_clean_merge_tag_value',\n\t\t\t\ttrue,\n\t\t\t\tvalue,\n\t\t\t\tformId,\n\t\t\t\tfieldId,\n\t\t\t\tformulaField\n\t\t\t) &&\n\t\t\t/*\n\t\t\t * Make sure `gfcalc` is available as it sometimes isn't available if using the Beaver Builder\n\t\t\t * editor. See ticket #48623\n\t\t\t */\n\t\t\ttypeof window.gf_global.gfcalc[formId] !== 'undefined'\n\t\t) {\n\t\t\tvalue = window.gf_global.gfcalc[formId].cleanNumber(\n\t\t\t\tvalue,\n\t\t\t\tformId,\n\t\t\t\tfieldId,\n\t\t\t\tformulaField\n\t\t\t);\n\t\t}\n\n\t\treturn value;\n\t};\n\n\tprocessExponents = (\n\t\tformula: string,\n\t\tformulaField: FormulaField,\n\t\tformId: number,\n\t\tcalcObj: any\n\t) => {\n\t\tconst items = this.parseFormula(formula),\n\t\t\tprocessed: ParsedFormula = [];\n\n\t\twhile (items.length > 0) {\n\t\t\tconst rootItem = items.shift()!;\n\n\t\t\tif (rootItem.type !== 'operator' || rootItem.value !== '^') {\n\t\t\t\tprocessed.push(rootItem);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst targetDepth = rootItem.depth;\n\n\t\t\t// get the base: dip back into the processed items and find all items that are at the same or greater depth than our target\n\t\t\tconst base: ParsedFormula = [];\n\t\t\twhile (processed.length > 0) {\n\t\t\t\tconst item = processed.pop()!;\n\t\t\t\t// accepts a single item at the same depth and only if an item of a greater depth has not already been added\n\t\t\t\tif (item.depth === targetDepth) {\n\t\t\t\t\tif (base.length === 0) {\n\t\t\t\t\t\tbase.push(item);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprocessed.push(item);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t// accepts multiple items at a greater depth\n\t\t\t\t} else if (item.depth > targetDepth) {\n\t\t\t\t\tbase.push(item);\n\t\t\t\t} else {\n\t\t\t\t\tprocessed.push(item);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.reverse();\n\n\t\t\t// get the power: only the first item at target depth or all items below target depth\n\t\t\tconst pow: ParsedFormula = [];\n\t\t\twhile (items.length > 0) {\n\t\t\t\tconst item = items.shift()!; // eslint-disable-line no-redeclare\n\t\t\t\t// accepts a single item at the same depth and only if an item of a greater depth has not already been added\n\t\t\t\tif (item.depth === targetDepth) {\n\t\t\t\t\tif (pow.length === 0) {\n\t\t\t\t\t\tpow.push(item);\n\t\t\t\t\t} else {\n\t\t\t\t\t\titems.unshift(item);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t// accepts multiple items at a greater depth\n\t\t\t\t} else if (item.depth > targetDepth) {\n\t\t\t\t\tpow.push(item);\n\t\t\t\t\t// if item is at a lesser depth, we're done collecting the pow. Add the current item back to the queue\n\t\t\t\t\t// so the outer while loop and loop for any other exponents.\n\t\t\t\t} else {\n\t\t\t\t\titems.unshift(item);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst baseEvaled = this.evalFormula(\n\t\t\t\tthis.processFunctions(\n\t\t\t\t\tcalcObj.replaceFieldTags(\n\t\t\t\t\t\tformId,\n\t\t\t\t\t\tthis.buildFormula(base),\n\t\t\t\t\t\tformulaField\n\t\t\t\t\t),\n\t\t\t\t\tformulaField,\n\t\t\t\t\tformId,\n\t\t\t\t\tcalcObj\n\t\t\t\t),\n\t\t\t\tformulaField.field_id\n\t\t\t);\n\n\t\t\tconst powEvaled = this.evalFormula(\n\t\t\t\tthis.processFunctions(\n\t\t\t\t\tcalcObj.replaceFieldTags(\n\t\t\t\t\t\tformId,\n\t\t\t\t\t\tthis.buildFormula(pow),\n\t\t\t\t\t\tformulaField\n\t\t\t\t\t),\n\t\t\t\t\tformulaField,\n\t\t\t\t\tformId,\n\t\t\t\t\tcalcObj\n\t\t\t\t),\n\t\t\t\tformulaField.field_id\n\t\t\t);\n\n\t\t\tprocessed.push({\n\t\t\t\t...rootItem,\n\t\t\t\ttype: 'value',\n\t\t\t\tvalue: Math.pow(baseEvaled, powEvaled),\n\t\t\t});\n\t\t}\n\n\t\tformula = this.buildFormula(processed);\n\n\t\treturn formula;\n\t};\n\n\tevalFormula = (formula: string, fieldId?: number) => {\n\t\tlet result = 0;\n\n\t\ttry {\n\t\t\tformula = formula.trim();\n\n\t\t\tif (formula.match(/^[0-9 +\\-\\/*()^><.=%&|!]+$/)) {\n\t\t\t\t// eslint-disable-next-line no-eval\n\t\t\t\tresult = eval(formula);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconst warning = fieldId\n\t\t\t\t? `GP Advanced Calculations: Could not process formula in field ID ${fieldId}. Formula: ${formula}`\n\t\t\t\t: `GP Advanced Calculations: Could not process formula. Formula: ${formula}`;\n\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(warning, e);\n\t\t}\n\n\t\treturn result;\n\t};\n\n\tprocessFunctions = (\n\t\tformula: string,\n\t\tformulaField: FormulaField,\n\t\tformId: number,\n\t\tcalcObj: any\n\t) => {\n\t\tlet items: ParsedFormula = this.parseFormula(formula);\n\n\t\t// Short-circuit if there are no functions.\n\t\tif (!items.some((item) => item.type === 'function')) {\n\t\t\treturn this.buildFormula(items);\n\t\t}\n\n\t\tconst functions: {\n\t\t\t[name: string]: (...args: any[]) => number;\n\t\t} = {\n\t\t\tabs: Math.abs,\n\t\t\taverage() {\n\t\t\t\treturn (\n\t\t\t\t\tArray.prototype.slice\n\t\t\t\t\t\t// eslint-disable-next-line prefer-rest-params\n\t\t\t\t\t\t.call(arguments)\n\t\t\t\t\t\t.reduce(function(a, b) {\n\t\t\t\t\t\t\treturn a + b;\n\t\t\t\t\t\t}, 0) / arguments.length\n\t\t\t\t);\n\t\t\t},\n\t\t\tceil: Math.ceil,\n\t\t\texp: Math.exp,\n\t\t\tfloor: Math.floor,\n\t\t\tfv(\n\t\t\t\trate: number,\n\t\t\t\tnumberOfPeriods: number,\n\t\t\t\tpaymentAmount: number,\n\t\t\t\tpresentValue: number,\n\t\t\t\tendOrBeginning: 0 | 1\n\t\t\t) {\n\t\t\t\tif (typeof endOrBeginning === 'undefined') {\n\t\t\t\t\tendOrBeginning = 0;\n\t\t\t\t}\n\n\t\t\t\t// Credit https://stackoverflow.com/a/17195572\n\t\t\t\tconst pow = Math.pow(1 + rate, numberOfPeriods);\n\t\t\t\tlet fv;\n\n\t\t\t\tif (rate) {\n\t\t\t\t\t// eslint-disable-next-line no-mixed-operators\n\t\t\t\t\tfv =\n\t\t\t\t\t\t(paymentAmount *\n\t\t\t\t\t\t\t(1 + rate * endOrBeginning) *\n\t\t\t\t\t\t\t(1 - pow)) /\n\t\t\t\t\t\t\trate -\n\t\t\t\t\t\tpresentValue * pow;\n\t\t\t\t} else {\n\t\t\t\t\t// eslint-disable-next-line no-mixed-operators\n\t\t\t\t\tfv = -1 * (presentValue + paymentAmount * numberOfPeriods);\n\t\t\t\t}\n\n\t\t\t\treturn fv;\n\t\t\t},\n\t\t\tln: Math.log,\n\t\t\tlog: Math.log10,\n\t\t\tmax: Math.max,\n\t\t\tmin: Math.min,\n\t\t\tpi: () => this.pi20DecimalPlaces,\n\t\t\tround: Math.round,\n\t\t\tsqrt: Math.sqrt,\n\t\t};\n\n\t\t// Find the highest depth in the remaining items.\n\t\tlet targetDepth = Math.max(...items.map((item) => item.depth));\n\n\t\t/*\n\t\t * Work through the formula by highest depth and working our way down to the root.\n\t\t *\n\t\t * Find groups of items that are at the same depth and process them as a group and remove them from items.\n\t\t */\n\t\titemWhile: while (\n\t\t\t!items.every((item) => item.processedAtDepth !== undefined)\n\t\t) {\n\t\t\tif (targetDepth < 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Find items at the target depth and stop when we find an item not in the current group.\n\t\t\tconst groupItems: ParsedFormula = [];\n\t\t\tlet indexToInsertResultAt!: number;\n\n\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\tconst item = items?.[i];\n\n\t\t\t\t// Skip items deleted while inside the loop\n\t\t\t\tif (typeof item === 'undefined' || item === null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Use GTE here in case there were a lot of parentheses and some items with inflated depths.\n\t\t\t\tif (\n\t\t\t\t\titem.depth >= targetDepth &&\n\t\t\t\t\t(!item.processedAtDepth ||\n\t\t\t\t\t\titem.processedAtDepth !== targetDepth)\n\t\t\t\t) {\n\t\t\t\t\tgroupItems.push(item);\n\t\t\t\t\t(items as any)[i] = null;\n\n\t\t\t\t\tif (!indexToInsertResultAt) {\n\t\t\t\t\t\tindexToInsertResultAt = i;\n\t\t\t\t\t}\n\t\t\t\t} else if (groupItems.length) {\n\t\t\t\t\t// Break out of the for loop if we find an item that is not in the current group.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// No items found at this depth, reduce target depth and start at the top of the loop again.\n\t\t\tif (!groupItems.length) {\n\t\t\t\ttargetDepth--;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * If there are is a function present, we need to split up the group into chunks and handle each.\n\t\t\t */\n\t\t\tif (groupItems.some((item) => item.type === 'function')) {\n\t\t\t\tconst subGroups: ParsedFormula[] = [[]];\n\n\t\t\t\tfor (const groupItem of groupItems) {\n\t\t\t\t\t/*\n\t\t\t\t\t * If the current item is a function and matches the current depth, create a new subgroup, so we can\n\t\t\t\t\t * add arguments to the function in the next iterations of this for loop.\n\t\t\t\t\t */\n\t\t\t\t\tif (\n\t\t\t\t\t\tgroupItem.type === 'function' &&\n\t\t\t\t\t\tgroupItem.depth === targetDepth\n\t\t\t\t\t) {\n\t\t\t\t\t\tsubGroups.push([]);\n\t\t\t\t\t\tsubGroups[subGroups.length - 1].push(groupItem);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Function arguments are at a depth of at least 1 greater than the function.\n\t\t\t\t\tif (groupItem.depth > targetDepth) {\n\t\t\t\t\t\tsubGroups[subGroups.length - 1].push({\n\t\t\t\t\t\t\t...groupItem,\n\t\t\t\t\t\t\tnonFunctionItem: false,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t * If the last subgroup contains one item, it is a function without params, and we need to\n\t\t\t\t\t\t * create a new subgroup.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (subGroups[subGroups.length - 1].length === 1) {\n\t\t\t\t\t\t\tsubGroups.push([]);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t * If the last subgroup item depth is greater than the current item depth, we need to create a\n\t\t\t\t\t\t * new subgroup as we've likely encountered an operator following a function.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsubGroups[subGroups.length - 1].length &&\n\t\t\t\t\t\t\tsubGroups[subGroups.length - 1][\n\t\t\t\t\t\t\t\tsubGroups[subGroups.length - 1].length - 1\n\t\t\t\t\t\t\t].depth > groupItem.depth\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tsubGroups.push([]);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t * Items that are not part of a function need to be added into their own subgroup but with a\n\t\t\t\t\t\t * flag to not touch them. We put them into a subgroup to re-add to items without losing their\n\t\t\t\t\t\t * order.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tsubGroups[subGroups.length - 1].push({\n\t\t\t\t\t\t\t...groupItem,\n\t\t\t\t\t\t\tnonFunctionItem: true,\n\t\t\t\t\t\t\tprocessedAtDepth: targetDepth,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Create a new array to hold the results of the subgroups. This will be spliced back into items.\n\t\t\t\tconst subGroupItems: ParsedFormula = [];\n\n\t\t\t\tfor (const subGroup of subGroups) {\n\t\t\t\t\tif (!subGroup.length) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t * If the subgroup contains non function items, just queue the subgroup items to be added back\n\t\t\t\t\t * into items.\n\t\t\t\t\t */\n\t\t\t\t\tif (subGroup.some((item) => item.nonFunctionItem)) {\n\t\t\t\t\t\tsubGroupItems.push(...subGroup);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst functionName = subGroup[0].value\n\t\t\t\t\t\t.toString()\n\t\t\t\t\t\t.toLowerCase();\n\n\t\t\t\t\tconst functionArgs = subGroup\n\t\t\t\t\t\t.slice(1)\n\t\t\t\t\t\t.map((item) =>\n\t\t\t\t\t\t\titem.type === 'value'\n\t\t\t\t\t\t\t\t? calcObj.replaceFieldTags(\n\t\t\t\t\t\t\t\t\t\tformId,\n\t\t\t\t\t\t\t\t\t\titem.value,\n\t\t\t\t\t\t\t\t\t\tformulaField\n\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.filter((item) => item !== null)\n\t\t\t\t\t\t.map(parseFloat);\n\n\t\t\t\t\tif (typeof functions[functionName] === 'function') {\n\t\t\t\t\t\tsubGroupItems.push({\n\t\t\t\t\t\t\tprocessedAtDepth: targetDepth,\n\t\t\t\t\t\t\tdepth: targetDepth,\n\t\t\t\t\t\t\ttype: 'value',\n\t\t\t\t\t\t\tvalue: functions[functionName](...functionArgs),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\titems.splice(indexToInsertResultAt, 0, ...subGroupItems);\n\n\t\t\t\titems = items.filter((item) => item !== null);\n\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * If there aren't any operators in this group, there is nothing to do at this point in the loop as\n\t\t\t * functions will have already been processed and the only thing left are handling operators.\n\t\t\t *\n\t\t\t * Just mark the items as processed and re-add them to the items array, so they're handled at lower depths.\n\t\t\t */\n\t\t\tif (!groupItems.some((item) => item.type === 'operator')) {\n\t\t\t\t// Re-add the items that were removed and mark them as processed.\n\t\t\t\tgroupItems.forEach((item) => {\n\t\t\t\t\titem.processedAtDepth = targetDepth;\n\t\t\t\t});\n\n\t\t\t\titems.splice(indexToInsertResultAt, 0, ...groupItems);\n\n\t\t\t\titems = items.filter((item) => item !== null);\n\n\t\t\t\tcontinue itemWhile;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * At this point, we should have a mixture of values and operators that need their merge tags replaced\n\t\t\t * and the results evaluated.\n\t\t\t *\n\t\t\t * We will create subgroups for each much like we do with functions. If there are no separators, then\n\t\t\t * we will only have one subgroup.\n\t\t\t */\n\t\t\tconst subGroupsSeps: ParsedFormula[] = [[]];\n\n\t\t\tfor (const groupItem of groupItems) {\n\t\t\t\tif (groupItem.type === 'sep') {\n\t\t\t\t\tsubGroupsSeps.push([]);\n\t\t\t\t} else {\n\t\t\t\t\tsubGroupsSeps[subGroupsSeps.length - 1].push(groupItem);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst subGroupSepsItems: ParsedFormula = [];\n\n\t\t\tfor (const subGroup of subGroupsSeps) {\n\t\t\t\tconst contained = calcObj\n\t\t\t\t\t.replaceFieldTags(\n\t\t\t\t\t\tformId,\n\t\t\t\t\t\tthis.buildFormula(\n\t\t\t\t\t\t\tJSON.parse(JSON.stringify(subGroup)), // Break reference to objects\n\t\t\t\t\t\t\ttargetDepth\n\t\t\t\t\t\t),\n\t\t\t\t\t\tformulaField\n\t\t\t\t\t)\n\t\t\t\t\t.trim();\n\n\t\t\t\tsubGroupSepsItems.push({\n\t\t\t\t\tdepth: targetDepth,\n\t\t\t\t\tprocessedAtDepth: targetDepth,\n\t\t\t\t\ttype: 'value',\n\t\t\t\t\tvalue: this.evalFormula(contained, formulaField.field_id),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\titems.splice(indexToInsertResultAt, 0, ...subGroupSepsItems);\n\n\t\t\titems = items.filter((item) => item !== null);\n\t\t}\n\n\t\tformula = this.buildFormula(items);\n\n\t\treturn formula;\n\t};\n\n\t/**\n\t * Moves the pointer forward when parsing the formula until the end of a specified pattern.\n\t *\n\t * char is always returned even if there's no match.\n\t *\n\t * @param formula The formula being parsed.\n\t * @param char The current character being read. Can be thought of as the pointer.\n\t * @param pattern The RegExp to find the end of the match.\n\t */\n\tmatchUntil = (\n\t\tformula: string,\n\t\tchar: string,\n\t\tpattern: RegExp\n\t): { formula: string; value: string } => {\n\t\tlet lastLetter: any = formula.match(pattern);\n\t\tlet value: string;\n\n\t\tif (lastLetter) {\n\t\t\tlastLetter = lastLetter[0].length;\n\t\t\tvalue = char + formula.substr(0, lastLetter);\n\t\t\tformula = formula.substr(lastLetter);\n\t\t} else {\n\t\t\tvalue = char;\n\t\t}\n\n\t\treturn { formula, value };\n\t};\n\n\tparseFormula = (formula: string): ParsedFormula => {\n\t\tformula = formula.replace('/s+/g', ' ').trim();\n\n\t\tconst items: ParsedFormula = [];\n\t\tlet depth = 0;\n\n\t\twhile (formula.length > 0) {\n\t\t\tconst char = formula.substr(0, 1);\n\n\t\t\tlet item: ParsedFormulaItem,\n\t\t\t\tvalue = '';\n\n\t\t\tlet matchResult: { formula: string; value: string };\n\n\t\t\tformula = formula.substr(1);\n\n\t\t\tswitch (true) {\n\t\t\t\tcase char === '(':\n\t\t\t\t\tdepth++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase char === ')':\n\t\t\t\t\tdepth--;\n\t\t\t\t\tbreak;\n\t\t\t\tcase jQuery.inArray(char, ['*', '-', '+', '/', '^', '%']) !==\n\t\t\t\t\t-1:\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'operator',\n\t\t\t\t\t\tvalue: char as Operator,\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase char === '{':\n\t\t\t\t\tconst closingBrace = formula.indexOf('}');\n\t\t\t\t\tvalue = char + formula.substr(0, closingBrace + 1);\n\t\t\t\t\tformula = formula.substr(closingBrace + 1);\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'value',\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase char === ',':\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'sep',\n\t\t\t\t\t\tvalue: ',',\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase jQuery.isNumeric(char):\n\t\t\t\t\tmatchResult = this.matchUntil(formula, char, /^[0-9.]+/); // Includes decimals; could be stricter.\n\n\t\t\t\t\tformula = matchResult.formula;\n\t\t\t\t\tvalue = matchResult.value;\n\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'value',\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase char.match(/[a-zA-Z]/i) &&\n\t\t\t\t\tchar.match(/[a-zA-Z]/i)!.length > 0:\n\t\t\t\t\tmatchResult = this.matchUntil(formula, char, /^[a-zA-Z]+/i);\n\n\t\t\t\t\tformula = matchResult.formula;\n\t\t\t\t\tvalue = matchResult.value;\n\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'function',\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase (char.match(/[<>!=]/)?.length ?? 0) > 0:\n\t\t\t\t\tmatchResult = this.matchUntil(formula, char, /^=+/);\n\n\t\t\t\t\tformula = matchResult.formula;\n\t\t\t\t\tvalue = matchResult.value;\n\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'comparisonOp',\n\t\t\t\t\t\tvalue: ' ' + value + ' ',\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t\tcase (char.match(/[&|]/)?.length ?? 0) > 0:\n\t\t\t\t\tmatchResult = this.matchUntil(formula, char, /^[&|]+/);\n\n\t\t\t\t\tformula = matchResult.formula;\n\t\t\t\t\tvalue = matchResult.value;\n\n\t\t\t\t\t/* char is always returned in matchUntil(). We can't do anything with a single & or | so we throw it out. */\n\t\t\t\t\tif (value.length === 1) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\titem = {\n\t\t\t\t\t\tdepth,\n\t\t\t\t\t\ttype: 'logicalOp',\n\t\t\t\t\t\tvalue: ' ' + value + ' ',\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (item! && item?.value) {\n\t\t\t\titems.push(item);\n\t\t\t}\n\t\t}\n\n\t\treturn items;\n\t};\n\n\t/**\n\t * @param {ParsedFormula} parsedFormula\n\t * @param {number} startingDepth Specify the starting depth to avoid building a formula with extraneous parentheses\n\t */\n\tbuildFormula = (parsedFormula: ParsedFormula, startingDepth = 0) => {\n\t\tlet depth = 0,\n\t\t\tformula = '';\n\n\t\tfor (let i = 0; i < parsedFormula.length; i++) {\n\t\t\tconst item = parsedFormula[i];\n\n\t\t\t/*\n\t\t\t * Remove starting depth from the item. For instance, if we're taking only items from inside a\n\t\t\t * function call, we give it the starting depth of the function to avoid building a formula that is wrapped\n\t\t\t * in numerous parentheses.\n\t\t\t */\n\t\t\titem.depth -= startingDepth;\n\n\t\t\tif (depth < item.depth) {\n\t\t\t\tformula += '('.repeat(item.depth - depth);\n\t\t\t\tdepth = item.depth;\n\t\t\t} else if (depth > item.depth) {\n\t\t\t\tformula += ')'.repeat(depth - item.depth);\n\t\t\t\tdepth = item.depth;\n\t\t\t}\n\n\t\t\tformula += item.value;\n\t\t}\n\n\t\tif (depth > 0) {\n\t\t\tformula += ')'.repeat(depth);\n\t\t}\n\n\t\treturn formula;\n\t};\n}\n\nwindow.GPAdvancedCalculations = GPAdvancedCalculations;\n\nString.prototype.repeat = function(num) {\n\t// @ts-ignore\n\treturn new Array(num + 1).join(this);\n};\n"],"names":["shorthandVariableRegex","GPAdvancedCalculations","constructor","formId","pi20DecimalPlaces","init","window","gform","addFilter","formula","formulaField","calcObj","parseInt","this","replaceShorthandVariables","processConditionals","processExponents","processFunctions","jQuery","document","trigger","bindShorthandCalcEvents","addGPPAListener","gf_global","gfcalc","formulaFields","i","length","extend","formulaFieldId","field_id","matches","match","isCalculating","hasOwnProperty","inputId","replace","fieldId","input","find","eventNamespace","off","prop","on","bindCalcEvent","is","doAction","event","regex","elseIfRegex","modified","exec","elseIfMatch","fullMatch","elseIfs","statements","push","tag","condition","replaceMergeTags","each","statement","evalFormula","shorthandVariableMatch","RegExp","replaceMergeTag","undefined","GFMergeTag","parseMergeTags","modifier","isProductRadio","isProductDropdown","isOptionCheckbox","value","gf_check_field_rule","getMergeTagValue","applyFilters","cleanNumber","items","parseFormula","processed","rootItem","shift","type","targetDepth","depth","base","item","pop","reverse","pow","unshift","baseEvaled","replaceFieldTags","buildFormula","powEvaled","Math","result","trim","eval","e","warning","console","warn","some","functions","abs","average","Array","prototype","slice","call","arguments","reduce","a","b","ceil","exp","floor","fv","rate","numberOfPeriods","paymentAmount","presentValue","endOrBeginning","ln","log","log10","max","min","pi","round","sqrt","map","itemWhile","every","processedAtDepth","groupItems","indexToInsertResultAt","subGroups","groupItem","nonFunctionItem","subGroupItems","subGroup","functionName","toString","toLowerCase","functionArgs","filter","parseFloat","splice","forEach","subGroupsSeps","subGroupSepsItems","contained","JSON","parse","stringify","matchUntil","char","pattern","lastLetter","substr","matchResult","inArray","closingBrace","indexOf","isNumeric","parsedFormula","startingDepth","repeat","String","num","join"],"sourceRoot":""}