{
"version": 3,
"sources": ["../../../../server/chat-plugins/calculator.ts"],
"sourcesContent": ["import {Utils} from '../../lib';\r\n\r\ntype Operator = '^' | 'negative' | '%' | '/' | '*' | '+' | '-' | '(';\r\ninterface Operators {\r\n\tprecedence: number;\r\n\tassociativity: \"Left\" | \"Right\";\r\n}\r\n\r\nconst OPERATORS: {[k in Operator]: Operators} = {\r\n\t\"^\": {\r\n\t\tprecedence: 5,\r\n\t\tassociativity: \"Right\",\r\n\t},\r\n\t\"negative\": {\r\n\t\tprecedence: 4,\r\n\t\tassociativity: \"Right\",\r\n\t},\r\n\t\"%\": {\r\n\t\tprecedence: 3,\r\n\t\tassociativity: \"Left\",\r\n\t},\r\n\t\"/\": {\r\n\t\tprecedence: 3,\r\n\t\tassociativity: \"Left\",\r\n\t},\r\n\t\"*\": {\r\n\t\tprecedence: 3,\r\n\t\tassociativity: \"Left\",\r\n\t},\r\n\t\"+\": {\r\n\t\tprecedence: 2,\r\n\t\tassociativity: \"Left\",\r\n\t},\r\n\t\"-\": {\r\n\t\tprecedence: 2,\r\n\t\tassociativity: \"Left\",\r\n\t},\r\n\t\"(\": {\r\n\t\tprecedence: 1,\r\n\t\tassociativity: \"Right\",\r\n\t},\r\n};\r\n\r\nconst BASE_PREFIXES: {[base: number]: string} = {\r\n\t2: \"0b\",\r\n\t8: \"0o\",\r\n\t10: \"\",\r\n\t16: \"0x\",\r\n};\r\n\r\nfunction parseMathematicalExpression(infix: string) {\r\n\t// Shunting-yard Algorithm -- https://en.wikipedia.org/wiki/Shunting-yard_algorithm\r\n\tconst outputQueue: string[] = [];\r\n\tconst operatorStack: Operator[] = [];\r\n\tinfix = infix.replace(/\\s+/g, \"\");\r\n\tconst infixArray = infix.split(/([+\\-*/%^()])/).filter(token => token);\r\n\tlet isExprExpected = true;\r\n\tfor (const token of infixArray) {\r\n\t\tif (isExprExpected && \"+-\".includes(token)) {\r\n\t\t\tif (token === '-') operatorStack.push('negative');\r\n\t\t} else if (\"^%*/+-\".includes(token)) {\r\n\t\t\tif (isExprExpected) throw new SyntaxError(`Got \"${token}\" where an expression should be`);\r\n\t\t\tconst op = OPERATORS[token as Operator];\r\n\t\t\tlet prevToken = operatorStack[operatorStack.length - 1] || '(';\r\n\t\t\tlet prevOp = OPERATORS[prevToken];\r\n\t\t\twhile (op.associativity === \"Left\" ? op.precedence <= prevOp.precedence : op.precedence < prevOp.precedence) {\r\n\t\t\t\toutputQueue.push(operatorStack.pop()!);\r\n\t\t\t\tprevToken = operatorStack[operatorStack.length - 1] || '(';\r\n\t\t\t\tprevOp = OPERATORS[prevToken];\r\n\t\t\t}\r\n\t\t\toperatorStack.push(token as Operator);\r\n\t\t\tisExprExpected = true;\r\n\t\t} else if (token === \"(\") {\r\n\t\t\tif (!isExprExpected) throw new SyntaxError(`Got \"(\" where an operator should be`);\r\n\t\t\toperatorStack.push(token as Operator);\r\n\t\t\tisExprExpected = true;\r\n\t\t} else if (token === \")\") {\r\n\t\t\tif (isExprExpected) throw new SyntaxError(`Got \")\" where an expression should be`);\r\n\t\t\twhile (operatorStack.length && operatorStack[operatorStack.length - 1] !== \"(\") {\r\n\t\t\t\toutputQueue.push(operatorStack.pop()!);\r\n\t\t\t}\r\n\t\t\toperatorStack.pop();\r\n\t\t\tisExprExpected = false;\r\n\t\t} else {\r\n\t\t\tif (!isExprExpected) throw new SyntaxError(`Got \"${token}\" where an operator should be`);\r\n\t\t\toutputQueue.push(token);\r\n\t\t\tisExprExpected = false;\r\n\t\t}\r\n\t}\r\n\tif (isExprExpected) throw new SyntaxError(`Input ended where an expression should be`);\r\n\twhile (operatorStack.length > 0) {\r\n\t\tconst token = operatorStack.pop()!;\r\n\t\tif (token === '(') continue;\r\n\t\toutputQueue.push(token);\r\n\t}\r\n\treturn outputQueue;\r\n}\r\n\r\nfunction solveRPN(rpn: string[]): [number, number] {\r\n\tlet base = 10;\r\n\tconst resultStack: number[] = [];\r\n\tfor (let token of rpn) {\r\n\t\tif (token === 'negative') {\r\n\t\t\tif (!resultStack.length) throw new SyntaxError(`Unknown syntax error`);\r\n\t\t\tresultStack.push(-resultStack.pop()!);\r\n\t\t} else if (!\"^%*/+-\".includes(token)) {\r\n\t\t\tif (token.endsWith('h')) {\r\n\t\t\t\t// Convert h suffix for hexadecimal to 0x prefix\r\n\t\t\t\ttoken = `0x${token.slice(0, -1)}`;\r\n\t\t\t} else if (token.endsWith('o')) {\r\n\t\t\t\t// Convert o suffix for octal to 0o prefix\r\n\t\t\t\ttoken = `0o${token.slice(0, -1)}`;\r\n\t\t\t} else if (token.endsWith('b')) {\r\n\t\t\t\t// Convert b suffix for binary to 0b prefix\r\n\t\t\t\ttoken = `0b${token.slice(0, -1)}`;\r\n\t\t\t}\r\n\t\t\tif (token.startsWith('0x')) base = 16;\r\n\t\t\tif (token.startsWith('0b')) base = 2;\r\n\t\t\tif (token.startsWith('0o')) base = 8;\r\n\t\t\tlet num = Number(token);\r\n\t\t\tif (isNaN(num) && token.toUpperCase() in Math) {\r\n\t\t\t\t// @ts-ignore\r\n\t\t\t\tnum = Math[token.toUpperCase()];\r\n\t\t\t}\r\n\t\t\tif (isNaN(num) && token !== 'NaN') {\r\n\t\t\t\tthrow new SyntaxError(`Unrecognized token ${token}`);\r\n\t\t\t}\r\n\t\t\tresultStack.push(num);\r\n\t\t} else {\r\n\t\t\tif (resultStack.length < 2) throw new SyntaxError(`Unknown syntax error`);\r\n\t\t\tconst a = resultStack.pop()!;\r\n\t\t\tconst b = resultStack.pop()!;\r\n\t\t\tswitch (token) {\r\n\t\t\tcase \"+\":\r\n\t\t\t\tresultStack.push(a + b);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"-\":\r\n\t\t\t\tresultStack.push(b - a);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"*\":\r\n\t\t\t\tresultStack.push(a * b);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"/\":\r\n\t\t\t\tresultStack.push(b / a);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"%\":\r\n\t\t\t\tresultStack.push(b % a);\r\n\t\t\t\tbreak;\r\n\t\t\tcase \"^\":\r\n\t\t\t\tresultStack.push(b ** a);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (resultStack.length !== 1) throw new SyntaxError(`Unknown syntax error`);\r\n\treturn [resultStack.pop()!, base];\r\n}\r\n\r\nexport const commands: Chat.ChatCommands = {\r\n\tmath: \"calculate\",\r\n\tcalculate(target, room, user) {\r\n\t\tif (!target) return this.parse('/help calculate');\r\n\r\n\t\tlet base = 0;\r\n\t\tconst baseMatchResult = (/\\b(?:in|to)\\s+([a-zA-Z]+)\\b/).exec(target);\r\n\t\tif (baseMatchResult) {\r\n\t\t\tswitch (toID(baseMatchResult[1])) {\r\n\t\t\tcase 'decimal': case 'dec': base = 10; break;\r\n\t\t\tcase 'hexadecimal': case 'hex': base = 16; break;\r\n\t\t\tcase 'octal': case 'oct': base = 8; break;\r\n\t\t\tcase 'binary': case 'bin': base = 2; break;\r\n\t\t\tdefault:\r\n\t\t\t\treturn this.errorReply(`Unrecognized base \"${baseMatchResult[1]}\". Valid options are binary or bin, octal or oct, decimal or dec, and hexadecimal or hex.`);\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst expression = target.replace(/\\b(in|to)\\s+([a-zA-Z]+)\\b/g, '').trim();\r\n\r\n\t\tif (!this.runBroadcast()) return;\r\n\t\ttry {\r\n\t\t\tconst [result, inferredBase] = solveRPN(parseMathematicalExpression(expression));\r\n\t\t\tif (!base) base = inferredBase;\r\n\t\t\tlet baseResult = '';\r\n\t\t\tif (result && base !== 10) {\r\n\t\t\t\tbaseResult = `${BASE_PREFIXES[base]}${result.toString(base).toUpperCase()}`;\r\n\t\t\t\tif (baseResult === expression) baseResult = '';\r\n\t\t\t}\r\n\t\t\tlet resultStr = '';\r\n\t\t\tif (baseResult) {\r\n\t\t\t\tresultStr = `${baseResult} = ${result}`;\r\n\t\t\t} else {\r\n\t\t\t\tresultStr = `${result}`;\r\n\t\t\t}\r\n\t\t\tthis.sendReplyBox(`${expression}
= ${resultStr}`);\r\n\t\t} catch (e: any) {\r\n\t\t\tthis.sendReplyBox(\r\n\t\t\t\tUtils.html`${expression}
= Invalid input: ${e.message}`\r\n\t\t\t);\r\n\t\t}\r\n\t},\r\n\tcalculatehelp: [\r\n\t\t`/calculate [arithmetic question] - Calculates an arithmetical question. Supports PEMDAS (Parenthesis, Exponents, Multiplication, Division, Addition and Subtraction), pi and e.`,\r\n\t\t`/calculate [arithmetic question] in [base] - Returns the result in a specific base. [base] can be bin, oct, dec or hex.`,\r\n\t],\r\n};\r\n"],
"mappings": "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",
"names": []
}