Re-organize formulas for better readability/maintainability
This commit is contained in:
parent
bb0f83e75a
commit
6e4c61155a
7 changed files with 1175 additions and 1187 deletions
|
@ -8,7 +8,8 @@ import { GenericMilestone } from "features/milestones/milestone";
|
||||||
import { displayResource, Resource } from "features/resources/resource";
|
import { displayResource, Resource } from "features/resources/resource";
|
||||||
import type { GenericTree, GenericTreeNode, TreeNode, TreeNodeOptions } from "features/trees/tree";
|
import type { GenericTree, GenericTreeNode, TreeNode, TreeNodeOptions } from "features/trees/tree";
|
||||||
import { createTreeNode } from "features/trees/tree";
|
import { createTreeNode } from "features/trees/tree";
|
||||||
import Formula, { FormulaSource, GenericFormula, InvertibleFormula } from "game/formulas";
|
import Formula from "game/formulas/formulas";
|
||||||
|
import type { FormulaSource, GenericFormula } from "game/formulas/types";
|
||||||
import type { Modifier } from "game/modifiers";
|
import type { Modifier } from "game/modifiers";
|
||||||
import type { Persistent } from "game/persistence";
|
import type { Persistent } from "game/persistence";
|
||||||
import { DefaultValue, persistent } from "game/persistence";
|
import { DefaultValue, persistent } from "game/persistence";
|
||||||
|
|
File diff suppressed because it is too large
Load diff
904
src/game/formulas/operations.ts
Normal file
904
src/game/formulas/operations.ts
Normal file
|
@ -0,0 +1,904 @@
|
||||||
|
import Decimal, { DecimalSource } from "util/bignum";
|
||||||
|
import { unref } from "vue";
|
||||||
|
import Formula, { hasVariable, unrefFormulaSource } from "./formulas";
|
||||||
|
import { FormulaSource, InvertFunction, SubstitutionStack } from "./types";
|
||||||
|
|
||||||
|
export function passthrough(value: DecimalSource) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertNeg(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.neg(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateNeg(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return Decimal.neg(lhs.evaluateIntegral(variable, stack));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applySubstitutionNeg(value: DecimalSource) {
|
||||||
|
return Decimal.neg(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAdd(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.sub(value, unrefFormulaSource(rhs)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.sub(value, unrefFormulaSource(lhs)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAdd(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.times(
|
||||||
|
unrefFormulaSource(rhs),
|
||||||
|
variable ?? unref(lhs.innermostVariable) ?? 0
|
||||||
|
).add(x);
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.times(
|
||||||
|
unrefFormulaSource(lhs),
|
||||||
|
variable ?? unref(rhs.innermostVariable) ?? 0
|
||||||
|
).add(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateInnerAdd(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.add(x, unrefFormulaSource(rhs));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.add(x, unrefFormulaSource(lhs));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateAdd(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sub(b));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const b = unrefFormulaSource(lhs);
|
||||||
|
return rhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sub(b));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.add(value, unrefFormulaSource(rhs)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.sub(unrefFormulaSource(lhs), value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateSub(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.sub(
|
||||||
|
x,
|
||||||
|
Decimal.times(unrefFormulaSource(rhs), variable ?? unref(lhs.innermostVariable) ?? 0)
|
||||||
|
);
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.times(
|
||||||
|
unrefFormulaSource(lhs),
|
||||||
|
variable ?? unref(rhs.innermostVariable) ?? 0
|
||||||
|
).sub(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateInnerSub(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.sub(x, unrefFormulaSource(rhs));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.sub(x, unrefFormulaSource(lhs));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sqrt().sub(b));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const b = unrefFormulaSource(lhs);
|
||||||
|
return rhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sqrt().sub(b));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.div(value, unrefFormulaSource(rhs)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.div(value, unrefFormulaSource(lhs)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateMul(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.times(x, unrefFormulaSource(rhs));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.times(x, unrefFormulaSource(lhs));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applySubstitutionMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return Decimal.div(value, unrefFormulaSource(rhs));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return Decimal.div(value, unrefFormulaSource(lhs));
|
||||||
|
}
|
||||||
|
throw "Could not apply substitution due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).div(Decimal.sqrt(b)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const b = unrefFormulaSource(lhs);
|
||||||
|
return rhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).div(Decimal.sqrt(b)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.mul(value, unrefFormulaSource(rhs)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.div(unrefFormulaSource(lhs), value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateDiv(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.div(x, unrefFormulaSource(rhs));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.div(unrefFormulaSource(lhs), x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applySubstitutionDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return Decimal.mul(value, unrefFormulaSource(rhs));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return Decimal.mul(value, unrefFormulaSource(lhs));
|
||||||
|
}
|
||||||
|
throw "Could not apply substitution due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).times(Decimal.sqrt(b)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const b = unrefFormulaSource(lhs);
|
||||||
|
return rhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).times(Decimal.sqrt(b)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertRecip(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.recip(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateRecip(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.ln(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateRecip(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.exp(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertLog10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.pow10(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateLog10(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.ln(x).sub(1).times(x).div(Decimal.ln(10));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateLog10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(
|
||||||
|
Decimal.exp(Decimal.ln(2).add(Decimal.ln(5)).times(value).div(Math.E).lambertw().add(1))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.pow(unrefFormulaSource(rhs), value));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateLog(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.ln(x)
|
||||||
|
.sub(1)
|
||||||
|
.times(x)
|
||||||
|
.div(Decimal.ln(unrefFormulaSource(rhs)));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const numerator = Decimal.ln(unrefFormulaSource(rhs)).times(value);
|
||||||
|
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertLog2(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.pow(2, value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateLog2(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.ln(x).sub(1).times(x).div(Decimal.ln(2));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateLog2(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.exp(Decimal.ln(2).times(value).div(Math.E).lambertw().add(1)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertLn(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.exp(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateLn(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.ln(x).sub(1).times(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateLn(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.exp(Decimal.div(value, Math.E).lambertw().add(1)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.root(value, unrefFormulaSource(rhs)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.ln(value).div(Decimal.ln(unrefFormulaSource(lhs))));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integratePow(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
const pow = Decimal.add(unrefFormulaSource(rhs), 1);
|
||||||
|
return Decimal.pow(x, pow).div(pow);
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
const b = unrefFormulaSource(lhs);
|
||||||
|
return Decimal.pow(b, x).div(Decimal.ln(b));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegratePow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(Decimal.negate(b).sub(1).negate().times(value).root(Decimal.add(b, 1)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const denominator = Decimal.ln(unrefFormulaSource(lhs));
|
||||||
|
return rhs.invert(Decimal.times(denominator, value).ln().div(denominator));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertPow10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.root(value, 10));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integratePow10(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.ln(x).sub(1).times(x).div(Decimal.ln(10));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegratePow10(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(
|
||||||
|
Decimal.ln(2).add(Decimal.ln(5)).times(value).div(Math.E).lambertw().add(1).exp()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.ln(value).div(unrefFormulaSource(rhs)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integratePowBase(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return Decimal.pow(b, x).div(Decimal.ln(b));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const x = rhs.evaluateIntegral(variable, stack);
|
||||||
|
const denominator = Decimal.add(unrefFormulaSource(lhs), 1);
|
||||||
|
return Decimal.pow(x, denominator).div(denominator);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegratePowBase(
|
||||||
|
value: DecimalSource,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(Decimal.ln(b).times(value).ln().div(Decimal.ln(b)));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
const b = unrefFormulaSource(lhs);
|
||||||
|
return rhs.invert(Decimal.neg(b).sub(1).negate().times(value).root(Decimal.add(b, 1)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.root(value, Decimal.recip(unrefFormulaSource(rhs))));
|
||||||
|
} else if (hasVariable(rhs)) {
|
||||||
|
return rhs.invert(Decimal.ln(unrefFormulaSource(lhs)).div(Decimal.ln(value)));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateRoot(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
rhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
const a = unrefFormulaSource(rhs);
|
||||||
|
return Decimal.pow(x, Decimal.recip(a).add(1)).times(a).div(Decimal.add(a, 1));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIntegrateRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const b = unrefFormulaSource(rhs);
|
||||||
|
return lhs.invert(
|
||||||
|
Decimal.add(b, 1)
|
||||||
|
.times(value)
|
||||||
|
.div(b)
|
||||||
|
.pow(Decimal.div(b, Decimal.add(b, 1)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertExp(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.ln(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateExp(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.exp(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tetrate(
|
||||||
|
value: DecimalSource,
|
||||||
|
height: DecimalSource = 2,
|
||||||
|
payload: DecimalSource = Decimal.fromComponents_noNormalize(1, 0, 1)
|
||||||
|
) {
|
||||||
|
const heightNumber = Decimal.minabs(height, 1e308).toNumber();
|
||||||
|
return Decimal.tetrate(value, heightNumber, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertTetrate(
|
||||||
|
value: DecimalSource,
|
||||||
|
base: FormulaSource,
|
||||||
|
height: FormulaSource,
|
||||||
|
payload: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(base)) {
|
||||||
|
return base.invert(Decimal.ssqrt(value));
|
||||||
|
}
|
||||||
|
// Other params can't be inverted ATM
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function iteratedexp(
|
||||||
|
value: DecimalSource,
|
||||||
|
height: DecimalSource = 2,
|
||||||
|
payload: DecimalSource = Decimal.fromComponents_noNormalize(1, 0, 1)
|
||||||
|
) {
|
||||||
|
const heightNumber = Decimal.minabs(height, 1e308).toNumber();
|
||||||
|
return Decimal.iteratedexp(value, heightNumber, new Decimal(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertIteratedExp(
|
||||||
|
value: DecimalSource,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
height: FormulaSource,
|
||||||
|
payload: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(
|
||||||
|
Decimal.iteratedlog(
|
||||||
|
value,
|
||||||
|
Math.E,
|
||||||
|
Decimal.minabs(1e308, unrefFormulaSource(height)).toNumber()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Other params can't be inverted ATM
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function iteratedLog(
|
||||||
|
value: DecimalSource,
|
||||||
|
lhs: DecimalSource = 10,
|
||||||
|
times: DecimalSource = 2
|
||||||
|
) {
|
||||||
|
const timesNumber = Decimal.minabs(times, 1e308).toNumber();
|
||||||
|
return Decimal.iteratedlog(value, lhs, timesNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function slog(value: DecimalSource, lhs: DecimalSource = 10) {
|
||||||
|
const baseNumber = Decimal.minabs(lhs, 1e308).toNumber();
|
||||||
|
return Decimal.slog(value, baseNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertSlog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(
|
||||||
|
Decimal.tetrate(value, Decimal.minabs(1e308, unrefFormulaSource(rhs)).toNumber())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Other params can't be inverted ATM
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function layeradd(value: DecimalSource, diff: DecimalSource, base: DecimalSource) {
|
||||||
|
const diffNumber = Decimal.minabs(diff, 1e308).toNumber();
|
||||||
|
return Decimal.layeradd(value, diffNumber, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertLayeradd(
|
||||||
|
value: DecimalSource,
|
||||||
|
lhs: FormulaSource,
|
||||||
|
diff: FormulaSource,
|
||||||
|
base: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(
|
||||||
|
Decimal.layeradd(
|
||||||
|
value,
|
||||||
|
Decimal.minabs(1e308, unrefFormulaSource(diff)).negate().toNumber()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Other params can't be inverted ATM
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertLambertw(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.pow(Math.E, value).times(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertSsqrt(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.tetrate(value, 2));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pentate(value: DecimalSource, height: DecimalSource, payload: DecimalSource) {
|
||||||
|
const heightNumber = Decimal.minabs(height, 1e308).toNumber();
|
||||||
|
return Decimal.pentate(value, heightNumber, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertSin(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.asin(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateSin(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.cos(x).neg();
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertCos(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.acos(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateCos(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.sin(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertTan(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.atan(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateTan(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.cos(x).ln().neg();
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAsin(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.sin(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAsin(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.asin(x)
|
||||||
|
.times(x)
|
||||||
|
.add(Decimal.sqrt(Decimal.sub(1, Decimal.pow(x, 2))));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAcos(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.cos(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAcos(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.acos(x)
|
||||||
|
.times(x)
|
||||||
|
.sub(Decimal.sqrt(Decimal.sub(1, Decimal.pow(x, 2))));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAtan(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.tan(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAtan(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.atan(x)
|
||||||
|
.times(x)
|
||||||
|
.sub(Decimal.ln(Decimal.pow(x, 2).add(1)).div(2));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertSinh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.asinh(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateSinh(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.cosh(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertCosh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.acosh(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateCosh(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.sinh(x);
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertTanh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.atanh(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateTanh(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.cosh(x).ln();
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAsinh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.sinh(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAsinh(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.asinh(x).times(x).sub(Decimal.pow(x, 2).add(1).sqrt());
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAcosh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.cosh(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAcosh(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.acosh(x)
|
||||||
|
.times(x)
|
||||||
|
.sub(Decimal.add(x, 1).sqrt().times(Decimal.sub(x, 1).sqrt()));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function invertAtanh(value: DecimalSource, lhs: FormulaSource) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
return lhs.invert(Decimal.tanh(value));
|
||||||
|
}
|
||||||
|
throw "Could not invert due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function integrateAtanh(
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack,
|
||||||
|
lhs: FormulaSource
|
||||||
|
) {
|
||||||
|
if (hasVariable(lhs)) {
|
||||||
|
const x = lhs.evaluateIntegral(variable, stack);
|
||||||
|
return Decimal.atanh(x)
|
||||||
|
.times(x)
|
||||||
|
.add(Decimal.sub(1, Decimal.pow(x, 2)).ln().div(2));
|
||||||
|
}
|
||||||
|
throw "Could not integrate due to no input being a variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createPassthroughBinaryFormula(
|
||||||
|
operation: (a: DecimalSource, b: DecimalSource) => DecimalSource
|
||||||
|
) {
|
||||||
|
return (value: FormulaSource, other: FormulaSource) =>
|
||||||
|
new Formula({
|
||||||
|
inputs: [value, other],
|
||||||
|
evaluate: operation,
|
||||||
|
invert: passthrough as InvertFunction<[FormulaSource, FormulaSource]>,
|
||||||
|
invertIntegral: passthrough as InvertFunction<[FormulaSource, FormulaSource]>
|
||||||
|
});
|
||||||
|
}
|
79
src/game/formulas/types.d.ts
vendored
Normal file
79
src/game/formulas/types.d.ts
vendored
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import Formula from "game/formulas/formulas";
|
||||||
|
import { DecimalSource } from "util/bignum";
|
||||||
|
import { ProcessedComputable } from "util/computed";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
type GenericFormula = Formula<any>;
|
||||||
|
type FormulaSource = ProcessedComputable<DecimalSource> | GenericFormula;
|
||||||
|
type InvertibleFormula = GenericFormula & {
|
||||||
|
invert: (value: DecimalSource) => DecimalSource;
|
||||||
|
};
|
||||||
|
type IntegrableFormula = GenericFormula & {
|
||||||
|
evaluateIntegral: (variable?: DecimalSource) => DecimalSource;
|
||||||
|
};
|
||||||
|
type InvertibleIntegralFormula = GenericFormula & {
|
||||||
|
invertIntegral: (value: DecimalSource) => DecimalSource;
|
||||||
|
};
|
||||||
|
|
||||||
|
type EvaluateFunction<T> = (
|
||||||
|
this: Formula<T>,
|
||||||
|
...inputs: GuardedFormulasToDecimals<T>
|
||||||
|
) => DecimalSource;
|
||||||
|
type InvertFunction<T> = (this: Formula<T>, value: DecimalSource, ...inputs: T) => DecimalSource;
|
||||||
|
type IntegrateFunction<T> = (
|
||||||
|
this: Formula<T>,
|
||||||
|
variable: DecimalSource | undefined,
|
||||||
|
stack: SubstitutionStack | undefined,
|
||||||
|
...inputs: T
|
||||||
|
) => DecimalSource;
|
||||||
|
type SubstitutionFunction<T> = (
|
||||||
|
this: Formula<T>,
|
||||||
|
variable: DecimalSource,
|
||||||
|
...inputs: T
|
||||||
|
) => DecimalSource;
|
||||||
|
type InvertIntegralFunction<T> = (
|
||||||
|
this: Formula<T>,
|
||||||
|
value: DecimalSource,
|
||||||
|
...inputs: T
|
||||||
|
) => DecimalSource;
|
||||||
|
|
||||||
|
type VariableFormulaOptions = { variable: ProcessedComputable<DecimalSource> };
|
||||||
|
type ConstantFormulaOptions = {
|
||||||
|
inputs: [FormulaSource];
|
||||||
|
};
|
||||||
|
type GeneralFormulaOptions<T extends [FormulaSource] | FormulaSource[]> = {
|
||||||
|
inputs: T;
|
||||||
|
evaluate: EvaluateFunction<T>;
|
||||||
|
invert?: InvertFunction<T>;
|
||||||
|
integrate?: IntegrateFunction<T>;
|
||||||
|
integrateInner?: IntegrateFunction<T>;
|
||||||
|
applySubstitution?: SubstitutionFunction<T>;
|
||||||
|
invertIntegral?: InvertIntegralFunction<T>;
|
||||||
|
hasVariable?: boolean;
|
||||||
|
};
|
||||||
|
type FormulaOptions<T extends [FormulaSource] | FormulaSource[]> =
|
||||||
|
| VariableFormulaOptions
|
||||||
|
| ConstantFormulaOptions
|
||||||
|
| GeneralFormulaOptions<T>;
|
||||||
|
|
||||||
|
type InternalFormulaProperties<T extends [FormulaSource] | FormulaSource[]> = {
|
||||||
|
inputs: T;
|
||||||
|
internalHasVariable: boolean;
|
||||||
|
internalEvaluate?: EvaluateFunction<T>;
|
||||||
|
internalInvert?: InvertFunction<T>;
|
||||||
|
internalIntegrate?: IntegrateFunction<T>;
|
||||||
|
internalIntegrateInner?: IntegrateFunction<T>;
|
||||||
|
internalInvertIntegral?: InvertIntegralFunction<T>;
|
||||||
|
applySubstitution?: SubstitutionFunction<T>;
|
||||||
|
innermostVariable?: ProcessedComputable<DecimalSource>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SubstitutionStack = ((value: DecimalSource) => DecimalSource)[] | undefined;
|
||||||
|
|
||||||
|
// It's really hard to type mapped tuples, but these classes seem to manage
|
||||||
|
type FormulasToDecimals<T extends FormulaSource[]> = {
|
||||||
|
[K in keyof T]: DecimalSource;
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
type TupleGuard<T extends any[]> = T extends any[] ? FormulasToDecimals<T> : never;
|
||||||
|
type GuardedFormulasToDecimals<T extends FormulaSource[]> = TupleGuard<T>;
|
|
@ -11,12 +11,8 @@ import {
|
||||||
import { createLazyProxy } from "util/proxies";
|
import { createLazyProxy } from "util/proxies";
|
||||||
import { joinJSX, renderJSX } from "util/vue";
|
import { joinJSX, renderJSX } from "util/vue";
|
||||||
import { computed, unref } from "vue";
|
import { computed, unref } from "vue";
|
||||||
import Formula, {
|
import Formula, { calculateCost, calculateMaxAffordable } from "./formulas/formulas";
|
||||||
calculateCost,
|
import type { GenericFormula, InvertibleFormula } from "./formulas/types";
|
||||||
calculateMaxAffordable,
|
|
||||||
GenericFormula,
|
|
||||||
InvertibleFormula
|
|
||||||
} from "./formulas";
|
|
||||||
import { DefaultValue, Persistent } from "./persistence";
|
import { DefaultValue, Persistent } from "./persistence";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,10 +2,9 @@ import { createResource, Resource } from "features/resources/resource";
|
||||||
import Formula, {
|
import Formula, {
|
||||||
calculateCost,
|
calculateCost,
|
||||||
calculateMaxAffordable,
|
calculateMaxAffordable,
|
||||||
GenericFormula,
|
|
||||||
InvertibleFormula,
|
|
||||||
unrefFormulaSource
|
unrefFormulaSource
|
||||||
} from "game/formulas";
|
} from "game/formulas/formulas";
|
||||||
|
import type { GenericFormula, InvertibleFormula } from "game/formulas/types";
|
||||||
import Decimal, { DecimalSource } from "util/bignum";
|
import Decimal, { DecimalSource } from "util/bignum";
|
||||||
import { beforeAll, describe, expect, test } from "vitest";
|
import { beforeAll, describe, expect, test } from "vitest";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Visibility } from "features/feature";
|
import { Visibility } from "features/feature";
|
||||||
import { createResource, Resource } from "features/resources/resource";
|
import { createResource, Resource } from "features/resources/resource";
|
||||||
import Formula from "game/formulas";
|
import Formula from "game/formulas/formulas";
|
||||||
import {
|
import {
|
||||||
CostRequirement,
|
CostRequirement,
|
||||||
createBooleanRequirement,
|
createBooleanRequirement,
|
||||||
|
|
Loading…
Reference in a new issue