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 { RollModifiers } from '../mod.d.ts';
 | 
				
			||||||
import { CountDetails, ReturnData, SolvedRoll, SolvedStep } from './solver.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 { formatRoll } from './rollFormatter.ts';
 | 
				
			||||||
import { fullSolver } from './solver.ts';
 | 
					import { fullSolver } from './solver.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// parseRoll(fullCmd, modifiers)
 | 
					// parseRoll(fullCmd, modifiers)
 | 
				
			||||||
// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
 | 
					// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
 | 
				
			||||||
export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
 | 
					export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
 | 
				
			||||||
  const operators = ['^', '*', '/', '%', '+', '-', '(', ')'];
 | 
					  const operators = ['(', ')', '^', '*', '/', '%', '+', '-'];
 | 
				
			||||||
  const returnMsg = <SolvedRoll> {
 | 
					  const returnMsg = <SolvedRoll> {
 | 
				
			||||||
    error: false,
 | 
					    error: false,
 | 
				
			||||||
    errorCode: '',
 | 
					    errorCode: '',
 | 
				
			||||||
| 
						 | 
					@ -78,14 +78,17 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
 | 
				
			||||||
      // Evaluate all rolls into stepSolve format and all numbers into floats
 | 
					      // Evaluate all rolls into stepSolve format and all numbers into floats
 | 
				
			||||||
      for (let i = 0; i < mathConf.length; i++) {
 | 
					      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])}`);
 | 
					        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
 | 
					          // 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(mathConf[i].toString())) {
 | 
					        } else if (mathConf[i] == parseFloat(strMathConfI)) {
 | 
				
			||||||
          // If its a number, parse the number out
 | 
					          // If its a number, parse the number out
 | 
				
			||||||
          mathConf[i] = parseFloat(mathConf[i].toString());
 | 
					          mathConf[i] = parseFloat(strMathConfI);
 | 
				
			||||||
        } else if (mathConf[i].toString().toLowerCase() === 'e') {
 | 
					        } else if (strMathConfI.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,
 | 
				
			||||||
| 
						 | 
					@ -93,25 +96,21 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
 | 
				
			||||||
            containsCrit: false,
 | 
					            containsCrit: false,
 | 
				
			||||||
            containsFail: false,
 | 
					            containsFail: false,
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        } else if (mathConf[i].toString().toLowerCase() === 'fart' || mathConf[i].toString().toLowerCase() === '💩') {
 | 
					        } else if (strMathConfI.toLowerCase() === 'fart' || strMathConfI.toLowerCase() === '💩') {
 | 
				
			||||||
          mathConf[i] = {
 | 
					          mathConf[i] = {
 | 
				
			||||||
            total: 7,
 | 
					            total: 7,
 | 
				
			||||||
            details: '💩',
 | 
					            details: '💩',
 | 
				
			||||||
            containsCrit: false,
 | 
					            containsCrit: false,
 | 
				
			||||||
            containsFail: false,
 | 
					            containsFail: false,
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        } else if (mathConf[i].toString().toLowerCase() === 'sex') {
 | 
					        } else if (strMathConfI.toLowerCase() === 'sex') {
 | 
				
			||||||
          mathConf[i] = {
 | 
					          mathConf[i] = {
 | 
				
			||||||
            total: 69,
 | 
					            total: 69,
 | 
				
			||||||
            details: '( ͡° ͜ʖ ͡°)',
 | 
					            details: '( ͡° ͜ʖ ͡°)',
 | 
				
			||||||
            containsCrit: false,
 | 
					            containsCrit: false,
 | 
				
			||||||
            containsFail: false,
 | 
					            containsFail: false,
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        } else if (
 | 
					        } else if (strMathConfI.toLowerCase() === 'inf' || strMathConfI.toLowerCase() === 'infinity' || strMathConfI.toLowerCase() === '∞') {
 | 
				
			||||||
          mathConf[i].toString().toLowerCase() === 'inf' ||
 | 
					 | 
				
			||||||
          mathConf[i].toString().toLowerCase() === 'infinity' ||
 | 
					 | 
				
			||||||
          mathConf[i].toString().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,
 | 
				
			||||||
| 
						 | 
					@ -119,7 +118,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
 | 
				
			||||||
            containsCrit: false,
 | 
					            containsCrit: false,
 | 
				
			||||||
            containsFail: 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
 | 
					          // If the operand is the constant pi, create a SolvedStep for it
 | 
				
			||||||
          mathConf[i] = {
 | 
					          mathConf[i] = {
 | 
				
			||||||
            total: Math.PI,
 | 
					            total: Math.PI,
 | 
				
			||||||
| 
						 | 
					@ -127,7 +126,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
 | 
				
			||||||
            containsCrit: false,
 | 
					            containsCrit: false,
 | 
				
			||||||
            containsFail: 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)
 | 
					          // 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,
 | 
				
			||||||
| 
						 | 
					@ -149,15 +148,28 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
          i += 2;
 | 
					          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
 | 
					          // 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;
 | 
					          mathConf[i] = formattedRoll.solvedStep;
 | 
				
			||||||
          tempCountDetails.push(formattedRoll.countDetails);
 | 
					          tempCountDetails.push(formattedRoll.countDetails);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Identify if we are in a state where the current number is a negative number
 | 
					        // 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 (mathConf[i - 1] === '-' && ((!mathConf[i - 2] && mathConf[i - 2] !== 0) || mathConf[i - 2] === '(')) {
 | 
				
			||||||
 | 
					          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 {
 | 
				
			||||||
 | 
					            // Handle normally, just set current item to negative
 | 
				
			||||||
            if (typeof mathConf[i] === 'number') {
 | 
					            if (typeof mathConf[i] === 'number') {
 | 
				
			||||||
              mathConf[i] = <number> mathConf[i] * -1;
 | 
					              mathConf[i] = <number> mathConf[i] * -1;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
| 
						 | 
					@ -168,6 +180,7 @@ export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll
 | 
				
			||||||
            i--;
 | 
					            i--;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Now that mathConf is parsed, send it into the solver
 | 
					      // Now that mathConf is parsed, send it into the solver
 | 
				
			||||||
      const tempSolved = fullSolver(mathConf, false);
 | 
					      const tempSolved = fullSolver(mathConf, false);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,8 @@ import { RollModifiers } from '../mod.d.ts';
 | 
				
			||||||
import { ReturnData, RollSet } from './solver.d.ts';
 | 
					import { ReturnData, RollSet } from './solver.d.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const loggingEnabled = false;
 | 
					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(size) returns number
 | 
				
			||||||
// genRoll rolls a die of size size and returns the result
 | 
					// genRoll rolls a die of size size and returns the result
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ import {
 | 
				
			||||||
} from '../../deps.ts';
 | 
					} from '../../deps.ts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { SolvedStep } from './solver.d.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(conf, wrapDetails) returns one condensed SolvedStep
 | 
				
			||||||
// fullSolver is a function that recursively solves the full roll and math
 | 
					// 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('(')) {
 | 
					  while (conf.includes('(')) {
 | 
				
			||||||
    loggingEnabled && log(LT.LOG, `Evaluating roll ${JSON.stringify(conf)} | Looking for (`);
 | 
					    loggingEnabled && log(LT.LOG, `Evaluating roll ${JSON.stringify(conf)} | Looking for (`);
 | 
				
			||||||
    // Get first open parenthesis
 | 
					    // Get first open parenthesis
 | 
				
			||||||
    const openParenIdx = conf.indexOf('(');
 | 
					    let openParenIdx = conf.indexOf('(');
 | 
				
			||||||
    let closeParenIdx = -1;
 | 
					    let closeParenIdx = -1;
 | 
				
			||||||
    let nextParenIdx = 0;
 | 
					    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
 | 
					    // Replace the items between openParenIdx and closeParenIdx (including the parens) with its solved equivalent
 | 
				
			||||||
    conf.splice(openParenIdx, closeParenIdx - openParenIdx + 1, parenSolve);
 | 
					    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)
 | 
					    // 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
 | 
					    // Check if a number was directly before openParenIdx and slip in the "*" if needed
 | 
				
			||||||
    if (openParenIdx - 1 > -1 && !signs.includes(conf[openParenIdx - 1].toString())) {
 | 
					    if (openParenIdx - 1 > -1 && !signs.includes(conf[openParenIdx - 1].toString())) {
 | 
				
			||||||
      insertedMult = 1;
 | 
					 | 
				
			||||||
      conf.splice(openParenIdx, 0, '*');
 | 
					      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
 | 
					    // 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
 | 
					    // 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())) {
 | 
					    if (openParenIdx + 1 < conf.length && !signs.includes(conf[openParenIdx + 1].toString())) {
 | 
				
			||||||
      conf.splice(openParenIdx + 1 + insertedMult, 0, '*');
 | 
					      conf.splice(openParenIdx + 1, 0, '*');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue