Initial commit

This commit is contained in:
2025-04-22 21:01:01 -04:00
parent c865355f2c
commit 4b93916aab
4 changed files with 237 additions and 0 deletions

163
placeholder-.ts Normal file
View File

@ -0,0 +1,163 @@
type DiceType = 'f' | 'r' | 't';
interface RollResult {
input: string;
value: number;
rolls: number[]; // Kept dice
discarded: number[]; // Discarded dice
summary: string; // Formatted string of all dice
}
function rollDie(diceType: DiceType): number {
const roll = {
f: Math.floor(Math.random() * 12) + 1 - 6,
r: Math.floor(Math.random() * 18) + 1 - 9,
t: Math.floor(Math.random() * 24) + 1 - 12,
};
return roll[diceType];
}
function rollDice(count: number, diceType: DiceType): number[] {
return Array.from({ length: count }, () => rollDie(diceType));
}
function getDieRange(diceType: DiceType): { min: number; max: number } {
const ranges = {
f: { min: -5, max: 6 },
r: { min: -8, max: 9 },
t: { min: -11, max: 12 },
};
return ranges[diceType];
}
function formatSummary(rolls: number[], discarded: number[], diceType: DiceType): string {
const { min, max } = getDieRange(diceType);
const all = rolls.map(r => ({ value: r, kept: true }))
.concat(discarded.map(r => ({ value: r, kept: false })));
return all
.sort((a, b) => b.value - a.value)
.map(({ value, kept }) => {
const isMinOrMax = value === min || value === max;
let formatted = `${value}`;
if (isMinOrMax) formatted = `**${formatted}**`;
if (!kept) formatted = `~${formatted}~`;
return formatted;
})
.join(' ');
}
function parseExpression(input: string): RollResult | RollResult[] {
const batchMatch = input.match(/^(\d+)#(.+)$/);
if (batchMatch) {
const [, batchCountStr, innerExpr] = batchMatch;
const batchCount = parseInt(batchCountStr, 10);
return Array.from({ length: batchCount }, () => parseSingleExpression(innerExpr));
} else {
return parseSingleExpression(input);
}
}
function parseSingleExpression(expr: string): RollResult {
const match = expr.match(/^(\d+)?([frt])(?:(kh|kl)(\d+))?(?:([+\-*])(\d+))?$/);
if (!match) throw new Error(`Invalid expression: ${expr}`);
const [, countStr, diceType, keepType, keepCountStr, op, modStr] = match;
const count = parseInt(countStr || '1', 10);
const dice = diceType as DiceType;
const keepCount = keepCountStr ? parseInt(keepCountStr, 10) : null;
const modifier = modStr ? parseInt(modStr, 10) : 0;
const operator = op || '+';
const allRolls = rollDice(count, dice);
let rolls = [...allRolls];
let discarded: number[] = [];
if (keepType && keepCount !== null) {
const sorted = [...allRolls].sort((a, b) => keepType === 'kh' ? b - a : a - b);
rolls = sorted.slice(0, keepCount);
discarded = sorted.slice(keepCount);
}
const baseSum = rolls.reduce((acc, val) => acc + val, 0);
let finalValue: number;
switch (operator) {
case '+':
finalValue = baseSum + modifier;
break;
case '-':
finalValue = baseSum - modifier;
break;
case '*':
finalValue = baseSum * modifier;
break;
default:
finalValue = baseSum;
}
return {
input: expr,
value: finalValue,
rolls,
discarded,
summary: formatSummary(rolls, discarded, dice)
};
}
function safeParseInput(message: string): RollResult | RollResult[] | null {
const trimmed = message.trim();
const isSingleWord = !trimmed.includes(' ');
// CASE 1: Single word without brackets
if (isSingleWord && !trimmed.startsWith('[') && !trimmed.endsWith(']')) {
try {
return parseExpression(trimmed);
} catch {
return null;
}
}
// CASE 2: Single word WITH brackets like "[3f]"
if (isSingleWord && trimmed.startsWith('[') && trimmed.endsWith(']')) {
const inside = trimmed.slice(1, -1).trim();
try {
return parseExpression(inside);
} catch {
return null;
}
}
// CASE 3: Multi-word input — check each word
const words = trimmed.split(/\s+/);
const expressions = words
.filter(word => word.startsWith('[') && word.endsWith(']'))
.map(word => word.slice(1, -1).trim());
if (expressions.length === 0) {
return null;
}
const results: RollResult[] = [];
for (const expr of expressions) {
try {
const result = parseExpression(expr);
if (Array.isArray(result)) {
results.push(...result);
} else {
results.push(result);
}
} catch {
// skip invalid
}
}
return results.length > 0 ? results : null;
}
console.log(safeParseInput('Hello I roll a 5rkh3+1'));
console.log(safeParseInput('I ROLL asdf[2#3fkl1*2]asdf'));
console.log(safeParseInput('[2#3fkl1*2] [2#3fkl1*2]'));