From 1270e320ce7298ce1332361ef88d739e0caf1e1c Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Fri, 17 Sep 2021 15:11:29 +0200 Subject: [PATCH] Basic testing for attribute calculations --- .../computeComputation/computeByType.js | 2 + .../computeByType/computeAction.js | 14 +++- .../computeAction/computeResources.js | 11 --- .../computeByType/computeAttribute.js | 9 +++ .../aggregate/aggregateDamageMultiplier.js | 4 - .../aggregate/aggregateDefinition.js | 3 +- .../computeVariableAsAttribute.js | 3 +- .../computeVariable/getAggregatorResult.js | 2 + .../tests/computeAttribute.testFn.js | 77 +++++++++++++++++++ .../computeComputation/tests/index.js | 10 +++ .../computeCreatureComputation.test.js | 4 +- app/imports/api/properties/Attributes.js | 4 +- 12 files changed, 120 insertions(+), 23 deletions(-) delete mode 100644 app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction/computeResources.js create mode 100644 app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAttribute.js create mode 100644 app/imports/api/creature/computation/newEngine/computeComputation/tests/computeAttribute.testFn.js create mode 100644 app/imports/api/creature/computation/newEngine/computeComputation/tests/index.js diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType.js index 4e3b4b3f..382a26c2 100644 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType.js +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType.js @@ -1,10 +1,12 @@ import _variable from './computeByType/computeVariable.js'; import action from './computeByType/computeAction.js'; +import attribute from './computeByType/computeAttribute.js'; import slot from './computeByType/computeSlot.js'; export default Object.freeze({ _variable, action, attack: action, + attribute, slot, }); diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction.js index e1f0d379..903e7cfb 100644 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction.js +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction.js @@ -1,5 +1,3 @@ -import computeResources from './computeAction/computeResources.js'; - export default function computeAction(graph, node, scope){ const prop = node.data; if (prop.uses){ @@ -20,3 +18,15 @@ export default function computeAction(graph, node, scope){ } }); } + +function computeResources(graph, node, scope){ + const resources = node.data?.resources; + if (!resources) return; + resources.attributesConsumed.forEach(attConsumed => { + if (!attConsumed.variableName) return; + const att = scope[attConsumed.variableName]; + attConsumed.available = att.value; + attConsumed.statId = att._id; + attConsumed.statName = att.name; + }); +} diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction/computeResources.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction/computeResources.js deleted file mode 100644 index 26dbe9a3..00000000 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAction/computeResources.js +++ /dev/null @@ -1,11 +0,0 @@ -export default function computeResources(graph, node, scope){ - const resources = node.data?.resources; - if (!resources) return; - resources.attributesConsumed.forEach(attConsumed => { - if (!attConsumed.variableName) return; - const att = scope[attConsumed.variableName]; - attConsumed.available = att.value; - attConsumed.statId = att._id; - attConsumed.statName = att.name; - }); -} diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAttribute.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAttribute.js new file mode 100644 index 00000000..86d13e11 --- /dev/null +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeAttribute.js @@ -0,0 +1,9 @@ +// If we compute this attribute without a variable name, it just +// uses its base value and damage since no effects can target it +// If this attribute does have a variable name, it is recomputed later +// by computeVariableAsAttribute +export default function computeAttribute(graph, node){ + const prop = node.data; + prop.total = prop.baseValue?.value || 0; + prop.value = prop.total - (prop.damage || 0); +} diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDamageMultiplier.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDamageMultiplier.js index 256a5c48..15b5309c 100644 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDamageMultiplier.js +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDamageMultiplier.js @@ -1,7 +1,3 @@ - -/** - * - */ export default function aggregateDamageMultipliers({node, linkedNode, link}){ if (link.data !== 'damageMultiplier') return; const multiplierValue = linkedNode.data.value; diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDefinition.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDefinition.js index b4fabd7f..1d94f61c 100644 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDefinition.js +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/aggregate/aggregateDefinition.js @@ -18,7 +18,8 @@ export default function aggregateDefinition({node, linkedNode, link}){ } // Aggregate the base value due to the defining properties - const propBaseValue = linkedNode.data.baseValue?.value; + const propBaseValue = prop.baseValue?.value; + if (propBaseValue === undefined) return; if (node.data.baseValue === undefined || propBaseValue > node.data.baseValue){ node.data.baseValue = propBaseValue; diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/computeVariableAsAttribute.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/computeVariableAsAttribute.js index b5048202..fc486d03 100644 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/computeVariableAsAttribute.js +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/computeVariableAsAttribute.js @@ -1,7 +1,8 @@ import getAggregatorResult from './getAggregatorResult.js'; export default function computeVariableAsAttribute(node, prop, scope){ - let result = getAggregatorResult(node); + let result = getAggregatorResult(node, prop) || 0; + prop.total = result; prop.value = prop.total - (prop.damage || 0); diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/getAggregatorResult.js b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/getAggregatorResult.js index 38c38a2a..573a5766 100644 --- a/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/getAggregatorResult.js +++ b/app/imports/api/creature/computation/newEngine/computeComputation/computeByType/computeVariable/getAggregatorResult.js @@ -3,7 +3,9 @@ import stripFloatingPointOddities from '/imports/api/creature/computation/newEng export default function getAggregatorResult(node){ // Work out the base value as the greater of the deining stat value or // the damage multiplier value + // This baseValue comes from aggregating definitions let statBase = node.data.baseValue; + const damageMultiplyValue = node.data.damageMultiplyValue; if (statBase === undefined || damageMultiplyValue > statBase){ statBase = damageMultiplyValue; diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/tests/computeAttribute.testFn.js b/app/imports/api/creature/computation/newEngine/computeComputation/tests/computeAttribute.testFn.js new file mode 100644 index 00000000..160e0615 --- /dev/null +++ b/app/imports/api/creature/computation/newEngine/computeComputation/tests/computeAttribute.testFn.js @@ -0,0 +1,77 @@ +import { buildComputationFromProps } from '/imports/api/creature/computation/newEngine/buildCreatureComputation.js'; +import { assert } from 'chai'; +import computeCreatureComputation from '../../computeCreatureComputation.js'; +import clean from '../../utility/cleanProp.testFn.js'; + +export default function(){ + const computation = buildComputationFromProps(testProperties); + computeCreatureComputation(computation); + const prop = id => computation.propsById[id]; + assert.equal(prop('emptyId').value, 0); + assert.equal(prop('noVariableNameId').value, 8); + assert.equal(prop('strengthId').value, 12); + assert.equal(prop('strengthId').modifier, 1); + assert.equal(prop('referencesDexId').value, 4); + assert.equal(prop('hitDiceId').constitutionMod, 5); +} + +var testProperties = [ + clean({ + _id: 'emptyId', + type: 'attribute', + attributeType: 'ability', + }), + clean({ + _id: 'noVariableNameId', + type: 'attribute', + attributeType: 'ability', + baseValue: { + calculation: '8' + }, + }), + clean({ + _id: 'strengthId', + variableName: 'strength', + type: 'attribute', + attributeType: 'ability', + baseValue: { + calculation: '12' + }, + }), + clean({ + _id: 'dexterityId', + variableName: 'dexterity', + type: 'attribute', + attributeType: 'ability', + baseValue: { + calculation: '15' + }, + }), + clean({ + _id: 'constitutionId', + variableName: 'constitution', + type: 'attribute', + attributeType: 'ability', + baseValue: { + calculation: '21' + }, + }), + clean({ + _id: 'referencesDexId', + variableName: 'refDex', + type: 'attribute', + baseValue: { + calculation: 'dexterity.modifier + 2' + }, + }), + clean({ + _id: 'hitDiceId', + variableName: 'hd', + type: 'attribute', + attributeType: 'hitDice', + hitDiceSize: 'd8', + baseValue: { + calculation: '4' + }, + }), +]; diff --git a/app/imports/api/creature/computation/newEngine/computeComputation/tests/index.js b/app/imports/api/creature/computation/newEngine/computeComputation/tests/index.js new file mode 100644 index 00000000..8c92682e --- /dev/null +++ b/app/imports/api/creature/computation/newEngine/computeComputation/tests/index.js @@ -0,0 +1,10 @@ +import computeAction from './computeAction.testFn.js'; +import computeAttribute from './computeAttribute.testFn.js'; + +export default [{ + text: 'Computes actions', + fn: computeAction, +},{ + text: 'Computes attributes', + fn: computeAttribute, +},] diff --git a/app/imports/api/creature/computation/newEngine/computeCreatureComputation.test.js b/app/imports/api/creature/computation/newEngine/computeCreatureComputation.test.js index 66eeaa82..f64e6e7f 100644 --- a/app/imports/api/creature/computation/newEngine/computeCreatureComputation.test.js +++ b/app/imports/api/creature/computation/newEngine/computeCreatureComputation.test.js @@ -2,7 +2,7 @@ import computeCreatureComputation from './computeCreatureComputation.js'; import { buildComputationFromProps } from './buildCreatureComputation.js'; import { assert } from 'chai'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; -import computeAction from './computeComputation/tests/computeAction.testFn.js'; +import computeTests from './computeComputation/tests/index.js'; describe('Compute compuation', function(){ it('Computes something at all', function(){ @@ -10,7 +10,7 @@ describe('Compute compuation', function(){ computeCreatureComputation(computation); assert.exists(computation); }); - it('Computes actions', computeAction); + computeTests.forEach(test => it(test.text, test.fn)); }); var testProperties = [ diff --git a/app/imports/api/properties/Attributes.js b/app/imports/api/properties/Attributes.js index b4d98161..b55194f4 100644 --- a/app/imports/api/properties/Attributes.js +++ b/app/imports/api/properties/Attributes.js @@ -9,15 +9,15 @@ import createPropertySchema from '/imports/api/properties/subSchemas/createPrope let AttributeSchema = createPropertySchema({ name: { type: String, - defaultValue: 'New Attribute', + optional: true, max: STORAGE_LIMITS.name, }, // The technical, lowercase, single-word name used in formulae variableName: { type: String, + optional: true, regEx: VARIABLE_NAME_REGEX, min: 2, - defaultValue: 'newAttribute', max: STORAGE_LIMITS.variableName, }, // How it is displayed and computed is determined by type