Add else statement to conditional formulas

This commit is contained in:
thepaperpilot 2023-04-18 20:13:12 -05:00
parent ba67ff4fe9
commit 0f2cc45a7e
2 changed files with 36 additions and 3 deletions

View file

@ -364,21 +364,30 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
* @param value The incoming formula value * @param value The incoming formula value
* @param condition Whether or not to apply the modifier * @param condition Whether or not to apply the modifier
* @param formulaModifier The modifier to apply to the incoming formula if the condition is true * @param formulaModifier The modifier to apply to the incoming formula if the condition is true
* @param elseFormulaModifier An optional modifier to apply to the incoming formula if the condition is false
*/ */
public static if( public static if(
value: FormulaSource, value: FormulaSource,
condition: Computable<boolean>, condition: Computable<boolean>,
formulaModifier: ( formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula,
elseFormulaModifier?: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula ) => GenericFormula
): GenericFormula { ): GenericFormula {
const lhsRef = ref<DecimalSource>(0); const lhsRef = ref<DecimalSource>(0);
const formula = formulaModifier(Formula.variable(lhsRef)); const variable = Formula.variable(lhsRef);
const formula = formulaModifier(variable);
const elseFormula = elseFormulaModifier?.(variable);
const processedCondition = convertComputable(condition); const processedCondition = convertComputable(condition);
function evalStep(lhs: DecimalSource) { function evalStep(lhs: DecimalSource) {
if (unref(processedCondition)) { if (unref(processedCondition)) {
lhsRef.value = lhs; lhsRef.value = lhs;
return formula.evaluate(); return formula.evaluate();
} else if (elseFormula) {
lhsRef.value = lhs;
return elseFormula.evaluate();
} else { } else {
return lhs; return lhs;
} }
@ -389,6 +398,8 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
} }
if (unref(processedCondition)) { if (unref(processedCondition)) {
return lhs.invert(formula.invert(value)); return lhs.invert(formula.invert(value));
} else if (elseFormula) {
return lhs.invert(elseFormula.invert(value));
} else { } else {
return lhs.invert(value); return lhs.invert(value);
} }
@ -399,15 +410,17 @@ export default class Formula<T extends [FormulaSource] | FormulaSource[]> {
invert: formula.isInvertible() && formula.hasVariable() ? invertStep : undefined invert: formula.isInvertible() && formula.hasVariable() ? invertStep : undefined
}); });
} }
/** @see {@link if} */
public static conditional( public static conditional(
value: FormulaSource, value: FormulaSource,
condition: Computable<boolean>, condition: Computable<boolean>,
formulaModifier: ( formulaModifier: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula,
elseFormulaModifier?: (
value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula
) => GenericFormula ) => GenericFormula
) { ) {
return Formula.if(value, condition, formulaModifier); return Formula.if(value, condition, formulaModifier, elseFormulaModifier);
} }
public static abs(value: FormulaSource): GenericFormula { public static abs(value: FormulaSource): GenericFormula {

View file

@ -868,6 +868,26 @@ describe("Conditionals", () => {
Formula.if(variable, false, value => Formula.sqrt(value)).invert(10) Formula.if(variable, false, value => Formula.sqrt(value)).invert(10)
).compare_tolerance(10)); ).compare_tolerance(10));
}); });
describe("Evaluates correctly with condition false and else statement", () => {
test("Evaluates correctly", () =>
expect(
Formula.if(
constant,
false,
value => Formula.sqrt(value),
value => value.times(2)
).evaluate()
).compare_tolerance(20));
test("Inverts correctly with variable in input", () =>
expect(
Formula.if(
variable,
false,
value => Formula.sqrt(value),
value => value.times(2)
).invert(20)
).compare_tolerance(10));
});
describe("Evaluates correctly with condition true", () => { describe("Evaluates correctly with condition true", () => {
test("Evaluates correctly", () => test("Evaluates correctly", () =>