From 0614f14ad6cd97bbab4cab118c36a2d46d86bc51 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Tue, 4 Apr 2023 22:10:35 -0500 Subject: [PATCH 1/5] Added tests for conversions --- src/features/conversion.ts | 29 +- tests/features/conversions.test.ts | 502 +++++++++++++++++++++++++++++ 2 files changed, 518 insertions(+), 13 deletions(-) create mode 100644 tests/features/conversions.test.ts diff --git a/src/features/conversion.ts b/src/features/conversion.ts index 1ccf26b..a184de0 100644 --- a/src/features/conversion.ts +++ b/src/features/conversion.ts @@ -133,11 +133,11 @@ export function createConversion( ); if (conversion.currentGain == null) { conversion.currentGain = computed(() => { - let gain = (conversion as GenericConversion).formula.evaluate( - conversion.baseResource.value - ); - gain = Decimal.floor(gain).max(0); - + let gain = Decimal.floor( + (conversion as GenericConversion).formula.evaluate( + conversion.baseResource.value + ) + ).max(0); if (unref(conversion.buyMax) === false) { gain = gain.min(1); } @@ -218,10 +218,11 @@ export function createIndependentConversion( if (conversion.currentGain == null) { conversion.currentGain = computed(() => { - let gain = (conversion as unknown as GenericConversion).formula.evaluate( - conversion.baseResource.value - ); - gain = Decimal.floor(gain).max(conversion.gainResource.value); + let gain = Decimal.floor( + (conversion as unknown as GenericConversion).formula.evaluate( + conversion.baseResource.value + ) + ).max(conversion.gainResource.value); if (unref(conversion.buyMax) === false) { gain = gain.min(Decimal.add(conversion.gainResource.value, 1)); } @@ -235,7 +236,9 @@ export function createIndependentConversion( conversion.baseResource.value ), conversion.gainResource.value - ).max(0); + ) + .floor() + .max(0); if (unref(conversion.buyMax) === false) { gain = gain.min(1); @@ -263,13 +266,13 @@ export function createIndependentConversion( * @param layer The layer this passive generation will be associated with. Typically `this` when calling this function from inside a layer's options function. * @param conversion The conversion that will determine how much generation there is. * @param rate A multiplier to multiply against the conversion's currentGain. - * @param cap A value that should not be passed via passive generation. If null, no cap is applied. + * @param cap A value that should not be passed via passive generation. */ export function setupPassiveGeneration( layer: BaseLayer, conversion: GenericConversion, rate: Computable = 1, - cap: Computable = null + cap: Computable = Decimal.dInf ): void { const processedRate = convertComputable(rate); const processedCap = convertComputable(cap); @@ -280,7 +283,7 @@ export function setupPassiveGeneration( conversion.gainResource.value, Decimal.times(currRate, diff).times(Decimal.ceil(unref(conversion.actualGain))) ) - .min(unref(processedCap) ?? Decimal.dInf) + .min(unref(processedCap)) .max(conversion.gainResource.value); } }); diff --git a/tests/features/conversions.test.ts b/tests/features/conversions.test.ts new file mode 100644 index 0000000..fc1d68d --- /dev/null +++ b/tests/features/conversions.test.ts @@ -0,0 +1,502 @@ +import { + createCumulativeConversion, + createIndependentConversion, + GenericConversion, + setupPassiveGeneration +} from "features/conversion"; +import { createResource, Resource } from "features/resources/resource"; +import { GenericFormula } from "game/formulas/types"; +import { createLayer } from "game/layers"; +import Decimal from "util/bignum"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; +import { ref, unref } from "vue"; +import "../utils"; + +describe("Creating conversion", () => { + let baseResource: Resource; + let gainResource: Resource; + let formula: (x: GenericFormula) => GenericFormula; + beforeEach(() => { + baseResource = createResource(ref(40)); + gainResource = createResource(ref(1)); + formula = x => x.div(10).sqrt(); + }); + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe("Cumulative conversion", () => { + describe("Calculates currentGain correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.currentGain)).compare_tolerance(100); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.currentGain)).compare_tolerance(99); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.currentGain)).compare_tolerance(100); + }); + }); + describe("Calculates actualGain correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.actualGain)).compare_tolerance(100); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.actualGain)).compare_tolerance(99); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.actualGain)).compare_tolerance(100); + }); + }); + describe("Calculates currentAt correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.currentAt)).compare_tolerance( + Decimal.pow(100, 2).times(10) + ); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.currentAt)).compare_tolerance(Decimal.pow(99, 2).times(10)); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.currentAt)).compare_tolerance( + Decimal.pow(100, 2).times(10) + ); + }); + }); + describe("Calculates nextAt correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.nextAt)).compare_tolerance(Decimal.pow(101, 2).times(10)); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.nextAt)).compare_tolerance(Decimal.pow(100, 2).times(10)); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.nextAt)).compare_tolerance(Decimal.pow(101, 2).times(10)); + }); + }); + test("Converts correctly", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + conversion.convert(); + expect(baseResource.value).compare_tolerance(0); + expect(gainResource.value).compare_tolerance(3); + }); + describe("Obeys buy max", () => { + test("buyMax = false", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: false + })); + expect(unref(conversion.actualGain)).compare_tolerance(1); + }); + test("buyMax = true", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: true + })); + expect(unref(conversion.actualGain)).compare_tolerance(2); + }); + }); + test("Spends correctly", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + conversion.convert(); + expect(baseResource.value).compare_tolerance(0); + }); + test("Calls onConvert", () => { + const onConvert = vi.fn(); + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula, + onConvert + })); + conversion.convert(); + expect(onConvert).toHaveBeenCalled(); + }); + }); + + describe("Independent conversion", () => { + describe("Calculates currentGain correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: true + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.currentGain)).compare_tolerance(100); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.currentGain)).compare_tolerance(99); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.currentGain)).compare_tolerance(100); + }); + }); + describe("Calculates actualGain correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: true + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.actualGain)).compare_tolerance(99); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.actualGain)).compare_tolerance(98); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.actualGain)).compare_tolerance(99); + }); + }); + describe("Calculates currentAt correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: true + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.currentAt)).compare_tolerance( + Decimal.pow(100, 2).times(10) + ); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.currentAt)).compare_tolerance(Decimal.pow(99, 2).times(10)); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.currentAt)).compare_tolerance( + Decimal.pow(100, 2).times(10) + ); + }); + }); + describe("Calculates nextAt correctly", () => { + let conversion: GenericConversion; + beforeEach(() => { + conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: true + })); + }); + test("Exactly enough", () => { + baseResource.value = Decimal.pow(100, 2).times(10); + expect(unref(conversion.nextAt)).compare_tolerance(Decimal.pow(101, 2).times(10)); + }); + test("Just under", () => { + baseResource.value = Decimal.pow(100, 2).times(10).sub(1); + expect(unref(conversion.nextAt)).compare_tolerance(Decimal.pow(100, 2).times(10)); + }); + test("Just over", () => { + baseResource.value = Decimal.pow(100, 2).times(10).add(1); + expect(unref(conversion.nextAt)).compare_tolerance(Decimal.pow(101, 2).times(10)); + }); + }); + test("Converts correctly", () => { + const conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula + })); + conversion.convert(); + expect(baseResource.value).compare_tolerance(0); + expect(gainResource.value).compare_tolerance(2); + }); + describe("Obeys buy max", () => { + test("buyMax = false", () => { + const conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: false + })); + baseResource.value = 90; + expect(unref(conversion.actualGain)).compare_tolerance(1); + }); + test("buyMax = true", () => { + const conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + buyMax: true + })); + baseResource.value = 90; + expect(unref(conversion.actualGain)).compare_tolerance(2); + }); + }); + test("Spends correctly", () => { + const conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula + })); + conversion.convert(); + expect(baseResource.value).compare_tolerance(0); + }); + test("Calls onConvert", () => { + const onConvert = vi.fn(); + const conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + onConvert + })); + conversion.convert(); + expect(onConvert).toHaveBeenCalled(); + }); + }); + describe("Custom conversion", () => { + describe("Custom cumulative", () => { + let conversion: GenericConversion; + const convert = vi.fn(); + const spend = vi.fn(); + const onConvert = vi.fn(); + beforeAll(() => { + conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula, + currentGain() { + return 10; + }, + actualGain() { + return 5; + }, + currentAt() { + return 100; + }, + nextAt() { + return 1000; + }, + convert, + spend, + onConvert + })); + }); + afterEach(() => { + vi.resetAllMocks(); + }); + test("Calculates currentGain correctly", () => { + expect(unref(conversion.currentGain)).compare_tolerance(10); + }); + test("Calculates actualGain correctly", () => { + expect(unref(conversion.actualGain)).compare_tolerance(5); + }); + test("Calculates currentAt correctly", () => { + expect(unref(conversion.currentAt)).compare_tolerance(100); + }); + test("Calculates nextAt correctly", () => { + expect(unref(conversion.nextAt)).compare_tolerance(1000); + }); + test("Calls convert", () => { + conversion.convert(); + expect(convert).toHaveBeenCalled(); + }); + test("Calls spend and onConvert", () => { + conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula, + spend, + onConvert + })); + conversion.convert(); + expect(spend).toHaveBeenCalled(); + expect(spend).toHaveBeenCalledWith(expect.compare_tolerance(2)); + expect(onConvert).toHaveBeenCalled(); + expect(onConvert).toHaveBeenCalledWith(expect.compare_tolerance(2)); + }); + }); + describe("Custom independent", () => { + let conversion: GenericConversion; + const convert = vi.fn(); + const spend = vi.fn(); + const onConvert = vi.fn(); + beforeAll(() => { + conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + currentGain() { + return 10; + }, + actualGain() { + return 5; + }, + currentAt() { + return 100; + }, + nextAt() { + return 1000; + }, + convert, + spend, + onConvert + })); + }); + afterEach(() => { + vi.resetAllMocks(); + }); + test("Calculates currentGain correctly", () => { + expect(unref(conversion.currentGain)).compare_tolerance(10); + }); + test("Calculates actualGain correctly", () => { + expect(unref(conversion.actualGain)).compare_tolerance(5); + }); + test("Calculates currentAt correctly", () => { + expect(unref(conversion.currentAt)).compare_tolerance(100); + }); + test("Calculates nextAt correctly", () => { + expect(unref(conversion.nextAt)).compare_tolerance(1000); + }); + test("Calls convert", () => { + conversion.convert(); + expect(convert).toHaveBeenCalled(); + }); + test("Calls spend and onConvert", () => { + conversion = createIndependentConversion(() => ({ + baseResource, + gainResource, + formula, + spend, + onConvert + })); + conversion.convert(); + expect(spend).toHaveBeenCalled(); + expect(spend).toHaveBeenCalledWith(expect.compare_tolerance(1)); + expect(onConvert).toHaveBeenCalled(); + expect(onConvert).toHaveBeenCalledWith(expect.compare_tolerance(1)); + }); + }); + }); +}); + +describe("Passive generation", () => { + let baseResource: Resource; + let gainResource: Resource; + let formula: (x: GenericFormula) => GenericFormula; + beforeEach(() => { + baseResource = createResource(ref(40)); + gainResource = createResource(ref(1)); + formula = x => x.div(10).sqrt(); + }); + test("Rate is 0", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + const layer = createLayer("dummy", () => ({ display: "" })); + setupPassiveGeneration(layer, conversion, 0); + layer.emit("preUpdate", 100); + expect(gainResource.value).compare_tolerance(1); + }); + test("Rate is 1", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + const layer = createLayer("dummy", () => ({ display: "" })); + setupPassiveGeneration(layer, conversion); + layer.emit("preUpdate", 100); + expect(gainResource.value).compare_tolerance(201); + }) + test("Rate is 100", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + const layer = createLayer("dummy", () => ({ display: "" })); + setupPassiveGeneration(layer, conversion, () => 100); + layer.emit("preUpdate", 100); + expect(gainResource.value).compare_tolerance(20001); + }) + test("Obeys cap", () => { + const conversion = createCumulativeConversion(() => ({ + baseResource, + gainResource, + formula + })); + const layer = createLayer("dummy", () => ({ display: "" })); + setupPassiveGeneration(layer, conversion, 100, () => 100); + layer.emit("preUpdate", 100); + expect(gainResource.value).compare_tolerance(100); + }) +}); From 7693aae4bfbc2c0dc7b6c3bc13cdc646ffcd8647 Mon Sep 17 00:00:00 2001 From: Anthony Lawn Date: Tue, 4 Apr 2023 23:20:31 -0500 Subject: [PATCH 2/5] Minor cleanup of tests --- tests/features/conversions.test.ts | 44 ++++++++++-------------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/tests/features/conversions.test.ts b/tests/features/conversions.test.ts index fc1d68d..c94df0a 100644 --- a/tests/features/conversions.test.ts +++ b/tests/features/conversions.test.ts @@ -6,7 +6,7 @@ import { } from "features/conversion"; import { createResource, Resource } from "features/resources/resource"; import { GenericFormula } from "game/formulas/types"; -import { createLayer } from "game/layers"; +import { createLayer, GenericLayer } from "game/layers"; import Decimal from "util/bignum"; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; import { ref, unref } from "vue"; @@ -450,53 +450,37 @@ describe("Passive generation", () => { let baseResource: Resource; let gainResource: Resource; let formula: (x: GenericFormula) => GenericFormula; + let conversion: GenericConversion; + let layer: GenericLayer; beforeEach(() => { - baseResource = createResource(ref(40)); + baseResource = createResource(ref(10)); gainResource = createResource(ref(1)); formula = x => x.div(10).sqrt(); - }); - test("Rate is 0", () => { - const conversion = createCumulativeConversion(() => ({ + conversion = createCumulativeConversion(() => ({ baseResource, gainResource, formula })); - const layer = createLayer("dummy", () => ({ display: "" })); + layer = createLayer("dummy", () => ({ display: "" })); + }); + test("Rate is 0", () => { setupPassiveGeneration(layer, conversion, 0); - layer.emit("preUpdate", 100); + layer.emit("preUpdate", 1); expect(gainResource.value).compare_tolerance(1); }); test("Rate is 1", () => { - const conversion = createCumulativeConversion(() => ({ - baseResource, - gainResource, - formula - })); - const layer = createLayer("dummy", () => ({ display: "" })); setupPassiveGeneration(layer, conversion); - layer.emit("preUpdate", 100); - expect(gainResource.value).compare_tolerance(201); + layer.emit("preUpdate", 1); + expect(gainResource.value).compare_tolerance(2); }) test("Rate is 100", () => { - const conversion = createCumulativeConversion(() => ({ - baseResource, - gainResource, - formula - })); - const layer = createLayer("dummy", () => ({ display: "" })); setupPassiveGeneration(layer, conversion, () => 100); - layer.emit("preUpdate", 100); - expect(gainResource.value).compare_tolerance(20001); + layer.emit("preUpdate", 1); + expect(gainResource.value).compare_tolerance(101); }) test("Obeys cap", () => { - const conversion = createCumulativeConversion(() => ({ - baseResource, - gainResource, - formula - })); - const layer = createLayer("dummy", () => ({ display: "" })); setupPassiveGeneration(layer, conversion, 100, () => 100); - layer.emit("preUpdate", 100); + layer.emit("preUpdate", 1); expect(gainResource.value).compare_tolerance(100); }) }); From 08a489d99735edc7cceb9f6b2f01fc61bb0997fb Mon Sep 17 00:00:00 2001 From: Anthony Lawn Date: Tue, 4 Apr 2023 23:45:56 -0500 Subject: [PATCH 3/5] Updated changelog --- CHANGELOG.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2afda6..b6e4c8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **BREAKING** New requirements system - Replaces many features' existing requirements with new generic form -- Formulas, which can be used to calculate buy max for you -- Action feature -- ETA util +- **BREAKING** Formulas, which can be used to calculate buy max for you + - Requirements can use them so repeatables and challenges can be "buy max" without any extra effort + - Conversions now use formulas instead of the old scaling functions system, allowing for arbitrary functions that are much easier to follow + - There's a utility for converting modifiers to formulas, thus replacing things like the gain modifier on conversions +- Action feature, which is a clickable with a cooldown +- ETA util (calculates time until a specific amount of a resource, based on its current gain rate) - createCollapsibleMilestones util - deleteLowerSaves util - Minimized layers can now display a component @@ -35,6 +38,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Tweaked modifier displays, incl showing negative modifiers in red - Hotkeys now appear on key graphic - Mofifier sections now accept computable strings for title and subtitle +- Every VueFeature's `[Component]` property is now typed as GenericComponent +- Make errors throw objects instead of strings - Updated b_e ### Fixed - NaN detection stopped working @@ -54,15 +59,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Tabs could sometimes not update correctly - offlineTime not capping properly - Tooltips being user-selectable +- Pinnable tooltips causing stack overflow - Workflows not working with submodules - Various minor typing issues +### Removed +- **BREAKING** Removed milestones (achievements now have small and large displays) ### Documented -- requirements.tsx -- formulas.tsx -- repeatables.tsx -### Tests -- requirements +- every single feature - formulas +- requirements +### Tests +- conversions +- formulas +- requirements Contributors: thepaperpilot, escapee, adsaf, ducdat From 73d060aeaf818246ec71b10d8f0930b4589f0086 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Wed, 5 Apr 2023 00:49:17 -0500 Subject: [PATCH 4/5] Fix some incorrect tags --- src/game/formulas/formulas.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/formulas/formulas.ts b/src/game/formulas/formulas.ts index 9806580..d0a0f81 100644 --- a/src/game/formulas/formulas.ts +++ b/src/game/formulas/formulas.ts @@ -317,8 +317,8 @@ export default class Formula { // TODO add integration support to step-wise functions /** - * Creates a step-wise formula. After {@ref start} the formula will have an additional modifier. - * This function assumes the incoming {@ref value} will be continuous and monotonically increasing. + * Creates a step-wise formula. After {@link start} the formula will have an additional modifier. + * This function assumes the incoming {@link value} will be continuous and monotonically increasing. * @param value The value before applying the step * @param start The value at which to start applying the step * @param formulaModifier How this step should modify the formula. The incoming value will be the unmodified formula value _minus the start value_. So for example if an incoming formula evaluates to 200 and has a step that starts at 150, the formulaModifier would be given 50 as the parameter @@ -1356,7 +1356,7 @@ export function printFormula(formula: FormulaSource): string { } /** - * Utility for calculating the maximum amount of purchases possible with a given formula and resource. If {@ref spendResources} is changed to false, the calculation will be much faster with higher numbers. + * Utility for calculating the maximum amount of purchases possible with a given formula and resource. If {@link spendResources} is changed to false, the calculation will be much faster with higher numbers. * @param formula The formula to use for calculating buy max from * @param resource The resource used when purchasing (is only read from) * @param spendResources Whether or not to count spent resources on each purchase or not. If true, costs will be approximated for performance, skewing towards fewer purchases @@ -1424,7 +1424,7 @@ export function calculateMaxAffordable( } /** - * Utility for calculating the cost of a formula for a given amount of purchases. If {@ref spendResources} is changed to false, the calculation will be much faster with higher numbers. + * Utility for calculating the cost of a formula for a given amount of purchases. If {@link spendResources} is changed to false, the calculation will be much faster with higher numbers. * @param formula The formula to use for calculating buy max from * @param amountToBuy The amount of purchases to calculate the cost for * @param spendResources Whether or not to count spent resources on each purchase or not. If true, costs will be approximated for performance, skewing towards higher cost From d0281e64bf02cf4bd4f21f73ba654157e44a3a21 Mon Sep 17 00:00:00 2001 From: thepaperpilot Date: Wed, 5 Apr 2023 07:43:48 -0500 Subject: [PATCH 5/5] Documented modifierToFormula --- src/data/common.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/data/common.tsx b/src/data/common.tsx index d163f72..3246135 100644 --- a/src/data/common.tsx +++ b/src/data/common.tsx @@ -492,6 +492,11 @@ export function createFormulaPreview( }); } +/** + * Utility for converting a modifier into a formula. Takes the input for this formula as the base parameter. + * @param modifier The modifier to convert to the formula + * @param base An existing formula or processed DecimalSource that will be the input to the formula + */ export function modifierToFormula( modifier: WithRequired, base: T