Condensed logs to a single card per action
This commit is contained in:
@@ -1,11 +1,9 @@
|
|||||||
import spendResources from '/imports/api/creature/actions/spendResources.js'
|
import spendResources from '/imports/api/creature/actions/spendResources.js'
|
||||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
|
||||||
|
|
||||||
export default function applyAction({prop, creature}){
|
export default function applyAction({prop, log}){
|
||||||
spendResources(prop);
|
spendResources(prop);
|
||||||
insertCreatureLog.call({
|
// If this is not the top level action, we can add its name to the log
|
||||||
log: {
|
if (log.content.length){
|
||||||
text: prop.name,
|
log.content.push({name: prop.name});
|
||||||
creatureId: creature._id},
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
||||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
|
||||||
import damagePropertiesByName from '/imports/api/creature/creatureProperties/methods/damagePropertiesByName.js';
|
import damagePropertiesByName from '/imports/api/creature/creatureProperties/methods/damagePropertiesByName.js';
|
||||||
|
|
||||||
export default function applyAdjustment({
|
export default function applyAdjustment({
|
||||||
prop,
|
prop,
|
||||||
creature,
|
creature,
|
||||||
targets,
|
targets,
|
||||||
actionContext
|
actionContext,
|
||||||
|
log
|
||||||
}){
|
}){
|
||||||
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
||||||
let scope = {
|
let scope = {
|
||||||
@@ -16,16 +16,10 @@ export default function applyAdjustment({
|
|||||||
try {
|
try {
|
||||||
var {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
var {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
||||||
if (typeof result !== 'number') {
|
if (typeof result !== 'number') {
|
||||||
return insertCreatureLog.call({ log: {
|
log.content.push({error: errors.join(', ') || 'Something went wrong'});
|
||||||
text: errors.join(', ') || 'Something went wrong',
|
|
||||||
creatureId: creature._id,
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
} catch (e){
|
} catch (e){
|
||||||
return insertCreatureLog.call({ log: {
|
log.content.push({error: e.toString()});
|
||||||
text: e.toString(),
|
|
||||||
creatureId: creature._id,
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
if (damageTargets) {
|
if (damageTargets) {
|
||||||
damageTargets.forEach(target => {
|
damageTargets.forEach(target => {
|
||||||
@@ -38,19 +32,15 @@ export default function applyAdjustment({
|
|||||||
operation: prop.operation || 'increment',
|
operation: prop.operation || 'increment',
|
||||||
value: result
|
value: result
|
||||||
});
|
});
|
||||||
insertCreatureLog.call({
|
log.content.push({
|
||||||
log: {
|
resultPrefix: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''}`,
|
||||||
text: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''} ${-result}`,
|
result: `${-result}`,
|
||||||
creatureId: target._id,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
insertCreatureLog.call({
|
log.content.push({
|
||||||
log: {
|
resultPrefix: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''}`,
|
||||||
text: `${prop.stat} ${prop.operation === 'set' ? 'set to' : ''} ${-result}`,
|
result: `${-result}`,
|
||||||
creatureId: creature._id,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
import roll from '/imports/parser/roll.js';
|
import roll from '/imports/parser/roll.js';
|
||||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
|
||||||
|
|
||||||
export default function applyAttack({
|
export default function applyAttack({
|
||||||
prop,
|
prop,
|
||||||
//children,
|
log,
|
||||||
creature,
|
|
||||||
//targets,
|
|
||||||
//actionContext
|
|
||||||
}){
|
}){
|
||||||
let result = roll(1, 20)[0] + prop.rollBonusResult;
|
let result = roll(1, 20)[0] + prop.rollBonusResult;
|
||||||
insertCreatureLog.call({
|
log.content.push({
|
||||||
log: {
|
// If this is not the first item in the log content, give it a name
|
||||||
text: `${prop.name} attack. ${result} to hit`,
|
name: log.content.length ? prop.name + ' attack' : undefined,
|
||||||
creatureId: creature._id,
|
result,
|
||||||
}
|
details: 'to hit',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
import evaluateString from '/imports/api/creature/computation/afterComputation/evaluateString.js';
|
||||||
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
|
||||||
import dealDamage from '/imports/api/creature/creatureProperties/methods/dealDamage.js';
|
import dealDamage from '/imports/api/creature/creatureProperties/methods/dealDamage.js';
|
||||||
|
import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js';
|
||||||
|
|
||||||
export default function applyDamage({
|
export default function applyDamage({
|
||||||
prop,
|
prop,
|
||||||
creature,
|
creature,
|
||||||
targets,
|
targets,
|
||||||
actionContext
|
actionContext,
|
||||||
|
log,
|
||||||
}){
|
}){
|
||||||
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
let damageTargets = prop.target === 'self' ? [creature] : targets;
|
||||||
let scope = {
|
let scope = {
|
||||||
@@ -16,18 +17,16 @@ export default function applyDamage({
|
|||||||
try {
|
try {
|
||||||
var {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
var {result, errors} = evaluateString(prop.amount, scope, 'reduce');
|
||||||
if (typeof result !== 'number') {
|
if (typeof result !== 'number') {
|
||||||
return insertCreatureLog.call({ log: {
|
log.content.push({
|
||||||
text: errors.join(', '),
|
error: errors.join(', '),
|
||||||
creatureId: creature._id,
|
});
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
} catch (e){
|
} catch (e){
|
||||||
return insertCreatureLog.call({ log: {
|
log.content.push({
|
||||||
text: e.toString(),
|
error: e.toString(),
|
||||||
creatureId: creature._id,
|
});
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
if (damageTargets) {
|
if (damageTargets && damageTargets.length) {
|
||||||
damageTargets.forEach(target => {
|
damageTargets.forEach(target => {
|
||||||
if (prop.target === 'each'){
|
if (prop.target === 'each'){
|
||||||
result = evaluateString(prop.amount, scope, 'reduce');
|
result = evaluateString(prop.amount, scope, 'reduce');
|
||||||
@@ -44,20 +43,17 @@ export default function applyDamage({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (target._id !== creature._id){
|
if (target._id !== creature._id){
|
||||||
insertCreatureLog.call({
|
log.content.push({
|
||||||
log: {
|
result: damageDealt,
|
||||||
text: `Dealt ${damageDealt} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
details: `${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}` +
|
||||||
creatureId: creature._id,
|
`${target.name && ' to '}${target.name}`,
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
insertCreatureLog.call({
|
log.content.push({
|
||||||
log: {
|
result,
|
||||||
text: `${result} ${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
details: `${prop.damageType}${prop.damageType !== 'healing'? ' damage': ''}`,
|
||||||
creatureId: creature._id,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,46 +6,49 @@ import applyBuff from '/imports/api/creature/actions/applyBuff.js';
|
|||||||
|
|
||||||
function applyProperty(options){
|
function applyProperty(options){
|
||||||
let prop = options.prop;
|
let prop = options.prop;
|
||||||
if (
|
if (prop.type === 'buff'){
|
||||||
prop.disabled === true || // ignore disabled props
|
// ignore only applied buffs
|
||||||
prop.equipped === false || // ignore unequipped items
|
if (prop.applied === true){
|
||||||
prop.toggleResult === false || // ignore untoggled toggles
|
return false;
|
||||||
prop.applied === true // ignore buffs that are already applied
|
}
|
||||||
){
|
// Ignore inactive props of other types
|
||||||
|
} else if (prop.inactive === true){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (prop.type){
|
switch (prop.type){
|
||||||
case 'action':
|
case 'action':
|
||||||
case 'spell':
|
case 'spell':
|
||||||
applyAction(options);
|
applyAction(options);
|
||||||
return true;
|
break;
|
||||||
case 'attack':
|
case 'attack':
|
||||||
applyAction(options);
|
applyAction(options);
|
||||||
applyAttack(options);
|
applyAttack(options);
|
||||||
return true;
|
break;
|
||||||
case 'damage':
|
case 'damage':
|
||||||
applyDamage(options);
|
applyDamage(options);
|
||||||
return true;
|
break;
|
||||||
case 'adjustment':
|
case 'adjustment':
|
||||||
applyAdjustment(options);
|
applyAdjustment(options);
|
||||||
return true;
|
break;
|
||||||
case 'buff':
|
case 'buff':
|
||||||
applyBuff(options);
|
applyBuff(options);
|
||||||
return false;
|
break;
|
||||||
case 'roll':
|
case 'roll':
|
||||||
// applyRoll(options);
|
// applyRoll(options);
|
||||||
return true;
|
break;
|
||||||
case 'savingThrow':
|
case 'savingThrow':
|
||||||
// applySavingThrow(options);
|
// applySavingThrow(options);
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function applyProperties({
|
export default function applyProperties({
|
||||||
forest,
|
forest,
|
||||||
creature,
|
creature,
|
||||||
targets,
|
targets,
|
||||||
actionContext
|
actionContext,
|
||||||
|
log,
|
||||||
}){
|
}){
|
||||||
forest.forEach(child => {
|
forest.forEach(child => {
|
||||||
let walkChildren = applyProperty({
|
let walkChildren = applyProperty({
|
||||||
@@ -53,14 +56,16 @@ export default function applyProperties({
|
|||||||
children: child.children,
|
children: child.children,
|
||||||
creature,
|
creature,
|
||||||
targets,
|
targets,
|
||||||
actionContext
|
actionContext,
|
||||||
|
log,
|
||||||
});
|
});
|
||||||
if (walkChildren){
|
if (walkChildren){
|
||||||
applyProperties({
|
applyProperties({
|
||||||
forest: child.children,
|
forest: child.children,
|
||||||
creature,
|
creature,
|
||||||
targets,
|
targets,
|
||||||
actionContext
|
actionContext,
|
||||||
|
log,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ const castSpellWithSlot = new ValidatedMethod({
|
|||||||
context: {slotLevel},
|
context: {slotLevel},
|
||||||
creature,
|
creature,
|
||||||
target,
|
target,
|
||||||
|
method: this,
|
||||||
});
|
});
|
||||||
// Note this only recomputes the top-level creature, not the nearest one
|
// Note this only recomputes the top-level creature, not the nearest one
|
||||||
recomputeCreatureByDoc(creature);
|
recomputeCreatureByDoc(creature);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
|||||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||||
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
|
||||||
import Creatures from '/imports/api/creature/Creatures.js';
|
import Creatures from '/imports/api/creature/Creatures.js';
|
||||||
|
import CreatureLogs, { CreatureLogSchema, insertCreatureLogWork } from '/imports/api/creature/log/CreatureLogs.js';
|
||||||
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js';
|
||||||
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
||||||
import { recomputeCreatureByDoc } from '/imports/api/creature/computation/methods/recomputeCreature.js';
|
import { recomputeCreatureByDoc } from '/imports/api/creature/computation/methods/recomputeCreature.js';
|
||||||
@@ -13,10 +14,15 @@ const doAction = new ValidatedMethod({
|
|||||||
name: 'creatureProperties.doAction',
|
name: 'creatureProperties.doAction',
|
||||||
validate: new SimpleSchema({
|
validate: new SimpleSchema({
|
||||||
actionId: SimpleSchema.RegEx.Id,
|
actionId: SimpleSchema.RegEx.Id,
|
||||||
targetId: {
|
targetIds: {
|
||||||
|
type: Array,
|
||||||
|
defaultValue: [],
|
||||||
|
maxCount: 10,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
'targetIds.$': {
|
||||||
type: String,
|
type: String,
|
||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
optional: true,
|
|
||||||
},
|
},
|
||||||
}).validator(),
|
}).validator(),
|
||||||
mixins: [RateLimiterMixin],
|
mixins: [RateLimiterMixin],
|
||||||
@@ -24,26 +30,41 @@ const doAction = new ValidatedMethod({
|
|||||||
numRequests: 10,
|
numRequests: 10,
|
||||||
timeInterval: 5000,
|
timeInterval: 5000,
|
||||||
},
|
},
|
||||||
run({actionId, targetId}) {
|
run({actionId, targetIds = []}) {
|
||||||
let action = CreatureProperties.findOne(actionId);
|
let action = CreatureProperties.findOne(actionId);
|
||||||
// Check permissions
|
// Check permissions
|
||||||
let creature = getRootCreatureAncestor(action);
|
let creature = getRootCreatureAncestor(action);
|
||||||
assertEditPermission(creature, this.userId);
|
assertEditPermission(creature, this.userId);
|
||||||
let target = undefined;
|
let targets = [];
|
||||||
if (targetId) {
|
targetIds.forEach(targetId => {
|
||||||
target = Creatures.findOne(targetId);
|
let target = Creatures.findOne(targetId);
|
||||||
assertEditPermission(target, this.userId);
|
assertEditPermission(target, this.userId);
|
||||||
}
|
targets.push(target);
|
||||||
doActionWork({action, creature, target});
|
});
|
||||||
// Note this only recomputes the top-level creature, not the nearest one
|
doActionWork({action, creature, targets, method: this});
|
||||||
|
|
||||||
|
// recompute creatures
|
||||||
recomputeCreatureByDoc(creature);
|
recomputeCreatureByDoc(creature);
|
||||||
if (target){
|
targets.forEach(target => {
|
||||||
recomputeCreatureByDoc(target);
|
recomputeCreatureByDoc(target);
|
||||||
}
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export function doActionWork({action, creature, target, context = {}}){
|
export function doActionWork({
|
||||||
|
action,
|
||||||
|
creature,
|
||||||
|
targets,
|
||||||
|
context = {},
|
||||||
|
method
|
||||||
|
}){
|
||||||
|
// Create the log
|
||||||
|
let log = CreatureLogSchema.clean({
|
||||||
|
name: action.name,
|
||||||
|
creatureId: creature._id,
|
||||||
|
creatureName: creature.name,
|
||||||
|
});
|
||||||
|
|
||||||
let decendantForest = nodesToTree({
|
let decendantForest = nodesToTree({
|
||||||
collection: CreatureProperties,
|
collection: CreatureProperties,
|
||||||
ancestorId: action._id,
|
ancestorId: action._id,
|
||||||
@@ -56,8 +77,10 @@ export function doActionWork({action, creature, target, context = {}}){
|
|||||||
forest: startingForest,
|
forest: startingForest,
|
||||||
actionContext: context,
|
actionContext: context,
|
||||||
creature,
|
creature,
|
||||||
target,
|
targets,
|
||||||
|
log,
|
||||||
});
|
});
|
||||||
|
insertCreatureLogWork({log, creature, method});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default doAction;
|
export default doAction;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ export default function evaluateString(string, scope, fn = 'compile'){
|
|||||||
errors.push('...');
|
errors.push('...');
|
||||||
return {result: string, errors};
|
return {result: string, errors};
|
||||||
}
|
}
|
||||||
console.log(node);
|
|
||||||
let context = new CompilationContext();
|
let context = new CompilationContext();
|
||||||
let result = node[fn](scope, context);
|
let result = node[fn](scope, context);
|
||||||
if (result instanceof ConstantNode){
|
if (result instanceof ConstantNode){
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import SimpleSchema from 'simpl-schema';
|
import SimpleSchema from 'simpl-schema';
|
||||||
import Creatures from '/imports/api/creature/Creatures.js';
|
import Creatures from '/imports/api/creature/Creatures.js';
|
||||||
|
import LogContentSchema from '/imports/api/creature/log/LogContentSchema.js';
|
||||||
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
||||||
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
||||||
import {assertEditPermission} from '/imports/api/creature/creaturePermissions.js';
|
import {assertEditPermission} from '/imports/api/creature/creaturePermissions.js';
|
||||||
@@ -13,13 +14,16 @@ if (Meteor.isServer){
|
|||||||
let CreatureLogs = new Mongo.Collection('creatureLogs');
|
let CreatureLogs = new Mongo.Collection('creatureLogs');
|
||||||
|
|
||||||
let CreatureLogSchema = new SimpleSchema({
|
let CreatureLogSchema = new SimpleSchema({
|
||||||
text: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
type: {
|
content: {
|
||||||
type: String,
|
type: Array,
|
||||||
allowedValues: ['roll', 'change', 'damage', 'info'],
|
defaultValue: [],
|
||||||
defaultValue: 'info',
|
},
|
||||||
|
'content.$': {
|
||||||
|
type: LogContentSchema,
|
||||||
},
|
},
|
||||||
// The real-world date that it occured, usually sorted by date
|
// The real-world date that it occured, usually sorted by date
|
||||||
date: {
|
date: {
|
||||||
@@ -37,6 +41,10 @@ let CreatureLogSchema = new SimpleSchema({
|
|||||||
regEx: SimpleSchema.RegEx.Id,
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
index: 1,
|
index: 1,
|
||||||
},
|
},
|
||||||
|
creatureName: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
CreatureLogs.attachSchema(CreatureLogSchema);
|
CreatureLogs.attachSchema(CreatureLogSchema);
|
||||||
@@ -73,7 +81,7 @@ const insertCreatureLog = new ValidatedMethod({
|
|||||||
timeInterval: 5000,
|
timeInterval: 5000,
|
||||||
},
|
},
|
||||||
validate: new SimpleSchema({
|
validate: new SimpleSchema({
|
||||||
log: CreatureLogSchema.omit('type', 'date'),
|
log: CreatureLogSchema.omit('date'),
|
||||||
}).validator(),
|
}).validator(),
|
||||||
run({log}){
|
run({log}){
|
||||||
const creatureId = log.creatureId;
|
const creatureId = log.creatureId;
|
||||||
@@ -87,21 +95,27 @@ const insertCreatureLog = new ValidatedMethod({
|
|||||||
}});
|
}});
|
||||||
assertEditPermission(creature, this.userId);
|
assertEditPermission(creature, this.userId);
|
||||||
// Build the new log
|
// Build the new log
|
||||||
if (typeof log === 'string'){
|
let id = insertCreatureLogWork({log, creature, method: this})
|
||||||
log = {text: log};
|
|
||||||
}
|
|
||||||
log.date = new Date();
|
|
||||||
// Insert it
|
|
||||||
let id = CreatureLogs.insert(log);
|
|
||||||
if (Meteor.isServer){
|
|
||||||
this.unblock();
|
|
||||||
removeOldLogs(creatureId);
|
|
||||||
logWebhook({log, creature});
|
|
||||||
}
|
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function insertCreatureLogWork({log, creature, method}){
|
||||||
|
// Build the new log
|
||||||
|
if (typeof log === 'string'){
|
||||||
|
log = {text: log};
|
||||||
|
}
|
||||||
|
log.date = new Date();
|
||||||
|
// Insert it
|
||||||
|
let id = CreatureLogs.insert(log);
|
||||||
|
if (Meteor.isServer){
|
||||||
|
method.unblock();
|
||||||
|
removeOldLogs(creature._id);
|
||||||
|
logWebhook({log, creature});
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function equalIgnoringWhitespace(a, b){
|
function equalIgnoringWhitespace(a, b){
|
||||||
if (typeof a !== 'string' || typeof b !== 'string') return a === b;
|
if (typeof a !== 'string' || typeof b !== 'string') return a === b;
|
||||||
@@ -136,38 +150,42 @@ const logRoll = new ValidatedMethod({
|
|||||||
}});
|
}});
|
||||||
assertEditPermission(creature, this.userId);
|
assertEditPermission(creature, this.userId);
|
||||||
let parsedResult = parse(roll);
|
let parsedResult = parse(roll);
|
||||||
let logText;
|
let logContent;
|
||||||
if (parsedResult === null) {
|
if (parsedResult === null) {
|
||||||
logText = 'Unexpected end of input';
|
logContent = [{error: 'Unexpected end of input'}];
|
||||||
}
|
}
|
||||||
else try {
|
else try {
|
||||||
logText = [];
|
logContent = [];
|
||||||
let rollContext = new CompilationContext();
|
let rollContext = new CompilationContext();
|
||||||
let compiled = parsedResult.compile(creature.variables, rollContext);
|
let compiled = parsedResult.compile(creature.variables, rollContext);
|
||||||
let compiledString = compiled.toString();
|
let compiledString = compiled.toString();
|
||||||
if (!equalIgnoringWhitespace(compiledString, roll)) logText.push(roll);
|
if (!equalIgnoringWhitespace(compiledString, roll)) logContent.push({
|
||||||
logText.push(compiledString);
|
result: roll
|
||||||
|
});
|
||||||
|
logContent.push({
|
||||||
|
details: compiledString
|
||||||
|
});
|
||||||
let rolled = compiled.roll(creature.variables, rollContext);
|
let rolled = compiled.roll(creature.variables, rollContext);
|
||||||
let rolledString = rolled.toString();
|
let rolledString = rolled.toString();
|
||||||
if (rolledString !== compiledString) logText.push(rolled.toString());
|
if (rolledString !== compiledString) logContent.push({
|
||||||
|
details: rolled.toString()
|
||||||
|
});
|
||||||
let result = rolled.reduce(creature.variables, rollContext);
|
let result = rolled.reduce(creature.variables, rollContext);
|
||||||
let resultString = result.toString();
|
let resultString = result.toString();
|
||||||
if (resultString !== rolledString) logText.push(resultString);
|
if (resultString !== rolledString) logContent.push({
|
||||||
logText = logText.join('\n\n');
|
result: resultString
|
||||||
|
});
|
||||||
} catch (e){
|
} catch (e){
|
||||||
logText = 'Calculation error';
|
logContent = [{error: 'Calculation error'}];
|
||||||
}
|
}
|
||||||
const log = {
|
const log = {
|
||||||
text: logText,
|
content: logContent,
|
||||||
creatureId,
|
creatureId,
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
};
|
};
|
||||||
let id = CreatureLogs.insert(log);
|
|
||||||
if (Meteor.isServer){
|
let id = insertCreatureLogWork({log, creature, method: this});
|
||||||
this.unblock();
|
|
||||||
removeOldLogs(creatureId);
|
|
||||||
logWebhook({log, creature});
|
|
||||||
}
|
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
54
app/imports/api/creature/log/LogContentSchema.js
Normal file
54
app/imports/api/creature/log/LogContentSchema.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import SimpleSchema from 'simpl-schema';
|
||||||
|
import ErrorSchema from '/imports/api/properties/subSchemas/ErrorSchema.js';
|
||||||
|
import RollDetailsSchema from '/imports/api/properties/subSchemas/RollDetailsSchema.js';
|
||||||
|
|
||||||
|
let LogContentSchema = new SimpleSchema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
resultPrefix: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
expandedResult: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
details: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
type: Object,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
'context.errors':{
|
||||||
|
type: Array,
|
||||||
|
defaultValue: [],
|
||||||
|
},
|
||||||
|
'context.errors.$': {
|
||||||
|
type: ErrorSchema,
|
||||||
|
},
|
||||||
|
'context.rolls': {
|
||||||
|
type: Array,
|
||||||
|
defaultValue: [],
|
||||||
|
},
|
||||||
|
'context.rolls.$': {
|
||||||
|
type: RollDetailsSchema,
|
||||||
|
},
|
||||||
|
'context.doubleRolls': {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default LogContentSchema;
|
||||||
19
app/imports/api/properties/subSchemas/RollDetailsSchema.js
Normal file
19
app/imports/api/properties/subSchemas/RollDetailsSchema.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import SimpleSchema from 'simpl-schema';
|
||||||
|
|
||||||
|
const RollDetailsSchema = new SimpleSchema({
|
||||||
|
number: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
diceSize: {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
type: Array,
|
||||||
|
defaultValue: [],
|
||||||
|
},
|
||||||
|
'values.$': {
|
||||||
|
type: Number,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default RollDetailsSchema;
|
||||||
@@ -30,14 +30,12 @@ export default class RollNode extends ParseNode {
|
|||||||
return new ErrorNode({
|
return new ErrorNode({
|
||||||
node: this,
|
node: this,
|
||||||
error: 'Number of dice is not an integer',
|
error: 'Number of dice is not an integer',
|
||||||
previousNodes: [this, left, right],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!right.isInteger){
|
if (!right.isInteger){
|
||||||
return new ErrorNode({
|
return new ErrorNode({
|
||||||
node: this,
|
node: this,
|
||||||
error: 'Dice size is not an integer',
|
error: 'Dice size is not an integer',
|
||||||
previousNodes: [this, left, right],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let number = left.value;
|
let number = left.value;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import LogTab from '/imports/ui/creature/character/CharacterLog.vue';
|
import LogTab from '/imports/ui/log/CharacterLog.vue';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
LogTab,
|
LogTab,
|
||||||
|
|||||||
@@ -7,15 +7,11 @@
|
|||||||
class="log flex layout column reverse align-end pa-3"
|
class="log flex layout column reverse align-end pa-3"
|
||||||
style="overflow: auto;"
|
style="overflow: auto;"
|
||||||
>
|
>
|
||||||
<v-card
|
<log-entry
|
||||||
v-for="log in logs"
|
v-for="log in logs"
|
||||||
:key="log._id"
|
:key="log._id"
|
||||||
class="ma-2"
|
:model="log"
|
||||||
>
|
/>
|
||||||
<v-card-text class="pa-2">
|
|
||||||
<markdown-text :markdown="log.text" />
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
</div>
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
@@ -39,11 +35,11 @@ import CreatureLogs, { logRoll } from '/imports/api/creature/log/CreatureLogs.js
|
|||||||
import Creatures from '/imports/api/creature/Creatures.js';
|
import Creatures from '/imports/api/creature/Creatures.js';
|
||||||
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
||||||
import { parse } from '/imports/parser/parser.js';
|
import { parse } from '/imports/parser/parser.js';
|
||||||
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
|
import LogEntry from '/imports/ui/log/LogEntry.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MarkdownText,
|
LogEntry,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
creatureId: {
|
creatureId: {
|
||||||
54
app/imports/ui/log/LogEntry.vue
Normal file
54
app/imports/ui/log/LogEntry.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template lang="html">
|
||||||
|
<v-card
|
||||||
|
class="ma-2"
|
||||||
|
>
|
||||||
|
<v-card-title
|
||||||
|
v-if="model.name"
|
||||||
|
class="pa-2"
|
||||||
|
>
|
||||||
|
<h3>
|
||||||
|
{{ model.name }}
|
||||||
|
</h3>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text
|
||||||
|
v-if="model.text || (model.content && model.content.length)"
|
||||||
|
class="pa-2"
|
||||||
|
>
|
||||||
|
{{ model.text }}
|
||||||
|
<div
|
||||||
|
v-for="(content, index) in model.content"
|
||||||
|
:key="index"
|
||||||
|
class="content-line"
|
||||||
|
>
|
||||||
|
{{ content.name }}
|
||||||
|
<span
|
||||||
|
v-if="content.error"
|
||||||
|
class="error"
|
||||||
|
>{{ content.error }}</span>
|
||||||
|
{{ content.resultPrefix }}
|
||||||
|
<span
|
||||||
|
v-if="content.result"
|
||||||
|
class="subheading font-weight-bold mx-1"
|
||||||
|
>{{ content.result }}</span>
|
||||||
|
{{ content.details }}
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
model: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.content-line {
|
||||||
|
min-height: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -39,8 +39,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
// We can't rely on autoValue running in every form, so recalculate errors
|
// We can't rely on autoValue running in every form, so recalculate errors
|
||||||
clientErrors(){
|
clientErrors(){
|
||||||
let validationContext = ConstantSchema.newContext();
|
let cleanModel = ConstantSchema.clean(this.model);
|
||||||
let cleanModel = validationContext.clean(this.model);
|
|
||||||
return cleanModel.errors;
|
return cleanModel.errors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user