From 2bcbe2cfb4e1939a2a2d574fcced0ff997d331bf Mon Sep 17 00:00:00 2001 From: spuxx1701 Date: Sun, 9 Jun 2024 15:08:43 +0200 Subject: [PATCH] fix: `Dependency` now checks against modified values instead of actual values when checking numeric properties. --- CHANGELOG.md | 6 ++ lib/dependency/dependency.test.ts | 123 +++++++++++++++++++++++++----- lib/dependency/dependency.ts | 10 ++- lib/dependency/types.ts | 1 + 4 files changed, 119 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c28a71..984f744 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [UNRELEASED] + +### Fixed + +- `Dependency` now checks against modified values instead of actual values when checking numeric properties. + ## [0.1.0] 2024-06-09 🌟 Initial release. diff --git a/lib/dependency/dependency.test.ts b/lib/dependency/dependency.test.ts index 85903a2..6207573 100644 --- a/lib/dependency/dependency.test.ts +++ b/lib/dependency/dependency.test.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { describe, expect, test } from 'vitest'; +import { describe, expect, it } from 'vitest'; import { GameObject } from '../game-object'; import { Dependency } from './dependency'; +import { Modifier } from '@/modifier'; class UnrelatedObject extends GameObject { name = 'unrelated.object' as any; @@ -25,7 +26,7 @@ describe('regular dependencies', () => { declare dependencies: Dependency[]; } - test('should pass if the dependency is met (existence check)', () => { + it('should pass if the dependency is met (existence check)', () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -37,7 +38,7 @@ describe('regular dependencies', () => { expect(result).toBe(true); }); - test("should fail if the dependency isn't met (existence check)", () => { + it("should fail if the dependency isn't met (existence check)", () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -50,7 +51,7 @@ describe('regular dependencies', () => { expect(result).toHaveLength(1); }); - test('should pass if the dependency is met (exact value check)', () => { + it('should pass if the dependency is met (exact value check)', () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -64,7 +65,7 @@ describe('regular dependencies', () => { expect(result).toBe(true); }); - test("should fail if the dependency isn't met (exact value check)", () => { + it("should fail if the dependency isn't met (exact value check)", () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -79,7 +80,7 @@ describe('regular dependencies', () => { expect(result).toHaveLength(1); }); - test('should pass if the dependency is met (numeric value check)', () => { + it('should pass if the dependency is met (numeric value check)', () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -93,7 +94,7 @@ describe('regular dependencies', () => { expect(result).toBe(true); }); - test("should fail if the dependency isn't met (numeric value check)", () => { + it("should fail if the dependency isn't met (numeric value check)", () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -108,7 +109,50 @@ describe('regular dependencies', () => { expect(result).toHaveLength(1); }); - test('should fail if the referenced child collection does not exist on the entity', () => { + it('should check against the modified value and pass (numeric value check)', () => { + const dependent = new Dependent({} as any); + dependent.dependencies = [ + new Dependency({ + name: 'dependency.target', + key: 'answer', + value: 52, + }), + ]; + const entity = new Entity({} as any); + entity.modifiers = [ + new Modifier({ + targetName: 'dependency.target' as any, + keys: ['answer'], + amount: 10, + }), + ]; + const result = dependent.checkDependencies(entity); + expect(result).toBe(true); + }); + + it('should check against the modified value and fail (numeric value check)', () => { + const dependent = new Dependent({} as any); + dependent.dependencies = [ + new Dependency({ + name: 'dependency.target', + key: 'answer', + value: 52, + }), + ]; + dependent.modifiers = [ + new Modifier({ + targetName: 'dependency.target' as any, + keys: ['answer'], + amount: -10, + }), + ]; + const entity = new Entity({} as any); + const result = dependent.checkDependencies(entity); + expect(result).toBeInstanceOf(Array); + expect(result).toHaveLength(1); + }); + + it('should fail if the referenced child collection does not exist on the entity', () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -121,7 +165,7 @@ describe('regular dependencies', () => { expect(result).toHaveLength(1); }); - test("should throw an error if the dependency references a value that doesn't exist", () => { + it("should throw an error if the dependency references a value that doesn't exist", () => { const dependent = new Dependent({} as any); dependent.dependencies = [ new Dependency({ @@ -141,7 +185,7 @@ describe('conflict dependencies', () => { declare dependencies: Dependency[]; } - test('should pass if there is no conflict (existence check)', () => { + it('should pass if there is no conflict (existence check)', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -154,7 +198,7 @@ describe('conflict dependencies', () => { expect(result).toBe(true); }); - test('should fail if there is a conflict (existence check)', () => { + it('should fail if there is a conflict (existence check)', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -168,7 +212,7 @@ describe('conflict dependencies', () => { expect(result).toHaveLength(1); }); - test('should pass if there is no conflict (exact value check)', () => { + it('should pass if there is no conflict (exact value check)', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -183,7 +227,7 @@ describe('conflict dependencies', () => { expect(result).toBe(true); }); - test('should fail if there is a conflict (exact value check)', () => { + it('should fail if there is a conflict (exact value check)', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -199,7 +243,7 @@ describe('conflict dependencies', () => { expect(result).toHaveLength(1); }); - test('should pass if there is no conflict (numeric value check)', () => { + it('should pass if there is no conflict (numeric value check)', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -214,7 +258,7 @@ describe('conflict dependencies', () => { expect(result).toBe(true); }); - test('should fail if there is a conflict (numeric value check)', () => { + it('should fail if there is a conflict (numeric value check)', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -230,7 +274,52 @@ describe('conflict dependencies', () => { expect(result).toHaveLength(1); }); - test('should pass if the referenced child collection does not exist on the entity', () => { + it('should check against the modified value and pass (numeric value check)', () => { + const conflict = new Conflict({} as any); + conflict.dependencies = [ + new Dependency({ + name: 'dependency.target', + key: 'answer', + value: 42, + isConflict: true, + }), + ]; + const entity = new Entity({} as any); + entity.modifiers = [ + new Modifier({ + targetName: 'dependency.target' as any, + keys: ['answer'], + amount: -10, + }), + ]; + const result = conflict.checkDependencies(entity); + expect(result).toBe(true); + }); + + it('should check against the modified value and fail (numeric value check)', () => { + const conflict = new Conflict({} as any); + conflict.dependencies = [ + new Dependency({ + name: 'dependency.target', + key: 'answer', + value: 42, + isConflict: true, + }), + ]; + const entity = new Entity({} as any); + entity.modifiers = [ + new Modifier({ + targetName: 'dependency.target' as any, + keys: ['answer'], + amount: 10, + }), + ]; + const result = conflict.checkDependencies(entity); + expect(result).toBeInstanceOf(Array); + expect(result).toHaveLength(1); + }); + + it('should pass if the referenced child collection does not exist on the entity', () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ @@ -242,7 +331,7 @@ describe('conflict dependencies', () => { expect(conflict.checkDependencies(entity)).toBe(true); }); - test("should throw an error if the dependency references a value that doesn't exist", () => { + it("should throw an error if the dependency references a value that doesn't exist", () => { const conflict = new Conflict({} as any); conflict.dependencies = [ new Dependency({ diff --git a/lib/dependency/dependency.ts b/lib/dependency/dependency.ts index 672ecc5..8922bc1 100644 --- a/lib/dependency/dependency.ts +++ b/lib/dependency/dependency.ts @@ -44,8 +44,9 @@ export class Dependency implements IDe throw new Error(`The property "${String(this.key)}" does not exist on the dependency.`); } else if (typeof value === 'number' && typeof this.value === 'number') { // If we look for a number, a conflict will depend on whether that number is greater than - // `this.value`, which we consider to be the maximum allowed value. - return value <= this.value; + // `this.value`, which we consider to be the maximum allowed value. We also need to make + // sure to check against the modified value. + return dependency.getModifiedValue(this.key as never, gameObject) <= this.value; } else { // If we look for a value that is not a number, a conflict will depend on whether that value // is equal to `this.value`. @@ -66,8 +67,9 @@ export class Dependency implements IDe throw new Error(`The property "${String(this.key)}" does not exist on the dependency.`); } else if (typeof value === 'number' && typeof this.value === 'number') { // If we look for a number, the dependency check will depend on whether that number is greater - // than `this.value`, which we consider to be the minimum required value. - return value >= this.value; + // than `this.value`, which we consider to be the minimum required value. We also need to make + // sure to check against the modified value. + return dependency.getModifiedValue(this.key as never, gameObject) >= this.value; } else { // If we look for a value that is not a number, the dependency will depend on whether that value // is equal to `this.value`. diff --git a/lib/dependency/types.ts b/lib/dependency/types.ts index 384f030..5b3622b 100644 --- a/lib/dependency/types.ts +++ b/lib/dependency/types.ts @@ -14,6 +14,7 @@ export interface IDependency { /** * The value that the checked property should have. Numbers will be considered as a minimum value. * Other types will be checked for equality. `key` must be provided for the value to be checked. + * Note that dependencies are being checked against modified values. */ value?: unknown; /**