Add support for variables (pulling from previous commands in same message)
This commit is contained in:
parent
d142b35522
commit
b7e58f56a5
|
@ -41,7 +41,7 @@ export const runCmd = (fullCmd: string, modifiers: RollModifiers): SolvedRoll =>
|
||||||
assertPrePostBalance(sepCmds);
|
assertPrePostBalance(sepCmds);
|
||||||
|
|
||||||
// Send the split roll into the command tokenizer to get raw response data
|
// Send the split roll into the command tokenizer to get raw response data
|
||||||
const [tempReturnData, tempCountDetails] = tokenizeCmd(sepCmds, modifiers, true);
|
const [tempReturnData, tempCountDetails] = tokenizeCmd(sepCmds, modifiers, true, []);
|
||||||
loggingEnabled && log(LT.LOG, `Return data is back ${JSON.stringify(tempReturnData)}`);
|
loggingEnabled && log(LT.LOG, `Return data is back ${JSON.stringify(tempReturnData)}`);
|
||||||
|
|
||||||
// Remove any floating spaces from fullCmd
|
// Remove any floating spaces from fullCmd
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { loggingEnabled } from 'artigen/utils/logFlag.ts';
|
||||||
import { getMatchingInternalIdx, getMatchingPostfixIdx } from 'artigen/utils/parenBalance.ts';
|
import { getMatchingInternalIdx, getMatchingPostfixIdx } from 'artigen/utils/parenBalance.ts';
|
||||||
|
|
||||||
// tokenizeCmd expects a string[] of items that are either config.prefix/config.postfix or some text that contains math and/or dice rolls
|
// tokenizeCmd expects a string[] of items that are either config.prefix/config.postfix or some text that contains math and/or dice rolls
|
||||||
export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: boolean): [ReturnData[], CountDetails[]] => {
|
export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: boolean, previousResults: number[]): [ReturnData[], CountDetails[]] => {
|
||||||
loggingEnabled && log(LT.LOG, `Tokenizing command ${JSON.stringify(cmd)}`);
|
loggingEnabled && log(LT.LOG, `Tokenizing command ${JSON.stringify(cmd)}`);
|
||||||
|
|
||||||
const returnData: ReturnData[] = [];
|
const returnData: ReturnData[] = [];
|
||||||
|
@ -28,8 +28,15 @@ export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: b
|
||||||
const openIdx = cmd.indexOf(config.prefix);
|
const openIdx = cmd.indexOf(config.prefix);
|
||||||
const closeIdx = getMatchingPostfixIdx(cmd, openIdx);
|
const closeIdx = getMatchingPostfixIdx(cmd, openIdx);
|
||||||
|
|
||||||
|
loggingEnabled && log(LT.LOG, `Setting previous results: topLevel:${topLevel} ${topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults}`);
|
||||||
|
|
||||||
// Handle any nested commands
|
// Handle any nested commands
|
||||||
const [tempData, tempCounts] = tokenizeCmd(cmd.slice(openIdx + 1, closeIdx), modifiers, false);
|
const [tempData, tempCounts] = tokenizeCmd(
|
||||||
|
cmd.slice(openIdx + 1, closeIdx),
|
||||||
|
modifiers,
|
||||||
|
false,
|
||||||
|
topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults,
|
||||||
|
);
|
||||||
const data = tempData[0];
|
const data = tempData[0];
|
||||||
|
|
||||||
if (topLevel) {
|
if (topLevel) {
|
||||||
|
@ -60,7 +67,7 @@ export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: b
|
||||||
loggingEnabled && log(LT.LOG, `Tokenizing math ${JSON.stringify(cmd)}`);
|
loggingEnabled && log(LT.LOG, `Tokenizing math ${JSON.stringify(cmd)}`);
|
||||||
|
|
||||||
// Solve the math and rolls for this cmd
|
// Solve the math and rolls for this cmd
|
||||||
const [tempData, tempCounts] = tokenizeMath(cmd.join(''), modifiers);
|
const [tempData, tempCounts] = tokenizeMath(cmd.join(''), modifiers, previousResults);
|
||||||
const data = tempData[0];
|
const data = tempData[0];
|
||||||
loggingEnabled && log(LT.LOG, `Solved math is back ${JSON.stringify(data)} | ${JSON.stringify(returnData)}`);
|
loggingEnabled && log(LT.LOG, `Solved math is back ${JSON.stringify(data)} | ${JSON.stringify(returnData)}`);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,21 @@ export const mathSolver = (conf: MathConf[], wrapDetails = false): SolvedStep =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Look for any implicit multiplication that may have been missed
|
||||||
|
// Start at index 1 as there will never be implicit multiplication before the first element
|
||||||
|
for (let i = 1; i < conf.length; i++) {
|
||||||
|
loopCountCheck();
|
||||||
|
|
||||||
|
const prevConfAsStr = <string> conf[i - 1];
|
||||||
|
const curConfAsStr = <string> conf[i];
|
||||||
|
if (!signs.includes(curConfAsStr) && !signs.includes(prevConfAsStr)) {
|
||||||
|
// Both previous and current conf are operators, slip in the "*"
|
||||||
|
conf.splice(i, 0, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, conf should be [num, op, num, op, num, op, num, etc]
|
||||||
|
|
||||||
// Evaluate all EMDAS by looping thru each tier of operators (exponential is the highest tier, addition/subtraction the lowest)
|
// Evaluate all EMDAS by looping thru each tier of operators (exponential is the highest tier, addition/subtraction the lowest)
|
||||||
const allCurOps = [['^'], ['*', '/', '%'], ['+', '-']];
|
const allCurOps = [['^'], ['*', '/', '%'], ['+', '-']];
|
||||||
allCurOps.forEach((curOps) => {
|
allCurOps.forEach((curOps) => {
|
||||||
|
|
|
@ -18,17 +18,17 @@ import { assertParenBalance } from 'artigen/utils/parenBalance.ts';
|
||||||
|
|
||||||
const operators = ['(', ')', '^', '*', '/', '%', '+', '-'];
|
const operators = ['(', ')', '^', '*', '/', '%', '+', '-'];
|
||||||
|
|
||||||
export const tokenizeMath = (cmd: string, modifiers: RollModifiers): [ReturnData[], CountDetails[]] => {
|
export const tokenizeMath = (cmd: string, modifiers: RollModifiers, previousResults: number[]): [ReturnData[], CountDetails[]] => {
|
||||||
const countDetails: CountDetails[] = [];
|
const countDetails: CountDetails[] = [];
|
||||||
|
|
||||||
loggingEnabled && log(LT.LOG, `Parsing roll ${cmd}`);
|
loggingEnabled && log(LT.LOG, `Parsing roll ${cmd} | ${JSON.stringify(modifiers)} | ${JSON.stringify(previousResults)}`);
|
||||||
|
|
||||||
// Remove all spaces from the operation config and split it by any operator (keeping the operator in mathConf for fullSolver to do math on)
|
// Remove all spaces from the operation config and split it by any operator (keeping the operator in mathConf for fullSolver to do math on)
|
||||||
const mathConf: MathConf[] = cmd
|
const mathConf: MathConf[] = cmd
|
||||||
.replace(cmdSplitRegex, '')
|
.replace(cmdSplitRegex, '')
|
||||||
.replace(internalWrapRegex, '')
|
.replace(internalWrapRegex, '')
|
||||||
.replace(/ /g, '')
|
.replace(/ /g, '')
|
||||||
.split(/([-+()*/^]|(?<![d%])%)/g)
|
.split(/([-+()*/^]|(?<![d%])%)|(x\d+(\.\d*)?)/g)
|
||||||
.filter((x) => x);
|
.filter((x) => x);
|
||||||
loggingEnabled && log(LT.LOG, `Split roll into mathConf ${JSON.stringify(mathConf)}`);
|
loggingEnabled && log(LT.LOG, `Split roll into mathConf ${JSON.stringify(mathConf)}`);
|
||||||
|
|
||||||
|
@ -41,16 +41,16 @@ export const tokenizeMath = (cmd: string, modifiers: RollModifiers): [ReturnData
|
||||||
|
|
||||||
loggingEnabled && log(LT.LOG, `Parsing roll ${JSON.stringify(cmd)} | Evaluating rolls into math-able items ${JSON.stringify(mathConf[i])}`);
|
loggingEnabled && log(LT.LOG, `Parsing roll ${JSON.stringify(cmd)} | Evaluating rolls into math-able items ${JSON.stringify(mathConf[i])}`);
|
||||||
|
|
||||||
const strMathConfI = mathConf[i].toString();
|
const curMathConfStr = mathConf[i].toString();
|
||||||
|
|
||||||
if (strMathConfI.length === 0) {
|
if (curMathConfStr.length === 0) {
|
||||||
// If its an empty string, get it out of here
|
// If its an empty string, get it out of here
|
||||||
mathConf.splice(i, 1);
|
mathConf.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
} else if (mathConf[i] == parseFloat(strMathConfI)) {
|
} else if (mathConf[i] == parseFloat(curMathConfStr)) {
|
||||||
// If its a number, parse the number out
|
// If its a number, parse the number out
|
||||||
mathConf[i] = parseFloat(strMathConfI);
|
mathConf[i] = parseFloat(curMathConfStr);
|
||||||
} else if (strMathConfI.toLowerCase() === 'e') {
|
} else if (curMathConfStr.toLowerCase() === 'e') {
|
||||||
// If the operand is the constant e, create a SolvedStep for it
|
// If the operand is the constant e, create a SolvedStep for it
|
||||||
mathConf[i] = {
|
mathConf[i] = {
|
||||||
total: Math.E,
|
total: Math.E,
|
||||||
|
@ -58,21 +58,21 @@ export const tokenizeMath = (cmd: string, modifiers: RollModifiers): [ReturnData
|
||||||
containsCrit: false,
|
containsCrit: false,
|
||||||
containsFail: false,
|
containsFail: false,
|
||||||
};
|
};
|
||||||
} else if (strMathConfI.toLowerCase() === 'fart' || strMathConfI.toLowerCase() === '💩') {
|
} else if (curMathConfStr.toLowerCase() === 'fart' || curMathConfStr.toLowerCase() === '💩') {
|
||||||
mathConf[i] = {
|
mathConf[i] = {
|
||||||
total: 7,
|
total: 7,
|
||||||
details: '💩',
|
details: '💩',
|
||||||
containsCrit: false,
|
containsCrit: false,
|
||||||
containsFail: false,
|
containsFail: false,
|
||||||
};
|
};
|
||||||
} else if (strMathConfI.toLowerCase() === 'sex') {
|
} else if (curMathConfStr.toLowerCase() === 'sex') {
|
||||||
mathConf[i] = {
|
mathConf[i] = {
|
||||||
total: 69,
|
total: 69,
|
||||||
details: '( ͡° ͜ʖ ͡°)',
|
details: '( ͡° ͜ʖ ͡°)',
|
||||||
containsCrit: false,
|
containsCrit: false,
|
||||||
containsFail: false,
|
containsFail: false,
|
||||||
};
|
};
|
||||||
} else if (strMathConfI.toLowerCase() === 'inf' || strMathConfI.toLowerCase() === 'infinity' || strMathConfI.toLowerCase() === '∞') {
|
} else if (curMathConfStr.toLowerCase() === 'inf' || curMathConfStr.toLowerCase() === 'infinity' || curMathConfStr.toLowerCase() === '∞') {
|
||||||
// If the operand is the constant Infinity, create a SolvedStep for it
|
// If the operand is the constant Infinity, create a SolvedStep for it
|
||||||
mathConf[i] = {
|
mathConf[i] = {
|
||||||
total: Infinity,
|
total: Infinity,
|
||||||
|
@ -80,7 +80,7 @@ export const tokenizeMath = (cmd: string, modifiers: RollModifiers): [ReturnData
|
||||||
containsCrit: false,
|
containsCrit: false,
|
||||||
containsFail: false,
|
containsFail: false,
|
||||||
};
|
};
|
||||||
} else if (strMathConfI.toLowerCase() === 'pi' || strMathConfI.toLowerCase() === '𝜋') {
|
} else if (curMathConfStr.toLowerCase() === 'pi' || curMathConfStr.toLowerCase() === '𝜋') {
|
||||||
// If the operand is the constant pi, create a SolvedStep for it
|
// If the operand is the constant pi, create a SolvedStep for it
|
||||||
mathConf[i] = {
|
mathConf[i] = {
|
||||||
total: Math.PI,
|
total: Math.PI,
|
||||||
|
@ -88,7 +88,7 @@ export const tokenizeMath = (cmd: string, modifiers: RollModifiers): [ReturnData
|
||||||
containsCrit: false,
|
containsCrit: false,
|
||||||
containsFail: false,
|
containsFail: false,
|
||||||
};
|
};
|
||||||
} else if (strMathConfI.toLowerCase() === 'pie') {
|
} else if (curMathConfStr.toLowerCase() === 'pie') {
|
||||||
// If the operand is pie, pi*e, create a SolvedStep for e and pi (and the multiplication symbol between them)
|
// If the operand is pie, pi*e, create a SolvedStep for e and pi (and the multiplication symbol between them)
|
||||||
mathConf[i] = {
|
mathConf[i] = {
|
||||||
total: Math.PI,
|
total: Math.PI,
|
||||||
|
@ -110,16 +110,31 @@ export const tokenizeMath = (cmd: string, modifiers: RollModifiers): [ReturnData
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
i += 2;
|
i += 2;
|
||||||
} else if (!legalMathOperators.includes(strMathConfI) && legalMathOperators.some((mathOp) => strMathConfI.endsWith(mathOp))) {
|
} else if (!legalMathOperators.includes(curMathConfStr) && legalMathOperators.some((mathOp) => curMathConfStr.endsWith(mathOp))) {
|
||||||
// Identify when someone does something weird like 4floor(2.5) and split 4 and floor
|
// Identify when someone does something weird like 4floor(2.5) and split 4 and floor
|
||||||
const matchedMathOp = legalMathOperators.filter((mathOp) => strMathConfI.endsWith(mathOp))[0];
|
const matchedMathOp = legalMathOperators.filter((mathOp) => curMathConfStr.endsWith(mathOp))[0];
|
||||||
mathConf[i] = parseFloat(strMathConfI.replace(matchedMathOp, ''));
|
mathConf[i] = parseFloat(curMathConfStr.replace(matchedMathOp, ''));
|
||||||
|
|
||||||
mathConf.splice(i + 1, 0, ...['*', matchedMathOp]);
|
mathConf.splice(i + 1, 0, ...['*', matchedMathOp]);
|
||||||
i += 2;
|
i += 2;
|
||||||
} else if (![...operators, ...legalMathOperators].includes(strMathConfI)) {
|
} else if (/(x\d+(\.\d*)?)/.test(curMathConfStr)) {
|
||||||
|
// Identify when someone is using a variable from previous commands
|
||||||
|
if (curMathConfStr.includes('.')) {
|
||||||
|
// Verify someone did not enter x1.1 as a variable
|
||||||
|
throw new Error(`IllegalVariable_${curMathConfStr}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const varIdx = parseInt(curMathConfStr.replaceAll('x', ''));
|
||||||
|
|
||||||
|
// Get the index from the variable and attempt to use it to query the previousResults
|
||||||
|
if (previousResults.length > varIdx) {
|
||||||
|
mathConf[i] = parseFloat(previousResults[varIdx].toString());
|
||||||
|
} else {
|
||||||
|
throw new Error(`IllegalVariable_${curMathConfStr}`);
|
||||||
|
}
|
||||||
|
} else if (![...operators, ...legalMathOperators].includes(curMathConfStr)) {
|
||||||
// If nothing else has handled it by now, try it as a roll
|
// If nothing else has handled it by now, try it as a roll
|
||||||
const formattedRoll = generateFormattedRoll(strMathConfI, modifiers);
|
const formattedRoll = generateFormattedRoll(curMathConfStr, modifiers);
|
||||||
mathConf[i] = formattedRoll.solvedStep;
|
mathConf[i] = formattedRoll.solvedStep;
|
||||||
countDetails.push(formattedRoll.countDetails);
|
countDetails.push(formattedRoll.countDetails);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,9 @@ export const translateError = (solverError: Error): [string, string] => {
|
||||||
case 'UndefinedStep':
|
case 'UndefinedStep':
|
||||||
errorMsg = 'Error: Roll became undefined, one or more operands are not a roll or a number, check input';
|
errorMsg = 'Error: Roll became undefined, one or more operands are not a roll or a number, check input';
|
||||||
break;
|
break;
|
||||||
|
case 'IllegalVariable':
|
||||||
|
errorMsg = `Error: \`${errorDetails}\` is not a valid variable`;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log(LT.ERROR, `Unhandled Parser Error: ${errorName}, ${errorDetails}`);
|
log(LT.ERROR, `Unhandled Parser Error: ${errorName}, ${errorDetails}`);
|
||||||
errorMsg = `Unhandled Error: ${solverError.message}\nCheck input and try again, if issue persists, please use \`${config.prefix}report\` to alert the devs of the issue`;
|
errorMsg = `Unhandled Error: ${solverError.message}\nCheck input and try again, if issue persists, please use \`${config.prefix}report\` to alert the devs of the issue`;
|
||||||
|
|
Loading…
Reference in New Issue