forked from profectus/Profectus
Fix non-integrable requirements crashing in cost requirements with spendResources true
(Which should be valid in the event the dev doesn't want to maximize)
This commit is contained in:
parent
97fcd28fe2
commit
f7f4d0aa9f
2 changed files with 90 additions and 10 deletions
|
@ -101,6 +101,7 @@ export type CostRequirement = Replace<
|
||||||
visibility: ProcessedComputable<Visibility.Visible | Visibility.None | boolean>;
|
visibility: ProcessedComputable<Visibility.Visible | Visibility.None | boolean>;
|
||||||
requiresPay: ProcessedComputable<boolean>;
|
requiresPay: ProcessedComputable<boolean>;
|
||||||
spendResources: ProcessedComputable<boolean>;
|
spendResources: ProcessedComputable<boolean>;
|
||||||
|
canMaximize: ProcessedComputable<boolean>;
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
@ -159,14 +160,33 @@ export function createCostRequirement<T extends CostRequirementOptions>(
|
||||||
req.resource.value = Decimal.sub(req.resource.value, cost).max(0);
|
req.resource.value = Decimal.sub(req.resource.value, cost).max(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
req.canMaximize = req.cost instanceof Formula && req.cost.isInvertible();
|
req.canMaximize = computed(
|
||||||
|
() =>
|
||||||
|
req.cost instanceof Formula &&
|
||||||
|
req.cost.isInvertible() &&
|
||||||
|
(unref(req.spendResources) === false || req.cost.isIntegrable())
|
||||||
|
);
|
||||||
|
|
||||||
if (req.canMaximize) {
|
if (req.cost instanceof Formula && req.cost.isInvertible()) {
|
||||||
req.requirementMet = calculateMaxAffordable(
|
const maxAffordable = calculateMaxAffordable(
|
||||||
req.cost as InvertibleFormula,
|
req.cost,
|
||||||
req.resource,
|
req.resource,
|
||||||
unref(req.spendResources) as boolean
|
unref(req.spendResources) as boolean
|
||||||
);
|
);
|
||||||
|
req.requirementMet = computed(() => {
|
||||||
|
if (unref(req.canMaximize)) {
|
||||||
|
return maxAffordable.value;
|
||||||
|
} else {
|
||||||
|
if (req.cost instanceof Formula) {
|
||||||
|
return Decimal.gte(req.resource.value, req.cost.evaluate());
|
||||||
|
} else {
|
||||||
|
return Decimal.gte(
|
||||||
|
req.resource.value,
|
||||||
|
unref(req.cost as ProcessedComputable<DecimalSource>)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
req.requirementMet = computed(() => {
|
req.requirementMet = computed(() => {
|
||||||
if (req.cost instanceof Formula) {
|
if (req.cost instanceof Formula) {
|
||||||
|
|
|
@ -16,11 +16,14 @@ import { isRef, ref, unref } from "vue";
|
||||||
import "../utils";
|
import "../utils";
|
||||||
|
|
||||||
describe("Creating cost requirement", () => {
|
describe("Creating cost requirement", () => {
|
||||||
|
let resource: Resource;
|
||||||
|
beforeAll(() => {
|
||||||
|
resource = createResource(ref(10));
|
||||||
|
});
|
||||||
|
|
||||||
describe("Minimal requirement", () => {
|
describe("Minimal requirement", () => {
|
||||||
let resource: Resource;
|
|
||||||
let requirement: CostRequirement;
|
let requirement: CostRequirement;
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
resource = createResource(ref(10));
|
|
||||||
requirement = createCostRequirement(() => ({
|
requirement = createCostRequirement(() => ({
|
||||||
resource,
|
resource,
|
||||||
cost: 10,
|
cost: 10,
|
||||||
|
@ -46,10 +49,8 @@ describe("Creating cost requirement", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Fully customized", () => {
|
describe("Fully customized", () => {
|
||||||
let resource: Resource;
|
|
||||||
let requirement: CostRequirement;
|
let requirement: CostRequirement;
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
resource = createResource(ref(10));
|
|
||||||
requirement = createCostRequirement(() => ({
|
requirement = createCostRequirement(() => ({
|
||||||
resource,
|
resource,
|
||||||
cost: Formula.variable(resource).times(10),
|
cost: Formula.variable(resource).times(10),
|
||||||
|
@ -73,7 +74,6 @@ describe("Creating cost requirement", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Requirement met when meeting the cost", () => {
|
test("Requirement met when meeting the cost", () => {
|
||||||
const resource = createResource(ref(10));
|
|
||||||
const requirement = createCostRequirement(() => ({
|
const requirement = createCostRequirement(() => ({
|
||||||
resource,
|
resource,
|
||||||
cost: 10,
|
cost: 10,
|
||||||
|
@ -83,7 +83,6 @@ describe("Creating cost requirement", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Requirement not met when not meeting the cost", () => {
|
test("Requirement not met when not meeting the cost", () => {
|
||||||
const resource = createResource(ref(10));
|
|
||||||
const requirement = createCostRequirement(() => ({
|
const requirement = createCostRequirement(() => ({
|
||||||
resource,
|
resource,
|
||||||
cost: 100,
|
cost: 100,
|
||||||
|
@ -91,6 +90,67 @@ describe("Creating cost requirement", () => {
|
||||||
}));
|
}));
|
||||||
expect(unref(requirement.requirementMet)).toBe(false);
|
expect(unref(requirement.requirementMet)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("canMaximize works correctly", () => {
|
||||||
|
test("Cost function cannot maximize", () =>
|
||||||
|
expect(
|
||||||
|
unref(
|
||||||
|
createCostRequirement(() => ({
|
||||||
|
resource,
|
||||||
|
cost: () => 10
|
||||||
|
})).canMaximize
|
||||||
|
)
|
||||||
|
).toBe(false));
|
||||||
|
test("Non-invertible formula cannot maximize", () =>
|
||||||
|
expect(
|
||||||
|
unref(
|
||||||
|
createCostRequirement(() => ({
|
||||||
|
resource,
|
||||||
|
cost: Formula.variable(resource).abs()
|
||||||
|
})).canMaximize
|
||||||
|
)
|
||||||
|
).toBe(false));
|
||||||
|
test("Invertible formula can maximize if spendResources is false", () =>
|
||||||
|
expect(
|
||||||
|
unref(
|
||||||
|
createCostRequirement(() => ({
|
||||||
|
resource,
|
||||||
|
cost: Formula.variable(resource).lambertw(),
|
||||||
|
spendResources: false
|
||||||
|
})).canMaximize
|
||||||
|
)
|
||||||
|
).toBe(true));
|
||||||
|
test("Invertible formula cannot maximize if spendResources is true", () =>
|
||||||
|
expect(
|
||||||
|
unref(
|
||||||
|
createCostRequirement(() => ({
|
||||||
|
resource,
|
||||||
|
cost: Formula.variable(resource).lambertw(),
|
||||||
|
spendResources: true
|
||||||
|
})).canMaximize
|
||||||
|
)
|
||||||
|
).toBe(false));
|
||||||
|
test("Integrable formula can maximize if spendResources is false", () =>
|
||||||
|
expect(
|
||||||
|
unref(
|
||||||
|
createCostRequirement(() => ({
|
||||||
|
resource,
|
||||||
|
cost: Formula.variable(resource).pow(2),
|
||||||
|
spendResources: false
|
||||||
|
})).canMaximize
|
||||||
|
)
|
||||||
|
).toBe(true));
|
||||||
|
test("Integrable formula can maximize if spendResources is true", () =>
|
||||||
|
expect(
|
||||||
|
unref(
|
||||||
|
createCostRequirement(() => ({
|
||||||
|
resource,
|
||||||
|
cost: Formula.variable(resource).pow(2),
|
||||||
|
spendResources: true
|
||||||
|
})).canMaximize
|
||||||
|
)
|
||||||
|
).toBe(true));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Creating visibility requirement", () => {
|
describe("Creating visibility requirement", () => {
|
||||||
|
|
Loading…
Reference in a new issue