Added dependency grouping, but commented out for now until it's needed
This commit is contained in:
@@ -82,6 +82,14 @@ const DenormalisedOnlyCreaturePropertySchema = new SimpleSchema({
|
|||||||
index: 1,
|
index: 1,
|
||||||
removeBeforeCompute: true,
|
removeBeforeCompute: true,
|
||||||
},
|
},
|
||||||
|
// Dependency tree, the ID of the lowest ordered doc connected to this doc
|
||||||
|
// via dependencies
|
||||||
|
/*depGroupId: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
index: 1,
|
||||||
|
removeBeforeCompute: true,
|
||||||
|
}*/
|
||||||
});
|
});
|
||||||
|
|
||||||
CreaturePropertySchema.extend(DenormalisedOnlyCreaturePropertySchema);
|
CreaturePropertySchema.extend(DenormalisedOnlyCreaturePropertySchema);
|
||||||
@@ -98,10 +106,6 @@ for (let key in propertySchemasIndex){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
import '/imports/api/creature/creatureProperties/methods/index.js';
|
|
||||||
//import '/imports/api/creature/actions/doAction.js';
|
|
||||||
//import '/imports/api/creature/actions/castSpellWithSlot.js';
|
|
||||||
|
|
||||||
export default CreatureProperties;
|
export default CreatureProperties;
|
||||||
export {
|
export {
|
||||||
DenormalisedOnlyCreaturePropertySchema,
|
DenormalisedOnlyCreaturePropertySchema,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import linkTypeDependencies from './buildComputation/linkTypeDependencies.js';
|
|||||||
import computeSlotQuantityFilled from './buildComputation/computeSlotQuantityFilled.js';
|
import computeSlotQuantityFilled from './buildComputation/computeSlotQuantityFilled.js';
|
||||||
import CreatureComputation from './CreatureComputation.js';
|
import CreatureComputation from './CreatureComputation.js';
|
||||||
import removeSchemaFields from './buildComputation/removeSchemaFields.js';
|
import removeSchemaFields from './buildComputation/removeSchemaFields.js';
|
||||||
|
// import assignDependencyGroups from '/imports/api/engine/computation/utility/assignDependencyGroups.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store index of properties
|
* Store index of properties
|
||||||
@@ -37,12 +38,30 @@ export default function buildCreatureComputation(creatureId){
|
|||||||
return computation;
|
return computation;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProperties(creatureId){
|
export function buildDependencyGroupComputation(depGroupIds, creatureId) {
|
||||||
|
const creature = getCreature(creatureId);
|
||||||
|
const properties = getGroupProperties(depGroupIds);
|
||||||
|
const computation = buildComputationFromProps(properties, creature);
|
||||||
|
return computation;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProperties(creatureId) {
|
||||||
return CreatureProperties.find({
|
return CreatureProperties.find({
|
||||||
'ancestors.id': creatureId,
|
'ancestors.id': creatureId,
|
||||||
'removed': {$ne: true},
|
'removed': {$ne: true},
|
||||||
}, {
|
}, {
|
||||||
sort: {order: 1}
|
sort: { order: 1 },
|
||||||
|
fields: { icon: 0 },
|
||||||
|
}).fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGroupProperties(depGroupIds) {
|
||||||
|
return CreatureProperties.find({
|
||||||
|
depGroupId: { $in: depGroupIds },
|
||||||
|
'removed': { $ne: true },
|
||||||
|
}, {
|
||||||
|
sort: { order: 1 },
|
||||||
|
fields: { icon: 0 },
|
||||||
}).fetch();
|
}).fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +101,7 @@ export function buildComputationFromProps(properties, creature){
|
|||||||
// Process the properties one by one
|
// Process the properties one by one
|
||||||
properties.forEach(prop => {
|
properties.forEach(prop => {
|
||||||
|
|
||||||
let computedSchema = computedOnlySchemas[prop.type];
|
const computedSchema = computedOnlySchemas[prop.type];
|
||||||
removeSchemaFields([computedSchema, denormSchema], prop);
|
removeSchemaFields([computedSchema, denormSchema], prop);
|
||||||
|
|
||||||
// Add a place to store all the computation details
|
// Add a place to store all the computation details
|
||||||
@@ -114,5 +133,9 @@ export function buildComputationFromProps(properties, creature){
|
|||||||
linkTypeDependencies(dependencyGraph, prop, computation);
|
linkTypeDependencies(dependencyGraph, prop, computation);
|
||||||
linkCalculationDependencies(dependencyGraph, prop, computation);
|
linkCalculationDependencies(dependencyGraph, prop, computation);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Store the connected groups of the dependency graph
|
||||||
|
// assignDependencyGroups(dependencyGraph);
|
||||||
|
|
||||||
return computation;
|
return computation;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
export default function assignDependencyGroups(graph) {
|
||||||
|
// Iterate through all the nodes
|
||||||
|
graph.forEachNode(node => {
|
||||||
|
if (node._depGroupVisited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DFS all the connected nodes to this node, mark visited, put in a group,
|
||||||
|
// store the lowest ordered id
|
||||||
|
const group = [];
|
||||||
|
const stack = [node];
|
||||||
|
let top, lowestOrderId, lowestOrder;
|
||||||
|
while (stack.length) {
|
||||||
|
top = stack.pop();
|
||||||
|
if (top._depGroupVisited) continue;
|
||||||
|
if (
|
||||||
|
(lowestOrderId === undefined && top.data?._id) ||
|
||||||
|
(top.data?._id && top.data?.order < lowestOrder)
|
||||||
|
) {
|
||||||
|
lowestOrderId = top.data?._id;
|
||||||
|
lowestOrder = top.data?.order;
|
||||||
|
}
|
||||||
|
if (top.data?._id) {
|
||||||
|
group.push(top)
|
||||||
|
}
|
||||||
|
top._depGroupVisited = true;
|
||||||
|
graph.forEachLinkedNode(top.id, linkedNode => stack.push(linkedNode));
|
||||||
|
}
|
||||||
|
// Assign group id
|
||||||
|
group.forEach(node => {
|
||||||
|
if (!lowestOrderId) return;
|
||||||
|
if (group.length > 1) {
|
||||||
|
node.data.depGroupId = lowestOrderId;
|
||||||
|
} else {
|
||||||
|
delete node.data.depGroupId;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ export default function writeAlteredProperties(computation){
|
|||||||
'deactivatedBySelf',
|
'deactivatedBySelf',
|
||||||
'deactivatedByAncestor',
|
'deactivatedByAncestor',
|
||||||
'deactivatedByToggle',
|
'deactivatedByToggle',
|
||||||
|
'depGroupId',
|
||||||
'damage',
|
'damage',
|
||||||
...schema.objectKeys(),
|
...schema.objectKeys(),
|
||||||
];
|
];
|
||||||
@@ -28,7 +29,8 @@ export default function writeAlteredProperties(computation){
|
|||||||
bulkWriteOperations.push(op);
|
bulkWriteOperations.push(op);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
writePropertiesSequentially(bulkWriteOperations);
|
bulkWriteProperties(bulkWriteOperations);
|
||||||
|
if (bulkWriteOperations.length) console.log(`Wrote ${bulkWriteOperations.length} props`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addChangedKeysToOp(op, keys, original, changed) {
|
function addChangedKeysToOp(op, keys, original, changed) {
|
||||||
@@ -79,10 +81,10 @@ function addUnsetOp(op, key){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use this instead of bulkWriteProperties because it functions with latency
|
// If we re-enable client-side sheet recalculation, this needs to be run on
|
||||||
// compensation without needing to roll back changes, which causes multiple
|
// both client and server to preserve latency compensation. Bulkwrite breaks
|
||||||
// expensive redraws of the character sheet
|
// latency compensation and causes flickering
|
||||||
function writePropertiesSequentially(bulkWriteOps){
|
function writePropertiesSequentially(bulkWriteOps) {
|
||||||
bulkWriteOps.forEach(op => {
|
bulkWriteOps.forEach(op => {
|
||||||
let updateOneOrMany = op.updateOne || op.updateMany;
|
let updateOneOrMany = op.updateOne || op.updateMany;
|
||||||
CreatureProperties.update(updateOneOrMany.filter, updateOneOrMany.update, {
|
CreatureProperties.update(updateOneOrMany.filter, updateOneOrMany.update, {
|
||||||
@@ -101,7 +103,7 @@ function writePropertiesSequentially(bulkWriteOps){
|
|||||||
function bulkWriteProperties(bulkWriteOps){
|
function bulkWriteProperties(bulkWriteOps){
|
||||||
if (!bulkWriteOps.length) return;
|
if (!bulkWriteOps.length) return;
|
||||||
// bulkWrite is only available on the server
|
// bulkWrite is only available on the server
|
||||||
if (Meteor.isServer){
|
if (Meteor.isServer) {
|
||||||
CreatureProperties.rawCollection().bulkWrite(
|
CreatureProperties.rawCollection().bulkWrite(
|
||||||
bulkWriteOps,
|
bulkWriteOps,
|
||||||
{ordered : false},
|
{ordered : false},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import buildCreatureComputation from './computation/buildCreatureComputation.js';
|
import buildCreatureComputation, { buildDependencyGroupComputation } from './computation/buildCreatureComputation.js';
|
||||||
import computeCreatureComputation from './computation/computeCreatureComputation.js';
|
import computeCreatureComputation from './computation/computeCreatureComputation.js';
|
||||||
import writeAlteredProperties from './computation/writeComputation/writeAlteredProperties.js';
|
import writeAlteredProperties from './computation/writeComputation/writeAlteredProperties.js';
|
||||||
import writeScope from './computation/writeComputation/writeScope.js';
|
import writeScope from './computation/writeComputation/writeScope.js';
|
||||||
@@ -7,21 +7,31 @@ import writeErrors from './computation/writeComputation/writeErrors.js';
|
|||||||
export default function computeCreature(creatureId){
|
export default function computeCreature(creatureId){
|
||||||
if (Meteor.isClient) return;
|
if (Meteor.isClient) return;
|
||||||
const computation = buildCreatureComputation(creatureId);
|
const computation = buildCreatureComputation(creatureId);
|
||||||
|
computeComputation(computation, creatureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recompute only some groups of the dependency tree
|
||||||
|
export function computeCreatureDependencyGroup(depGroupIds, creatureId) {
|
||||||
|
const computation = buildDependencyGroupComputation(depGroupIds, creatureId);
|
||||||
|
computeComputation(computation, creatureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeComputation(computation, creatureId) {
|
||||||
try {
|
try {
|
||||||
computeCreatureComputation(computation);
|
computeCreatureComputation(computation);
|
||||||
writeAlteredProperties(computation);
|
writeAlteredProperties(computation);
|
||||||
writeScope(creatureId, computation.scope);
|
writeScope(creatureId, computation.scope);
|
||||||
} catch (e){
|
} catch (e) {
|
||||||
const errorText = e.reason || e.message || e.toString();
|
const errorText = e.reason || e.message || e.toString();
|
||||||
computation.errors.push({
|
computation.errors.push({
|
||||||
type: 'crash',
|
type: 'crash',
|
||||||
details: {error: errorText},
|
details: { error: errorText },
|
||||||
});
|
});
|
||||||
const logError = {
|
const logError = {
|
||||||
creatureId,
|
creatureId,
|
||||||
computeError: errorText,
|
computeError: errorText,
|
||||||
};
|
};
|
||||||
if (e.stack){
|
if (e.stack) {
|
||||||
logError.location = e.stack.split('\n')[1];
|
logError.location = e.stack.split('\n')[1];
|
||||||
}
|
}
|
||||||
console.error(logError);
|
console.error(logError);
|
||||||
@@ -29,10 +39,3 @@ export default function computeCreature(creatureId){
|
|||||||
writeErrors(creatureId, computation.errors);
|
writeErrors(creatureId, computation.errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now just recompute the whole creature, TODO only recompute a single
|
|
||||||
// connected section of the depdendency graph
|
|
||||||
export function computeCreatureDependencyGroup(property){
|
|
||||||
let creatureId = property.ancestors[0].id;
|
|
||||||
computeCreature(creatureId);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"author": "Stefan Zermatten",
|
"author": "Stefan Zermatten",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"run": "meteor",
|
"run": "meteor",
|
||||||
|
"debug": "meteor debug",
|
||||||
"test": "meteor test --driver-package meteortesting:mocha --port 3001"
|
"test": "meteor test --driver-package meteortesting:mocha --port 3001"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -13,3 +13,5 @@ import '/imports/api/engine/actions/index.js';
|
|||||||
import '/imports/migrations/server/index.js';
|
import '/imports/migrations/server/index.js';
|
||||||
import '/imports/migrations/methods/index.js'
|
import '/imports/migrations/methods/index.js'
|
||||||
import '/imports/constants/MAINTENANCE_MODE.js';
|
import '/imports/constants/MAINTENANCE_MODE.js';
|
||||||
|
import '/imports/api/creature/creatureProperties/methods/index.js';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user