Improve error handling
This commit is contained in:
parent
d3a74da5ab
commit
539282bef8
12 changed files with 424 additions and 155 deletions
39
src/App.vue
39
src/App.vue
|
@ -1,18 +1,25 @@
|
|||
<template>
|
||||
<div id="modal-root" :style="theme" />
|
||||
<div class="app" :style="theme" :class="{ useHeader }">
|
||||
<Nav v-if="useHeader" />
|
||||
<Game />
|
||||
<TPS v-if="unref(showTPS)" />
|
||||
<GameOverScreen />
|
||||
<NaNScreen />
|
||||
<component :is="gameComponent" />
|
||||
</div>
|
||||
<div v-if="appErrors.length > 0" class="error-container" :style="theme"><Error :errors="appErrors" /></div>
|
||||
<template v-else>
|
||||
<div id="modal-root" :style="theme" />
|
||||
<div class="app" :style="theme" :class="{ useHeader }">
|
||||
<Nav v-if="useHeader" />
|
||||
<Game />
|
||||
<TPS v-if="unref(showTPS)" />
|
||||
<GameOverScreen />
|
||||
<NaNScreen />
|
||||
<component :is="gameComponent" />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import "@fontsource/roboto-mono";
|
||||
import Error from "components/Error.vue";
|
||||
import { jsx } from "features/feature";
|
||||
import state from "game/state";
|
||||
import { coerceComponent, render } from "util/vue";
|
||||
import { CSSProperties, watch } from "vue";
|
||||
import { computed, toRef, unref } from "vue";
|
||||
import Game from "./components/Game.vue";
|
||||
import GameOverScreen from "./components/GameOverScreen.vue";
|
||||
|
@ -23,12 +30,11 @@ import projInfo from "./data/projInfo.json";
|
|||
import themes from "./data/themes";
|
||||
import settings, { gameComponents } from "./game/settings";
|
||||
import "./main.css";
|
||||
import "@fontsource/roboto-mono";
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
const useHeader = projInfo.useHeader;
|
||||
const theme = computed(() => themes[settings.theme].variables as CSSProperties);
|
||||
const showTPS = toRef(settings, "showTPS");
|
||||
const appErrors = toRef(state, "errors");
|
||||
|
||||
const gameComponent = computed(() => {
|
||||
return coerceComponent(jsx(() => (<>{gameComponents.map(render)}</>)));
|
||||
|
@ -51,4 +57,15 @@ const gameComponent = computed(() => {
|
|||
height: 100%;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.error-container {
|
||||
background: var(--background);
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.error-container > .error {
|
||||
position: static;
|
||||
}
|
||||
</style>
|
||||
|
|
103
src/components/Error.vue
Normal file
103
src/components/Error.vue
Normal file
|
@ -0,0 +1,103 @@
|
|||
<template>
|
||||
<div class="error">
|
||||
<h1 class="error-title">{{ firstError.name }}: {{ firstError.message }}</h1>
|
||||
<div class="error-details" style="margin-top: -10px">
|
||||
<div v-if="firstError.cause">
|
||||
<div v-for="row in causes[0]" :key="row">{{ row }}</div>
|
||||
</div>
|
||||
<div v-if="firstError.stack" :style="firstError.cause ? 'margin-top: 10px' : ''">
|
||||
<div v-for="row in stacks[0]" :key="row">{{ row }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="instructions">
|
||||
Check the console for more details, and consider sharing it with the developers on
|
||||
<a :href="projInfo.discordLink || 'https://discord.gg/yJ4fjnjU54'" class="discord-link"
|
||||
>discord</a
|
||||
>!<br />
|
||||
<div v-if="errors.length > 1" style="margin-top: 20px"><h3>Other errors</h3></div>
|
||||
<div v-for="(error, i) in errors.slice(1)" :key="i" style="margin-top: 20px">
|
||||
<details class="error-details">
|
||||
<summary>{{ error.name }}: {{ error.message }}</summary>
|
||||
<div v-if="error.cause" style="margin-top: 10px">
|
||||
<div v-for="row in causes[i + 1]" :key="row">{{ row }}</div>
|
||||
</div>
|
||||
<div v-if="error.stack" style="margin-top: 10px">
|
||||
<div v-for="row in stacks[i + 1]" :key="row">{{ row }}</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import projInfo from "data/projInfo.json";
|
||||
import player from "game/player";
|
||||
import { computed, onMounted } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
errors: Error[];
|
||||
}>();
|
||||
|
||||
const firstError = computed(() => props.errors[0]);
|
||||
const stacks = computed(() =>
|
||||
props.errors.map(error => (error.stack == null ? [] : error.stack.split("\n")))
|
||||
);
|
||||
const causes = computed(() =>
|
||||
props.errors.map(error =>
|
||||
error.cause == null
|
||||
? []
|
||||
: (typeof error.cause === "string" ? error.cause : JSON.stringify(error.cause)).split(
|
||||
"\n"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
player.autosave = false;
|
||||
player.devSpeed = 0;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.error {
|
||||
border: solid 10px var(--danger);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: left;
|
||||
min-height: calc(100% - 20px);
|
||||
text-align: left;
|
||||
color: var(--foreground);
|
||||
}
|
||||
|
||||
.error-title {
|
||||
background: var(--danger);
|
||||
color: var(--feature-foreground);
|
||||
display: block;
|
||||
margin: -10px 0 10px 0;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.error-details {
|
||||
white-space: nowrap;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
background-color: var(--raised-background);
|
||||
}
|
||||
|
||||
.instructions {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.discord-link {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div class="layer-container" :style="{ '--layer-color': unref(color) }">
|
||||
<ErrorVue v-if="errors.length > 0" :errors="errors" />
|
||||
<div class="layer-container" :style="{ '--layer-color': unref(color) }" v-bind="$attrs" v-else>
|
||||
<button v-if="showGoBack" class="goBack" @click="goBack">❌</button>
|
||||
|
||||
<button
|
||||
|
@ -28,12 +29,12 @@ import type { CoercableComponent } from "features/feature";
|
|||
import type { FeatureNode } from "game/layers";
|
||||
import player from "game/player";
|
||||
import { computeComponent, computeOptionalComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import type { PropType, Ref } from "vue";
|
||||
import { computed, defineComponent, toRefs, unref } from "vue";
|
||||
import { PropType, Ref, computed, defineComponent, onErrorCaptured, ref, toRefs, unref } from "vue";
|
||||
import Context from "./Context.vue";
|
||||
import ErrorVue from "./Error.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { Context },
|
||||
components: { Context, ErrorVue },
|
||||
props: {
|
||||
index: {
|
||||
type: Number,
|
||||
|
@ -77,13 +78,23 @@ export default defineComponent({
|
|||
props.nodes.value = nodes;
|
||||
}
|
||||
|
||||
const errors = ref<Error[]>([]);
|
||||
onErrorCaptured((err, instance, info) => {
|
||||
console.warn(`Error caught in "${props.name}" layer`, err, instance, info);
|
||||
errors.value.push(
|
||||
err instanceof Error ? (err as Error) : new Error(JSON.stringify(err))
|
||||
);
|
||||
return false;
|
||||
});
|
||||
|
||||
return {
|
||||
component,
|
||||
minimizedComponent,
|
||||
showGoBack,
|
||||
updateNodes,
|
||||
unref,
|
||||
goBack
|
||||
goBack,
|
||||
errors
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -459,7 +459,7 @@ export function createFormulaPreview(
|
|||
const processedShowPreview = convertComputable(showPreview);
|
||||
const processedPreviewAmount = convertComputable(previewAmount);
|
||||
if (!formula.hasVariable()) {
|
||||
throw new Error("Cannot create formula preview if the formula does not have a variable");
|
||||
console.error("Cannot create formula preview if the formula does not have a variable");
|
||||
}
|
||||
return jsx(() => {
|
||||
if (unref(processedShowPreview)) {
|
||||
|
|
|
@ -151,8 +151,7 @@ export function createTabFamily<T extends TabFamilyOptions>(
|
|||
optionsFunc?: OptionsFunc<T, BaseTabFamily, GenericTabFamily>
|
||||
): TabFamily<T> {
|
||||
if (Object.keys(tabs).length === 0) {
|
||||
console.warn("Cannot create tab family with 0 tabs");
|
||||
throw new Error("Cannot create tab family with 0 tabs");
|
||||
console.error("Cannot create tab family with 0 tabs");
|
||||
}
|
||||
|
||||
const selected = persistent(Object.keys(tabs)[0], false);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Resource } from "features/resources/resource";
|
|||
import { NonPersistent } from "game/persistence";
|
||||
import Decimal, { DecimalSource, format } from "util/bignum";
|
||||
import { Computable, ProcessedComputable, convertComputable } from "util/computed";
|
||||
import { ComputedRef, Ref, computed, ref, unref } from "vue";
|
||||
import { Ref, computed, ref, unref } from "vue";
|
||||
import * as ops from "./operations";
|
||||
import type {
|
||||
EvaluateFunction,
|
||||
|
@ -104,7 +104,7 @@ export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[
|
|||
|
||||
private setupConstant({ inputs }: { inputs: [FormulaSource] }): InternalFormulaProperties<T> {
|
||||
if (inputs.length !== 1) {
|
||||
throw new Error("Evaluate function is required if inputs is not length 1");
|
||||
console.error("Evaluate function is required if inputs is not length 1");
|
||||
}
|
||||
return {
|
||||
inputs: inputs as T,
|
||||
|
@ -250,7 +250,8 @@ export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[
|
|||
}
|
||||
return lhs.invert(value);
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
return new Formula({
|
||||
inputs: [value],
|
||||
|
@ -294,7 +295,8 @@ export abstract class InternalFormula<T extends [FormulaSource] | FormulaSource[
|
|||
!formula.isInvertible() ||
|
||||
(elseFormula != null && !elseFormula.isInvertible())
|
||||
) {
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
if (unref(processedCondition)) {
|
||||
return lhs.invert(formula.invert(value));
|
||||
|
@ -1260,7 +1262,8 @@ export default class Formula<
|
|||
} else if (this.inputs.length === 1 && this.hasVariable()) {
|
||||
return value;
|
||||
}
|
||||
throw new Error("Cannot invert non-invertible formula");
|
||||
console.error("Cannot invert non-invertible formula");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1270,7 +1273,8 @@ export default class Formula<
|
|||
*/
|
||||
evaluateIntegral(variable?: DecimalSource): DecimalSource {
|
||||
if (!this.isIntegrable()) {
|
||||
throw new Error("Cannot evaluate integral of formula without integral");
|
||||
console.error("Cannot evaluate integral of formula without integral");
|
||||
return 0;
|
||||
}
|
||||
return this.getIntegralFormula().evaluate(variable);
|
||||
}
|
||||
|
@ -1282,7 +1286,8 @@ export default class Formula<
|
|||
*/
|
||||
invertIntegral(value: DecimalSource): DecimalSource {
|
||||
if (!this.isIntegrable() || !this.getIntegralFormula().isInvertible()) {
|
||||
throw new Error("Cannot invert integral of formula without invertible integral");
|
||||
console.error("Cannot invert integral of formula without invertible integral");
|
||||
return 0;
|
||||
}
|
||||
return (this.getIntegralFormula() as InvertibleFormula).invert(value);
|
||||
}
|
||||
|
@ -1309,7 +1314,8 @@ export default class Formula<
|
|||
// We're the complex operation of this formula
|
||||
stack = [];
|
||||
if (this.internalIntegrate == null) {
|
||||
throw new Error("Cannot integrate formula with non-integrable operation");
|
||||
console.error("Cannot integrate formula with non-integrable operation");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
let value = this.internalIntegrate.call(this, stack, ...this.inputs);
|
||||
stack.forEach(func => (value = func(value)));
|
||||
|
@ -1329,14 +1335,15 @@ export default class Formula<
|
|||
) {
|
||||
this.integralFormula = this;
|
||||
} else {
|
||||
throw new Error("Cannot integrate formula without variable");
|
||||
console.error("Cannot integrate formula without variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
}
|
||||
return this.integralFormula;
|
||||
} else {
|
||||
// "Inner" part of the formula
|
||||
if (this.applySubstitution == null) {
|
||||
throw new Error("Cannot have two complex operations in an integrable formula");
|
||||
console.error("Cannot have two complex operations in an integrable formula");
|
||||
}
|
||||
stack.push((variable: GenericFormula) =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
|
@ -1353,7 +1360,8 @@ export default class Formula<
|
|||
) {
|
||||
return this;
|
||||
} else {
|
||||
throw new Error("Cannot integrate formula without variable");
|
||||
console.error("Cannot integrate formula without variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1429,9 +1437,10 @@ export function calculateMaxAffordable(
|
|||
let affordable;
|
||||
if (unref(computedSpendResources)) {
|
||||
if (!formula.isIntegrable() || !formula.isIntegralInvertible()) {
|
||||
throw new Error(
|
||||
console.error(
|
||||
"Cannot calculate max affordable of formula with non-invertible integral"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
affordable = Decimal.floor(
|
||||
formula.invertIntegral(Decimal.add(resource.value, formula.evaluateIntegral()))
|
||||
|
@ -1441,7 +1450,8 @@ export function calculateMaxAffordable(
|
|||
}
|
||||
} else {
|
||||
if (!formula.isInvertible()) {
|
||||
throw new Error("Cannot calculate max affordable of non-invertible formula");
|
||||
console.error("Cannot calculate max affordable of non-invertible formula");
|
||||
return 0;
|
||||
}
|
||||
affordable = Decimal.floor(formula.invert(resource.value));
|
||||
if (summedPurchases == null) {
|
||||
|
@ -1501,9 +1511,10 @@ export function calculateCost(
|
|||
if (spendResources) {
|
||||
if (Decimal.gt(amountToBuy, summedPurchases)) {
|
||||
if (!formula.isIntegrable()) {
|
||||
throw new Error(
|
||||
console.error(
|
||||
"Cannot calculate cost with spending resources of non-integrable formula"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
cost = Decimal.sub(formula.evaluateIntegral(newValue), formula.evaluateIntegral());
|
||||
}
|
||||
|
|
|
@ -12,17 +12,20 @@ export function invertNeg(value: DecimalSource, lhs: FormulaSource) {
|
|||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.neg(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateNeg(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
return Formula.neg(lhs.getIntegralFormula(stack));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function applySubstitutionNeg(value: GenericFormula) {
|
||||
|
@ -35,24 +38,28 @@ export function invertAdd(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.sub(value, unrefFormulaSource(lhs)));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAdd(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.times(rhs, lhs.innermostVariable ?? 0).add(x);
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.times(lhs, rhs.innermostVariable ?? 0).add(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function integrateInnerAdd(
|
||||
|
@ -62,18 +69,21 @@ export function integrateInnerAdd(
|
|||
) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.add(x, rhs);
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.add(x, lhs);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -82,24 +92,28 @@ export function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.sub(unrefFormulaSource(lhs), value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateSub(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.sub(x, Formula.times(rhs, lhs.innermostVariable ?? 0));
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.times(lhs, rhs.innermostVariable ?? 0).sub(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function integrateInnerSub(
|
||||
|
@ -109,18 +123,21 @@ export function integrateInnerSub(
|
|||
) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.sub(x, rhs);
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.sub(x, lhs);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -129,24 +146,28 @@ export function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.div(value, unrefFormulaSource(lhs)));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateMul(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.times(x, rhs);
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.times(x, lhs);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function applySubstitutionMul(
|
||||
|
@ -159,7 +180,8 @@ export function applySubstitutionMul(
|
|||
} else if (hasVariable(rhs)) {
|
||||
return Formula.div(value, lhs);
|
||||
}
|
||||
throw new Error("Could not apply substitution due to no input being a variable");
|
||||
console.error("Could not apply substitution due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -168,24 +190,28 @@ export function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.div(unrefFormulaSource(lhs), value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateDiv(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.div(x, rhs);
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.div(lhs, x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function applySubstitutionDiv(
|
||||
|
@ -198,32 +224,37 @@ export function applySubstitutionDiv(
|
|||
} else if (hasVariable(rhs)) {
|
||||
return Formula.mul(value, lhs);
|
||||
}
|
||||
throw new Error("Could not apply substitution due to no input being a variable");
|
||||
console.error("Could not apply substitution due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertRecip(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.recip(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateRecip(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.ln(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertLog10(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.pow10(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
function internalIntegrateLog10(lhs: DecimalSource) {
|
||||
|
@ -235,13 +266,15 @@ function internalInvertIntegralLog10(value: DecimalSource, lhs: FormulaSource) {
|
|||
const numerator = ln10.times(value);
|
||||
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateLog10(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
return new Formula({
|
||||
inputs: [lhs.getIntegralFormula(stack)],
|
||||
|
@ -249,7 +282,8 @@ export function integrateLog10(stack: SubstitutionStack, lhs: FormulaSource) {
|
|||
invert: internalInvertIntegralLog10
|
||||
});
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -258,7 +292,8 @@ export function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
function internalIntegrateLog(lhs: DecimalSource, rhs: DecimalSource) {
|
||||
|
@ -270,13 +305,15 @@ function internalInvertIntegralLog(value: DecimalSource, lhs: FormulaSource, rhs
|
|||
const numerator = Decimal.ln(unrefFormulaSource(rhs)).times(value);
|
||||
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateLog(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
return new Formula({
|
||||
inputs: [lhs.getIntegralFormula(stack), rhs],
|
||||
|
@ -284,14 +321,16 @@ export function integrateLog(stack: SubstitutionStack, lhs: FormulaSource, rhs:
|
|||
invert: internalInvertIntegralLog
|
||||
});
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertLog2(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.pow(2, value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
function internalIntegrateLog2(lhs: DecimalSource) {
|
||||
|
@ -303,13 +342,15 @@ function internalInvertIntegralLog2(value: DecimalSource, lhs: FormulaSource) {
|
|||
const numerator = Decimal.ln(2).times(value);
|
||||
return lhs.invert(numerator.div(numerator.div(Math.E).lambertw()));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateLog2(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
return new Formula({
|
||||
inputs: [lhs.getIntegralFormula(stack)],
|
||||
|
@ -317,14 +358,16 @@ export function integrateLog2(stack: SubstitutionStack, lhs: FormulaSource) {
|
|||
invert: internalInvertIntegralLog2
|
||||
});
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertLn(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.exp(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
function internalIntegrateLn(lhs: DecimalSource) {
|
||||
|
@ -335,13 +378,15 @@ function internalInvertIntegralLn(value: DecimalSource, lhs: FormulaSource) {
|
|||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.div(value, Decimal.div(value, Math.E).lambertw()));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateLn(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
return new Formula({
|
||||
inputs: [lhs.getIntegralFormula(stack)],
|
||||
|
@ -349,7 +394,8 @@ export function integrateLn(stack: SubstitutionStack, lhs: FormulaSource) {
|
|||
invert: internalInvertIntegralLn
|
||||
});
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -358,43 +404,50 @@ export function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: Formula
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.ln(value).div(Decimal.ln(unrefFormulaSource(lhs))));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integratePow(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
const pow = Formula.add(rhs, 1);
|
||||
return Formula.pow(x, pow).div(pow);
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
return Formula.pow(lhs, x).div(Formula.ln(lhs));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertPow10(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.root(value, 10));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integratePow10(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.pow10(x).div(Formula.ln(10));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -403,25 +456,29 @@ export function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: For
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integratePowBase(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.pow(rhs, x).div(Formula.ln(rhs));
|
||||
} else if (hasVariable(rhs)) {
|
||||
if (!rhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = rhs.getIntegralFormula(stack);
|
||||
const denominator = Formula.add(lhs, 1);
|
||||
return Formula.pow(x, denominator).div(denominator);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
|
@ -430,36 +487,42 @@ export function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: Formul
|
|||
} else if (hasVariable(rhs)) {
|
||||
return rhs.invert(Decimal.ln(unrefFormulaSource(lhs)).div(Decimal.ln(value)));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateRoot(stack: SubstitutionStack, lhs: FormulaSource, rhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.pow(x, Formula.recip(rhs).add(1)).times(rhs).div(Formula.add(rhs, 1));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertExp(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.ln(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateExp(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.exp(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function tetrate(
|
||||
|
@ -481,7 +544,8 @@ export function invertTetrate(
|
|||
return base.invert(Decimal.ssqrt(value));
|
||||
}
|
||||
// Other params can't be inverted ATM
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function iteratedexp(
|
||||
|
@ -509,7 +573,8 @@ export function invertIteratedExp(
|
|||
);
|
||||
}
|
||||
// Other params can't be inverted ATM
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function iteratedLog(
|
||||
|
@ -533,7 +598,8 @@ export function invertSlog(value: DecimalSource, lhs: FormulaSource, rhs: Formul
|
|||
);
|
||||
}
|
||||
// Other params can't be inverted ATM
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function layeradd(value: DecimalSource, diff: DecimalSource, base: DecimalSource) {
|
||||
|
@ -556,21 +622,24 @@ export function invertLayeradd(
|
|||
);
|
||||
}
|
||||
// Other params can't be inverted ATM
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function invertLambertw(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.pow(Math.E, value).times(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function invertSsqrt(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.tetrate(value, 2));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function pentate(value: DecimalSource, height: DecimalSource, payload: DecimalSource) {
|
||||
|
@ -582,226 +651,262 @@ export function invertSin(value: DecimalSource, lhs: FormulaSource) {
|
|||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.asin(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateSin(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.cos(x).neg();
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertCos(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.acos(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateCos(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.sin(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertTan(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.atan(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateTan(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.cos(x).ln().neg();
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertAsin(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.sin(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAsin(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.asin(x)
|
||||
.times(x)
|
||||
.add(Formula.sqrt(Formula.sub(1, Formula.pow(x, 2))));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertAcos(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.cos(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAcos(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.acos(x)
|
||||
.times(x)
|
||||
.sub(Formula.sqrt(Formula.sub(1, Formula.pow(x, 2))));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertAtan(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.tan(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAtan(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.atan(x)
|
||||
.times(x)
|
||||
.sub(Formula.ln(Formula.pow(x, 2).add(1)).div(2));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertSinh(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.asinh(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateSinh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.cosh(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertCosh(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.acosh(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateCosh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.sinh(x);
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertTanh(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.atanh(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateTanh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.cosh(x).ln();
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertAsinh(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.sinh(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAsinh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.asinh(x).times(x).sub(Formula.pow(x, 2).add(1).sqrt());
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertAcosh(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.cosh(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAcosh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.acosh(x)
|
||||
.times(x)
|
||||
.sub(Formula.add(x, 1).sqrt().times(Formula.sub(x, 1).sqrt()));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function invertAtanh(value: DecimalSource, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
return lhs.invert(Decimal.tanh(value));
|
||||
}
|
||||
throw new Error("Could not invert due to no input being a variable");
|
||||
console.error("Could not invert due to no input being a variable");
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function integrateAtanh(stack: SubstitutionStack, lhs: FormulaSource) {
|
||||
if (hasVariable(lhs)) {
|
||||
if (!lhs.isIntegrable()) {
|
||||
throw new Error("Could not integrate due to variable not being integrable");
|
||||
console.error("Could not integrate due to variable not being integrable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
const x = lhs.getIntegralFormula(stack);
|
||||
return Formula.atanh(x)
|
||||
.times(x)
|
||||
.add(Formula.sub(1, Formula.pow(x, 2)).ln().div(2));
|
||||
}
|
||||
throw new Error("Could not integrate due to no input being a variable");
|
||||
console.error("Could not integrate due to no input being a variable");
|
||||
return Formula.constant(0);
|
||||
}
|
||||
|
||||
export function createPassthroughBinaryFormula(
|
||||
|
|
|
@ -225,7 +225,9 @@ export function createLayer<T extends LayerOptions>(
|
|||
addingLayers[addingLayers.length - 1] == null ||
|
||||
addingLayers[addingLayers.length - 1] !== id
|
||||
) {
|
||||
throw `Adding layers stack in invalid state. This should not happen\nStack: ${addingLayers}\nTrying to pop ${layer.id}`;
|
||||
throw new Error(
|
||||
`Adding layers stack in invalid state. This should not happen\nStack: ${addingLayers}\nTrying to pop ${layer.id}`
|
||||
);
|
||||
}
|
||||
addingLayers.pop();
|
||||
|
||||
|
|
|
@ -116,12 +116,7 @@ function checkNaNAndWrite<T extends State>(persistent: Persistent<T>, value: T)
|
|||
state.NaNPath = persistent[SaveDataPath];
|
||||
state.NaNPersistent = persistent as Persistent<DecimalSource>;
|
||||
}
|
||||
console.error(
|
||||
`Attempted to save NaN value to`,
|
||||
persistent[SaveDataPath]?.join("."),
|
||||
persistent
|
||||
);
|
||||
throw new Error("Attempted to set NaN value. See above for details");
|
||||
console.error(`Attempted to save NaN value to ${persistent[SaveDataPath]?.join(".")}`);
|
||||
}
|
||||
persistent[PersistentState].value = value;
|
||||
}
|
||||
|
@ -292,8 +287,8 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
|
|||
"."
|
||||
)}\` when it's already present at \`${value[SaveDataPath].join(
|
||||
"."
|
||||
)}\`. This can cause unexpected behavior when loading saves between updates.`,
|
||||
value
|
||||
)}\`.`,
|
||||
"This can cause unexpected behavior when loading saves between updates."
|
||||
);
|
||||
}
|
||||
value[SaveDataPath] = newPath;
|
||||
|
@ -368,9 +363,9 @@ globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>
|
|||
return;
|
||||
}
|
||||
console.error(
|
||||
`Created persistent ref in ${layer.id} without registering it to the layer! Make sure to include everything persistent in the returned object`,
|
||||
persistent,
|
||||
"\nCreated at:\n" + persistent[StackTrace]
|
||||
`Created persistent ref in ${layer.id} without registering it to the layer!`,
|
||||
"Make sure to include everything persistent in the returned object.\n\nCreated at:\n" +
|
||||
persistent[StackTrace]
|
||||
);
|
||||
});
|
||||
persistentRefs[layer.id].clear();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { DecimalSource } from "util/bignum";
|
||||
import { shallowReactive } from "vue";
|
||||
import { reactive, shallowReactive } from "vue";
|
||||
import type { Persistent } from "./persistence";
|
||||
|
||||
/** An object of global data that is not persistent. */
|
||||
|
@ -12,6 +12,8 @@ export interface Transient {
|
|||
NaNPath?: string[];
|
||||
/** The ref that was being set to NaN. */
|
||||
NaNPersistent?: Persistent<DecimalSource>;
|
||||
/** List of errors that have occurred, to show the user. */
|
||||
errors: Error[];
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -24,5 +26,6 @@ declare global {
|
|||
export default window.state = shallowReactive<Transient>({
|
||||
lastTenTicks: [],
|
||||
hasNaN: false,
|
||||
NaNPath: []
|
||||
NaNPath: [],
|
||||
errors: reactive([])
|
||||
});
|
||||
|
|
27
src/main.ts
27
src/main.ts
|
@ -2,6 +2,7 @@ import "@fontsource/material-icons";
|
|||
import App from "App.vue";
|
||||
import projInfo from "data/projInfo.json";
|
||||
import "game/notifications";
|
||||
import state from "game/state";
|
||||
import { load } from "util/save";
|
||||
import { useRegisterSW } from "virtual:pwa-register/vue";
|
||||
import type { App as VueApp } from "vue";
|
||||
|
@ -23,11 +24,30 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
const error = console.error;
|
||||
console.error = function (...args) {
|
||||
if (import.meta.env.DEV) {
|
||||
state.errors.push(new Error(args[0], { cause: args[1] }));
|
||||
}
|
||||
error(...args);
|
||||
};
|
||||
|
||||
window.onerror = function (event, source, lineno, colno, error) {
|
||||
state.errors.push(error instanceof Error ? error : new Error(JSON.stringify(error)));
|
||||
return true;
|
||||
};
|
||||
window.onunhandledrejection = function (event) {
|
||||
state.errors.push(
|
||||
event.reason instanceof Error ? event.reason : new Error(JSON.stringify(event.reason))
|
||||
);
|
||||
};
|
||||
|
||||
document.title = projInfo.title;
|
||||
window.projInfo = projInfo;
|
||||
if (projInfo.id === "") {
|
||||
throw new Error(
|
||||
"Project ID is empty! Please select a unique ID for this project in /src/data/projInfo.json"
|
||||
console.error(
|
||||
"Project ID is empty!",
|
||||
"Please select a unique ID for this project in /src/data/projInfo.json"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -43,6 +63,9 @@ requestAnimationFrame(async () => {
|
|||
|
||||
// Create Vue
|
||||
const vue = (window.vue = createApp(App));
|
||||
vue.config.errorHandler = function (err, instance, info) {
|
||||
console.error(err, info, instance);
|
||||
};
|
||||
globalBus.emit("setupVue", vue);
|
||||
vue.mount("#app");
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ export function createLazyProxy<T extends object, S extends T>(
|
|||
function calculateObj(): T {
|
||||
if (!calculated) {
|
||||
if (calculating) {
|
||||
throw new Error("Cyclical dependency detected. Cannot evaluate lazy proxy.");
|
||||
console.error("Cyclical dependency detected. Cannot evaluate lazy proxy.");
|
||||
}
|
||||
calculating = true;
|
||||
Object.assign(obj, objectFunc.call(obj, obj));
|
||||
|
|
Loading…
Reference in a new issue