Move count reducer to artigen/utils/counter.ts, implement auto-confirm-crit flag

This commit is contained in:
Ean Milligan 2025-05-06 02:50:56 -04:00
parent b169ee8632
commit 14e909c89f
7 changed files with 54 additions and 25 deletions

View File

@ -5,7 +5,7 @@ meta {
} }
get { get {
url: http://localhost:8166/api/roll?user=[discord-user-id]&channel=[discord-channel-id]&rollstr=[artificer-roll-cmd]&documentation=All items below are optional. Flags do not need values.&nd=[no-details-flag]&snd=[super-no-details-flag]&hr=[hide-raw-roll-details-flag]&s=[spoiler-results-flag]&m-or-max=[max-roll-flag, cannot be used with n flag]&min=[[min-roll-flag, cannot be used with n or max]&n=[nominal-roll-flag, cannot be used with max or min flag]&gms=[csv-of-discord-user-ids-to-be-dmed-results]&o=[order-rolls, must be a or d]&c=[count-flag] url: http://localhost:8166/api/roll?user=[discord-user-id]&channel=[discord-channel-id]&rollstr=[artificer-roll-cmd]&documentation=All items below are optional. Flags do not need values.&nd=[no-details-flag]&snd=[super-no-details-flag]&hr=[hide-raw-roll-details-flag]&s=[spoiler-results-flag]&m-or-max=[max-roll-flag, cannot be used with n flag]&min=[[min-roll-flag, cannot be used with n or max]&n=[nominal-roll-flag, cannot be used with max or min flag]&gms=[csv-of-discord-user-ids-to-be-dmed-results]&o=[order-rolls, must be a or d]&c=[count-flag]&cc=[confirm-crit-flag]
body: none body: none
auth: inherit auth: inherit
} }
@ -25,4 +25,5 @@ params:query {
gms: [csv-of-discord-user-ids-to-be-dmed-results] gms: [csv-of-discord-user-ids-to-be-dmed-results]
o: [order-rolls, must be a or d] o: [order-rolls, must be a or d]
c: [count-flag] c: [count-flag]
cc: [confirm-crit-flag]
} }

View File

@ -10,6 +10,7 @@ import { loggingEnabled } from 'artigen/utils/logFlag.ts';
import { assertPrePostBalance } from 'artigen/utils/parenBalance.ts'; import { assertPrePostBalance } from 'artigen/utils/parenBalance.ts';
import { compareTotalRolls, compareTotalRollsReverse } from 'artigen/utils/sortFuncs.ts'; import { compareTotalRolls, compareTotalRollsReverse } from 'artigen/utils/sortFuncs.ts';
import { translateError } from 'artigen/utils/translateError.ts'; import { translateError } from 'artigen/utils/translateError.ts';
import { reduceCountDetails } from 'artigen/utils/counter.ts';
// runCmd(rollRequest) // runCmd(rollRequest)
// runCmd handles converting rollRequest into a computer readable format for processing, and finally executes the solving // runCmd handles converting rollRequest into a computer readable format for processing, and finally executes the solving
@ -115,24 +116,7 @@ export const runCmd = (rollRequest: QueuedRoll): SolvedRoll => {
returnMsg.line3 = line3; returnMsg.line3 = line3;
// Reduce counts to a single object // Reduce counts to a single object
returnMsg.counts = tempCountDetails.reduce( returnMsg.counts = reduceCountDetails(tempCountDetails);
(acc, cnt) => ({
total: acc.total + cnt.total,
successful: acc.successful + cnt.successful,
failed: acc.failed + cnt.failed,
rerolled: acc.rerolled + cnt.rerolled,
dropped: acc.dropped + cnt.dropped,
exploded: acc.exploded + cnt.exploded,
}),
{
total: 0,
successful: 0,
failed: 0,
rerolled: 0,
dropped: 0,
exploded: 0,
},
);
} catch (e) { } catch (e) {
// Fill in the return block // Fill in the return block
const solverError = e as Error; const solverError = e as Error;

View File

@ -13,6 +13,7 @@ import { tokenizeMath } from 'artigen/math/mathTokenizer.ts';
import { closeInternal, internalWrapRegex, openInternal } from 'artigen/utils/escape.ts'; import { closeInternal, internalWrapRegex, openInternal } from 'artigen/utils/escape.ts';
import { loggingEnabled } from 'artigen/utils/logFlag.ts'; import { loggingEnabled } from 'artigen/utils/logFlag.ts';
import { getMatchingInternalIdx, getMatchingPostfixIdx } from 'artigen/utils/parenBalance.ts'; import { getMatchingInternalIdx, getMatchingPostfixIdx } from 'artigen/utils/parenBalance.ts';
import { reduceCountDetails } from 'artigen/utils/counter.ts';
// tokenizeCmd expects a string[] of items that are either config.prefix/config.postfix or some text that contains math and/or dice rolls // tokenizeCmd expects a string[] of items that are either config.prefix/config.postfix or some text that contains math and/or dice rolls
export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: boolean, previousResults: number[] = []): [ReturnData[], CountDetails[]] => { export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: boolean, previousResults: number[] = []): [ReturnData[], CountDetails[]] => {
@ -28,15 +29,12 @@ export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: b
const openIdx = cmd.indexOf(config.prefix); const openIdx = cmd.indexOf(config.prefix);
const closeIdx = getMatchingPostfixIdx(cmd, openIdx); const closeIdx = getMatchingPostfixIdx(cmd, openIdx);
const currentCmd = cmd.slice(openIdx + 1, closeIdx);
loggingEnabled && log(LT.LOG, `Setting previous results: topLevel:${topLevel} ${topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults}`); loggingEnabled && log(LT.LOG, `Setting previous results: topLevel:${topLevel} ${topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults}`);
// Handle any nested commands // Handle any nested commands
const [tempData, tempCounts] = tokenizeCmd( const [tempData, tempCounts] = tokenizeCmd(currentCmd, modifiers, false, topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults);
cmd.slice(openIdx + 1, closeIdx),
modifiers,
false,
topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults,
);
const data = tempData[0]; const data = tempData[0];
if (topLevel) { if (topLevel) {
@ -55,6 +53,24 @@ export const tokenizeCmd = (cmd: string[], modifiers: RollModifiers, topLevel: b
// Store results // Store results
returnData.push(data); returnData.push(data);
countDetails.push(...tempCounts); countDetails.push(...tempCounts);
if (topLevel && modifiers.confirmCrit && reduceCountDetails(tempCounts).successful) {
loggingEnabled && log(LT.LOG, `ConfirmCrit on ${JSON.stringify(currentCmd)}`);
let done = false;
while (!done) {
const [ccTempData, ccTempCounts] = tokenizeCmd(currentCmd, modifiers, false, topLevel ? returnData.map((rd) => rd.rollTotal) : previousResults);
const ccData = ccTempData[0];
ccData.rollPreFormat = '\nAuto-Confirming Crit: ';
loggingEnabled && log(LT.LOG, `ConfirmCrit on ${JSON.stringify(currentCmd)} | Rolled again ${JSON.stringify(ccData)} ${JSON.stringify(ccTempCounts)}`);
// Store CC results
returnData.push(ccData);
countDetails.push(...ccTempCounts);
done = reduceCountDetails(ccTempCounts).successful === 0;
}
}
} }
if (topLevel) { if (topLevel) {

View File

@ -45,6 +45,7 @@ export interface RollModifiers {
order: string; order: string;
count: boolean; count: boolean;
commaTotals: boolean; commaTotals: boolean;
confirmCrit: boolean;
apiWarn: string; apiWarn: string;
valid: boolean; valid: boolean;
error: Error; error: Error;

View File

@ -15,6 +15,7 @@ export const Modifiers = Object.freeze({
GM: '-gm', GM: '-gm',
Order: '-o', Order: '-o',
CommaTotals: '-ct', CommaTotals: '-ct',
ConfirmCrit: '-cc',
}); });
export const getModifiers = (args: string[]): [RollModifiers, string[]] => { export const getModifiers = (args: string[]): [RollModifiers, string[]] => {
@ -31,6 +32,7 @@ export const getModifiers = (args: string[]): [RollModifiers, string[]] => {
order: '', order: '',
count: false, count: false,
commaTotals: false, commaTotals: false,
confirmCrit: false,
apiWarn: '', apiWarn: '',
valid: false, valid: false,
error: new Error(), error: new Error(),
@ -66,6 +68,9 @@ export const getModifiers = (args: string[]): [RollModifiers, string[]] => {
case Modifiers.Nominal: case Modifiers.Nominal:
modifiers.nominalRoll = true; modifiers.nominalRoll = true;
break; break;
case Modifiers.ConfirmCrit:
modifiers.confirmCrit = true;
break;
case Modifiers.GM: case Modifiers.GM:
modifiers.gmRoll = true; modifiers.gmRoll = true;

View File

@ -21,3 +21,24 @@ export const rollCounter = (rollSet: RollSet[]): CountDetails => {
return countDetails; return countDetails;
}; };
export const reduceCountDetails = (counts: CountDetails[]): CountDetails => {
return counts.reduce(
(acc, cnt) => ({
total: acc.total + cnt.total,
successful: acc.successful + cnt.successful,
failed: acc.failed + cnt.failed,
rerolled: acc.rerolled + cnt.rerolled,
dropped: acc.dropped + cnt.dropped,
exploded: acc.exploded + cnt.exploded,
}),
{
total: 0,
successful: 0,
failed: 0,
rerolled: 0,
dropped: 0,
exploded: 0,
},
);
};

View File

@ -94,6 +94,7 @@ export const apiRoll = async (query: Map<string, string>, apiUserid: bigint): Pr
order: query.has('o') ? query.get('o')?.toLowerCase() || '' : '', order: query.has('o') ? query.get('o')?.toLowerCase() || '' : '',
count: query.has('c'), count: query.has('c'),
commaTotals: query.has('ct'), commaTotals: query.has('ct'),
confirmCrit: query.has('cc'),
apiWarn: hideWarn ? '' : apiWarning, apiWarn: hideWarn ? '' : apiWarning,
valid: true, valid: true,
error: new Error(), error: new Error(),