Started work on adding count decorator

This commit is contained in:
Ean Milligan (Bastion) 2022-05-19 02:53:30 -04:00
parent 04d7324769
commit a270a4b8f7
7 changed files with 50 additions and 27 deletions

View File

@ -98,6 +98,7 @@ The Artificer comes with a few supplemental commands to the main rolling command
* `[[d20/40]]` will roll a d20 die and divide it by 40. * `[[d20/40]]` will roll a d20 die and divide it by 40.
* `[[((d20+20) - 10) / 5]]` will roll a d20, add 20 to that roll, subtract off 10, and finally divide by 5. * `[[((d20+20) - 10) / 5]]` will roll a d20, add 20 to that roll, subtract off 10, and finally divide by 5.
* This command also has some useful decorators that can used. These decorators simply need to be placed after all rolls in the message: * This command also has some useful decorators that can used. These decorators simply need to be placed after all rolls in the message:
* `-c` - Count - Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions
* `-nd` - No Details - Suppresses all details of the requested roll * `-nd` - No Details - Suppresses all details of the requested roll
* `-snd` - Super No Details - Suppresses all details of the requested roll and hides no details message * `-snd` - Super No Details - Suppresses all details of the requested roll and hides no details message
* `-s` - Spoiler - Spoilers all details of the requested roll * `-s` - Spoiler - Spoilers all details of the requested roll
@ -134,8 +135,9 @@ Available Endpoints and Methods Required:
* `channel` - The Discord Channel ID that the bot is to send the results into. * `channel` - The Discord Channel ID that the bot is to send the results into.
* `rollstr` - A roll string formatted identically to the roll command detailed in the "Available Commands" section. * `rollstr` - A roll string formatted identically to the roll command detailed in the "Available Commands" section.
* Optional query parameters (these parameters do not require values unless specified): * Optional query parameters (these parameters do not require values unless specified):
* `snd` - Super No Details - Suppresses all details of the requested roll and hides no details message. * `c` - Count - Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions
* `nd` - No Details - Suppresses all details of the requested roll. * `nd` - No Details - Suppresses all details of the requested roll.
* `snd` - Super No Details - Suppresses all details of the requested roll and hides no details message.
* `s` - Spoiler - Spoilers all details of the requested roll. * `s` - Spoiler - Spoilers all details of the requested roll.
* `m` - Maximize Roll - Rolls the theoretical maximum roll, cannot be used with Nominal roll. * `m` - Maximize Roll - Rolls the theoretical maximum roll, cannot be used with Nominal roll.
* `n` - Nominal Roll - Rolls the theoretical nominal roll, cannot be used with Maximise roll. * `n` - Nominal Roll - Rolls the theoretical nominal roll, cannot be used with Maximise roll.
@ -200,11 +202,6 @@ If you choose to run version `1.1.0` or newer, ensure you disable the API in `co
--- ---
## Development Plans
Current and future plans are listed on [the Milestones page](https://github.com/Burn-E99/TheArtificer/milestones).
---
## Privacy Policy and Terms of Service ## Privacy Policy and Terms of Service
The Artificer has a Privacy Policy and Terms of Service to detail expectations of what user data is stored and how users should use The Artificer. The following Privacy Policy and Terms of Service only apply to the officially hosted version of The Artificer (`The Artificer#8166`, Discord ID: `789045930011656223`). The Artificer has a Privacy Policy and Terms of Service to detail expectations of what user data is stored and how users should use The Artificer. The following Privacy Policy and Terms of Service only apply to the officially hosted version of The Artificer (`The Artificer#8166`, Discord ID: `789045930011656223`).

View File

@ -19,6 +19,7 @@ import {
LT, log LT, log
} from "../deps.ts"; } from "../deps.ts";
import { RollModifiers } from "./mod.d.ts";
import { dbClient, queries } from "./db.ts"; import { dbClient, queries } from "./db.ts";
import solver from "./solver/_index.ts"; import solver from "./solver/_index.ts";
import { import {
@ -238,8 +239,21 @@ const start = async (): Promise<void> => {
// Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord // Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord
rollCmd = rollCmd.substring(rollCmd.indexOf(config.prefix) + 2).replace(/%20/g, " "); rollCmd = rollCmd.substring(rollCmd.indexOf(config.prefix) + 2).replace(/%20/g, " ");
const modifiers: RollModifiers = {
noDetails: false,
superNoDetails: false,
spoiler: "",
maxRoll: query.has("m"),
nominalRoll: query.has("n"),
gmRoll: false,
gms: [],
order: query.has("o") ? (query.get("o")?.toLowerCase() || "") : "",
valid: true,
count: query.has("c")
};
// Parse the roll and get the return text // Parse the roll and get the return text
const returnmsg = solver.parseRoll(rollCmd, config.prefix, config.postfix, query.has("m"), query.has("n"), query.has("o") ? (query.get("o")?.toLowerCase() || "") : ""); const returnmsg = solver.parseRoll(rollCmd, modifiers);
// Alert users why this message just appeared and how they can report abues pf this feature // Alert users why this message just appeared and how they can report abues pf this feature
const apiPrefix = hideWarn ? '' : `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>\n\n`; const apiPrefix = hideWarn ? '' : `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>\n\n`;

View File

@ -42,7 +42,7 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in // Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in
const rollCmd = `${command} ${args.join(" ")}`; const rollCmd = `${command} ${args.join(" ")}`;
const returnmsg = solver.parseRoll(rollCmd, config.prefix, config.postfix, modifiers.maxRoll, modifiers.nominalRoll, modifiers.order) || { error: true, errorCode: "EmptyMessage", errorMsg: "Error: Empty message", line1: "", line2: "", line3: "" }; const returnmsg = solver.parseRoll(rollCmd, modifiers) || { error: true, errorCode: "EmptyMessage", errorMsg: "Error: Empty message", line1: "", line2: "", line3: "" };
let returnText = ""; let returnText = "";

View File

@ -22,7 +22,8 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
gmRoll: false, gmRoll: false,
gms: [], gms: [],
order: "", order: "",
valid: false valid: false,
count: false
}; };
// Check if any of the args are command flags and pull those out into the modifiers object // Check if any of the args are command flags and pull those out into the modifiers object
@ -30,6 +31,9 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
log(LT.LOG, `Checking ${command}${args.join(" ")} for command modifiers ${i}`); log(LT.LOG, `Checking ${command}${args.join(" ")} for command modifiers ${i}`);
let defaultCase = false; let defaultCase = false;
switch (args[i].toLowerCase()) { switch (args[i].toLowerCase()) {
case "-c":
modifiers.count = true;
break;
case "-nd": case "-nd":
modifiers.noDetails = true; modifiers.noDetails = true;
break; break;
@ -69,6 +73,7 @@ export const getModifiers = (m: DiscordenoMessage, args: string[], command: stri
} }
break; break;
case "-o": case "-o":
// Shift the -o out of the array so the next item is the direction
args.splice(i, 1); args.splice(i, 1);
if (!args[i] || args[i].toLowerCase()[0] !== "d" && args[i].toLowerCase()[0] !== "a") { if (!args[i] || args[i].toLowerCase()[0] !== "d" && args[i].toLowerCase()[0] !== "a") {

View File

@ -365,6 +365,10 @@ export const constantCmds = {
name: "`-gm @user1 @user2 @usern` - GM Roll", name: "`-gm @user1 @user2 @usern` - GM Roll",
value: "Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs", value: "Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs",
inline: true inline: true
}, {
name: "`-c` - Count Rolls",
value: "Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions",
inline: true
}, { }, {
name: "`-o [direction]` - Order Roll", name: "`-o [direction]` - Order Roll",
value: `Rolls the requested roll and orders the results in the requested direction value: `Rolls the requested roll and orders the results in the requested direction

4
src/mod.d.ts vendored
View File

@ -9,6 +9,7 @@ export type EmojiConf = {
deleteSender: boolean deleteSender: boolean
}; };
// RollModifiers is the structure to keep track of the decorators applied to a roll command
export type RollModifiers = { export type RollModifiers = {
noDetails: boolean, noDetails: boolean,
superNoDetails: boolean, superNoDetails: boolean,
@ -18,5 +19,6 @@ export type RollModifiers = {
gmRoll: boolean, gmRoll: boolean,
gms: string[], gms: string[],
order: string, order: string,
valid: boolean valid: boolean,
count: boolean
} }

View File

@ -5,14 +5,15 @@ import {
import config from "../../config.ts"; import config from "../../config.ts";
import { RollModifiers } from "../mod.d.ts";
import { SolvedStep, SolvedRoll, ReturnData } from "./solver.d.ts"; import { SolvedStep, SolvedRoll, ReturnData } from "./solver.d.ts";
import { compareTotalRolls, escapeCharacters } from "./rollUtils.ts"; import { compareTotalRolls, escapeCharacters } from "./rollUtils.ts";
import { formatRoll } from "./rollFormatter.ts"; import { formatRoll } from "./rollFormatter.ts";
import { fullSolver } from "./solver.ts"; import { fullSolver } from "./solver.ts";
// parseRoll(fullCmd, localPrefix, localPostfix, maximiseRoll, nominalRoll) // parseRoll(fullCmd, modifiers)
// parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving // parseRoll handles converting fullCmd into a computer readable format for processing, and finally executes the solving
export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: string, maximiseRoll: boolean, nominalRoll: boolean, order: string): SolvedRoll => { export const parseRoll = (fullCmd: string, modifiers: RollModifiers): SolvedRoll => {
const returnmsg = { const returnmsg = {
error: false, error: false,
errorMsg: "", errorMsg: "",
@ -25,7 +26,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
// Whole function lives in a try-catch to allow safe throwing of errors on purpose // Whole function lives in a try-catch to allow safe throwing of errors on purpose
try { try {
// Split the fullCmd by the command prefix to allow every roll/math op to be handled individually // Split the fullCmd by the command prefix to allow every roll/math op to be handled individually
const sepRolls = fullCmd.split(localPrefix); const sepRolls = fullCmd.split(config.prefix);
const tempReturnData: ReturnData[] = []; const tempReturnData: ReturnData[] = [];
@ -33,7 +34,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
for (let i = 0; i < sepRolls.length; i++) { for (let i = 0; i < sepRolls.length; i++) {
log(LT.LOG, `Parsing roll ${fullCmd} | Working ${sepRolls[i]}`); log(LT.LOG, `Parsing roll ${fullCmd} | Working ${sepRolls[i]}`);
// Split the current iteration on the command postfix to separate the operation to be parsed and the text formatting after the opertaion // Split the current iteration on the command postfix to separate the operation to be parsed and the text formatting after the opertaion
const [tempConf, tempFormat] = sepRolls[i].split(localPostfix); const [tempConf, tempFormat] = sepRolls[i].split(config.postfix);
// Remove all spaces from the operation config and split it by any operator (keeping the operator in mathConf for fullSolver to do math on) // Remove all spaces from the operation config and split it by any operator (keeping the operator in mathConf for fullSolver to do math on)
const mathConf: (string | number | SolvedStep)[] = <(string | number | SolvedStep)[]>tempConf.replace(/ /g, "").split(/([-+()*/%^])/g); const mathConf: (string | number | SolvedStep)[] = <(string | number | SolvedStep)[]>tempConf.replace(/ /g, "").split(/([-+()*/%^])/g);
@ -66,7 +67,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
mathConf[i] = parseFloat(mathConf[i].toString()); mathConf[i] = parseFloat(mathConf[i].toString());
} else if (/([0123456789])/g.test(mathConf[i].toString())) { } else if (/([0123456789])/g.test(mathConf[i].toString())) {
// If there is a number somewhere in mathconf[i] but there are also other characters preventing it from parsing correctly as a number, it should be a dice roll, parse it as such (if it for some reason is not a dice roll, formatRoll/roll will handle it) // If there is a number somewhere in mathconf[i] but there are also other characters preventing it from parsing correctly as a number, it should be a dice roll, parse it as such (if it for some reason is not a dice roll, formatRoll/roll will handle it)
mathConf[i] = formatRoll(mathConf[i].toString(), maximiseRoll, nominalRoll); mathConf[i] = formatRoll(mathConf[i].toString(), modifiers.maxRoll, modifiers.nominalRoll);
} else if (mathConf[i].toString().toLowerCase() === "e") { } else if (mathConf[i].toString().toLowerCase() === "e") {
// If the operand is the constant e, create a SolvedStep for it // If the operand is the constant e, create a SolvedStep for it
mathConf[i] = { mathConf[i] = {
@ -130,23 +131,23 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
let line3 = ""; let line3 = "";
// If maximiseRoll or nominalRoll are on, mark the output as such, else use default formatting // If maximiseRoll or nominalRoll are on, mark the output as such, else use default formatting
if (maximiseRoll) { if (modifiers.maxRoll) {
line1 = ` requested the theoretical maximum of: \`${localPrefix}${fullCmd}\``; line1 = ` requested the theoretical maximum of: \`${config.prefix}${fullCmd}\``;
line2 = "Theoretical Maximum Results: "; line2 = "Theoretical Maximum Results: ";
} else if (nominalRoll) { } else if (modifiers.nominalRoll) {
line1 = ` requested the theoretical nominal of: \`${localPrefix}${fullCmd}\``; line1 = ` requested the theoretical nominal of: \`${config.prefix}${fullCmd}\``;
line2 = "Theoretical Nominal Results: "; line2 = "Theoretical Nominal Results: ";
} else if (order === "a") { } else if (modifiers.order === "a") {
line1 = ` requested the following rolls to be ordered from least to greatest: \`${localPrefix}${fullCmd}\``; line1 = ` requested the following rolls to be ordered from least to greatest: \`${config.prefix}${fullCmd}\``;
line2 = "Results: "; line2 = "Results: ";
tempReturnData.sort(compareTotalRolls); tempReturnData.sort(compareTotalRolls);
} else if (order === "d") { } else if (modifiers.order === "d") {
line1 = ` requested the following rolls to be ordered from greatest to least: \`${localPrefix}${fullCmd}\``; line1 = ` requested the following rolls to be ordered from greatest to least: \`${config.prefix}${fullCmd}\``;
line2 = "Results: "; line2 = "Results: ";
tempReturnData.sort(compareTotalRolls); tempReturnData.sort(compareTotalRolls);
tempReturnData.reverse(); tempReturnData.reverse();
} else { } else {
line1 = ` rolled: \`${localPrefix}${fullCmd}\``; line1 = ` rolled: \`${config.prefix}${fullCmd}\``;
line2 = "Results: "; line2 = "Results: ";
} }
@ -167,7 +168,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
} }
// Populate line2 (the results) and line3 (the details) with their data // Populate line2 (the results) and line3 (the details) with their data
if (order === "") { if (modifiers.order === "") {
line2 += `${preFormat}${e.rollTotal}${postFormat}${escapeCharacters(e.rollPostFormat, "|*_~`")}`; line2 += `${preFormat}${e.rollTotal}${postFormat}${escapeCharacters(e.rollPostFormat, "|*_~`")}`;
} else { } else {
// If order is on, turn rolls into csv without formatting // If order is on, turn rolls into csv without formatting
@ -180,7 +181,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
}); });
// If order is on, remove trailing ", " // If order is on, remove trailing ", "
if (order !== "") { if (modifiers.order !== "") {
line2 = line2.substring(0, (line2.length - 2)); line2 = line2.substring(0, (line2.length - 2));
} }
@ -213,7 +214,7 @@ export const parseRoll = (fullCmd: string, localPrefix: string, localPostfix: st
if (errorDetails === "-") { if (errorDetails === "-") {
errorMsg += "\nNote: Negative numbers are not supported"; errorMsg += "\nNote: Negative numbers are not supported";
} else if (errorDetails === " ") { } else if (errorDetails === " ") {
errorMsg += `\nNote: Every roll must be closed by ${localPostfix}`; errorMsg += `\nNote: Every roll must be closed by ${config.postfix}`;
} }
break; break;
case "NoZerosAllowed": case "NoZerosAllowed":