Add support for floor/abs/other math operators
This commit is contained in:
parent
fd7bc5f152
commit
ac8602f598
|
@ -8,14 +8,14 @@ import config from '../../config.ts';
|
|||
|
||||
import { RollModifiers } from '../mod.d.ts';
|
||||
import { CountDetails, ReturnData, SolvedRoll, SolvedStep } from './solver.d.ts';
|
||||
import { compareTotalRolls, compareTotalRollsReverse, escapeCharacters, loggingEnabled } from './rollUtils.ts';
|
||||
import { compareTotalRolls, compareTotalRollsReverse, escapeCharacters, legalMathOperators, loggingEnabled } from './rollUtils.ts';
|
||||
import { formatRoll } from './rollFormatter.ts';
|
||||
import { fullSolver } from './solver.ts';
|
||||
|
||||
// parseRoll(fullCmd, modifiers)
|
||||
// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
|
||||
export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
|
||||
const operators = ['^', '*', '/', '%', '+', '-', '(', ')'];
|
||||
const operators = ['(', ')', '^', '*', '/', '%', '+', '-'];
|
||||
const returnMsg = <SolvedRoll> {
|
||||
error: false,
|
||||
errorCode: '',
|
||||
|
@ -78,14 +78,17 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
|
|||
// Evaluate all rolls into stepSolve format and all numbers into floats
|
||||
for (let i = 0; i < mathConf.length; i++) {
|
||||
loggingEnabled && log(LT.LOG, `Parsing roll ${fullCmd} | Evaluating rolls into math-able items ${JSON.stringify(mathConf[i])}`);
|
||||
if (mathConf[i].toString().length === 0) {
|
||||
|
||||
const strMathConfI = mathConf[i].toString();
|
||||
|
||||
if (strMathConfI.length === 0) {
|
||||
// If its an empty string, get it out of here
|
||||
mathConf.splice(i, 1);
|
||||
i--;
|
||||
} else if (mathConf[i] == parseFloat(mathConf[i].toString())) {
|
||||
} else if (mathConf[i] == parseFloat(strMathConfI)) {
|
||||
// If its a number, parse the number out
|
||||
mathConf[i] = parseFloat(mathConf[i].toString());
|
||||
} else if (mathConf[i].toString().toLowerCase() === 'e') {
|
||||
mathConf[i] = parseFloat(strMathConfI);
|
||||
} else if (strMathConfI.toLowerCase() === 'e') {
|
||||
// If the operand is the constant e, create a SolvedStep for it
|
||||
mathConf[i] = {
|
||||
total: Math.E,
|
||||
|
@ -93,25 +96,21 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
|
|||
containsCrit: false,
|
||||
containsFail: false,
|
||||
};
|
||||
} else if (mathConf[i].toString().toLowerCase() === 'fart' || mathConf[i].toString().toLowerCase() === '💩') {
|
||||
} else if (strMathConfI.toLowerCase() === 'fart' || strMathConfI.toLowerCase() === '💩') {
|
||||
mathConf[i] = {
|
||||
total: 7,
|
||||
details: '💩',
|
||||
containsCrit: false,
|
||||
containsFail: false,
|
||||
};
|
||||
} else if (mathConf[i].toString().toLowerCase() === 'sex') {
|
||||
} else if (strMathConfI.toLowerCase() === 'sex') {
|
||||
mathConf[i] = {
|
||||
total: 69,
|
||||
details: '( ͡° ͜ʖ ͡°)',
|
||||
containsCrit: false,
|
||||
containsFail: false,
|
||||
};
|
||||
} else if (
|
||||
mathConf[i].toString().toLowerCase() === 'inf' ||
|
||||
mathConf[i].toString().toLowerCase() === 'infinity' ||
|
||||
mathConf[i].toString().toLowerCase() === '∞'
|
||||
) {
|
||||
} else if (strMathConfI.toLowerCase() === 'inf' || strMathConfI.toLowerCase() === 'infinity' || strMathConfI.toLowerCase() === '∞') {
|
||||
// If the operand is the constant Infinity, create a SolvedStep for it
|
||||
mathConf[i] = {
|
||||
total: Infinity,
|
||||
|
@ -119,7 +118,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
|
|||
containsCrit: false,
|
||||
containsFail: false,
|
||||
};
|
||||
} else if (mathConf[i].toString().toLowerCase() === 'pi' || mathConf[i].toString().toLowerCase() === '𝜋') {
|
||||
} else if (strMathConfI.toLowerCase() === 'pi' || strMathConfI.toLowerCase() === '𝜋') {
|
||||
// If the operand is the constant pi, create a SolvedStep for it
|
||||
mathConf[i] = {
|
||||
total: Math.PI,
|
||||
|
@ -127,7 +126,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
|
|||
containsCrit: false,
|
||||
containsFail: false,
|
||||
};
|
||||
} else if (mathConf[i].toString().toLowerCase() === 'pie') {
|
||||
} else if (strMathConfI.toLowerCase() === 'pie') {
|
||||
// If the operand is pie, pi*e, create a SolvedStep for e and pi (and the multiplication symbol between them)
|
||||
mathConf[i] = {
|
||||
total: Math.PI,
|
||||
|
@ -149,23 +148,37 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
|
|||
],
|
||||
);
|
||||
i += 2;
|
||||
} else if (!operators.includes(mathConf[i].toString())) {
|
||||
} else if (!legalMathOperators.includes(strMathConfI) && legalMathOperators.some((mathOp) => strMathConfI.endsWith(mathOp))) {
|
||||
// Identify when someone does something weird like 4floor(2.5) and split 4 and floor
|
||||
const matchedMathOp = legalMathOperators.filter((mathOp) => strMathConfI.endsWith(mathOp))[0];
|
||||
mathConf[i] = parseFloat(strMathConfI.replace(matchedMathOp, ''));
|
||||
|
||||
mathConf.splice(i + 1, 0, ...['*', matchedMathOp]);
|
||||
i += 2;
|
||||
} else if (![...operators, ...legalMathOperators].includes(strMathConfI)) {
|
||||
// If nothing else has handled it by now, try it as a roll
|
||||
const formattedRoll = formatRoll(mathConf[i].toString(), modifiers);
|
||||
const formattedRoll = formatRoll(strMathConfI, modifiers);
|
||||
mathConf[i] = formattedRoll.solvedStep;
|
||||
tempCountDetails.push(formattedRoll.countDetails);
|
||||
}
|
||||
|
||||
// Identify if we are in a state where the current number is a negative number
|
||||
if (mathConf[i - 1] === '-' && ((!mathConf[i - 2] && mathConf[i - 2] !== 0) || mathConf[i - 2] === '(')) {
|
||||
if (typeof mathConf[i] === 'number') {
|
||||
mathConf[i] = <number> mathConf[i] * -1;
|
||||
if (typeof mathConf[i] === 'string') {
|
||||
// Current item is a mathOp, need to insert a "-1 *" before it
|
||||
mathConf.splice(i - 1, 1, ...[parseFloat('-1'), '*']);
|
||||
i += 2;
|
||||
} else {
|
||||
(<SolvedStep> mathConf[i]).total = (<SolvedStep> mathConf[i]).total * -1;
|
||||
(<SolvedStep> mathConf[i]).details = `-${(<SolvedStep> mathConf[i]).details}`;
|
||||
// Handle normally, just set current item to negative
|
||||
if (typeof mathConf[i] === 'number') {
|
||||
mathConf[i] = <number> mathConf[i] * -1;
|
||||
} else {
|
||||
(<SolvedStep> mathConf[i]).total = (<SolvedStep> mathConf[i]).total * -1;
|
||||
(<SolvedStep> mathConf[i]).details = `-${(<SolvedStep> mathConf[i]).details}`;
|
||||
}
|
||||
mathConf.splice(i - 1, 1);
|
||||
i--;
|
||||
}
|
||||
mathConf.splice(i - 1, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import { RollModifiers } from '../mod.d.ts';
|
|||
import { ReturnData, RollSet } from './solver.d.ts';
|
||||
|
||||
export const loggingEnabled = false;
|
||||
export const legalMath = [Math.abs, Math.ceil, Math.floor, Math.round, Math.sqrt, Math.cbrt];
|
||||
export const legalMathOperators = legalMath.map((oper) => oper.name);
|
||||
|
||||
// genRoll(size) returns number
|
||||
// genRoll rolls a die of size size and returns the result
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
} from '../../deps.ts';
|
||||
|
||||
import { SolvedStep } from './solver.d.ts';
|
||||
import { loggingEnabled } from './rollUtils.ts';
|
||||
import { legalMath, legalMathOperators, loggingEnabled } from './rollUtils.ts';
|
||||
|
||||
// fullSolver(conf, wrapDetails) returns one condensed SolvedStep
|
||||
// fullSolver is a function that recursively solves the full roll and math
|
||||
|
@ -35,7 +35,7 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
|
|||
while (conf.includes('(')) {
|
||||
loggingEnabled && log(LT.LOG, `Evaluating roll ${JSON.stringify(conf)} | Looking for (`);
|
||||
// Get first open parenthesis
|
||||
const openParenIdx = conf.indexOf('(');
|
||||
let openParenIdx = conf.indexOf('(');
|
||||
let closeParenIdx = -1;
|
||||
let nextParenIdx = 0;
|
||||
|
||||
|
@ -66,18 +66,28 @@ export const fullSolver = (conf: (string | number | SolvedStep)[], wrapDetails:
|
|||
// Replace the items between openParenIdx and closeParenIdx (including the parens) with its solved equivalent
|
||||
conf.splice(openParenIdx, closeParenIdx - openParenIdx + 1, parenSolve);
|
||||
|
||||
// Determine if previous idx is a Math operator and execute it
|
||||
if (openParenIdx - 1 > -1 && legalMathOperators.includes(conf[openParenIdx - 1].toString())) {
|
||||
// Update total and details of parenSolve
|
||||
parenSolve.total = legalMath[legalMathOperators.indexOf(conf[openParenIdx - 1].toString())](parenSolve.total);
|
||||
parenSolve.details = `${conf[openParenIdx - 1]}${parenSolve.details}`;
|
||||
|
||||
conf.splice(openParenIdx - 1, 2, parenSolve);
|
||||
// shift openParenIdx as we have just removed something before it
|
||||
openParenIdx--;
|
||||
}
|
||||
|
||||
// Determining if we need to add in a multiplication sign to handle implicit multiplication (like "(4)2" = 8)
|
||||
// insertedMult flags if there was a multiplication sign inserted before the parens
|
||||
let insertedMult = 0;
|
||||
// Check if a number was directly before openParenIdx and slip in the "*" if needed
|
||||
if (openParenIdx - 1 > -1 && !signs.includes(conf[openParenIdx - 1].toString())) {
|
||||
insertedMult = 1;
|
||||
conf.splice(openParenIdx, 0, '*');
|
||||
// shift openParenIdx as we have just added something before it
|
||||
openParenIdx++;
|
||||
}
|
||||
// Check if a number is directly after the closing paren and slip in the "*" if needed
|
||||
// openParenIdx is used here as the conf array has already been collapsed down
|
||||
if (openParenIdx + 1 + insertedMult < conf.length && !signs.includes(conf[openParenIdx + 1 + insertedMult].toString())) {
|
||||
conf.splice(openParenIdx + 1 + insertedMult, 0, '*');
|
||||
if (openParenIdx + 1 < conf.length && !signs.includes(conf[openParenIdx + 1].toString())) {
|
||||
conf.splice(openParenIdx + 1, 0, '*');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue