mathsteps-experimental-fork
Version:
Step by step math solutions. Experimental Fork
87 lines (84 loc) • 3.77 kB
JavaScript
import { findAllNextStepOptions } from '../simplifyExpression/stepEvaluationCoreNextStepOptionsHelper.js';
import { isOpEqual, isAnOp } from '../types/changeType/changeAndMistakeUtils.js';
import { cleanString } from '../util/cleanString.js';
function findMatchingAddRemoveTerms(eqProcessedStep) {
const isTermMatchingForAddRemoveFn = (termA, termB) => {
const tryGetOpFn = (op) => isAnOp(op) ? op : null;
const opEqualsFn = (op1, op2) => isOpEqual(tryGetOpFn(op1), tryGetOpFn(op2));
const termAOp = termA?.addedNumOp?.op || termA?.removeNumberOp?.op;
const termANumber = termA?.addedNumOp?.number || termA?.removeNumberOp?.number;
const termBOp = termB?.addedNumOp?.op || termB?.removeNumberOp?.op;
const termBNumber = termB?.removeNumberOp?.number || termB?.addedNumOp?.number;
const termAAdded = termA.changeType.includes("ADD_TERM");
const termBRemoved = termB.changeType.includes("REMOVE_TERM");
const termARemoved = termA.changeType.includes("REMOVE_TERM");
const termBAdded = termB.changeType.includes("ADD_TERM");
if (termANumber !== termBNumber)
return false;
if (termAAdded && termBAdded || termARemoved && termBRemoved)
return false;
if (!opEqualsFn(termAOp, termBOp))
return false;
return true;
};
const filterOutNonAddRemoveTermsFn = (options) => options.filter(
(option) => option.changeType.includes("ADD_TERM") || option.changeType.includes("REMOVE_TERM")
);
const leftOnlyAddRemoveTerms = filterOutNonAddRemoveTermsFn(eqProcessedStep.left);
const rightOnlyAddRemoveTerms = filterOutNonAddRemoveTermsFn(eqProcessedStep.right);
return leftOnlyAddRemoveTerms.map((leftProcessedStep) => {
const matchedRight = rightOnlyAddRemoveTerms.find(
(rightProcessedStep) => isTermMatchingForAddRemoveFn(leftProcessedStep, rightProcessedStep)
);
return { left: leftProcessedStep, right: matchedRight };
}).filter((option) => option.right !== void 0);
}
function makeStartingLeftAndRightEqSteps(equation) {
const expressions = equation.split("=").map((expression) => cleanString(expression));
return {
left: {
from: expressions[0],
to: expressions[0],
changeType: "NO_CHANGE",
availableChangeTypes: [],
isMistake: false
},
right: {
from: expressions[1],
to: expressions[1],
changeType: "NO_CHANGE",
availableChangeTypes: [],
isMistake: false
}
};
}
function findNonAddRemoveRuleMatches(eqProcessedSteps, starting) {
const isNotAddOrRemoveTermFn = (option) => !option.changeType.includes("ADD_TERM") && !option.changeType.includes("REMOVE_TERM");
const nonAddRemoveTermsLeft = eqProcessedSteps.left.filter((option) => isNotAddOrRemoveTermFn(option));
const nonAddRemoveTermsRight = eqProcessedSteps.right.filter((option) => isNotAddOrRemoveTermFn(option));
const newFullEquationsFromLeft = nonAddRemoveTermsLeft.map((option) => ({
left: option,
right: starting.right
}));
const newFullEquationsFromRight = nonAddRemoveTermsRight.map((option) => ({
left: starting.left,
right: option
}));
return newFullEquationsFromLeft.concat(newFullEquationsFromRight);
}
function makeEquationProcessSteps(equation) {
const expressions = equation.split("=").map((expression) => cleanString(expression));
const leftExpression = expressions[0];
const rightExpression = expressions[1];
return {
left: findAllNextStepOptions(leftExpression, {
otherSide: rightExpression,
history: []
}),
right: findAllNextStepOptions(rightExpression, {
otherSide: leftExpression,
history: []
})
};
}
export { findMatchingAddRemoveTerms, findNonAddRemoveRuleMatches, makeEquationProcessSteps, makeStartingLeftAndRightEqSteps };