From 1167538977f5baa619b72d09a2f57672aa040447 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Fri, 29 Jan 2021 12:29:01 +0200 Subject: [PATCH] Denormalised inline calculations to property documents, needs to be referenced by UI still --- ...evalutateStringWithEmbeddedCalculations.js | 2 + .../computation/computeEndStepProperty.js | 1 + .../computation/computeInlineCalculations.js | 34 +++++++++++ .../api/creature/computation/computeMemo.js | 5 ++ .../computation/evaluateCalculation.js | 7 +++ .../computation/getComputationProperties.js | 35 ++++++++++++ .../creature/computation/recomputeCreature.js | 56 +++---------------- .../computation/writeAlteredProperties.js | 29 +--------- app/imports/api/properties/Actions.js | 14 ++++- app/imports/api/properties/Adjustments.js | 23 +++++++- app/imports/api/properties/Attributes.js | 6 ++ app/imports/api/properties/Buffs.js | 19 ++++--- app/imports/api/properties/ClassLevels.js | 1 + app/imports/api/properties/Containers.js | 8 ++- app/imports/api/properties/Damages.js | 21 ++++++- app/imports/api/properties/Features.js | 23 +++++++- app/imports/api/properties/Items.js | 16 +++++- app/imports/api/properties/Notes.js | 23 +++++++- app/imports/api/properties/Rolls.js | 21 ++++++- app/imports/api/properties/Slots.js | 18 +++++- app/imports/api/properties/SpellLists.js | 7 +++ app/imports/api/properties/Spells.js | 5 -- .../computedOnlyPropertySchemasIndex.js | 52 +++++++++++++++++ .../computedPropertySchemasIndex.js | 36 ++++++------ .../subSchemas/InlineComputationSchema.js | 16 ++++++ 25 files changed, 360 insertions(+), 118 deletions(-) create mode 100644 app/imports/api/creature/computation/computeInlineCalculations.js create mode 100644 app/imports/api/creature/computation/getComputationProperties.js create mode 100644 app/imports/api/properties/computedOnlyPropertySchemasIndex.js create mode 100644 app/imports/api/properties/subSchemas/InlineComputationSchema.js diff --git a/app/imports/api/creature/computation/afterComputation/evalutateStringWithEmbeddedCalculations.js b/app/imports/api/creature/computation/afterComputation/evalutateStringWithEmbeddedCalculations.js index 4f36b4ee..23869348 100644 --- a/app/imports/api/creature/computation/afterComputation/evalutateStringWithEmbeddedCalculations.js +++ b/app/imports/api/creature/computation/afterComputation/evalutateStringWithEmbeddedCalculations.js @@ -2,6 +2,8 @@ import evaluateString from '/imports/api/creature/computation/afterComputation/e // Strings can have computations in bracers like so: {computation} export default function evalutateStringWithEmbeddedCalculations(string, scope){ + console.warn('evalutateStringWithEmbeddedCalculations should be replaced with ' + + 'fetching the result from the compuations on the property doc'); if (!string) return string; // Compute everything inside bracers return string.replace(/\{([^{}]*)\}/g, function(match, p1){ diff --git a/app/imports/api/creature/computation/computeEndStepProperty.js b/app/imports/api/creature/computation/computeEndStepProperty.js index 07494e15..6317549c 100644 --- a/app/imports/api/creature/computation/computeEndStepProperty.js +++ b/app/imports/api/creature/computation/computeEndStepProperty.js @@ -18,6 +18,7 @@ export default function computeEndStepProperty(prop, memo){ break; case 'propertySlot': computeSlot(prop, memo); + break; } } diff --git a/app/imports/api/creature/computation/computeInlineCalculations.js b/app/imports/api/creature/computation/computeInlineCalculations.js new file mode 100644 index 00000000..feb6ee19 --- /dev/null +++ b/app/imports/api/creature/computation/computeInlineCalculations.js @@ -0,0 +1,34 @@ +import evaluateCalculation from '/imports/api/creature/computation/evaluateCalculation.js'; + +export default function computeInlineCalculations(prop, memo){ + if (prop.summary){ + computeInlineCalcsForField(prop, memo, 'summary'); + } + if (prop.description){ + computeInlineCalcsForField(prop, memo, 'description'); + } +} + +function computeInlineCalcsForField(prop, memo, field){ + let string = prop[field]; + let inlineComputations = []; + let matches = string.matchAll(/\{([^{}]*)\}/g); + for (let match of matches){ + let calculation = match[1]; + let { + result, + context, + dependencies, + } = evaluateCalculation(calculation, memo, 'compile'); + let computation = { + calculation, + result: result.value, + }; + if (context.errors.length){ + computation.errors = context.errors; + } + inlineComputations.push(computation); + prop.dependencies.push(...dependencies); + } + prop[`${field}Calculations`] = inlineComputations; +} diff --git a/app/imports/api/creature/computation/computeMemo.js b/app/imports/api/creature/computation/computeMemo.js index 061a4bb8..52d20881 100644 --- a/app/imports/api/creature/computation/computeMemo.js +++ b/app/imports/api/creature/computation/computeMemo.js @@ -4,6 +4,7 @@ import computeStat from '/imports/api/creature/computation/computeStat.js'; import computeEffect from '/imports/api/creature/computation/computeEffect.js'; import computeToggle from '/imports/api/creature/computation/computeToggle.js'; import computeEndStepProperty from '/imports/api/creature/computation/computeEndStepProperty.js'; +import computeInlineCalculations from '/imports/api/creature/computation/computeInlineCalculations.js'; export default function computeMemo(memo){ // Compute level @@ -24,4 +25,8 @@ export default function computeMemo(memo){ forOwn(memo.endStepPropsById, prop => { computeEndStepProperty(prop, memo); }); + // Compute inline calculations + forOwn(memo.propsById, prop => { + computeInlineCalculations(prop, memo); + }); } diff --git a/app/imports/api/creature/computation/evaluateCalculation.js b/app/imports/api/creature/computation/evaluateCalculation.js index bc8fa5a5..58037dc8 100644 --- a/app/imports/api/creature/computation/evaluateCalculation.js +++ b/app/imports/api/creature/computation/evaluateCalculation.js @@ -28,6 +28,13 @@ export default function evaluateCalculation(string, memo, fn = 'reduce'){ dependencies, }; } + if (!calc){ + return { + context: {errors}, + result: new ConstantNode({value: calc, type: 'string'}), + dependencies, + }; + } // Ensure all symbol nodes are defined and computed calc.traverse(node => { if (node instanceof SymbolNode || node instanceof AccessorNode){ diff --git a/app/imports/api/creature/computation/getComputationProperties.js b/app/imports/api/creature/computation/getComputationProperties.js new file mode 100644 index 00000000..bbfc5606 --- /dev/null +++ b/app/imports/api/creature/computation/getComputationProperties.js @@ -0,0 +1,35 @@ +import CreatureProperties from '/imports/api/creature/CreatureProperties.js'; + +export default function getComputationProperties(creatureId){ + // find ids of all toggles that have conditions, even if they are inactive + let toggleIds = CreatureProperties.find({ + 'ancestors.id': creatureId, + type: 'toggle', + removed: {$ne: true}, + condition: { $exists: true }, + }, { + fields: {_id: 1}, + }).map(t => t._id); + // Find all the relevant properties + return CreatureProperties.find({ + 'ancestors.id': creatureId, + removed: {$ne: true}, + $or: [ + // All active properties + {inactive: {$ne: true}}, + // All active and inactive toggles with conditions + // Same as {$in: toggleIds}, but should be slightly faster + {type: 'toggle', condition: { $exists: true }}, + // All decendents of the above toggles + {'ancestors.id': {$in: toggleIds}}, + ] + }, { + // Filter out fields never used by calculations + fields: { + icon: 0, + }, + sort: { + order: 1, + } + }).fetch(); +} diff --git a/app/imports/api/creature/computation/recomputeCreature.js b/app/imports/api/creature/computation/recomputeCreature.js index 6e4babd6..9618fe38 100644 --- a/app/imports/api/creature/computation/recomputeCreature.js +++ b/app/imports/api/creature/computation/recomputeCreature.js @@ -3,7 +3,7 @@ import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import SimpleSchema from 'simpl-schema'; import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js'; import ComputationMemo from '/imports/api/creature/computation/ComputationMemo.js'; -import CreatureProperties from '/imports/api/creature/CreatureProperties.js'; +import getComputationProperties from '/imports/api/creature/computation/getComputationProperties.js'; import computeMemo from '/imports/api/creature/computation/computeMemo.js'; import writeAlteredProperties from '/imports/api/creature/computation/writeAlteredProperties.js'; import writeCreatureVariables from '/imports/api/creature/computation/writeCreatureVariables.js'; @@ -37,23 +37,6 @@ export const recomputeCreature = new ValidatedMethod({ }); -const calculationPropertyTypes = [ - 'attribute', - 'skill', - 'effect', - 'proficiency', - 'classLevel', - 'toggle', - 'item', - // End step types - 'action', - 'attack', - 'savingThrow', - 'spellList', - 'spell', - 'propertySlot', -]; - export function recomputeCreatureById(creatureId){ let creature = Creatures.findOne(creatureId); recomputeCreatureByDoc(creature); @@ -97,38 +80,13 @@ export function recomputeCreatureById(creatureId){ */ export function recomputeCreatureByDoc(creature){ const creatureId = creature._id; - // find all toggles that have conditions, even if they are inactive - let toggleIds = CreatureProperties.find({ - 'ancestors.id': creatureId, - type: 'toggle', - removed: {$ne: true}, - condition: { $exists: true }, - }, { - fields: {_id: 1}, - }).map(t => t._id); - // Find all the active properties - let props = CreatureProperties.find({ - 'ancestors.id': creatureId, - removed: {$ne: true}, - type: {$in: calculationPropertyTypes}, - $or: [ - {inactive: {$ne: true}}, - // But also the inactive computed toggles and their decendants - {'ancestors.id': {$in: toggleIds}}, - {_id: {$in: toggleIds}}, - ] - }, { - fields: { // Filter out potentially large fields - icon: 0, - summary: 0, - description: 0, - }, - sort: { - order: 1, - } - }).fetch(); - let computationMemo = new ComputationMemo(props, creature); + + // Make sure the active state of all properties is correct before doing work + // TODO: Separate this into it's own recompute function and only call it + // when things change activation state recomputeInactiveProperties(creatureId); + let props = getComputationProperties(creatureId); + let computationMemo = new ComputationMemo(props, creature); computeMemo(computationMemo); writeAlteredProperties(computationMemo); writeCreatureVariables(computationMemo, creatureId); diff --git a/app/imports/api/creature/computation/writeAlteredProperties.js b/app/imports/api/creature/computation/writeAlteredProperties.js index bf2c505f..f2dcdaf0 100644 --- a/app/imports/api/creature/computation/writeAlteredProperties.js +++ b/app/imports/api/creature/computation/writeAlteredProperties.js @@ -1,38 +1,13 @@ import { Meteor } from 'meteor/meteor' import { isEqual, forOwn } from 'lodash'; import CreatureProperties from '/imports/api/creature/CreatureProperties.js'; -// Schemas -// Calculated props -import { ComputedOnlySkillSchema } from '/imports/api/properties/Skills.js'; -import { ComputedOnlyAttributeSchema } from '/imports/api/properties/Attributes.js'; -import { ComputedOnlyEffectSchema } from '/imports/api/properties/Effects.js'; -import { ComputedOnlyToggleSchema } from '/imports/api/properties/Toggles.js'; -// End step props -import { ComputedOnlyActionSchema } from '/imports/api/properties/Actions.js'; -import { ComputedOnlyAttackSchema } from '/imports/api/properties/Attacks.js'; -import { ComputedOnlySavingThrowSchema } from '/imports/api/properties/SavingThrows.js'; -import { ComputedOnlySpellListSchema } from '/imports/api/properties/SpellLists.js'; -import { ComputedOnlySpellSchema } from '/imports/api/properties/Spells.js'; -import { ComputedOnlySlotSchema } from '/imports/api/properties/Slots.js'; - -const schemasByType = { - 'skill': ComputedOnlySkillSchema, - 'attribute': ComputedOnlyAttributeSchema, - 'effect': ComputedOnlyEffectSchema, - 'toggle': ComputedOnlyToggleSchema, - 'action': ComputedOnlyActionSchema, - 'attack': ComputedOnlyAttackSchema, - 'savingThrow': ComputedOnlySavingThrowSchema, - 'spellList': ComputedOnlySpellListSchema, - 'spell': ComputedOnlySpellSchema, - 'propertySlot': ComputedOnlySlotSchema, -}; +import propertySchemasIndex from '/imports/api/properties/computedOnlyPropertySchemasIndex.js'; export default function writeAlteredProperties(memo){ let bulkWriteOperations = []; // Loop through all properties on the memo forOwn(memo.propsById, changed => { - let schema = schemasByType[changed.type]; + let schema = propertySchemasIndex[changed.type]; if (!schema) return; let extraIds = changed.computationDetails.idsOfSameName; let ids; diff --git a/app/imports/api/properties/Actions.js b/app/imports/api/properties/Actions.js index 338aae49..e2a0edc1 100644 --- a/app/imports/api/properties/Actions.js +++ b/app/imports/api/properties/Actions.js @@ -1,7 +1,7 @@ import SimpleSchema from 'simpl-schema'; import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; import { storedIconsSchema } from '/imports/api/icons/Icons.js' - /* * Actions are things a character can do * Any rolls that are children of actions will be rolled when taking the action @@ -117,6 +117,18 @@ let ActionSchema = new SimpleSchema({ }); const ComputedOnlyActionSchema = new SimpleSchema({ + summaryCalculations: { + type: Array, + maxCount: 32, + }, + 'summaryCalculations.$': InlineComputationSchema, + + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, + usesResult: { type: SimpleSchema.Integer, optional: true, diff --git a/app/imports/api/properties/Adjustments.js b/app/imports/api/properties/Adjustments.js index 42a6ce1e..035595ac 100644 --- a/app/imports/api/properties/Adjustments.js +++ b/app/imports/api/properties/Adjustments.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; const AdjustmentSchema = new SimpleSchema({ // The roll that determines how much to change the attribute @@ -13,7 +14,7 @@ const AdjustmentSchema = new SimpleSchema({ type: String, defaultValue: 'every', allowedValues: [ - 'self', // the character who took the action + 'self', // the character who took the Adjustment 'each', // rolled once for `each` target 'every', // rolled once and applied to `every` target ], @@ -30,4 +31,22 @@ const AdjustmentSchema = new SimpleSchema({ }, }); -export { AdjustmentSchema }; +const ComputedOnlyAdjustmentSchema = new SimpleSchema({ + amountResult: { + type: SimpleSchema.Integer, + optional: true, + }, + amountErrors: { + type: Array, + optional: true, + }, + 'amountErrors.$':{ + type: ErrorSchema, + }, +}); + +const ComputedAdjustmentSchema = new SimpleSchema() + .extend(AdjustmentSchema) + .extend(ComputedOnlyAdjustmentSchema); + +export { AdjustmentSchema, ComputedAdjustmentSchema, ComputedOnlyAdjustmentSchema }; diff --git a/app/imports/api/properties/Attributes.js b/app/imports/api/properties/Attributes.js index 87042284..c1b50619 100644 --- a/app/imports/api/properties/Attributes.js +++ b/app/imports/api/properties/Attributes.js @@ -1,6 +1,7 @@ import SimpleSchema from 'simpl-schema'; import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; /* * Attributes are numbered stats of a character @@ -75,6 +76,11 @@ let AttributeSchema = new SimpleSchema({ }); let ComputedOnlyAttributeSchema = new SimpleSchema({ + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, // The result of baseValueCalculation baseValue: { type: SimpleSchema.oneOf(Number, String, Boolean), diff --git a/app/imports/api/properties/Buffs.js b/app/imports/api/properties/Buffs.js index 25ff45f5..927134ea 100644 --- a/app/imports/api/properties/Buffs.js +++ b/app/imports/api/properties/Buffs.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; let BuffSchema = new SimpleSchema({ name: { @@ -29,12 +30,12 @@ let BuffSchema = new SimpleSchema({ }, }); -let AppliedBuffSchema = new SimpleSchema({ - applied: { - type: Boolean, - defaultValue: true, - index: 1, +let ComputedOnlyBuffSchema = new SimpleSchema({ + descriptionCalculations: { + type: Array, + maxCount: 32, }, + 'descriptionCalculations.$': InlineComputationSchema, durationSpent: { type: Number, optional: true, @@ -54,6 +55,10 @@ let AppliedBuffSchema = new SimpleSchema({ 'appliedBy.collection': { type: String, }, -}).extend(BuffSchema); +}) -export { AppliedBuffSchema, BuffSchema }; +const ComputedBuffSchema = new SimpleSchema() + .extend(BuffSchema) + .extend(ComputedOnlyBuffSchema); + +export { BuffSchema, ComputedOnlyBuffSchema, ComputedBuffSchema }; diff --git a/app/imports/api/properties/ClassLevels.js b/app/imports/api/properties/ClassLevels.js index b49b4b4c..eaf89fd8 100644 --- a/app/imports/api/properties/ClassLevels.js +++ b/app/imports/api/properties/ClassLevels.js @@ -6,6 +6,7 @@ let ClassLevelSchema = new SimpleSchema({ type: String, optional: true, }, + // Only used by slot filling dialog, not computed description: { type: String, optional: true, diff --git a/app/imports/api/properties/Containers.js b/app/imports/api/properties/Containers.js index 8e878f70..91217956 100644 --- a/app/imports/api/properties/Containers.js +++ b/app/imports/api/properties/Containers.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; let ContainerSchema = new SimpleSchema({ name: { @@ -33,6 +34,11 @@ let ContainerSchema = new SimpleSchema({ }); const ComputedOnlyContainerSchema = new SimpleSchema({ + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, // Weight of all the contents, zero if `contentsWeightless` is true contentsWeight:{ type: Number, @@ -48,4 +54,4 @@ const ComputedContainerSchema = new SimpleSchema() .extend(ComputedOnlyContainerSchema) .extend(ContainerSchema); -export { ContainerSchema, ComputedContainerSchema }; +export { ContainerSchema, ComputedOnlyContainerSchema, ComputedContainerSchema }; diff --git a/app/imports/api/properties/Damages.js b/app/imports/api/properties/Damages.js index 8f049187..2d736b0a 100644 --- a/app/imports/api/properties/Damages.js +++ b/app/imports/api/properties/Damages.js @@ -1,5 +1,6 @@ import SimpleSchema from 'simpl-schema'; import DAMAGE_TYPES from '/imports/constants/DAMAGE_TYPES.js'; +import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; const DamageSchema = new SimpleSchema({ // The roll that determines how much to damage the attribute @@ -26,4 +27,22 @@ const DamageSchema = new SimpleSchema({ }, }); -export { DamageSchema }; +const ComputedOnlyDamageSchema = new SimpleSchema({ + amountResult: { + type: SimpleSchema.Integer, + optional: true, + }, + amountErrors: { + type: Array, + optional: true, + }, + 'amountErrors.$':{ + type: ErrorSchema, + }, +}); + +const ComputedDamageSchema = new SimpleSchema() + .extend(DamageSchema) + .extend(ComputedOnlyDamageSchema); + +export { DamageSchema, ComputedDamageSchema, ComputedOnlyDamageSchema }; diff --git a/app/imports/api/properties/Features.js b/app/imports/api/properties/Features.js index d6e15b8a..59f9a274 100644 --- a/app/imports/api/properties/Features.js +++ b/app/imports/api/properties/Features.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; let FeatureSchema = new SimpleSchema({ name: { @@ -14,4 +15,24 @@ let FeatureSchema = new SimpleSchema({ }, }); -export { FeatureSchema } +let ComputedOnlyFeatureSchema = new SimpleSchema({ + + summaryCalculations: { + type: Array, + maxCount: 32, + }, + 'summaryCalculations.$': InlineComputationSchema, + + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, + +}); + +const ComputedFeatureSchema = new SimpleSchema() + .extend(FeatureSchema) + .extend(ComputedOnlyFeatureSchema); + +export { FeatureSchema, ComputedFeatureSchema, ComputedOnlyFeatureSchema } diff --git a/app/imports/api/properties/Items.js b/app/imports/api/properties/Items.js index e944310e..5978847f 100644 --- a/app/imports/api/properties/Items.js +++ b/app/imports/api/properties/Items.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; const ItemSchema = new SimpleSchema({ name: { @@ -33,7 +34,6 @@ const ItemSchema = new SimpleSchema({ optional: true, }, // If this item is equipped, it requires attunement - // Being equipped is `enabled === true` requiresAttunement: { type: Boolean, optional: true, @@ -54,4 +54,16 @@ const ItemSchema = new SimpleSchema({ }, }); -export { ItemSchema }; +let ComputedOnlyItemSchema = new SimpleSchema({ + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, +}); + +const ComputedItemSchema = new SimpleSchema() + .extend(ItemSchema) + .extend(ComputedOnlyItemSchema); + +export { ItemSchema, ComputedItemSchema, ComputedOnlyItemSchema }; diff --git a/app/imports/api/properties/Notes.js b/app/imports/api/properties/Notes.js index 4e7a5176..89d392bb 100644 --- a/app/imports/api/properties/Notes.js +++ b/app/imports/api/properties/Notes.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; let NoteSchema = new SimpleSchema({ name: { @@ -11,4 +12,24 @@ let NoteSchema = new SimpleSchema({ }, }); -export { NoteSchema }; +let ComputedOnlyNoteSchema = new SimpleSchema({ + + summaryCalculations: { + type: Array, + maxCount: 32, + }, + 'summaryCalculations.$': InlineComputationSchema, + + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, + +}); + +const ComputedNoteSchema = new SimpleSchema() + .extend(NoteSchema) + .extend(ComputedOnlyNoteSchema); + +export { NoteSchema, ComputedNoteSchema, ComputedOnlyNoteSchema, }; diff --git a/app/imports/api/properties/Rolls.js b/app/imports/api/properties/Rolls.js index 09fe948b..ec2b1337 100644 --- a/app/imports/api/properties/Rolls.js +++ b/app/imports/api/properties/Rolls.js @@ -1,4 +1,5 @@ import SimpleSchema from 'simpl-schema'; +import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; /** * Rolls are children to actions or other rolls, they are triggered with 0 or @@ -35,4 +36,22 @@ let RollSchema = new SimpleSchema({ }, }); -export { RollSchema }; +let ComputedOnlyRollSchema = new SimpleSchema({ + rollResult: { + type: SimpleSchema.Integer, + optional: true, + }, + rollErrors: { + type: Array, + optional: true, + }, + 'rollErrors.$':{ + type: ErrorSchema, + }, +}); + +const ComputedRollSchema = new SimpleSchema() + .extend(RollSchema) + .extend(ComputedOnlyRollSchema); + +export { RollSchema, ComputedRollSchema, ComputedOnlyRollSchema }; diff --git a/app/imports/api/properties/Slots.js b/app/imports/api/properties/Slots.js index e1f9bbf4..b07db858 100644 --- a/app/imports/api/properties/Slots.js +++ b/app/imports/api/properties/Slots.js @@ -41,12 +41,11 @@ let SlotSchema = new SimpleSchema({ }); const ComputedOnlySlotSchema = new SimpleSchema({ - // The computed result of the effect + // Condition calculation results slotConditionResult: { type: SimpleSchema.oneOf(Number, String, Boolean), optional: true, }, - // The errors encountered while computing the result slotConditionErrors: { type: Array, optional: true, @@ -54,6 +53,21 @@ const ComputedOnlySlotSchema = new SimpleSchema({ 'slotConditionErrors.$':{ type: ErrorSchema, }, + + // Quantity Expected calculation results + quantityExpectedResult: { + type: SimpleSchema.Integer, + optional: true, + }, + quantityExpectedErrors: { + type: Array, + optional: true, + }, + 'quantityExpectedErrors.$':{ + type: ErrorSchema, + }, + + // Denormalised fields totalFilled: { type: SimpleSchema.Integer, defaultValue: 0, diff --git a/app/imports/api/properties/SpellLists.js b/app/imports/api/properties/SpellLists.js index 4e14b217..b9c0560b 100644 --- a/app/imports/api/properties/SpellLists.js +++ b/app/imports/api/properties/SpellLists.js @@ -1,6 +1,7 @@ import SimpleSchema from 'simpl-schema'; import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js'; +import InlineComputationSchema from '/imports/api/properties/subSchemas/InlineComputationSchema.js'; let SpellListSchema = new SimpleSchema({ name: { @@ -25,6 +26,12 @@ let SpellListSchema = new SimpleSchema({ }); const ComputedOnlySpellListSchema = new SimpleSchema({ + descriptionCalculations: { + type: Array, + maxCount: 32, + }, + 'descriptionCalculations.$': InlineComputationSchema, + maxPreparedResult: { type: Number, optional: true, diff --git a/app/imports/api/properties/Spells.js b/app/imports/api/properties/Spells.js index 92a42be2..6440ceca 100644 --- a/app/imports/api/properties/Spells.js +++ b/app/imports/api/properties/Spells.js @@ -1,6 +1,5 @@ import { ActionSchema, ComputedOnlyActionSchema } from '/imports/api/properties/Actions.js'; import SimpleSchema from 'simpl-schema'; -import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js'; const magicSchools = [ 'abjuration', @@ -39,10 +38,6 @@ let SpellSchema = new SimpleSchema({}) type: Boolean, optional: true, }, - description: { - type: String, - optional: true, - }, castingTime: { type: String, optional: true, diff --git a/app/imports/api/properties/computedOnlyPropertySchemasIndex.js b/app/imports/api/properties/computedOnlyPropertySchemasIndex.js new file mode 100644 index 00000000..c97f62f3 --- /dev/null +++ b/app/imports/api/properties/computedOnlyPropertySchemasIndex.js @@ -0,0 +1,52 @@ +import SimpleSchema from 'simpl-schema'; +import { ComputedOnlyActionSchema } from '/imports/api/properties/Actions.js'; +import { ComputedOnlyAdjustmentSchema } from '/imports/api/properties/Adjustments.js'; +import { ComputedOnlyAttackSchema } from '/imports/api/properties/Attacks.js'; +import { ComputedOnlyAttributeSchema } from '/imports/api/properties/Attributes.js'; +import { ComputedOnlyBuffSchema } from '/imports/api/properties/Buffs.js'; +// import { ClassLevelSchema } from '/imports/api/properties/ClassLevels.js'; +import { ComputedOnlyContainerSchema } from '/imports/api/properties/Containers.js'; +import { ComputedOnlyDamageSchema } from '/imports/api/properties/Damages.js'; +import { DamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers.js'; +import { ComputedOnlyEffectSchema } from '/imports/api/properties/Effects.js'; +import { ComputedOnlyFeatureSchema } from '/imports/api/properties/Features.js'; +// import { FolderSchema } from '/imports/api/properties/Folders.js'; +import { ComputedOnlyItemSchema } from '/imports/api/properties/Items.js'; +import { ComputedOnlyNoteSchema } from '/imports/api/properties/Notes.js'; +// import { ProficiencySchema } from '/imports/api/properties/Proficiencies.js'; +import { ComputedOnlyRollSchema } from '/imports/api/properties/Rolls.js'; +import { ComputedOnlySavingThrowSchema } from '/imports/api/properties/SavingThrows.js'; +import { ComputedOnlySkillSchema } from '/imports/api/properties/Skills.js'; +import { ComputedOnlySlotSchema } from '/imports/api/properties/Slots.js'; +// import { SlotFillerSchema } from '/imports/api/properties/SlotFillers.js'; +import { ComputedOnlySpellSchema } from '/imports/api/properties/Spells.js'; +import { ComputedOnlySpellListSchema } from '/imports/api/properties/SpellLists.js'; +import { ComputedOnlyToggleSchema } from '/imports/api/properties/Toggles.js'; + +const propertySchemasIndex = { + action: ComputedOnlyActionSchema, + adjustment: ComputedOnlyAdjustmentSchema, + attack: ComputedOnlyAttackSchema, + attribute: ComputedOnlyAttributeSchema, + buff: ComputedOnlyBuffSchema, + // classLevel: ClassLevelSchema, + damage: ComputedOnlyDamageSchema, + damageMultiplier: DamageMultiplierSchema, + effect: ComputedOnlyEffectSchema, + feature: ComputedOnlyFeatureSchema, + // folder: FolderSchema, + note: ComputedOnlyNoteSchema, + // proficiency: ProficiencySchema, + propertySlot: ComputedOnlySlotSchema, + roll: ComputedOnlyRollSchema, + savingThrow: ComputedOnlySavingThrowSchema, + skill: ComputedOnlySkillSchema, + spellList: ComputedOnlySpellListSchema, + spell: ComputedOnlySpellSchema, + toggle: ComputedOnlyToggleSchema, + container: ComputedOnlyContainerSchema, + item: ComputedOnlyItemSchema, + any: new SimpleSchema({}), +}; + +export default propertySchemasIndex; diff --git a/app/imports/api/properties/computedPropertySchemasIndex.js b/app/imports/api/properties/computedPropertySchemasIndex.js index b5156b8e..273ae54f 100644 --- a/app/imports/api/properties/computedPropertySchemasIndex.js +++ b/app/imports/api/properties/computedPropertySchemasIndex.js @@ -1,52 +1,52 @@ import SimpleSchema from 'simpl-schema'; import { ComputedActionSchema } from '/imports/api/properties/Actions.js'; -import { AdjustmentSchema } from '/imports/api/properties/Adjustments.js'; +import { ComputedAdjustmentSchema } from '/imports/api/properties/Adjustments.js'; import { ComputedAttackSchema } from '/imports/api/properties/Attacks.js'; import { ComputedAttributeSchema } from '/imports/api/properties/Attributes.js'; -import { BuffSchema } from '/imports/api/properties/Buffs.js'; +import { ComputedBuffSchema } from '/imports/api/properties/Buffs.js'; import { ClassLevelSchema } from '/imports/api/properties/ClassLevels.js'; -import { ContainerSchema } from '/imports/api/properties/Containers.js'; -import { DamageSchema } from '/imports/api/properties/Damages.js'; +import { ComputedContainerSchema } from '/imports/api/properties/Containers.js'; +import { ComputedDamageSchema } from '/imports/api/properties/Damages.js'; import { DamageMultiplierSchema } from '/imports/api/properties/DamageMultipliers.js'; import { ComputedEffectSchema } from '/imports/api/properties/Effects.js'; -import { FeatureSchema } from '/imports/api/properties/Features.js'; +import { ComputedFeatureSchema } from '/imports/api/properties/Features.js'; import { FolderSchema } from '/imports/api/properties/Folders.js'; -import { ItemSchema } from '/imports/api/properties/Items.js'; -import { NoteSchema } from '/imports/api/properties/Notes.js'; +import { ComputedItemSchema } from '/imports/api/properties/Items.js'; +import { ComputedNoteSchema } from '/imports/api/properties/Notes.js'; import { ProficiencySchema } from '/imports/api/properties/Proficiencies.js'; -import { RollSchema } from '/imports/api/properties/Rolls.js'; +import { ComputedRollSchema } from '/imports/api/properties/Rolls.js'; import { ComputedSavingThrowSchema } from '/imports/api/properties/SavingThrows.js'; import { ComputedSkillSchema } from '/imports/api/properties/Skills.js'; import { ComputedSlotSchema } from '/imports/api/properties/Slots.js'; import { SlotFillerSchema } from '/imports/api/properties/SlotFillers.js'; import { ComputedSpellSchema } from '/imports/api/properties/Spells.js'; import { ComputedSpellListSchema } from '/imports/api/properties/SpellLists.js'; -import { ToggleSchema } from '/imports/api/properties/Toggles.js'; +import { ComputedToggleSchema } from '/imports/api/properties/Toggles.js'; const propertySchemasIndex = { action: ComputedActionSchema, - adjustment: AdjustmentSchema, + adjustment: ComputedAdjustmentSchema, attack: ComputedAttackSchema, attribute: ComputedAttributeSchema, - buff: BuffSchema, + buff: ComputedBuffSchema, classLevel: ClassLevelSchema, - damage: DamageSchema, + damage: ComputedDamageSchema, damageMultiplier: DamageMultiplierSchema, effect: ComputedEffectSchema, - feature: FeatureSchema, + feature: ComputedFeatureSchema, folder: FolderSchema, - note: NoteSchema, + note: ComputedNoteSchema, proficiency: ProficiencySchema, propertySlot: ComputedSlotSchema, - roll: RollSchema, + roll: ComputedRollSchema, savingThrow: ComputedSavingThrowSchema, skill: ComputedSkillSchema, slotFiller: SlotFillerSchema, spellList: ComputedSpellListSchema, spell: ComputedSpellSchema, - toggle: ToggleSchema, - container: ContainerSchema, - item: ItemSchema, + toggle: ComputedToggleSchema, + container: ComputedContainerSchema, + item: ComputedItemSchema, any: new SimpleSchema({}), }; diff --git a/app/imports/api/properties/subSchemas/InlineComputationSchema.js b/app/imports/api/properties/subSchemas/InlineComputationSchema.js new file mode 100644 index 00000000..8f39692b --- /dev/null +++ b/app/imports/api/properties/subSchemas/InlineComputationSchema.js @@ -0,0 +1,16 @@ +import SimpleSchema from 'simpl-schema'; +import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js'; + +const InlineComputationSchema = new SimpleSchema({ + // The part between bracers {} + calculation: { + type: String, + }, + result: { + type: String, + optional: true, + }, + errors: ErrorSchema, +}); + +export default InlineComputationSchema;