Fixed failing tests
This commit is contained in:
@@ -274,6 +274,7 @@ export async function applyAction(action: Action, userInput?: any[] | Function,
|
|||||||
action._isSimulation = simulate;
|
action._isSimulation = simulate;
|
||||||
action.taskCount = 0;
|
action.taskCount = 0;
|
||||||
const prop = await getSingleProperty(action.creatureId, action.rootPropId);
|
const prop = await getSingleProperty(action.creatureId, action.rootPropId);
|
||||||
|
if (!prop) throw new Meteor.Error('Not found', 'Root action property could not be found');
|
||||||
await applyTask(action, {
|
await applyTask(action, {
|
||||||
prop,
|
prop,
|
||||||
targetIds: action.targetIds || [],
|
targetIds: action.targetIds || [],
|
||||||
@@ -311,6 +312,7 @@ async function applyTask(action: Action, task: Task, userInput?): Promise<void>
|
|||||||
if (prop.triggerIds?.before?.length) {
|
if (prop.triggerIds?.before?.length) {
|
||||||
for (const triggerId of prop.triggerIds.before) {
|
for (const triggerId of prop.triggerIds.before) {
|
||||||
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
||||||
|
if (!trigger) continue;
|
||||||
await applyTask(action, { prop: trigger, targetIds: task.targetIds }, userInput);
|
await applyTask(action, { prop: trigger, targetIds: task.targetIds }, userInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,6 +369,7 @@ async function applyAfterChildrenTriggers(action: Action, prop, targetIds, userI
|
|||||||
if (!prop.triggerIds?.afterChildren) return;
|
if (!prop.triggerIds?.afterChildren) return;
|
||||||
for (const triggerId of prop.triggerIds.afterChildren) {
|
for (const triggerId of prop.triggerIds.afterChildren) {
|
||||||
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
||||||
|
if (!trigger) continue;
|
||||||
await applyTask(action, { prop: trigger, targetIds }, userInput);
|
await applyTask(action, { prop: trigger, targetIds }, userInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,6 +378,7 @@ async function applyAfterTriggers(action: Action, prop, targetIds, userInput) {
|
|||||||
if (!prop.triggerIds?.after) return;
|
if (!prop.triggerIds?.after) return;
|
||||||
for (const triggerId of prop.triggerIds.after) {
|
for (const triggerId of prop.triggerIds.after) {
|
||||||
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
||||||
|
if (!trigger) continue;
|
||||||
await applyTask(action, { prop: trigger, targetIds }, userInput);
|
await applyTask(action, { prop: trigger, targetIds }, userInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,6 +441,7 @@ async function applyTriggers(action: Action, prop, targetIds: string[], triggerP
|
|||||||
if (!triggerIds) return;
|
if (!triggerIds) return;
|
||||||
for (const triggerId of triggerIds) {
|
for (const triggerId of triggerIds) {
|
||||||
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
const trigger = await getSingleProperty(action.creatureId, triggerId);
|
||||||
|
if (!trigger) continue;
|
||||||
await applyTask(action, { prop: trigger, targetIds }, userInput);
|
await applyTask(action, { prop: trigger, targetIds }, userInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -461,6 +466,8 @@ async function applyTaskToEachTarget(action: Action, task: PropTask, targetIds:
|
|||||||
// Combine all the action results into the scope at present
|
// Combine all the action results into the scope at present
|
||||||
export async function getEffectiveActionScope(action: Action) {
|
export async function getEffectiveActionScope(action: Action) {
|
||||||
const scope = await getVariables(action.creatureId);
|
const scope = await getVariables(action.creatureId);
|
||||||
|
delete scope._id;
|
||||||
|
delete scope._creatureId;
|
||||||
// Combine the applied results
|
// Combine the applied results
|
||||||
for (const result of action.results) {
|
for (const result of action.results) {
|
||||||
// Pop keys that are not longer used by a busy property
|
// Pop keys that are not longer used by a busy property
|
||||||
@@ -524,7 +531,7 @@ const applyPropertyByType = {
|
|||||||
//Log the name and summary, check that the property has enough resources to fire
|
//Log the name and summary, check that the property has enough resources to fire
|
||||||
const content: LogContent = { name: prop.name };
|
const content: LogContent = { name: prop.name };
|
||||||
if (prop.summary?.text) {
|
if (prop.summary?.text) {
|
||||||
recalculateInlineCalculations(prop.summary, action);
|
await recalculateInlineCalculations(prop.summary, action);
|
||||||
content.value = prop.summary.value;
|
content.value = prop.summary.value;
|
||||||
}
|
}
|
||||||
if (prop.silent) content.silenced = true;
|
if (prop.silent) content.silenced = true;
|
||||||
@@ -591,7 +598,7 @@ const applyPropertyByType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the amount
|
// Evaluate the amount
|
||||||
recalculateCalculation(prop.amount, action, 'reduce');
|
await recalculateCalculation(prop.amount, action, 'reduce');
|
||||||
const value = +prop.amount.value;
|
const value = +prop.amount.value;
|
||||||
if (!isFinite(value)) {
|
if (!isFinite(value)) {
|
||||||
return;
|
return;
|
||||||
@@ -648,7 +655,7 @@ const applyPropertyByType = {
|
|||||||
if (!children.length) {
|
if (!children.length) {
|
||||||
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
return applyAfterTasksSkipChildren(action, prop, targets, userInput);
|
||||||
}
|
}
|
||||||
recalculateCalculation(prop.condition, action, 'reduce');
|
await recalculateCalculation(prop.condition, action, 'reduce');
|
||||||
if (!isFinite(prop.condition?.value)) {
|
if (!isFinite(prop.condition?.value)) {
|
||||||
result.appendLog({
|
result.appendLog({
|
||||||
name: 'Branch Error',
|
name: 'Branch Error',
|
||||||
@@ -1070,7 +1077,7 @@ async function spendResources(action: Action, prop, targetIds: string[], result:
|
|||||||
throw 'No ammo was selected';
|
throw 'No ammo was selected';
|
||||||
}
|
}
|
||||||
const item = getSingleProperty(action.creatureId, itemConsumed.itemId);
|
const item = getSingleProperty(action.creatureId, itemConsumed.itemId);
|
||||||
if (!item || item.ancestors[0].id !== prop.ancestors[0].id) {
|
if (!item || item.root.id !== prop.root.id) {
|
||||||
throw 'The prop\'s ammo was not found on the creature';
|
throw 'The prop\'s ammo was not found on the creature';
|
||||||
}
|
}
|
||||||
const quantity = +itemConsumed?.quantity?.value;
|
const quantity = +itemConsumed?.quantity?.value;
|
||||||
|
|||||||
@@ -29,8 +29,9 @@ describe('Interrupt action system', function () {
|
|||||||
dirty: true,
|
dirty: true,
|
||||||
});
|
});
|
||||||
await insertActionTestProps();
|
await insertActionTestProps();
|
||||||
loadCreature(creatureId, dummySubscription);
|
// Compute before load or we might run tests before the computation changes reflect in the cache
|
||||||
computeCreature(creatureId);
|
computeCreature(creatureId);
|
||||||
|
loadCreature(creatureId, dummySubscription);
|
||||||
});
|
});
|
||||||
after(function () {
|
after(function () {
|
||||||
unload?.();
|
unload?.();
|
||||||
@@ -113,7 +114,7 @@ describe('Interrupt action system', function () {
|
|||||||
|
|
||||||
function createAction(prop, targetIds?) {
|
function createAction(prop, targetIds?) {
|
||||||
const action: Action = {
|
const action: Action = {
|
||||||
creatureId: prop.ancestors[0].id,
|
creatureId: prop.root.id,
|
||||||
rootPropId: prop._id,
|
rootPropId: prop._id,
|
||||||
results: [],
|
results: [],
|
||||||
taskCount: 0,
|
taskCount: 0,
|
||||||
@@ -254,7 +255,7 @@ const propForest = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
function insertActionTestProps() {
|
function insertActionTestProps() {
|
||||||
const promises = propsFromForest(propForest, [{ id: creatureId, collection: 'creatures' }]).map(prop => {
|
const promises = propsFromForest(propForest, creatureId).map(prop => {
|
||||||
return CreatureProperties.insertAsync(prop);
|
return CreatureProperties.insertAsync(prop);
|
||||||
});
|
});
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import logErrors from './logErrors';
|
import logErrors from './logErrors';
|
||||||
import { toPrimitiveOrString } from '/imports/parser/resolve';
|
import { Context, toPrimitiveOrString } from '/imports/parser/resolve';
|
||||||
import {
|
import {
|
||||||
aggregateCalculationEffects,
|
aggregateCalculationEffects,
|
||||||
aggregateCalculationProficiencies,
|
aggregateCalculationProficiencies,
|
||||||
@@ -7,15 +7,16 @@ import {
|
|||||||
} from '/imports/api/engine/computation/computeComputation/computeByType/computeCalculation';
|
} from '/imports/api/engine/computation/computeComputation/computeByType/computeCalculation';
|
||||||
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
import { getSingleProperty } from '/imports/api/engine/loadCreatures';
|
||||||
import resolve from '/imports/parser/resolve';
|
import resolve from '/imports/parser/resolve';
|
||||||
|
import { getEffectiveActionScope } from '/imports/api/engine/actions/Actions';
|
||||||
|
|
||||||
// TODO move this whole file to Actions.ts
|
// TODO move this whole file to Actions.ts
|
||||||
// Redo the work of imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js
|
// Redo the work of imports/api/engine/computation/computeComputation/computeByType/computeCalculation.js
|
||||||
// But in the action scope
|
// But in the action scope
|
||||||
export default function recalculateCalculation(calcObj, action, parseLevel = 'reduce', context, scope) {
|
export default async function recalculateCalculation(calcObj, action, parseLevel = 'reduce', context, scope) {
|
||||||
if (!calcObj?.parseNode) return;
|
if (!calcObj?.parseNode) return;
|
||||||
calcObj._parseLevel = parseLevel;
|
calcObj._parseLevel = parseLevel;
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
scope = getEffectiveActionScope(action);
|
scope = await getEffectiveActionScope(action);
|
||||||
}
|
}
|
||||||
// Re-resolve the parse node
|
// Re-resolve the parse node
|
||||||
resolveCalculationNode(calcObj, calcObj.parseNode, scope, context);
|
resolveCalculationNode(calcObj, calcObj.parseNode, scope, context);
|
||||||
@@ -41,9 +42,9 @@ export default function recalculateCalculation(calcObj, action, parseLevel = 're
|
|||||||
// TODO log errors
|
// TODO log errors
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rollAndReduceCalculation(calcObj, action) {
|
export async function rollAndReduceCalculation(calcObj, action) {
|
||||||
const context = new Context();
|
const context = new Context();
|
||||||
const scope = getEffectiveActionScope(action);
|
const scope = await getEffectiveActionScope(action);
|
||||||
// Compile
|
// Compile
|
||||||
recalculateCalculation(calcObj, action, 'compile', context, scope);
|
recalculateCalculation(calcObj, action, 'compile', context, scope);
|
||||||
const compiled = calcObj.valueNode;
|
const compiled = calcObj.valueNode;
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import embedInlineCalculations from '/imports/api/engine/computation/utility/embedInlineCalculations';
|
import embedInlineCalculations from '/imports/api/engine/computation/utility/embedInlineCalculations';
|
||||||
import recalculateCalculation from './recalculateCalculation'
|
import recalculateCalculation from './recalculateCalculation'
|
||||||
|
|
||||||
export default function recalculateInlineCalculations(inlineCalcObj, actionContext) {
|
export default async function recalculateInlineCalculations(inlineCalcObj, action) {
|
||||||
// Skip if there are no calculations
|
// Skip if there are no calculations
|
||||||
if (!inlineCalcObj?.inlineCalculations?.length) return;
|
if (!inlineCalcObj?.inlineCalculations?.length) return;
|
||||||
// Recalculate each calculation with the current scope
|
// Recalculate each calculation with the current scope
|
||||||
inlineCalcObj.inlineCalculations.forEach(calc => {
|
const promises = [];
|
||||||
recalculateCalculation(calc, action);
|
for (const calc of inlineCalcObj.inlineCalculations) {
|
||||||
});
|
promises.push(recalculateCalculation(calc, action));
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
// Embed the new calculated values
|
// Embed the new calculated values
|
||||||
embedInlineCalculations(inlineCalcObj);
|
embedInlineCalculations(inlineCalcObj);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,10 +96,7 @@ export async function doActionWork({
|
|||||||
|
|
||||||
// Apply the top level property, it is responsible for applying its children
|
// Apply the top level property, it is responsible for applying its children
|
||||||
// recursively
|
// recursively
|
||||||
console.log('start apply properties')
|
|
||||||
await applyProperty(propertyForest[0], actionContext);
|
await applyProperty(propertyForest[0], actionContext);
|
||||||
console.log('end apply properties')
|
|
||||||
|
|
||||||
// Insert the log
|
// Insert the log
|
||||||
actionContext.writeLog();
|
actionContext.writeLog();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,12 +87,7 @@ export function buildComputationFromProps(properties, creature, variables) {
|
|||||||
|
|
||||||
// Get all the properties as a forest, with their nested set properties set
|
// Get all the properties as a forest, with their nested set properties set
|
||||||
const forest = applyNestedSetProperties(properties);
|
const forest = applyNestedSetProperties(properties);
|
||||||
const ops = calculateNestedSetOperations(properties);
|
|
||||||
if (ops.length > 20) {
|
|
||||||
console.log(ops.length + ' operations to get fixed nested sets');
|
|
||||||
} else {
|
|
||||||
console.log(JSON.stringify(ops, null, 2));
|
|
||||||
}
|
|
||||||
// Walk the property trees computing things that need to be inherited
|
// Walk the property trees computing things that need to be inherited
|
||||||
walkDown(forest, node => {
|
walkDown(forest, node => {
|
||||||
computeInactiveStatus(node);
|
computeInactiveStatus(node);
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class LoadedCreature {
|
|||||||
self.properties = new Map();
|
self.properties = new Map();
|
||||||
// Observe all creature properties which are needed for computation
|
// Observe all creature properties which are needed for computation
|
||||||
self.propertyObserver = CreatureProperties.find({
|
self.propertyObserver = CreatureProperties.find({
|
||||||
'ancestors.id': creatureId,
|
'root.id': creatureId,
|
||||||
removed: { $ne: true },
|
removed: { $ne: true },
|
||||||
}, {
|
}, {
|
||||||
sort: { order: 1 },
|
sort: { order: 1 },
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export interface TreeDoc {
|
|||||||
parentId?: string,
|
parentId?: string,
|
||||||
left: number,
|
left: number,
|
||||||
right: number,
|
right: number,
|
||||||
|
removed?: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const RefSchema = new SimpleSchema({
|
const RefSchema = new SimpleSchema({
|
||||||
|
|||||||
@@ -369,8 +369,6 @@ export async function moveDocWithinRoot(doc: TreeDoc, collection: Mongo.Collecti
|
|||||||
throw new Meteor.Error('invalid-move', 'Destination must be outside the doc\'s current location');
|
throw new Meteor.Error('invalid-move', 'Destination must be outside the doc\'s current location');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Moving ${doc._id} ${move} spaces, while everything between ${includedRange.left} and ${includedRange.right} is shifted by ${shiftDistance}`);
|
|
||||||
|
|
||||||
// If the move isn't meaningfully changing the doc's location, skip
|
// If the move isn't meaningfully changing the doc's location, skip
|
||||||
if (Math.abs(move) < 1) {
|
if (Math.abs(move) < 1) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { applyNestedSetProperties } from '/imports/api/parenting/parentingFunctions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take a forest of props, which can have sub-props nested in children: [], and return a list of
|
* Take a forest of props, which can have sub-props nested in children: [], and return a list of
|
||||||
* clean props with correct tree and ancestry data
|
* clean props with correct tree and ancestry data
|
||||||
@@ -6,7 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
export function propsFromForest(
|
export function propsFromForest(
|
||||||
props,
|
props,
|
||||||
ancestry = [{ id: 'creatureId', collection: 'creatures' }],
|
creatureId = Random.id(),
|
||||||
|
parentId = undefined,
|
||||||
|
recursionDepth = 0
|
||||||
) {
|
) {
|
||||||
const result = [];
|
const result = [];
|
||||||
props.forEach(prop => {
|
props.forEach(prop => {
|
||||||
@@ -17,24 +21,29 @@ export function propsFromForest(
|
|||||||
throw 'Type is required on every property, not found on above doc';
|
throw 'Type is required on every property, not found on above doc';
|
||||||
}
|
}
|
||||||
// Create the clean doc
|
// Create the clean doc
|
||||||
const doc = { ...prop };
|
const doc = {
|
||||||
|
...prop,
|
||||||
|
left: result.length,
|
||||||
|
root: { id: creatureId, collection: 'creatures' },
|
||||||
|
};
|
||||||
|
if (parentId) {
|
||||||
|
doc.parentId = parentId;
|
||||||
|
}
|
||||||
if (!doc._id) {
|
if (!doc._id) {
|
||||||
doc._id = Random.id();
|
doc._id = Random.id();
|
||||||
}
|
}
|
||||||
delete doc.children;
|
delete doc.children;
|
||||||
doc.order = result.length;
|
|
||||||
doc.parent = { ...ancestry[ancestry.length - 1] };
|
|
||||||
doc.ancestors = [...ancestry];
|
|
||||||
|
|
||||||
// Add the doc to the result and ancestry
|
// Add the doc to the result and ancestry
|
||||||
result.push(doc);
|
result.push(doc);
|
||||||
if (children) {
|
if (children) {
|
||||||
ancestry.push({ id: doc._id, collection: 'creatureProperties' });
|
result.push(...propsFromForest(children, creatureId, doc._id, recursionDepth + 1));
|
||||||
// Add the children to the result
|
|
||||||
result.push(...propsFromForest(children, ancestry));
|
|
||||||
// Remove the doc from the ancestry after its children are done
|
|
||||||
ancestry.pop();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Apply the nested set properties on the top level
|
||||||
|
if (recursionDepth === 0) {
|
||||||
|
applyNestedSetProperties(result);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user