Improved custom rolls on log tab

This commit is contained in:
Stefan Zermatten
2020-10-06 09:53:08 +02:00
parent 844588cdbf
commit a87cb1286a
3 changed files with 115 additions and 14 deletions

View File

@@ -1,4 +1,11 @@
import SimpleSchema from 'simpl-schema';
import Creatures from '/imports/api/creature/Creatures.js';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import {assertEditPermission} from '/imports/api/creature/creaturePermissions.js';
import { parse, CompilationContext } from '/imports/parser/parser.js';
const PER_CREATURE_LOG_LIMIT = 100;
if (Meteor.isServer){
var sendWebhookAsCreature = require('/imports/server/discord/sendWebhook.js').sendWebhookAsCreature;
}
@@ -36,11 +43,28 @@ CreatureLogs.attachSchema(CreatureLogSchema);
// This function should only be called by trusted code. No permission checks
const insertCreatureLog = function({log, creature}){
const creatureId = creature._id;
// Build the new log
if (typeof log === 'string'){
log = {text: log};
}
log.creatureId = creature._id;
log.creatureId = creatureId;
// Insert it
let id = CreatureLogs.insert(log);
// Find the first log that is over the limit
let firstExpiredLog = CreatureLogs.find({
creatureId
}, {
sort: {date: -1},
skip: PER_CREATURE_LOG_LIMIT,
});
// Remove all logs older than the one over the limit
CreatureLogs.remove({
creatureId,
date: {$lte: firstExpiredLog.date},
});
//TODO unblock before sending webhooks
// Send webhooks
if (Meteor.isServer){
sendWebhookAsCreature({
creature,
@@ -50,5 +74,55 @@ const insertCreatureLog = function({log, creature}){
return id;
};
function equalIgnoringWhitespace(a, b){
if (typeof a !== 'string' || typeof b !== 'string') return a === b;
return a.replace(/\s/g,'') === b.replace(/\s/g, '');
}
const logRoll = new ValidatedMethod({
name: 'creatureLogs.methods.logForCreature',
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 5,
timeInterval: 5000,
},
validate: new SimpleSchema({
roll: {
type: String,
},
creatureId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
}).validator(),
run({roll, creatureId}){
const creature = Creatures.findOne(creatureId);
assertEditPermission(creature, this.userId);
let parsedResult = parse(roll);
let log;
if (parsedResult === null) {
log = 'Unexpected end of input';
}
else try {
let logText = [];
let rollContext = new CompilationContext();
let compiled = parsedResult.compile(creature.variables, rollContext);
let compiledString = compiled.toString();
if (!equalIgnoringWhitespace(compiledString, roll)) logText.push(roll);
logText.push(compiledString);
let rolled = compiled.roll(creature.variables, rollContext);
let rolledString = rolled.toString();
if (rolledString !== compiledString) logText.push(rolled.toString());
let result = rolled.reduce(creature.variables, rollContext);
let resultString = result.toString();
if (resultString !== rolledString) logText.push(resultString);
log = logText.join('\n\n');
} catch (e){
log = 'Calculation error';
}
return insertCreatureLog({log, creature});
},
});
export default CreatureLogs;
export { CreatureLogSchema, insertCreatureLog};
export { CreatureLogSchema, insertCreatureLog, logRoll};

View File

@@ -64,7 +64,7 @@
<v-snackbar
v-for="(snackbar, index) in snackbars"
:key="index"
v-model="snackbar.open"
:value="true"
>
{{ snackbar.text }}
<v-btn
@@ -142,7 +142,7 @@
added(doc){
console.log({added: doc});
that.snackbars.add(doc);
setTimeout(function(){that.snackbars.remove(doc)}, 8000);
setTimeout(function(){that.snackbars.delete(doc)}, 8000);
},
});
console.log(observer);

View File

@@ -1,15 +1,21 @@
<template lang="html">
<div
style="min-height: calc(100vh - 96px);"
class="layout column justify-end"
style="height: calc(100vh - 96px); overflow: hidden;"
class="log-tab layout column justify-end"
>
<div class="log flex layout column reverse">
<div
<div
class="log flex layout column reverse align-start pa-3"
style="overflow: auto;"
>
<v-card
v-for="log in logs"
:key="log._id"
class="ma-2"
>
{{ log.text }}
</div>
<v-card-text class="pa-2">
<markdown-text :markdown="log.text" />
</v-card-text>
</v-card>
</div>
<v-card>
<v-text-field
@@ -17,22 +23,28 @@
solo
persistent-hint
style="flex-grow: 0"
append-outer-icon="send"
:hint="inputHint"
:error="inputError"
:error-messages="inputError"
:disabled="!editPermission"
@input="inputChanged"
@click:append-outer="submit"
@keyup.enter="submit"
/>
</v-card>
</div>
</template>
<script>
import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js';
import CreatureLogs, { logRoll } from '/imports/api/creature/log/CreatureLogs.js';
import Creatures from '/imports/api/creature/Creatures.js';
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
import { parse } from '/imports/parser/parser.js';
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
export default {
components: {
MarkdownText,
},
props: {
creatureId: {
type: String,
@@ -71,6 +83,18 @@ export default {
}
},
},
methods: {
submit(){
if (this.inputError) return;
logRoll.call({
roll: this.input,
creatureId: this.creatureId,
}, (error) => {
if (error) console.error(error);
});
this.input = '';
},
},
meteor: {
logs(){
return CreatureLogs.find({
@@ -95,5 +119,8 @@ export default {
}
</script>
<style lang="css" scoped>
<style lang="css">
.log-tab p:last-child {
margin-bottom: 0;
}
</style>