Migrated loadCreatures to nested sets
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { findLast, difference, intersection, filter } from 'lodash';
|
import { findLast, difference, intersection, filter } from 'lodash';
|
||||||
import applyProperty from '../applyProperty';
|
import applyProperty from '../applyProperty';
|
||||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||||
import { getProperyAncestors, getPropertiesOfType } from '/imports/api/engine/loadCreatures';
|
import { getPropertyAncestors, getPropertiesOfType } from '/imports/api/engine/loadCreatures';
|
||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||||
import { softRemove } from '/imports/api/parenting/softRemove';
|
import { softRemove } from '/imports/api/parenting/softRemove';
|
||||||
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
import getEffectivePropTags from '/imports/api/engine/computation/utility/getEffectivePropTags';
|
||||||
@@ -21,7 +21,7 @@ export default function applyBuffRemover(node, actionContext) {
|
|||||||
// Remove buffs
|
// Remove buffs
|
||||||
if (prop.targetParentBuff) {
|
if (prop.targetParentBuff) {
|
||||||
// Remove nearest ancestor buff
|
// Remove nearest ancestor buff
|
||||||
const ancestors = getProperyAncestors(actionContext.creature._id, prop._id);
|
const ancestors = getPropertyAncestors(actionContext.creature._id, prop._id);
|
||||||
const nearestBuff = findLast(ancestors, ancestor => ancestor.type === 'buff');
|
const nearestBuff = findLast(ancestors, ancestor => ancestor.type === 'buff');
|
||||||
if (!nearestBuff) {
|
if (!nearestBuff) {
|
||||||
actionContext.addLog({
|
actionContext.addLog({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getPropertyDecendants } from '/imports/api/engine/loadCreatures';
|
import { getPropertyDescendants } from '/imports/api/engine/loadCreatures';
|
||||||
import applyProperty from '../applyProperty';
|
import applyProperty from '../applyProperty';
|
||||||
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
import { applyNodeTriggers } from '/imports/api/engine/actions/applyTriggers';
|
||||||
import { docsToForest as nodeArrayToTree } from '/imports/api/parenting/parentingFunctions';
|
import { docsToForest as nodeArrayToTree } from '/imports/api/parenting/parentingFunctions';
|
||||||
@@ -8,7 +8,7 @@ export default function applyItemAsAmmo(node, actionContext) {
|
|||||||
// The item node should come without children, since it is not part of the original action tree
|
// The item node should come without children, since it is not part of the original action tree
|
||||||
const prop = node.doc
|
const prop = node.doc
|
||||||
// Get all the item's descendant properties
|
// Get all the item's descendant properties
|
||||||
const properties = getPropertyDecendants(actionContext.creature._id, prop._id);
|
const properties = getPropertyDescendants(actionContext.creature._id, prop._id);
|
||||||
properties.sort((a, b) => a.order - b.order);
|
properties.sort((a, b) => a.order - b.order);
|
||||||
const propertyForest = nodeArrayToTree(properties);
|
const propertyForest = nodeArrayToTree(properties);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation';
|
import recalculateCalculation from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateCalculation';
|
||||||
import recalculateInlineCalculations from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateInlineCalculations';
|
import recalculateInlineCalculations from '/imports/api/engine/actions/applyPropertyByType/shared/recalculateInlineCalculations';
|
||||||
import { getPropertyDecendants } from '/imports/api/engine/loadCreatures';
|
import { getPropertyDescendants } from '/imports/api/engine/loadCreatures';
|
||||||
import { TreeNode, docsToForest as nodeArrayToTree } from '/imports/api/parenting/parentingFunctions';
|
import { TreeNode, docsToForest as nodeArrayToTree } from '/imports/api/parenting/parentingFunctions';
|
||||||
import applyProperty from '/imports/api/engine/actions/applyProperty';
|
import applyProperty from '/imports/api/engine/actions/applyProperty';
|
||||||
import { difference, intersection } from 'lodash';
|
import { difference, intersection } from 'lodash';
|
||||||
@@ -68,7 +68,7 @@ export function applyTrigger(trigger, prop, actionContext) {
|
|||||||
if (!trigger.silent) actionContext.addLog(content);
|
if (!trigger.silent) actionContext.addLog(content);
|
||||||
|
|
||||||
// Get all the trigger's properties and apply them
|
// Get all the trigger's properties and apply them
|
||||||
const properties = getPropertyDecendants(actionContext.creature._id, trigger._id);
|
const properties = getPropertyDescendants(actionContext.creature._id, trigger._id);
|
||||||
properties.sort((a, b) => a.order - b.order);
|
properties.sort((a, b) => a.order - b.order);
|
||||||
const propertyForest = nodeArrayToTree(properties);
|
const propertyForest = nodeArrayToTree(properties);
|
||||||
propertyForest.forEach(node => {
|
propertyForest.forEach(node => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
|||||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
||||||
import { docsToForest } from '/imports/api/parenting/parentingFunctions';
|
import { docsToForest } from '/imports/api/parenting/parentingFunctions';
|
||||||
import {
|
import {
|
||||||
getProperyAncestors, getPropertyDecendants
|
getPropertyAncestors, getPropertyDescendants
|
||||||
} from '/imports/api/engine/loadCreatures';
|
} from '/imports/api/engine/loadCreatures';
|
||||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||||
@@ -49,10 +49,10 @@ const doAction = new ValidatedMethod({
|
|||||||
assertEditPermission(target, this.userId);
|
assertEditPermission(target, this.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
const ancestors = getProperyAncestors(creatureId, action._id);
|
const ancestors = getPropertyAncestors(creatureId, action._id);
|
||||||
ancestors.sort((a, b) => a.order - b.order);
|
ancestors.sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
const properties = getPropertyDecendants(creatureId, action._id);
|
const properties = getPropertyDescendants(creatureId, action._id);
|
||||||
properties.push(action);
|
properties.push(action);
|
||||||
properties.sort((a, b) => a.order - b.order);
|
properties.sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
|||||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||||
import {
|
import {
|
||||||
getProperyAncestors, getPropertyDecendants
|
getPropertyAncestors, getPropertyDescendants
|
||||||
} from '/imports/api/engine/loadCreatures';
|
} from '/imports/api/engine/loadCreatures';
|
||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||||
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions';
|
||||||
@@ -57,10 +57,10 @@ const doAction = new ValidatedMethod({
|
|||||||
assertEditPermission(target, this.userId);
|
assertEditPermission(target, this.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
const ancestors = getProperyAncestors(creatureId, spell._id);
|
const ancestors = getPropertyAncestors(creatureId, spell._id);
|
||||||
ancestors.sort((a, b) => a.order - b.order);
|
ancestors.sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
const properties = getPropertyDecendants(creatureId, spell._id);
|
const properties = getPropertyDescendants(creatureId, spell._id);
|
||||||
properties.push(spell);
|
properties.push(spell);
|
||||||
properties.sort((a, b) => a.order - b.order);
|
properties.sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import Creatures from '/imports/api/creature/creatures/Creatures';
|
import Creatures from '/imports/api/creature/creatures/Creatures';
|
||||||
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables';
|
||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
|
import CreatureProperties, { CreatureProperty } from '/imports/api/creature/creatureProperties/CreatureProperties';
|
||||||
import computeCreature from './computeCreature';
|
import computeCreature from './computeCreature';
|
||||||
|
import { getFilter } from '/imports/api/parenting/parentingFunctions';
|
||||||
|
|
||||||
const COMPUTE_DEBOUNCE_TIME = 100; // ms
|
const COMPUTE_DEBOUNCE_TIME = 100; // ms
|
||||||
export const loadedCreatures = new Map(); // creatureId => {creature, properties, etc.}
|
export const loadedCreatures: Map<string, LoadedCreature> = new Map(); // creatureId => {creature, properties, etc.}
|
||||||
// TODO: migrate to nested sets
|
// TODO: migrate to nested sets
|
||||||
|
|
||||||
export function loadCreature(creatureId, subscription) {
|
export function loadCreature(creatureId: string, subscription: Tracker.Computation) {
|
||||||
if (!creatureId) throw 'creatureId is required';
|
if (!creatureId) throw 'creatureId is required';
|
||||||
let creature = loadedCreatures.get(creatureId);
|
let creature = loadedCreatures.get(creatureId);
|
||||||
if (loadedCreatures.has(creatureId)) {
|
if (creature) {
|
||||||
creature.subs.add(subscription);
|
creature.subs.add(subscription);
|
||||||
} else {
|
} else {
|
||||||
creature = new LoadedCreature(subscription, creatureId);
|
creature = new LoadedCreature(subscription, creatureId);
|
||||||
@@ -33,75 +34,67 @@ function unloadCreature(creatureId, subscription) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSingleProperty(creatureId, propertyId) {
|
export function getSingleProperty(creatureId: string, propertyId: string) {
|
||||||
if (loadedCreatures.has(creatureId)) {
|
const creature = loadedCreatures.get(creatureId)
|
||||||
const creature = loadedCreatures.get(creatureId);
|
const property = creature?.properties.get(propertyId);
|
||||||
const property = creature.properties.get(propertyId);
|
if (property) {
|
||||||
const cloneProp = EJSON.clone(property);
|
return EJSON.clone(property);
|
||||||
return cloneProp;
|
|
||||||
}
|
}
|
||||||
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
||||||
const prop = CreatureProperties.findOne({
|
const prop = CreatureProperties.findOne({
|
||||||
_id: propertyId,
|
_id: propertyId,
|
||||||
'ancestors.id': creatureId,
|
'root.id': creatureId,
|
||||||
'removed': { $ne: true },
|
'removed': { $ne: true },
|
||||||
}, {
|
|
||||||
sort: { order: 1 },
|
|
||||||
});
|
});
|
||||||
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProperties(creatureId) {
|
export function getProperties(creatureId) {
|
||||||
if (loadedCreatures.has(creatureId)) {
|
const creature = loadedCreatures.get(creatureId);
|
||||||
const creature = loadedCreatures.get(creatureId);
|
if (creature) {
|
||||||
const props = Array.from(creature.properties.values());
|
const props = Array.from(creature.properties.values());
|
||||||
const cloneProps = EJSON.clone(props);
|
return EJSON.clone(props);
|
||||||
return cloneProps
|
|
||||||
}
|
}
|
||||||
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
||||||
const props = CreatureProperties.find({
|
const props = CreatureProperties.find({
|
||||||
'ancestors.id': creatureId,
|
'root.id': creatureId,
|
||||||
'removed': { $ne: true },
|
'removed': { $ne: true },
|
||||||
}, {
|
}, {
|
||||||
sort: { order: 1 },
|
sort: { left: 1 },
|
||||||
}).fetch();
|
}).fetch();
|
||||||
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPropertiesOfType(creatureId, propType) {
|
export function getPropertiesOfType(creatureId, propType) {
|
||||||
if (loadedCreatures.has(creatureId)) {
|
const creature = loadedCreatures.get(creatureId);
|
||||||
const creature = loadedCreatures.get(creatureId);
|
if (creature) {
|
||||||
const props = []
|
const props: CreatureProperty[] = []
|
||||||
for (const prop of creature.properties.values()) {
|
for (const prop of creature.properties.values()) {
|
||||||
if (prop.type === propType) {
|
if (prop.type === propType) {
|
||||||
props.push(prop);
|
props.push(prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const cloneProps = EJSON.clone(props);
|
return EJSON.clone(props);
|
||||||
return cloneProps
|
|
||||||
}
|
}
|
||||||
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
// console.time(`Cache miss on creature properties: ${creatureId}`)
|
||||||
const props = CreatureProperties.find({
|
const props = CreatureProperties.find({
|
||||||
'ancestors.id': creatureId,
|
'root.id': creatureId,
|
||||||
'removed': { $ne: true },
|
'removed': { $ne: true },
|
||||||
'type': propType,
|
'type': propType,
|
||||||
}, {
|
}, {
|
||||||
sort: { order: 1 },
|
sort: { left: 1 },
|
||||||
}).fetch();
|
}).fetch();
|
||||||
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
// console.timeEnd(`Cache miss on creature properties: ${creatureId}`);
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCreature(creatureId) {
|
export function getCreature(creatureId) {
|
||||||
if (loadedCreatures.has(creatureId)) {
|
const loadedCreature = loadedCreatures.get(creatureId);
|
||||||
const loadedCreature = loadedCreatures.get(creatureId);
|
const loadedCreatureDoc = loadedCreature?.creature;
|
||||||
const creature = loadedCreature.creature;
|
if (loadedCreatureDoc) {
|
||||||
if (creature) {
|
return EJSON.clone(loadedCreatureDoc);
|
||||||
const cloneCreature = EJSON.clone(creature);
|
|
||||||
return cloneCreature;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// console.time(`Cache miss on Creature: ${creatureId}`);
|
// console.time(`Cache miss on Creature: ${creatureId}`);
|
||||||
const creature = Creatures.findOne(creatureId);
|
const creature = Creatures.findOne(creatureId);
|
||||||
@@ -110,13 +103,10 @@ export function getCreature(creatureId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getVariables(creatureId) {
|
export function getVariables(creatureId) {
|
||||||
if (loadedCreatures.has(creatureId)) {
|
const loadedCreature = loadedCreatures.get(creatureId);
|
||||||
const loadedCreature = loadedCreatures.get(creatureId);
|
const loadedVariables = loadedCreature?.variables;
|
||||||
const variables = loadedCreature.variables;
|
if (loadedVariables) {
|
||||||
if (variables) {
|
return EJSON.clone(loadedVariables);
|
||||||
const cloneVarables = EJSON.clone(variables);
|
|
||||||
return cloneVarables;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// console.time(`Cache miss on variables: ${creatureId}`);
|
// console.time(`Cache miss on variables: ${creatureId}`);
|
||||||
const variables = CreatureVariables.findOne({ _creatureId: creatureId });
|
const variables = CreatureVariables.findOne({ _creatureId: creatureId });
|
||||||
@@ -124,49 +114,44 @@ export function getVariables(creatureId) {
|
|||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProperyAncestors(creatureId, propertyId) {
|
export function getPropertyAncestors(creatureId: string, propertyId: string) {
|
||||||
const prop = getSingleProperty(creatureId, propertyId);
|
const prop = getSingleProperty(creatureId, propertyId);
|
||||||
if (!prop) return [];
|
if (!prop) return [];
|
||||||
const ancestorIds = [];
|
const loadedCreature = loadedCreatures.get(creatureId);
|
||||||
prop.ancestors.forEach(ref => {
|
if (loadedCreature) {
|
||||||
if (ref.collection === 'creatureProperties') {
|
|
||||||
ancestorIds.push(ref.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (loadedCreatures.has(creatureId)) {
|
|
||||||
// Get the ancestor properties from the cache
|
// Get the ancestor properties from the cache
|
||||||
const creature = loadedCreatures.get(creatureId);
|
const props: CreatureProperty[] = [];
|
||||||
const props = [];
|
let currentProp: CreatureProperty | undefined = prop;
|
||||||
ancestorIds.forEach(id => {
|
// Iterate through parent chain to get all linked ancestors
|
||||||
const prop = creature.properties.get(id);
|
while (currentProp?.parentId) {
|
||||||
if (prop) {
|
currentProp = getSingleProperty(creatureId, currentProp.parentId);
|
||||||
props.push(prop);
|
if (currentProp) props.push(currentProp);
|
||||||
}
|
}
|
||||||
});
|
return EJSON.clone(props);
|
||||||
const cloneProps = EJSON.clone(props);
|
|
||||||
return cloneProps
|
|
||||||
} else {
|
} else {
|
||||||
// Fetch from database
|
// Fetch from database
|
||||||
return CreatureProperties.find({
|
return CreatureProperties.find({
|
||||||
_id: { $in: ancestorIds },
|
...getFilter.ancestors(prop),
|
||||||
removed: { $ne: true },
|
removed: { $ne: true },
|
||||||
}, {
|
}, {
|
||||||
sort: { order: 1 },
|
sort: { left: 1 }
|
||||||
}).fetch();
|
}).fetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPropertyDecendants(creatureId, propertyId) {
|
export function getPropertyDescendants(creatureId, propertyId) {
|
||||||
const property = getSingleProperty(creatureId, propertyId);
|
const property = getSingleProperty(creatureId, propertyId);
|
||||||
if (!property) return [];
|
if (!property) return [];
|
||||||
// This prop will always appear at the same position in the ancestor array
|
|
||||||
// of its decendants, so only check there
|
|
||||||
const expectedAncestorPostition = property.ancestors.length;
|
|
||||||
if (loadedCreatures.has(creatureId)) {
|
if (loadedCreatures.has(creatureId)) {
|
||||||
const creature = loadedCreatures.get(creatureId);
|
const creature = loadedCreatures.get(creatureId);
|
||||||
const props = [];
|
if (!creature) return [];
|
||||||
|
const props: CreatureProperty[] = [];
|
||||||
|
// Loop through all properties and find ones that match the nested set condition
|
||||||
for (const prop of creature.properties.values()) {
|
for (const prop of creature.properties.values()) {
|
||||||
if (prop.ancestors[expectedAncestorPostition]?.id === propertyId) {
|
if (
|
||||||
|
prop.left > property.left
|
||||||
|
&& prop.right < property.right
|
||||||
|
) {
|
||||||
props.push(prop);
|
props.push(prop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,23 +159,30 @@ export function getPropertyDecendants(creatureId, propertyId) {
|
|||||||
return cloneProps
|
return cloneProps
|
||||||
} else {
|
} else {
|
||||||
return CreatureProperties.find({
|
return CreatureProperties.find({
|
||||||
'ancestors.id': propertyId,
|
...getFilter.descendants(property),
|
||||||
removed: { $ne: true },
|
removed: { $ne: true },
|
||||||
}, {
|
}, {
|
||||||
sort: { order: 1 },
|
sort: { left: 1 },
|
||||||
}).fetch();
|
}).fetch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadedCreature {
|
class LoadedCreature {
|
||||||
|
subs: Set<Tracker.Computation>;
|
||||||
|
propertyObserver: Meteor.LiveQueryHandle;
|
||||||
|
creatureObserver: Meteor.LiveQueryHandle;
|
||||||
|
variablesObserver: Meteor.LiveQueryHandle;
|
||||||
|
properties: Map<string, CreatureProperty>;
|
||||||
|
creature: any;
|
||||||
|
variables: any;
|
||||||
|
|
||||||
constructor(sub, creatureId) {
|
constructor(sub, creatureId) {
|
||||||
|
const self = this;
|
||||||
// This may be called from a subscription, but we don't want the observers
|
// This may be called from a subscription, but we don't want the observers
|
||||||
// to be destroyed with it, so use a non-reactive context to observe
|
// to be destroyed with it, so use a non-reactive context to observe
|
||||||
// the required documents
|
// the required documents
|
||||||
const self = this;
|
|
||||||
Tracker.nonreactive(() => {
|
Tracker.nonreactive(() => {
|
||||||
self.subs = new Set([sub]);
|
self.subs = new Set([sub]);
|
||||||
|
|
||||||
const compute = debounce(Meteor.bindEnvironment(() => {
|
const compute = debounce(Meteor.bindEnvironment(() => {
|
||||||
computeCreature(creatureId);
|
computeCreature(creatureId);
|
||||||
}), COMPUTE_DEBOUNCE_TIME);
|
}), COMPUTE_DEBOUNCE_TIME);
|
||||||
@@ -231,8 +223,8 @@ class LoadedCreature {
|
|||||||
self.changeCreature(id, fields);
|
self.changeCreature(id, fields);
|
||||||
if (fields.dirty) compute();
|
if (fields.dirty) compute();
|
||||||
},
|
},
|
||||||
removed(id) {
|
removed() {
|
||||||
self.removeCreature(id);
|
self.removeCreature();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -249,8 +241,8 @@ class LoadedCreature {
|
|||||||
changed(id, fields) {
|
changed(id, fields) {
|
||||||
self.changeVariables(id, fields);
|
self.changeVariables(id, fields);
|
||||||
},
|
},
|
||||||
removed(id) {
|
removed() {
|
||||||
self.removeVariables(id);
|
self.removeVariables();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -293,7 +285,7 @@ class LoadedCreature {
|
|||||||
}
|
}
|
||||||
static changeDoc(doc, fields) {
|
static changeDoc(doc, fields) {
|
||||||
if (!doc) return;
|
if (!doc) return;
|
||||||
for (let key in fields) {
|
for (const key in fields) {
|
||||||
if (key === undefined) {
|
if (key === undefined) {
|
||||||
delete doc[key];
|
delete doc[key];
|
||||||
} else {
|
} else {
|
||||||
@@ -1,6 +1,19 @@
|
|||||||
import SimpleSchema from 'simpl-schema';
|
import SimpleSchema from 'simpl-schema';
|
||||||
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS';
|
||||||
|
|
||||||
|
export interface Reference {
|
||||||
|
collection: string,
|
||||||
|
id: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TreeDoc {
|
||||||
|
_id: string,
|
||||||
|
root: Reference,
|
||||||
|
parentId?: string,
|
||||||
|
left: number,
|
||||||
|
right: number,
|
||||||
|
}
|
||||||
|
|
||||||
const RefSchema = new SimpleSchema({
|
const RefSchema = new SimpleSchema({
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -57,19 +70,6 @@ const ChildSchema = new SimpleSchema({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface Reference {
|
|
||||||
collection: string,
|
|
||||||
id: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TreeDoc {
|
|
||||||
_id: string,
|
|
||||||
root: Reference,
|
|
||||||
parentId?: string,
|
|
||||||
left: number,
|
|
||||||
right: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const treeDocFields = {
|
export const treeDocFields = {
|
||||||
_id: 1,
|
_id: 1,
|
||||||
root: 1,
|
root: 1,
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ type FilteredDoc = {
|
|||||||
export default async function filterToForest(
|
export default async function filterToForest(
|
||||||
collection: Mongo.Collection<TreeDoc>,
|
collection: Mongo.Collection<TreeDoc>,
|
||||||
rootId: string,
|
rootId: string,
|
||||||
filter: Mongo.Query<TreeDoc>,
|
filter: Mongo.Selector<TreeDoc>,
|
||||||
options: Mongo.Options<object> = {},
|
options: Mongo.Options<object> = {},
|
||||||
includeFilteredDocAncestors = false,
|
includeFilteredDocAncestors = false,
|
||||||
includeFilteredDocDescendants = false
|
includeFilteredDocDescendants = false
|
||||||
@@ -200,14 +200,14 @@ export const getFilter = {
|
|||||||
* @param doc A document or array of documents that share a root
|
* @param doc A document or array of documents that share a root
|
||||||
* @returns A query filter that finds all the ancestors of the doc(s)
|
* @returns A query filter that finds all the ancestors of the doc(s)
|
||||||
*/
|
*/
|
||||||
ancestors(doc: TreeDoc): Mongo.Query<TreeDoc> {
|
ancestors(doc: TreeDoc) {
|
||||||
return {
|
return {
|
||||||
'root.id': doc.root.id,
|
'root.id': doc.root.id,
|
||||||
left: { $lt: doc.left },
|
left: { $lt: doc.left },
|
||||||
right: { $gt: doc.right },
|
right: { $gt: doc.right },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
ancestorsOfAll(docs: Array<TreeDoc>): Mongo.Query<TreeDoc> {
|
ancestorsOfAll(docs: Array<TreeDoc>) {
|
||||||
// The ancestors of no documents is a query that returns nothing
|
// The ancestors of no documents is a query that returns nothing
|
||||||
if (docs.length === 0) {
|
if (docs.length === 0) {
|
||||||
return { _id: '' };
|
return { _id: '' };
|
||||||
@@ -229,14 +229,14 @@ export const getFilter = {
|
|||||||
});
|
});
|
||||||
return filter;
|
return filter;
|
||||||
},
|
},
|
||||||
descendants(doc: TreeDoc): Mongo.Query<TreeDoc> {
|
descendants(doc: TreeDoc) {
|
||||||
return {
|
return {
|
||||||
'root.id': doc.root.id,
|
'root.id': doc.root.id,
|
||||||
left: { $gt: doc.left },
|
left: { $gt: doc.left },
|
||||||
right: { $lt: doc.right },
|
right: { $lt: doc.right },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
descendantsOfAll(docs: Array<TreeDoc>): Mongo.Query<TreeDoc> {
|
descendantsOfAll(docs: Array<TreeDoc>) {
|
||||||
// The descendants of no documents is a query that returns nothing
|
// The descendants of no documents is a query that returns nothing
|
||||||
if (docs.length === 0) {
|
if (docs.length === 0) {
|
||||||
return { _id: '' };
|
return { _id: '' };
|
||||||
@@ -248,7 +248,10 @@ export const getFilter = {
|
|||||||
// Build a filter that selects all descendants
|
// Build a filter that selects all descendants
|
||||||
const filter = {
|
const filter = {
|
||||||
'root.id': docs[0].root.id,
|
'root.id': docs[0].root.id,
|
||||||
$or: <object[]>[],
|
$or: <{
|
||||||
|
left: { $gt: number },
|
||||||
|
right: { $lt: number },
|
||||||
|
}[]>[],
|
||||||
};
|
};
|
||||||
docs.forEach(doc => {
|
docs.forEach(doc => {
|
||||||
filter.$or.push({
|
filter.$or.push({
|
||||||
@@ -258,13 +261,13 @@ export const getFilter = {
|
|||||||
});
|
});
|
||||||
return filter;
|
return filter;
|
||||||
},
|
},
|
||||||
children(doc: TreeDoc): Mongo.Query<TreeDoc> {
|
children(doc: TreeDoc) {
|
||||||
return {
|
return {
|
||||||
'root.id': doc.root.id,
|
'root.id': doc.root.id,
|
||||||
parentId: doc._id,
|
parentId: doc._id,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
parent(doc: TreeDoc): Mongo.Query<TreeDoc> {
|
parent(doc: TreeDoc) {
|
||||||
return {
|
return {
|
||||||
_id: doc.parentId,
|
_id: doc.parentId,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -123,7 +123,8 @@
|
|||||||
"quotes": [
|
"quotes": [
|
||||||
"error",
|
"error",
|
||||||
"single"
|
"single"
|
||||||
]
|
],
|
||||||
|
"@typescript-eslint/no-this-alias": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user