@dicelette/core 1.23.0 → 1.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +15 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -339,6 +339,7 @@ function replaceInFormula(element, diceResult, compareResult, res, engine = impo
|
|
|
339
339
|
}
|
|
340
340
|
function compareSignFormule(toRoll, compareRegex, element, diceResult, engine = import_rpg_dice_roller.NumberGenerator.engines.nodeCrypto, pity) {
|
|
341
341
|
let results = "";
|
|
342
|
+
let trivial = false;
|
|
342
343
|
const compareResult = getCompare(toRoll, compareRegex, engine);
|
|
343
344
|
const toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;
|
|
344
345
|
let res;
|
|
@@ -348,6 +349,8 @@ function compareSignFormule(toRoll, compareRegex, element, diceResult, engine =
|
|
|
348
349
|
res = roll(toCompare, engine, pity);
|
|
349
350
|
}
|
|
350
351
|
if (typeof res === "boolean") {
|
|
352
|
+
trivial = true;
|
|
353
|
+
if (compareResult.compare) compareResult.compare.trivial = true;
|
|
351
354
|
results = replaceInFormula(element, diceResult, compareResult, res, engine, pity);
|
|
352
355
|
} else if (res instanceof Object) {
|
|
353
356
|
const diceResult2 = res;
|
|
@@ -359,9 +362,10 @@ function compareSignFormule(toRoll, compareRegex, element, diceResult, engine =
|
|
|
359
362
|
const invertedSign = toEvaluate ? diceResult2.compare.sign : inverseSign(diceResult2.compare.sign);
|
|
360
363
|
const dice = replaceText(element, 0, diceResult2.dice).diceAll;
|
|
361
364
|
results = `${sign} ${dice}: ${diceResult2.result.split(":").splice(1).join(":").trim()}${invertedSign}${diceResult2.compare.value}`;
|
|
365
|
+
if (diceResult2.compare.trivial) trivial = true;
|
|
362
366
|
}
|
|
363
367
|
}
|
|
364
|
-
return { dice: compareResult.dice, results };
|
|
368
|
+
return { dice: compareResult.dice, results, compare: compareResult.compare, trivial };
|
|
365
369
|
}
|
|
366
370
|
function replaceText(element, total, dice) {
|
|
367
371
|
return {
|
|
@@ -417,6 +421,8 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
|
|
|
417
421
|
} else return void 0;
|
|
418
422
|
}
|
|
419
423
|
if (!diceResult || !diceResult.total) return void 0;
|
|
424
|
+
let aggregatedCompare = diceResult.compare;
|
|
425
|
+
let hasTrivialComparison = diceResult.compare?.trivial === true;
|
|
420
426
|
results.push(`\u203B ${comments}${diceResult.result}`);
|
|
421
427
|
let total = diceResult.total;
|
|
422
428
|
diceResult.comment = mainComment;
|
|
@@ -436,6 +442,8 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
|
|
|
436
442
|
);
|
|
437
443
|
toRoll = compareResult.dice;
|
|
438
444
|
results.push(compareResult.results);
|
|
445
|
+
if (!aggregatedCompare && compareResult.compare) aggregatedCompare = compareResult.compare;
|
|
446
|
+
if (compareResult.trivial) hasTrivialComparison = true;
|
|
439
447
|
} else {
|
|
440
448
|
const { formule, diceAll } = replaceText(
|
|
441
449
|
element,
|
|
@@ -448,11 +456,14 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
|
|
|
448
456
|
total += Number.parseInt(evaluated, 10);
|
|
449
457
|
} catch (error) {
|
|
450
458
|
const evaluated = roll(toRoll, engine, pity);
|
|
451
|
-
if (evaluated)
|
|
459
|
+
if (evaluated) {
|
|
452
460
|
results.push(
|
|
453
461
|
`\u25C8 ${comment}${diceAll}: ${evaluated.result.split(":").slice(1).join(":")}`
|
|
454
462
|
);
|
|
455
|
-
|
|
463
|
+
if (!aggregatedCompare && evaluated.compare)
|
|
464
|
+
aggregatedCompare = evaluated.compare;
|
|
465
|
+
if (evaluated.compare?.trivial) hasTrivialComparison = true;
|
|
466
|
+
} else results.push(`\u25C8 ${comment}${diceAll}: ${formule} = ${evaluated}`);
|
|
456
467
|
total += evaluated?.total ?? 0;
|
|
457
468
|
}
|
|
458
469
|
}
|
|
@@ -463,7 +474,7 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
|
|
|
463
474
|
dice: diceMain,
|
|
464
475
|
result: results.join(";"),
|
|
465
476
|
comment: mainComment,
|
|
466
|
-
compare:
|
|
477
|
+
compare: hasTrivialComparison && aggregatedCompare ? { ...aggregatedCompare, trivial: true } : aggregatedCompare,
|
|
467
478
|
modifier: diceResult.modifier,
|
|
468
479
|
total
|
|
469
480
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/dice.ts","../src/errors.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/utils.ts","../src/verify_template.ts"],"sourcesContent":["export * from \"./dice\";\nexport * from \"./errors\";\nexport * from \"./interfaces\";\nexport * from \"./interfaces/constant\";\nexport * from \"./interfaces/toJsonSchema\";\nexport * from \"./interfaces/zod\";\nexport * from \"./utils\";\nexport * from \"./verify_template\";\n","import { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport {\n\tCOMMENT_REGEX,\n\ttype Compare,\n\ttype ComparedValue,\n\ttype CustomCritical,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tdiceTypeRandomParse,\n\tisNumber,\n\ttype Modifier,\n\tOPTIONAL_COMMENT,\n\ttype Resultat,\n\treplaceFormulaInDice,\n\tSIGN_REGEX,\n\tSIGN_REGEX_SPACE,\n\ttype Sign,\n\ttype StatisticalTemplate,\n\tSYMBOL_DICE,\n\tstandardizeDice,\n} from \".\";\n\n/**\n * Check if a comparison is trivial (always true or always false)\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\n * @param maxValue Maximum possible value from the dice roll\n * @param minValue Minimum possible value from the dice roll\n * @param compare The comparison object\n * @returns true if the comparison is trivial (always true or always false)\n */\nfunction isTrivialComparison(\n\tmaxValue: number,\n\tminValue: number,\n\tcompare: ComparedValue\n): boolean {\n\t// Check if comparison can never succeed (always false)\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\n\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\n\n\t// Trivial if it can never succeed OR can never fail\n\treturn !canSucceed || !canFail;\n}\n\n/**\n * Check if a comparison can theoretically fail given roll bounds\n * @param maxRollValue Maximum possible roll value\n * @param compare The comparison object\n * @param minRollValue Minimum possible roll value (defaults to 1)\n * @returns true if the comparison can fail at least once\n */\nfunction canComparisonFail(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue = 1\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\n\t\tcase \">=\":\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\n\t\tcase \"<\":\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\n\t\tcase \"<=\":\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\n\t\tcase \"!=\":\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; compare: ComparedValue | undefined } {\n\t/**\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\n\t * Some system count the number of a dice that are greater than or equal to a target, and not the \"total\" of rolled dice.\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\n\t * To support this, we use the group notation. It a little different than the notation of dice-roller, but it a sacrifice to not break the current notation.\n\t * @note:\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\n\t * - `{2d3>=4}` will count the total of dice that are greater than or equal to 4, and not the total of the dice.\n\t * - `{2d3,1d4}>=4` won't use the comparison, but will count the number of dice that are greater than or equal to 4. If the total of the dice is needed, just remove the group notation and use `2d3+1d4>=4`.\n\t */\n\tif (\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\n\t)\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\n\tconst calc = compareRegex[2];\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\n\n\tif (sign) {\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\n\t\tconst total = evaluate(rCompare.value.toString());\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: total,\n\t\t\toriginalDice: rCompare.dice,\n\t\t\trollValue: rCompare.diceResult,\n\t\t};\n\t} else {\n\t\tconst rcompare = rollCompare(calc, engine, pity);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: rcompare.value,\n\t\t\toriginalDice: rcompare.dice,\n\t\t\trollValue: rcompare.diceResult,\n\t\t};\n\t}\n\n\treturn { dice, compare };\n}\n\nfunction rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\t// Handle empty value or string - return 0 as default\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n\t\treturn { value: 0, diceResult: value as string };\n\t}\n\tconst rollComp = roll(value as string, engine, pity);\n\tif (!rollComp?.total) {\n\t\t//not a dice throw\n\t\ttry {\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\n\t\t} catch (error) {\n\t\t\t// If evaluate fails, return 0\n\t\t\treturn { value: 0, diceResult: value as string };\n\t\t}\n\t}\n\treturn {\n\t\tdice: value as string,\n\t\tvalue: rollComp.total,\n\t\tdiceResult: rollComp?.result,\n\t};\n}\n\n/**\n * Allow to replace the compare part of a dice and use the critical customized one\n * @example\n * dice = \"1d20=20\";\n * custom critical {sign: \">\", value: \"$/2\"}\n * Random stats = 6\n * result = \"1d20>3\"\n */\nexport function createCriticalCustom(\n\tdice: string,\n\tcustomCritical: CustomCritical,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet customDice = dice;\n\tconst compareValue = diceTypeRandomParse(customCritical.value, template, engine);\n\tif (compareValue.includes(\"$\"))\n\t\tthrow new DiceTypeError(compareValue, \"createCriticalCustom\");\n\tconst comparaison = `${customCritical.sign}${compareValue}`;\n\tif (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);\n\telse customDice += comparaison;\n\treturn diceTypeRandomParse(customDice, template, engine);\n}\n\nfunction getModifier(dice: string) {\n\tconst modifier = dice.matchAll(/(\\+|-|%|\\/|\\^|\\*|\\*{2})(\\d+)/gi);\n\tlet modificator: Modifier | undefined;\n\tfor (const mod of modifier) {\n\t\t//calculate the modifier if multiple\n\t\tif (modificator) {\n\t\t\tconst sign = modificator.sign;\n\t\t\tlet value = modificator.value;\n\t\t\tif (sign) value = calculator(sign, value, Number.parseInt(mod[2], 10));\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue,\n\t\t\t};\n\t\t} else {\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue: Number.parseInt(mod[2], 10),\n\t\t\t};\n\t\t}\n\t}\n\treturn modificator;\n}\n\n/**\n * Parse the string provided and turn it as a readable dice for dice parser\n * @param dice {string}\n * @param engine\n * @param pity\n */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\t//parse dice string\n\tdice = standardizeDice(replaceFormulaInDice(dice))\n\t\t.replace(/^\\+/, \"\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimStart();\n\tif (!dice.includes(\"d\")) return undefined;\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet compare: ComparedValue | undefined;\n\tif (dice.includes(\";\")) return sharedRolls(dice, engine);\n\n\tdice = fixParenthesis(dice);\n\tconst modificator = getModifier(dice);\n\n\t// Extract compare BEFORE rolling to remove it from the dice notation\n\tif (compareRegex) {\n\t\tconst compareResult = getCompare(dice, compareRegex, engine, pity);\n\t\tdice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\n\tif (dice.match(/\\d+?#(.*)/)) {\n\t\tconst diceArray = dice.split(\"#\");\n\t\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\n\t\tconst diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\n\t\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\n\t\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\n\t\tconst roller = new DiceRoller();\n\t\tNumberGenerator.generator.engine = engine;\n\t\t//remove comments if any\n\t\tfor (let i = 0; i < numberOfDice; i++) {\n\t\t\ttry {\n\t\t\t\troller.roll(diceToRoll);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdice: diceToRoll,\n\t\t\tresult: roller.output,\n\t\t\tcomment: comments,\n\t\t\tcompare: compare ? compare : undefined,\n\t\t\tmodifier: modificator,\n\t\t\ttotal: roller.total,\n\t\t};\n\t}\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tconst diceWithoutComment = dice.replace(COMMENT_REGEX, \"\").trimEnd();\n\n\tlet diceRoll: DiceRoll | DiceRoll[];\n\ttry {\n\t\tdiceRoll = roller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\n\t// Update compare.trivial after rolling to get access to diceRoll for trivial detection\n\tif (compare && diceRoll) {\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxDiceValue = currentRoll.maxTotal;\n\t\tconst minDiceValue = currentRoll.minTotal;\n\t\tconst trivial = isTrivialComparison(maxDiceValue, minDiceValue, compare);\n\t\tcompare.trivial = trivial ? true : undefined;\n\t}\n\n\tconst commentMatch = dice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\n\tlet rerollCount = 0;\n\tlet res: Resultat | undefined;\n\tif (pity && compare) {\n\t\t// Vérifier si la comparaison est théoriquement possible\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\n\t\tconst isComparisonPossible =\n\t\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\n\n\t\tif (isComparisonPossible) {\n\t\t\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\n\t\t\tif (!isFail) {\n\t\t\t\t//reroll until success\n\t\t\t\tconst maxReroll = 100;\n\t\t\t\twhile (!isFail && rerollCount < maxReroll) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tres = roll(diceWithoutComment, engine, false); // désactiver pity pour éviter la récursion infinie\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t\t\t\t\t}\n\t\t\t\t\trerollCount++;\n\t\t\t\t\tif (res && res.total !== undefined)\n\t\t\t\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\n\t\t\t\t}\n\t\t\t\tif (res) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...res,\n\t\t\t\t\t\tdice,\n\t\t\t\t\t\tcomment,\n\t\t\t\t\t\tcompare: compare,\n\t\t\t\t\t\tmodifier: modificator,\n\t\t\t\t\t\tpityLogs: rerollCount,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t} else console.log(\"Comparison impossible, pity ignored\");\n\t}\n\treturn {\n\t\tdice,\n\t\tresult: roller.output,\n\t\tcomment,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t};\n}\n\n/**\n * Check if a comparison can theoretically succeed given a maximum roll value\n * @example\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\n */\nfunction canComparisonSucceed(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue?: number\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn maxRollValue > compare.value;\n\t\tcase \">=\":\n\t\t\treturn maxRollValue >= compare.value;\n\t\tcase \"<\":\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"<=\":\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\n\t\tcase \"!=\":\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction fixParenthesis(dice: string) {\n\t//dice with like 1d(20) are not valid, we need to remove the parenthesis\n\t//warning: the 1d(20+5) is valid and should not be changed\n\tconst parenthesisRegex = /d\\((\\d+)\\)/g;\n\treturn dice.replaceAll(parenthesisRegex, (_match, p1) => `d${p1}`);\n}\n\n/**\n * Evaluate a formula and replace \"^\" by \"**\" if any\n * @param {Sign} sign\n * @param {number} value\n * @param {number} total\n * @returns\n */\nexport function calculator(sign: Sign, value: number, total: number): number {\n\tif (sign === \"^\") sign = \"**\";\n\treturn evaluate(`${total} ${sign} ${value}`);\n}\n\nfunction inverseSign(\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\"\n): \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\" {\n\tswitch (sign) {\n\t\tcase \"<\":\n\t\t\treturn \">\";\n\t\tcase \">\":\n\t\t\treturn \"<\";\n\t\tcase \"<=\":\n\t\t\treturn \">=\";\n\t\tcase \">=\":\n\t\t\treturn \"<=\";\n\t\tcase \"=\":\n\t\t\treturn \"!=\";\n\t\tcase \"==\":\n\t\t\treturn \"!=\";\n\t\tcase \"!=\":\n\t\t\treturn \"==\";\n\t}\n}\n\nfunction replaceInFormula(\n\telement: string,\n\tdiceResult: Resultat,\n\tcompareResult: { dice: string; compare: Compare | undefined },\n\tres: boolean,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tconst { formule, diceAll } = replaceText(\n\t\telement,\n\t\tdiceResult.total ?? 0,\n\t\tdiceResult.dice\n\t);\n\tconst validSign = res ? \"✓\" : \"✕\";\n\tconst invertedSign = res\n\t\t? compareResult.compare!.sign\n\t\t: inverseSign(compareResult.compare!.sign);\n\tlet evaluateRoll: unknown;\n\ttry {\n\t\tevaluateRoll = evaluate(compareResult.dice);\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t} catch (error) {\n\t\tconst evaluateRoll = roll(compareResult.dice, engine, pity) as Resultat | undefined;\n\t\tif (evaluateRoll)\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\n\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t}\n}\n\nfunction compareSignFormule(\n\ttoRoll: string,\n\tcompareRegex: RegExpMatchArray,\n\telement: string,\n\tdiceResult: Resultat,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet results = \"\";\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\n\tlet res: unknown;\n\ttry {\n\t\tres = evaluate(toCompare);\n\t} catch (error) {\n\t\tres = roll(toCompare, engine, pity);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\n\t} else if (res instanceof Object) {\n\t\tconst diceResult = res as Resultat;\n\t\tif (diceResult.compare) {\n\t\t\tconst toEvaluate = evaluate(\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\n\t\t\t);\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\n\t\t\tconst invertedSign = toEvaluate\n\t\t\t\t? diceResult.compare.sign\n\t\t\t\t: inverseSign(diceResult.compare.sign);\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\n\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\n\t\t}\n\t}\n\treturn { dice: compareResult.dice, results };\n}\n\nfunction replaceText(element: string, total: number, dice: string) {\n\treturn {\n\t\tformule: element.replace(SYMBOL_DICE, `[${total}]`).replace(/%.*%/g, \"\").trim(),\n\t\tdiceAll: element\n\t\t\t.replace(SYMBOL_DICE, `[${dice.replace(COMMENT_REGEX, \"\")}]`)\n\t\t\t.replace(/%.*%/g, \"\")\n\t\t\t.trim(),\n\t};\n}\n\nfunction formatComment(dice: string) {\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\n\tconst commentsMatch = commentsRegex.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\n\t// to avoid conflicts with parentheses inside bracket comments\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\n\n\t//fusion of both comments with a space if both exists\n\t//result expected = \"__comment1 comment2__ — \"\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\n\tlet finalComment = \"\";\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\n\telse if (comments) finalComment = `__${comments}__ — `;\n\telse if (optional) finalComment = `__${optional}__ — `;\n\treturn finalComment;\n}\n\nfunction sharedRolls(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\tif (dice.match(/\\d+?#(.*?)/))\n\t\tthrow new DiceTypeError(\n\t\t\tdice,\n\t\t\t\"noBulkRoll\",\n\t\t\t\"bulk roll are not allowed in shared rolls\"\n\t\t);\n\tconst results = [];\n\tconst mainComment =\n\t\t/\\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? undefined;\n\tconst split = dice.split(\";\");\n\tlet diceMain = fixParenthesis(split[0]);\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\t// Remove comments before checking for hidden dice (parentheses)\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\n\tlet hidden = false;\n\tif (toHide?.dice) {\n\t\tdiceMain = toHide.dice;\n\t\thidden = true;\n\t} else if (toHide) {\n\t\tdiceMain = \"1d1\";\n\t\thidden = true;\n\t} else {\n\t\t// No hidden dice, use the dice without comments\n\t\tdiceMain = diceMainWithoutComments;\n\t}\n\tlet diceResult = roll(diceMain, engine, pity);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\n\t\t\thidden = false;\n\t\t} else return undefined;\n\t}\n\tif (!diceResult || !diceResult.total) return undefined;\n\tresults.push(`※ ${comments}${diceResult.result}`);\n\tlet total = diceResult.total;\n\tdiceResult.comment = mainComment;\n\tif (!total) return diceResult;\n\tfor (let element of split.slice(1)) {\n\t\tconst comment = formatComment(element);\n\t\telement = element\n\t\t\t.replaceAll(commentsRegex, \"\")\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\n\t\t\t.trim();\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\n\t\t//remove comments\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\n\t\tif (compareRegex) {\n\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\ttoRoll,\n\t\t\t\tcompareRegex,\n\t\t\t\telement,\n\t\t\t\tdiceResult,\n\t\t\t\tengine\n\t\t\t);\n\t\t\ttoRoll = compareResult.dice;\n\t\t\tresults.push(compareResult.results);\n\t\t} else {\n\t\t\tconst { formule, diceAll } = replaceText(\n\t\t\t\telement,\n\t\t\t\tdiceResult.total,\n\t\t\t\tdiceResult.dice\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\n\t\t\t} catch (error) {\n\t\t\t\tconst evaluated = roll(toRoll, engine, pity);\n\t\t\t\tif (evaluated)\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\n\t\t\t\t\t);\n\t\t\t\telse results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += evaluated?.total ?? 0;\n\t\t\t}\n\t\t}\n\t}\n\tif (hidden)\n\t\t//remove the first in result\n\t\tresults.shift();\n\treturn {\n\t\tdice: diceMain,\n\t\tresult: results.join(\";\"),\n\t\tcomment: mainComment,\n\t\tcompare: diceResult.compare,\n\t\tmodifier: diceResult.modifier,\n\t\ttotal,\n\t};\n}\n","export class DiceTypeError extends Error {\n\tpublic readonly dice: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(dice: string, cause?: string, method?: unknown) {\n\t\tsuper(dice);\n\t\tthis.name = \"Invalid_Dice_Type\";\n\t\tthis.dice = dice;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class FormulaError extends Error {\n\tpublic readonly formula: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(formula: string, cause?: string, method?: unknown) {\n\t\tsuper(formula);\n\t\tthis.name = \"Invalid_Formula\";\n\t\tthis.formula = formula;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class MaxGreater extends Error {\n\tpublic readonly name: string;\n\tpublic readonly value: number;\n\tpublic readonly max: number;\n\n\tconstructor(value: number, max: number) {\n\t\tsuper(value.toString());\n\t\tthis.name = \"Max_Greater\";\n\t\tthis.value = value;\n\t\tthis.max = max;\n\t}\n}\n\nexport class EmptyObjectError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Empty_Object\";\n\t}\n}\n\nexport class TooManyDice extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Dice\";\n\t}\n}\n\nexport class TooManyStats extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Stats\";\n\t}\n}\n\nexport class NoStatisticsError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"No_Statistics\";\n\t}\n}\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\n// Use negative lookbehind to check for ![<>] before any comparison operator\nexport const SIGN_REGEX =\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\nexport const SIGN_REGEX_SPACE =\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\n","/**\n * Definition of the Zod schema for template data\n */\nimport { z } from \"zod\";\n\nconst statisticValueSchema = z\n\t.object({\n\t\tmax: z\n\t\t\t.number()\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t\t.optional(),\n\t\tmin: z\n\t\t\t.number()\n\t\t\t.transform((val) =>\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\n\t\t\t)\n\t\t\t.optional(),\n\t\tcombinaison: z\n\t\t\t.string()\n\t\t\t.transform((str) => str.trim() || undefined)\n\t\t\t.optional(),\n\t\texclude: z.boolean().optional(),\n\t})\n\t.superRefine((data, ctx) => {\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\n\t\t\t\tpath: [\"max\"],\n\t\t\t});\n\t\t}\n\t});\n\nconst statisticSchema = z\n\t.record(z.string(), statisticValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyStats\",\n\t});\n\nconst criticalSchema = z\n\t.object({\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\n\t})\n\t.transform((values) => {\n\t\tif (values.success === \"\") values.success = undefined;\n\t\tif (values.failure === \"\") values.failure = undefined;\n\t\tif (values.failure === 0) values.failure = undefined;\n\t\tif (values.success === 0) values.success = undefined;\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\n\t\treturn values;\n\t});\n\nconst criticalValueSchema = z.object({\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\n\tvalue: z.string(),\n\tonNaturalDice: z.boolean().optional(),\n\taffectSkill: z.boolean().optional(),\n});\n\nconst damageSchema = z\n\t.record(z.string(), z.string())\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nconst customCriticalSchema = z\n\t.record(z.string(), criticalValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nexport const templateSchema = z.object({\n\tcharName: z.boolean().optional(),\n\tstatistics: statisticSchema,\n\ttotal: z\n\t\t.number()\n\t\t.min(0)\n\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t.optional(),\n\tforceDistrib: z.boolean().optional(),\n\tdiceType: z.string().optional(),\n\tcritical: criticalSchema.optional(),\n\tcustomCritical: customCriticalSchema,\n\tdamage: damageSchema,\n});\n","import { evaluate } from \"mathjs\";\nimport \"uniformize\";\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { type Engine, Random } from \"random-js\";\nimport { FormulaError } from \".\";\n\n/**\n * Escape regex string\n * @param string {string}\n */\nexport function escapeRegex(string: string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Allow to keep the text as if in brackets\n * @param dice {string}\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\n */\nexport function standardizeDice(dice: string): string {\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\n\t);\n}\n\n/**\n * Replace the stat name by their value using stat\n * and after evaluate any formula using `replaceFormulaInDice`\n * @param {string} originalDice\n * @param {Record<string,number>|undefined} stats\n * @param {string|undefined} dollarValue\n */\nexport function generateStatsDice(\n\toriginalDice: string,\n\tstats?: Record<string, number>,\n\tdollarValue?: string\n) {\n\tlet dice = originalDice.standardize();\n\tif (stats && Object.keys(stats).length > 0) {\n\t\tconst statKeys = Object.keys(stats);\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\n\t\tlet result = \"\";\n\t\tlet match: RegExpExecArray | null;\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\n\t\t\tconst insideBrackets = match[1];\n\t\t\tconst outsideText = match[2];\n\t\t\tif (insideBrackets) {\n\t\t\t\tresult += insideBrackets;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!outsideText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\n\t\t\tlet lastIndex = 0;\n\t\t\tlet tokenMatch: RegExpExecArray | null;\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\n\t\t\t\tconst token = tokenMatch[0];\n\t\t\t\tconst tokenStd = token.standardize();\n\t\t\t\tlet bestKey: string | null = null;\n\t\t\t\tlet bestScore = 0;\n\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\tif (\n\t\t\t\t\t\ttokenStd === keyStd ||\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\n\t\t\t\t\t) {\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t\tbestScore = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\n\t\t\t\t\tif (score > bestScore) {\n\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\n\t\t\t\t\tconst statValue = stats[bestKey];\n\t\t\t\t\tresult += statValue.toString();\n\t\t\t\t} else {\n\t\t\t\t\tresult += token;\n\t\t\t\t}\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t}\n\t\t\tresult += outsideText.slice(lastIndex);\n\t\t}\n\t\tdice = result;\n\t}\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\n\treturn replaceFormulaInDice(dice);\n}\n\n/**\n * Replace the {{}} in the dice string and evaluate the interior if any\n * @param dice {string}\n */\nexport function replaceFormulaInDice(dice: string) {\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\n\tlet match;\n\tlet modifiedDice = dice;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\twhile ((match = formula.exec(dice)) !== null) {\n\t\tif (match.groups?.formula) {\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\n\t\t\ttry {\n\t\t\t\tconst result = evaluate(formulae);\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cleanedDice(modifiedDice);\n}\n\n/**\n * Replace the ++ +- -- by their proper value:\n * - `++` = `+`\n * - `+-` = `-`\n * - `--` = `+`\n * @param dice {string}\n */\nfunction cleanedDice(dice: string) {\n\treturn dice\n\t\t.replaceAll(\"+-\", \"-\")\n\t\t.replaceAll(\"--\", \"+\")\n\t\t.replaceAll(\"++\", \"+\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimEnd();\n}\n\n/**\n * Verify if a value is a number, even if it's a \"number\" string\n * @param value {unknown}\n * @returns {boolean}\n */\nexport function isNumber(value: unknown): boolean {\n\treturn (\n\t\tvalue !== undefined &&\n\t\t(typeof value === \"number\" ||\n\t\t\t(!Number.isNaN(Number(value)) &&\n\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\tvalue.trim().length > 0))\n\t);\n}\n\n/**\n * Replace the `{exp}` in the dice.\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\n * @param {string} dice\n * @param engine\n * @returns {string} the dice with the {exp} replaced by a random value\n */\nexport function replaceExpByRandom(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): string {\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\n\t\tconst defaultValue = groups?.default;\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\n\t});\n}\n\n/**\n * Utility function to get a random integer between min and max and using the specified engine\n * @param min {number}\n * @param max {number}\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\n * @returns {number} Random integer between min and max\n */\nexport function randomInt(\n\tmin: number,\n\tmax: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\trng?: Random\n): number {\n\tif (!rng) rng = new Random(engine || undefined);\n\treturn rng.integer(min, max);\n}\n/**\n * Utility function that allow to get the id of an engine\n * @param engine {unknown} Engine to identify\n * @returns {string} Id of the engine or \"unknown\"\n * @private\n */\nexport function getEngineId(engine: unknown): string {\n\t// Comparaisons directes avec les engines exposés par la lib\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\n\t// Fallback: essayer de lire un nom ou le constructeur\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\n\t\tconst e = engine as any;\n\t\tif (e && typeof e === \"object\") {\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\n\t\t\tif (e.constructor?.name) return e.constructor.name;\n\t\t}\n\t} catch {\n\t\t/* ignore */\n\t}\n\treturn \"unknown\";\n}\n\n/**\n * Utility function to get the engine from its name\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\n * @returns {Engine} The engine\n * @public\n */\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\n\tswitch (engine) {\n\t\tcase \"nativeMath\":\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t\tcase \"browserCrypto\":\n\t\t\treturn NumberGenerator.engines.browserCrypto;\n\t\tcase \"nodeCrypto\":\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\n\t\tdefault:\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t}\n}\n\n/**\n * Calcule la distance de Levenshtein entre deux chaînes\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\tif (a === b) return 0;\n\tconst al = a.length;\n\tconst bl = b.length;\n\tif (al === 0) return bl;\n\tif (bl === 0) return al;\n\tconst v0 = new Array<number>(bl + 1);\n\tconst v1 = new Array<number>(bl + 1);\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\n\tfor (let i = 0; i < al; i++) {\n\t\tv1[0] = i + 1;\n\t\tfor (let j = 0; j < bl; j++) {\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n\t\t}\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\n\t}\n\treturn v1[bl];\n}\n\n/**\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\n */\nfunction similarityScore(a: string, b: string): number {\n\tconst la = a.length;\n\tconst lb = b.length;\n\tif (la === 0 && lb === 0) return 1;\n\tconst dist = levenshteinDistance(a, b);\n\tconst max = Math.max(la, lb);\n\treturn 1 - dist / max;\n}\n","import { evaluate } from \"mathjs\";\nimport { type Engine, Random } from \"random-js\";\nimport \"uniformize\";\n\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport {\n\tcreateCriticalCustom,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tEmptyObjectError,\n\tescapeRegex,\n\tFormulaError,\n\tNoStatisticsError,\n\treplaceExpByRandom,\n\treplaceFormulaInDice,\n\troll,\n\ttype StatisticalTemplate,\n\tTooManyDice,\n\ttemplateSchema,\n} from \".\";\nimport { isNumber, randomInt } from \"./utils\";\n\n/**\n * Verify if the provided dice work with random value\n * @param testDice {string}\n * @param allStats {Record<string,number>}\n * @param engine\n * @param pity\n */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet dice = testDice.trimEnd();\n\tif (allStats && Object.keys(allStats).length > 0) {\n\t\tconst names = Object.keys(allStats);\n\t\tfor (const name of names) {\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\t\tif (dice.standardize().match(regex)) {\n\t\t\t\tconst statValue = allStats[name];\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\n\t\t\t}\n\t\t}\n\t}\n\ttry {\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\n\t\treturn testDice;\n\t} catch (error) {\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\n\t}\n}\n\n/**\n * Generate a random dice and remove the formula (+ evaluate it)\n * Used for diceDamage only\n * @param value {string}\n * @param template {StatisticalTemplate}\n * @param engine\n * @returns\n */\nexport function diceRandomParse(\n\tvalue: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\n\tvalue = value.standardize();\n\tconst statNames = Object.keys(template.statistics);\n\tlet newDice = value;\n\tfor (const name of statNames) {\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\tif (value.match(regex)) {\n\t\t\tlet max: undefined | number;\n\t\t\tlet min: undefined | number;\n\t\t\tconst foundStat = template.statistics?.[name];\n\t\t\tif (foundStat) {\n\t\t\t\tmax = foundStat.max;\n\t\t\t\tmin = foundStat.min;\n\t\t\t}\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\n\t\t}\n\t}\n\treturn replaceFormulaInDice(newDice);\n}\n\n/**\n * Same as damageDice but for DiceType\n * @param dice {string}\n * @param template {StatisticalTemplate}\n * @param engine\n */\nexport function diceTypeRandomParse(\n\tdice: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tdice = replaceExpByRandom(dice);\n\tif (!template.statistics) return dice;\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\n\t\t(stat) => !template.statistics?.[stat].combinaison\n\t);\n\tif (!firstStatNotcombinaison) return dice;\n\tconst stats = template.statistics[firstStatNotcombinaison];\n\tconst { min, max } = stats;\n\tconst total = template.total || 100;\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\n}\n\n/**\n * Random the combinaison and evaluate it to check if everything is valid\n * @param combinaison {Record<string,string>}\n * @param stats {Record<string,number|number>}\n */\nexport function evalCombinaison(\n\tcombinaison: Record<string, string>,\n\tstats: Record<string, number | string>\n) {\n\tconst newStats: Record<string, number> = {};\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\n\t\t//replace the stats in formula\n\t\tlet formula = combin.standardize();\n\t\tfor (const [statName, value] of Object.entries(stats)) {\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\t\tformula = formula.replace(regex, value.toString());\n\t\t}\n\t\ttry {\n\t\t\tnewStats[stat] = evaluate(formula);\n\t\t} catch (error) {\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\n\t\t}\n\t}\n\treturn newStats;\n}\n\n/**\n * Evaluate one selected combinaison\n * @param combinaison {string}\n * @param stats {[name: string]: string|number}\n */\nexport function evalOneCombinaison(\n\tcombinaison: string,\n\tstats: Record<string, number | string>\n) {\n\tlet formula = combinaison.standardize();\n\tfor (const [statName, value] of Object.entries(stats)) {\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\tformula = formula.replace(regex, value.toString());\n\t}\n\ttry {\n\t\treturn evaluate(formula);\n\t} catch (error) {\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\n\t}\n}\n\nfunction convertNumber(number: string | number | undefined) {\n\tif (number === undefined || number === null) return undefined;\n\tif (\n\t\tnumber.toString().length === 0 ||\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\n\t)\n\t\treturn undefined;\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\n\treturn undefined;\n}\n\n/**\n * Parse the provided JSON and verify each field to check if everything could work when rolling\n * @param {unknown} template\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\n * @param engine\n * @returns {StatisticalTemplate}\n */\nexport function verifyTemplateValue(\n\ttemplate: unknown,\n\tverify = true,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): StatisticalTemplate {\n\tconst parsedTemplate = templateSchema.parse(template);\n\tconst { success, failure } = parsedTemplate.critical ?? {};\n\tconst criticicalVal = {\n\t\tsuccess: convertNumber(success),\n\t\tfailure: convertNumber(failure),\n\t};\n\tconst statistiqueTemplate: StatisticalTemplate = {\n\t\tdiceType: parsedTemplate.diceType,\n\t\tstatistics: parsedTemplate.statistics,\n\t\tcritical: criticicalVal,\n\t\ttotal: parsedTemplate.total,\n\t\tcharName: parsedTemplate.charName,\n\t\tdamage: parsedTemplate.damage,\n\t\tcustomCritical: parsedTemplate.customCritical,\n\t\tforceDistrib: parsedTemplate.forceDistrib,\n\t};\n\tif (!verify) return statistiqueTemplate;\n\tif (statistiqueTemplate.diceType) {\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\n\t\t\tthrow new DiceTypeError(\n\t\t\t\tstatistiqueTemplate.diceType,\n\t\t\t\t\"critical_dice_type\",\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\n\t\t\t);\n\t\t}\n\t\tconst cleanedDice = diceTypeRandomParse(\n\t\t\tstatistiqueTemplate.diceType,\n\t\t\tstatistiqueTemplate,\n\t\t\tengine\n\t\t);\n\t\tconst rolled = roll(cleanedDice, engine);\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\n\t}\n\tif (statistiqueTemplate.customCritical) {\n\t\tif (!statistiqueTemplate.diceType) {\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\n\t\t}\n\t\tconst customCritical = statistiqueTemplate.customCritical;\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\n\t\t\tconst cleanedDice = createCriticalCustom(\n\t\t\t\tstatistiqueTemplate.diceType!,\n\t\t\t\tcustom,\n\t\t\t\tstatistiqueTemplate,\n\t\t\t\tengine\n\t\t\t);\n\t\t\tconst rolled = roll(cleanedDice, engine);\n\t\t\tif (!rolled)\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\n\t\t}\n\t}\n\ttestDiceRegistered(statistiqueTemplate, engine);\n\ttestStatCombinaison(statistiqueTemplate, engine);\n\treturn statistiqueTemplate;\n}\n\n/**\n * Test each damage roll from the template.damage\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testDiceRegistered(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.damage) return;\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\n\tfor (const [name, dice] of Object.entries(template.damage)) {\n\t\tif (!dice) continue;\n\t\tconst diceReplaced = replaceExpByRandom(dice);\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\n\t\ttry {\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\n\t\t}\n\t}\n}\n\n/**\n * Test all combinaison with generated random value\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testStatCombinaison(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return;\n\tconst onlycombinaisonStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(\n\t\t\t([_, value]) => value.combinaison !== undefined\n\t\t)\n\t);\n\tconst allOtherStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\n\t);\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\n\tconst allStats = Object.keys(template.statistics).filter(\n\t\t(stat) => !template.statistics![stat].combinaison\n\t);\n\tif (allStats.length === 0) throw new NoStatisticsError();\n\tconst error = [];\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\n\t\tlet formula = value.combinaison as string;\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\n\t\t\tconst { max, min } = data;\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tconst regex = new RegExp(other, \"gi\");\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\n\t\t}\n\t\ttry {\n\t\t\tevaluate(formula);\n\t\t} catch (e) {\n\t\t\terror.push(stat);\n\t\t}\n\t}\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\n\treturn;\n}\n\n/**\n * Generate a random stat based on the template and the statistical min and max\n * @param {number|undefined} total\n * @param {number | undefined} max\n * @param {number | undefined} min\n * @param engine\n * @returns\n */\nexport function generateRandomStat(\n\ttotal: number | undefined = 100,\n\tmax?: number,\n\tmin?: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tlet randomStatValue = total + 1;\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\n\twhile (randomStatValue >= total || randomStatValue === 0) {\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\n\t\telse randomStatValue = randomInt(1, total, engine, random);\n\t}\n\treturn randomStatValue;\n}\n"],"mappings":"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","names":["roller","evaluateRoll","diceResult","import_mathjs","import_rpg_dice_roller","import_mathjs","import_random_js","import_uniformize","import_rpg_dice_roller","cleanedDice"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/dice.ts","../src/errors.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/utils.ts","../src/verify_template.ts"],"sourcesContent":["export * from \"./dice\";\nexport * from \"./errors\";\nexport * from \"./interfaces\";\nexport * from \"./interfaces/constant\";\nexport * from \"./interfaces/toJsonSchema\";\nexport * from \"./interfaces/zod\";\nexport * from \"./utils\";\nexport * from \"./verify_template\";\n","import { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport {\n\tCOMMENT_REGEX,\n\ttype Compare,\n\ttype ComparedValue,\n\ttype CustomCritical,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tdiceTypeRandomParse,\n\tisNumber,\n\ttype Modifier,\n\tOPTIONAL_COMMENT,\n\ttype Resultat,\n\treplaceFormulaInDice,\n\tSIGN_REGEX,\n\tSIGN_REGEX_SPACE,\n\ttype Sign,\n\ttype StatisticalTemplate,\n\tSYMBOL_DICE,\n\tstandardizeDice,\n} from \".\";\n\n/**\n * Check if a comparison is trivial (always true or always false)\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\n * @param maxValue Maximum possible value from the dice roll\n * @param minValue Minimum possible value from the dice roll\n * @param compare The comparison object\n * @returns true if the comparison is trivial (always true or always false)\n */\nfunction isTrivialComparison(\n\tmaxValue: number,\n\tminValue: number,\n\tcompare: ComparedValue\n): boolean {\n\t// Check if comparison can never succeed (always false)\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\n\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\n\n\t// Trivial if it can never succeed OR can never fail\n\treturn !canSucceed || !canFail;\n}\n\n/**\n * Check if a comparison can theoretically fail given roll bounds\n * @param maxRollValue Maximum possible roll value\n * @param compare The comparison object\n * @param minRollValue Minimum possible roll value (defaults to 1)\n * @returns true if the comparison can fail at least once\n */\nfunction canComparisonFail(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue = 1\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\n\t\tcase \">=\":\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\n\t\tcase \"<\":\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\n\t\tcase \"<=\":\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\n\t\tcase \"!=\":\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; compare: ComparedValue | undefined } {\n\t/**\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\n\t * Some system count the number of a dice that are greater than or equal to a target, and not the \"total\" of rolled dice.\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\n\t * To support this, we use the group notation. It a little different than the notation of dice-roller, but it a sacrifice to not break the current notation.\n\t * @note:\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\n\t * - `{2d3>=4}` will count the total of dice that are greater than or equal to 4, and not the total of the dice.\n\t * - `{2d3,1d4}>=4` won't use the comparison, but will count the number of dice that are greater than or equal to 4. If the total of the dice is needed, just remove the group notation and use `2d3+1d4>=4`.\n\t */\n\tif (\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\n\t)\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\n\tconst calc = compareRegex[2];\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\n\n\tif (sign) {\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\n\t\tconst total = evaluate(rCompare.value.toString());\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: total,\n\t\t\toriginalDice: rCompare.dice,\n\t\t\trollValue: rCompare.diceResult,\n\t\t};\n\t} else {\n\t\tconst rcompare = rollCompare(calc, engine, pity);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: rcompare.value,\n\t\t\toriginalDice: rcompare.dice,\n\t\t\trollValue: rcompare.diceResult,\n\t\t};\n\t}\n\n\treturn { dice, compare };\n}\n\nfunction rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\t// Handle empty value or string - return 0 as default\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n\t\treturn { value: 0, diceResult: value as string };\n\t}\n\tconst rollComp = roll(value as string, engine, pity);\n\tif (!rollComp?.total) {\n\t\t//not a dice throw\n\t\ttry {\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\n\t\t} catch (error) {\n\t\t\t// If evaluate fails, return 0\n\t\t\treturn { value: 0, diceResult: value as string };\n\t\t}\n\t}\n\treturn {\n\t\tdice: value as string,\n\t\tvalue: rollComp.total,\n\t\tdiceResult: rollComp?.result,\n\t};\n}\n\n/**\n * Allow to replace the compare part of a dice and use the critical customized one\n * @example\n * dice = \"1d20=20\";\n * custom critical {sign: \">\", value: \"$/2\"}\n * Random stats = 6\n * result = \"1d20>3\"\n */\nexport function createCriticalCustom(\n\tdice: string,\n\tcustomCritical: CustomCritical,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet customDice = dice;\n\tconst compareValue = diceTypeRandomParse(customCritical.value, template, engine);\n\tif (compareValue.includes(\"$\"))\n\t\tthrow new DiceTypeError(compareValue, \"createCriticalCustom\");\n\tconst comparaison = `${customCritical.sign}${compareValue}`;\n\tif (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);\n\telse customDice += comparaison;\n\treturn diceTypeRandomParse(customDice, template, engine);\n}\n\nfunction getModifier(dice: string) {\n\tconst modifier = dice.matchAll(/(\\+|-|%|\\/|\\^|\\*|\\*{2})(\\d+)/gi);\n\tlet modificator: Modifier | undefined;\n\tfor (const mod of modifier) {\n\t\t//calculate the modifier if multiple\n\t\tif (modificator) {\n\t\t\tconst sign = modificator.sign;\n\t\t\tlet value = modificator.value;\n\t\t\tif (sign) value = calculator(sign, value, Number.parseInt(mod[2], 10));\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue,\n\t\t\t};\n\t\t} else {\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue: Number.parseInt(mod[2], 10),\n\t\t\t};\n\t\t}\n\t}\n\treturn modificator;\n}\n\n/**\n * Parse the string provided and turn it as a readable dice for dice parser\n * @param dice {string}\n * @param engine\n * @param pity\n */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\t//parse dice string\n\tdice = standardizeDice(replaceFormulaInDice(dice))\n\t\t.replace(/^\\+/, \"\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimStart();\n\tif (!dice.includes(\"d\")) return undefined;\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet compare: ComparedValue | undefined;\n\tif (dice.includes(\";\")) return sharedRolls(dice, engine);\n\n\tdice = fixParenthesis(dice);\n\tconst modificator = getModifier(dice);\n\n\t// Extract compare BEFORE rolling to remove it from the dice notation\n\tif (compareRegex) {\n\t\tconst compareResult = getCompare(dice, compareRegex, engine, pity);\n\t\tdice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\n\tif (dice.match(/\\d+?#(.*)/)) {\n\t\tconst diceArray = dice.split(\"#\");\n\t\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\n\t\tconst diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\n\t\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\n\t\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\n\t\tconst roller = new DiceRoller();\n\t\tNumberGenerator.generator.engine = engine;\n\t\t//remove comments if any\n\t\tfor (let i = 0; i < numberOfDice; i++) {\n\t\t\ttry {\n\t\t\t\troller.roll(diceToRoll);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdice: diceToRoll,\n\t\t\tresult: roller.output,\n\t\t\tcomment: comments,\n\t\t\tcompare: compare ? compare : undefined,\n\t\t\tmodifier: modificator,\n\t\t\ttotal: roller.total,\n\t\t};\n\t}\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tconst diceWithoutComment = dice.replace(COMMENT_REGEX, \"\").trimEnd();\n\n\tlet diceRoll: DiceRoll | DiceRoll[];\n\ttry {\n\t\tdiceRoll = roller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\n\t// Update compare.trivial after rolling to get access to diceRoll for trivial detection\n\tif (compare && diceRoll) {\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxDiceValue = currentRoll.maxTotal;\n\t\tconst minDiceValue = currentRoll.minTotal;\n\t\tconst trivial = isTrivialComparison(maxDiceValue, minDiceValue, compare);\n\t\tcompare.trivial = trivial ? true : undefined;\n\t}\n\n\tconst commentMatch = dice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\n\tlet rerollCount = 0;\n\tlet res: Resultat | undefined;\n\tif (pity && compare) {\n\t\t// Vérifier si la comparaison est théoriquement possible\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\n\t\tconst isComparisonPossible =\n\t\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\n\n\t\tif (isComparisonPossible) {\n\t\t\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\n\t\t\tif (!isFail) {\n\t\t\t\t//reroll until success\n\t\t\t\tconst maxReroll = 100;\n\t\t\t\twhile (!isFail && rerollCount < maxReroll) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tres = roll(diceWithoutComment, engine, false); // désactiver pity pour éviter la récursion infinie\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t\t\t\t\t}\n\t\t\t\t\trerollCount++;\n\t\t\t\t\tif (res && res.total !== undefined)\n\t\t\t\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\n\t\t\t\t}\n\t\t\t\tif (res) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...res,\n\t\t\t\t\t\tdice,\n\t\t\t\t\t\tcomment,\n\t\t\t\t\t\tcompare: compare,\n\t\t\t\t\t\tmodifier: modificator,\n\t\t\t\t\t\tpityLogs: rerollCount,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t} else console.log(\"Comparison impossible, pity ignored\");\n\t}\n\treturn {\n\t\tdice,\n\t\tresult: roller.output,\n\t\tcomment,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t};\n}\n\n/**\n * Check if a comparison can theoretically succeed given a maximum roll value\n * @example\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\n */\nfunction canComparisonSucceed(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue?: number\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn maxRollValue > compare.value;\n\t\tcase \">=\":\n\t\t\treturn maxRollValue >= compare.value;\n\t\tcase \"<\":\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"<=\":\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\n\t\tcase \"!=\":\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction fixParenthesis(dice: string) {\n\t//dice with like 1d(20) are not valid, we need to remove the parenthesis\n\t//warning: the 1d(20+5) is valid and should not be changed\n\tconst parenthesisRegex = /d\\((\\d+)\\)/g;\n\treturn dice.replaceAll(parenthesisRegex, (_match, p1) => `d${p1}`);\n}\n\n/**\n * Evaluate a formula and replace \"^\" by \"**\" if any\n * @param {Sign} sign\n * @param {number} value\n * @param {number} total\n * @returns\n */\nexport function calculator(sign: Sign, value: number, total: number): number {\n\tif (sign === \"^\") sign = \"**\";\n\treturn evaluate(`${total} ${sign} ${value}`);\n}\n\nfunction inverseSign(\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\"\n): \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\" {\n\tswitch (sign) {\n\t\tcase \"<\":\n\t\t\treturn \">\";\n\t\tcase \">\":\n\t\t\treturn \"<\";\n\t\tcase \"<=\":\n\t\t\treturn \">=\";\n\t\tcase \">=\":\n\t\t\treturn \"<=\";\n\t\tcase \"=\":\n\t\t\treturn \"!=\";\n\t\tcase \"==\":\n\t\t\treturn \"!=\";\n\t\tcase \"!=\":\n\t\t\treturn \"==\";\n\t}\n}\n\nfunction replaceInFormula(\n\telement: string,\n\tdiceResult: Resultat,\n\tcompareResult: { dice: string; compare: Compare | undefined },\n\tres: boolean,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tconst { formule, diceAll } = replaceText(\n\t\telement,\n\t\tdiceResult.total ?? 0,\n\t\tdiceResult.dice\n\t);\n\tconst validSign = res ? \"✓\" : \"✕\";\n\tconst invertedSign = res\n\t\t? compareResult.compare!.sign\n\t\t: inverseSign(compareResult.compare!.sign);\n\tlet evaluateRoll: unknown;\n\ttry {\n\t\tevaluateRoll = evaluate(compareResult.dice);\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t} catch (error) {\n\t\tconst evaluateRoll = roll(compareResult.dice, engine, pity) as Resultat | undefined;\n\t\tif (evaluateRoll)\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\n\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t}\n}\n\nfunction compareSignFormule(\n\ttoRoll: string,\n\tcompareRegex: RegExpMatchArray,\n\telement: string,\n\tdiceResult: Resultat,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; results: string; compare?: Compare; trivial: boolean } {\n\tlet results = \"\";\n\tlet trivial = false;\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\n\tlet res: unknown;\n\ttry {\n\t\tres = evaluate(toCompare);\n\t} catch (error) {\n\t\tres = roll(toCompare, engine, pity);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\ttrivial = true;\n\t\tif (compareResult.compare) compareResult.compare.trivial = true;\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\n\t} else if (res instanceof Object) {\n\t\tconst diceResult = res as Resultat;\n\t\tif (diceResult.compare) {\n\t\t\tconst toEvaluate = evaluate(\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\n\t\t\t);\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\n\t\t\tconst invertedSign = toEvaluate\n\t\t\t\t? diceResult.compare.sign\n\t\t\t\t: inverseSign(diceResult.compare.sign);\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\n\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\n\t\t\tif (diceResult.compare.trivial) trivial = true;\n\t\t}\n\t}\n\treturn { dice: compareResult.dice, results, compare: compareResult.compare, trivial };\n}\n\nfunction replaceText(element: string, total: number, dice: string) {\n\treturn {\n\t\tformule: element.replace(SYMBOL_DICE, `[${total}]`).replace(/%.*%/g, \"\").trim(),\n\t\tdiceAll: element\n\t\t\t.replace(SYMBOL_DICE, `[${dice.replace(COMMENT_REGEX, \"\")}]`)\n\t\t\t.replace(/%.*%/g, \"\")\n\t\t\t.trim(),\n\t};\n}\n\nfunction formatComment(dice: string) {\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\n\tconst commentsMatch = commentsRegex.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\n\t// to avoid conflicts with parentheses inside bracket comments\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\n\n\t//fusion of both comments with a space if both exists\n\t//result expected = \"__comment1 comment2__ — \"\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\n\tlet finalComment = \"\";\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\n\telse if (comments) finalComment = `__${comments}__ — `;\n\telse if (optional) finalComment = `__${optional}__ — `;\n\treturn finalComment;\n}\n\nfunction sharedRolls(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\tif (dice.match(/\\d+?#(.*?)/))\n\t\tthrow new DiceTypeError(\n\t\t\tdice,\n\t\t\t\"noBulkRoll\",\n\t\t\t\"bulk roll are not allowed in shared rolls\"\n\t\t);\n\tconst results = [];\n\tconst mainComment =\n\t\t/\\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? undefined;\n\tconst split = dice.split(\";\");\n\tlet diceMain = fixParenthesis(split[0]);\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\t// Remove comments before checking for hidden dice (parentheses)\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\n\tlet hidden = false;\n\tif (toHide?.dice) {\n\t\tdiceMain = toHide.dice;\n\t\thidden = true;\n\t} else if (toHide) {\n\t\tdiceMain = \"1d1\";\n\t\thidden = true;\n\t} else {\n\t\t// No hidden dice, use the dice without comments\n\t\tdiceMain = diceMainWithoutComments;\n\t}\n\tlet diceResult = roll(diceMain, engine, pity);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\n\t\t\thidden = false;\n\t\t} else return undefined;\n\t}\n\tif (!diceResult || !diceResult.total) return undefined;\n\tlet aggregatedCompare = diceResult.compare;\n\tlet hasTrivialComparison = diceResult.compare?.trivial === true;\n\tresults.push(`※ ${comments}${diceResult.result}`);\n\tlet total = diceResult.total;\n\tdiceResult.comment = mainComment;\n\tif (!total) return diceResult;\n\tfor (let element of split.slice(1)) {\n\t\tconst comment = formatComment(element);\n\t\telement = element\n\t\t\t.replaceAll(commentsRegex, \"\")\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\n\t\t\t.trim();\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\n\t\t//remove comments\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\n\t\tif (compareRegex) {\n\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\ttoRoll,\n\t\t\t\tcompareRegex,\n\t\t\t\telement,\n\t\t\t\tdiceResult,\n\t\t\t\tengine\n\t\t\t);\n\t\t\ttoRoll = compareResult.dice;\n\t\t\tresults.push(compareResult.results);\n\t\t\tif (!aggregatedCompare && compareResult.compare) aggregatedCompare = compareResult.compare;\n\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\n\t\t} else {\n\t\t\tconst { formule, diceAll } = replaceText(\n\t\t\t\telement,\n\t\t\t\tdiceResult.total,\n\t\t\t\tdiceResult.dice\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\n\t\t\t} catch (error) {\n\t\t\t\tconst evaluated = roll(toRoll, engine, pity);\n\t\t\t\tif (evaluated) {\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\n\t\t\t\t\t);\n\t\t\t\t\tif (!aggregatedCompare && evaluated.compare)\n\t\t\t\t\t\taggregatedCompare = evaluated.compare;\n\t\t\t\t\tif (evaluated.compare?.trivial) hasTrivialComparison = true;\n\t\t\t\t} else results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += evaluated?.total ?? 0;\n\t\t\t}\n\t\t}\n\t}\n\tif (hidden)\n\t\t//remove the first in result\n\t\tresults.shift();\n\treturn {\n\t\tdice: diceMain,\n\t\tresult: results.join(\";\"),\n\t\tcomment: mainComment,\n\t\tcompare: hasTrivialComparison && aggregatedCompare\n\t\t\t? { ...aggregatedCompare, trivial: true }\n\t\t\t: aggregatedCompare,\n\t\tmodifier: diceResult.modifier,\n\t\ttotal,\n\t};\n}\n","export class DiceTypeError extends Error {\n\tpublic readonly dice: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(dice: string, cause?: string, method?: unknown) {\n\t\tsuper(dice);\n\t\tthis.name = \"Invalid_Dice_Type\";\n\t\tthis.dice = dice;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class FormulaError extends Error {\n\tpublic readonly formula: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(formula: string, cause?: string, method?: unknown) {\n\t\tsuper(formula);\n\t\tthis.name = \"Invalid_Formula\";\n\t\tthis.formula = formula;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class MaxGreater extends Error {\n\tpublic readonly name: string;\n\tpublic readonly value: number;\n\tpublic readonly max: number;\n\n\tconstructor(value: number, max: number) {\n\t\tsuper(value.toString());\n\t\tthis.name = \"Max_Greater\";\n\t\tthis.value = value;\n\t\tthis.max = max;\n\t}\n}\n\nexport class EmptyObjectError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Empty_Object\";\n\t}\n}\n\nexport class TooManyDice extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Dice\";\n\t}\n}\n\nexport class TooManyStats extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Stats\";\n\t}\n}\n\nexport class NoStatisticsError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"No_Statistics\";\n\t}\n}\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\n// Use negative lookbehind to check for ![<>] before any comparison operator\nexport const SIGN_REGEX =\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\nexport const SIGN_REGEX_SPACE =\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\n","/**\n * Definition of the Zod schema for template data\n */\nimport { z } from \"zod\";\n\nconst statisticValueSchema = z\n\t.object({\n\t\tmax: z\n\t\t\t.number()\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t\t.optional(),\n\t\tmin: z\n\t\t\t.number()\n\t\t\t.transform((val) =>\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\n\t\t\t)\n\t\t\t.optional(),\n\t\tcombinaison: z\n\t\t\t.string()\n\t\t\t.transform((str) => str.trim() || undefined)\n\t\t\t.optional(),\n\t\texclude: z.boolean().optional(),\n\t})\n\t.superRefine((data, ctx) => {\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\n\t\t\t\tpath: [\"max\"],\n\t\t\t});\n\t\t}\n\t});\n\nconst statisticSchema = z\n\t.record(z.string(), statisticValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyStats\",\n\t});\n\nconst criticalSchema = z\n\t.object({\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\n\t})\n\t.transform((values) => {\n\t\tif (values.success === \"\") values.success = undefined;\n\t\tif (values.failure === \"\") values.failure = undefined;\n\t\tif (values.failure === 0) values.failure = undefined;\n\t\tif (values.success === 0) values.success = undefined;\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\n\t\treturn values;\n\t});\n\nconst criticalValueSchema = z.object({\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\n\tvalue: z.string(),\n\tonNaturalDice: z.boolean().optional(),\n\taffectSkill: z.boolean().optional(),\n});\n\nconst damageSchema = z\n\t.record(z.string(), z.string())\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nconst customCriticalSchema = z\n\t.record(z.string(), criticalValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nexport const templateSchema = z.object({\n\tcharName: z.boolean().optional(),\n\tstatistics: statisticSchema,\n\ttotal: z\n\t\t.number()\n\t\t.min(0)\n\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t.optional(),\n\tforceDistrib: z.boolean().optional(),\n\tdiceType: z.string().optional(),\n\tcritical: criticalSchema.optional(),\n\tcustomCritical: customCriticalSchema,\n\tdamage: damageSchema,\n});\n","import { evaluate } from \"mathjs\";\nimport \"uniformize\";\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { type Engine, Random } from \"random-js\";\nimport { FormulaError } from \".\";\n\n/**\n * Escape regex string\n * @param string {string}\n */\nexport function escapeRegex(string: string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Allow to keep the text as if in brackets\n * @param dice {string}\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\n */\nexport function standardizeDice(dice: string): string {\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\n\t);\n}\n\n/**\n * Replace the stat name by their value using stat\n * and after evaluate any formula using `replaceFormulaInDice`\n * @param {string} originalDice\n * @param {Record<string,number>|undefined} stats\n * @param {string|undefined} dollarValue\n */\nexport function generateStatsDice(\n\toriginalDice: string,\n\tstats?: Record<string, number>,\n\tdollarValue?: string\n) {\n\tlet dice = originalDice.standardize();\n\tif (stats && Object.keys(stats).length > 0) {\n\t\tconst statKeys = Object.keys(stats);\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\n\t\tlet result = \"\";\n\t\tlet match: RegExpExecArray | null;\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\n\t\t\tconst insideBrackets = match[1];\n\t\t\tconst outsideText = match[2];\n\t\t\tif (insideBrackets) {\n\t\t\t\tresult += insideBrackets;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!outsideText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\n\t\t\tlet lastIndex = 0;\n\t\t\tlet tokenMatch: RegExpExecArray | null;\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\n\t\t\t\tconst token = tokenMatch[0];\n\t\t\t\tconst tokenStd = token.standardize();\n\t\t\t\tlet bestKey: string | null = null;\n\t\t\t\tlet bestScore = 0;\n\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\tif (\n\t\t\t\t\t\ttokenStd === keyStd ||\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\n\t\t\t\t\t) {\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t\tbestScore = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\n\t\t\t\t\tif (score > bestScore) {\n\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\n\t\t\t\t\tconst statValue = stats[bestKey];\n\t\t\t\t\tresult += statValue.toString();\n\t\t\t\t} else {\n\t\t\t\t\tresult += token;\n\t\t\t\t}\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t}\n\t\t\tresult += outsideText.slice(lastIndex);\n\t\t}\n\t\tdice = result;\n\t}\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\n\treturn replaceFormulaInDice(dice);\n}\n\n/**\n * Replace the {{}} in the dice string and evaluate the interior if any\n * @param dice {string}\n */\nexport function replaceFormulaInDice(dice: string) {\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\n\tlet match;\n\tlet modifiedDice = dice;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\twhile ((match = formula.exec(dice)) !== null) {\n\t\tif (match.groups?.formula) {\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\n\t\t\ttry {\n\t\t\t\tconst result = evaluate(formulae);\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cleanedDice(modifiedDice);\n}\n\n/**\n * Replace the ++ +- -- by their proper value:\n * - `++` = `+`\n * - `+-` = `-`\n * - `--` = `+`\n * @param dice {string}\n */\nfunction cleanedDice(dice: string) {\n\treturn dice\n\t\t.replaceAll(\"+-\", \"-\")\n\t\t.replaceAll(\"--\", \"+\")\n\t\t.replaceAll(\"++\", \"+\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimEnd();\n}\n\n/**\n * Verify if a value is a number, even if it's a \"number\" string\n * @param value {unknown}\n * @returns {boolean}\n */\nexport function isNumber(value: unknown): boolean {\n\treturn (\n\t\tvalue !== undefined &&\n\t\t(typeof value === \"number\" ||\n\t\t\t(!Number.isNaN(Number(value)) &&\n\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\tvalue.trim().length > 0))\n\t);\n}\n\n/**\n * Replace the `{exp}` in the dice.\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\n * @param {string} dice\n * @param engine\n * @returns {string} the dice with the {exp} replaced by a random value\n */\nexport function replaceExpByRandom(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): string {\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\n\t\tconst defaultValue = groups?.default;\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\n\t});\n}\n\n/**\n * Utility function to get a random integer between min and max and using the specified engine\n * @param min {number}\n * @param max {number}\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\n * @returns {number} Random integer between min and max\n */\nexport function randomInt(\n\tmin: number,\n\tmax: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\trng?: Random\n): number {\n\tif (!rng) rng = new Random(engine || undefined);\n\treturn rng.integer(min, max);\n}\n/**\n * Utility function that allow to get the id of an engine\n * @param engine {unknown} Engine to identify\n * @returns {string} Id of the engine or \"unknown\"\n * @private\n */\nexport function getEngineId(engine: unknown): string {\n\t// Comparaisons directes avec les engines exposés par la lib\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\n\t// Fallback: essayer de lire un nom ou le constructeur\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\n\t\tconst e = engine as any;\n\t\tif (e && typeof e === \"object\") {\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\n\t\t\tif (e.constructor?.name) return e.constructor.name;\n\t\t}\n\t} catch {\n\t\t/* ignore */\n\t}\n\treturn \"unknown\";\n}\n\n/**\n * Utility function to get the engine from its name\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\n * @returns {Engine} The engine\n * @public\n */\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\n\tswitch (engine) {\n\t\tcase \"nativeMath\":\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t\tcase \"browserCrypto\":\n\t\t\treturn NumberGenerator.engines.browserCrypto;\n\t\tcase \"nodeCrypto\":\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\n\t\tdefault:\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t}\n}\n\n/**\n * Calcule la distance de Levenshtein entre deux chaînes\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\tif (a === b) return 0;\n\tconst al = a.length;\n\tconst bl = b.length;\n\tif (al === 0) return bl;\n\tif (bl === 0) return al;\n\tconst v0 = new Array<number>(bl + 1);\n\tconst v1 = new Array<number>(bl + 1);\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\n\tfor (let i = 0; i < al; i++) {\n\t\tv1[0] = i + 1;\n\t\tfor (let j = 0; j < bl; j++) {\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n\t\t}\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\n\t}\n\treturn v1[bl];\n}\n\n/**\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\n */\nfunction similarityScore(a: string, b: string): number {\n\tconst la = a.length;\n\tconst lb = b.length;\n\tif (la === 0 && lb === 0) return 1;\n\tconst dist = levenshteinDistance(a, b);\n\tconst max = Math.max(la, lb);\n\treturn 1 - dist / max;\n}\n","import { evaluate } from \"mathjs\";\nimport { type Engine, Random } from \"random-js\";\nimport \"uniformize\";\n\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport {\n\tcreateCriticalCustom,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tEmptyObjectError,\n\tescapeRegex,\n\tFormulaError,\n\tNoStatisticsError,\n\treplaceExpByRandom,\n\treplaceFormulaInDice,\n\troll,\n\ttype StatisticalTemplate,\n\tTooManyDice,\n\ttemplateSchema,\n} from \".\";\nimport { isNumber, randomInt } from \"./utils\";\n\n/**\n * Verify if the provided dice work with random value\n * @param testDice {string}\n * @param allStats {Record<string,number>}\n * @param engine\n * @param pity\n */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet dice = testDice.trimEnd();\n\tif (allStats && Object.keys(allStats).length > 0) {\n\t\tconst names = Object.keys(allStats);\n\t\tfor (const name of names) {\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\t\tif (dice.standardize().match(regex)) {\n\t\t\t\tconst statValue = allStats[name];\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\n\t\t\t}\n\t\t}\n\t}\n\ttry {\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\n\t\treturn testDice;\n\t} catch (error) {\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\n\t}\n}\n\n/**\n * Generate a random dice and remove the formula (+ evaluate it)\n * Used for diceDamage only\n * @param value {string}\n * @param template {StatisticalTemplate}\n * @param engine\n * @returns\n */\nexport function diceRandomParse(\n\tvalue: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\n\tvalue = value.standardize();\n\tconst statNames = Object.keys(template.statistics);\n\tlet newDice = value;\n\tfor (const name of statNames) {\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\tif (value.match(regex)) {\n\t\t\tlet max: undefined | number;\n\t\t\tlet min: undefined | number;\n\t\t\tconst foundStat = template.statistics?.[name];\n\t\t\tif (foundStat) {\n\t\t\t\tmax = foundStat.max;\n\t\t\t\tmin = foundStat.min;\n\t\t\t}\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\n\t\t}\n\t}\n\treturn replaceFormulaInDice(newDice);\n}\n\n/**\n * Same as damageDice but for DiceType\n * @param dice {string}\n * @param template {StatisticalTemplate}\n * @param engine\n */\nexport function diceTypeRandomParse(\n\tdice: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tdice = replaceExpByRandom(dice);\n\tif (!template.statistics) return dice;\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\n\t\t(stat) => !template.statistics?.[stat].combinaison\n\t);\n\tif (!firstStatNotcombinaison) return dice;\n\tconst stats = template.statistics[firstStatNotcombinaison];\n\tconst { min, max } = stats;\n\tconst total = template.total || 100;\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\n}\n\n/**\n * Random the combinaison and evaluate it to check if everything is valid\n * @param combinaison {Record<string,string>}\n * @param stats {Record<string,number|number>}\n */\nexport function evalCombinaison(\n\tcombinaison: Record<string, string>,\n\tstats: Record<string, number | string>\n) {\n\tconst newStats: Record<string, number> = {};\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\n\t\t//replace the stats in formula\n\t\tlet formula = combin.standardize();\n\t\tfor (const [statName, value] of Object.entries(stats)) {\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\t\tformula = formula.replace(regex, value.toString());\n\t\t}\n\t\ttry {\n\t\t\tnewStats[stat] = evaluate(formula);\n\t\t} catch (error) {\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\n\t\t}\n\t}\n\treturn newStats;\n}\n\n/**\n * Evaluate one selected combinaison\n * @param combinaison {string}\n * @param stats {[name: string]: string|number}\n */\nexport function evalOneCombinaison(\n\tcombinaison: string,\n\tstats: Record<string, number | string>\n) {\n\tlet formula = combinaison.standardize();\n\tfor (const [statName, value] of Object.entries(stats)) {\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\tformula = formula.replace(regex, value.toString());\n\t}\n\ttry {\n\t\treturn evaluate(formula);\n\t} catch (error) {\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\n\t}\n}\n\nfunction convertNumber(number: string | number | undefined) {\n\tif (number === undefined || number === null) return undefined;\n\tif (\n\t\tnumber.toString().length === 0 ||\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\n\t)\n\t\treturn undefined;\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\n\treturn undefined;\n}\n\n/**\n * Parse the provided JSON and verify each field to check if everything could work when rolling\n * @param {unknown} template\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\n * @param engine\n * @returns {StatisticalTemplate}\n */\nexport function verifyTemplateValue(\n\ttemplate: unknown,\n\tverify = true,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): StatisticalTemplate {\n\tconst parsedTemplate = templateSchema.parse(template);\n\tconst { success, failure } = parsedTemplate.critical ?? {};\n\tconst criticicalVal = {\n\t\tsuccess: convertNumber(success),\n\t\tfailure: convertNumber(failure),\n\t};\n\tconst statistiqueTemplate: StatisticalTemplate = {\n\t\tdiceType: parsedTemplate.diceType,\n\t\tstatistics: parsedTemplate.statistics,\n\t\tcritical: criticicalVal,\n\t\ttotal: parsedTemplate.total,\n\t\tcharName: parsedTemplate.charName,\n\t\tdamage: parsedTemplate.damage,\n\t\tcustomCritical: parsedTemplate.customCritical,\n\t\tforceDistrib: parsedTemplate.forceDistrib,\n\t};\n\tif (!verify) return statistiqueTemplate;\n\tif (statistiqueTemplate.diceType) {\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\n\t\t\tthrow new DiceTypeError(\n\t\t\t\tstatistiqueTemplate.diceType,\n\t\t\t\t\"critical_dice_type\",\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\n\t\t\t);\n\t\t}\n\t\tconst cleanedDice = diceTypeRandomParse(\n\t\t\tstatistiqueTemplate.diceType,\n\t\t\tstatistiqueTemplate,\n\t\t\tengine\n\t\t);\n\t\tconst rolled = roll(cleanedDice, engine);\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\n\t}\n\tif (statistiqueTemplate.customCritical) {\n\t\tif (!statistiqueTemplate.diceType) {\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\n\t\t}\n\t\tconst customCritical = statistiqueTemplate.customCritical;\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\n\t\t\tconst cleanedDice = createCriticalCustom(\n\t\t\t\tstatistiqueTemplate.diceType!,\n\t\t\t\tcustom,\n\t\t\t\tstatistiqueTemplate,\n\t\t\t\tengine\n\t\t\t);\n\t\t\tconst rolled = roll(cleanedDice, engine);\n\t\t\tif (!rolled)\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\n\t\t}\n\t}\n\ttestDiceRegistered(statistiqueTemplate, engine);\n\ttestStatCombinaison(statistiqueTemplate, engine);\n\treturn statistiqueTemplate;\n}\n\n/**\n * Test each damage roll from the template.damage\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testDiceRegistered(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.damage) return;\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\n\tfor (const [name, dice] of Object.entries(template.damage)) {\n\t\tif (!dice) continue;\n\t\tconst diceReplaced = replaceExpByRandom(dice);\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\n\t\ttry {\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\n\t\t}\n\t}\n}\n\n/**\n * Test all combinaison with generated random value\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testStatCombinaison(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return;\n\tconst onlycombinaisonStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(\n\t\t\t([_, value]) => value.combinaison !== undefined\n\t\t)\n\t);\n\tconst allOtherStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\n\t);\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\n\tconst allStats = Object.keys(template.statistics).filter(\n\t\t(stat) => !template.statistics![stat].combinaison\n\t);\n\tif (allStats.length === 0) throw new NoStatisticsError();\n\tconst error = [];\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\n\t\tlet formula = value.combinaison as string;\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\n\t\t\tconst { max, min } = data;\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tconst regex = new RegExp(other, \"gi\");\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\n\t\t}\n\t\ttry {\n\t\t\tevaluate(formula);\n\t\t} catch (e) {\n\t\t\terror.push(stat);\n\t\t}\n\t}\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\n\treturn;\n}\n\n/**\n * Generate a random stat based on the template and the statistical min and max\n * @param {number|undefined} total\n * @param {number | undefined} max\n * @param {number | undefined} min\n * @param engine\n * @returns\n */\nexport function generateRandomStat(\n\ttotal: number | undefined = 100,\n\tmax?: number,\n\tmin?: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tlet randomStatValue = total + 1;\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\n\twhile (randomStatValue >= total || randomStatValue === 0) {\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\n\t\telse randomStatValue = randomInt(1, total, engine, random);\n\t}\n\treturn randomStatValue;\n}\n"],"mappings":"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","names":["roller","evaluateRoll","diceResult","import_mathjs","import_rpg_dice_roller","import_mathjs","import_random_js","import_uniformize","import_rpg_dice_roller","cleanedDice"]}
|
package/dist/index.mjs
CHANGED
|
@@ -279,6 +279,7 @@ function replaceInFormula(element, diceResult, compareResult, res, engine = Numb
|
|
|
279
279
|
}
|
|
280
280
|
function compareSignFormule(toRoll, compareRegex, element, diceResult, engine = NumberGenerator.engines.nodeCrypto, pity) {
|
|
281
281
|
let results = "";
|
|
282
|
+
let trivial = false;
|
|
282
283
|
const compareResult = getCompare(toRoll, compareRegex, engine);
|
|
283
284
|
const toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;
|
|
284
285
|
let res;
|
|
@@ -288,6 +289,8 @@ function compareSignFormule(toRoll, compareRegex, element, diceResult, engine =
|
|
|
288
289
|
res = roll(toCompare, engine, pity);
|
|
289
290
|
}
|
|
290
291
|
if (typeof res === "boolean") {
|
|
292
|
+
trivial = true;
|
|
293
|
+
if (compareResult.compare) compareResult.compare.trivial = true;
|
|
291
294
|
results = replaceInFormula(element, diceResult, compareResult, res, engine, pity);
|
|
292
295
|
} else if (res instanceof Object) {
|
|
293
296
|
const diceResult2 = res;
|
|
@@ -299,9 +302,10 @@ function compareSignFormule(toRoll, compareRegex, element, diceResult, engine =
|
|
|
299
302
|
const invertedSign = toEvaluate ? diceResult2.compare.sign : inverseSign(diceResult2.compare.sign);
|
|
300
303
|
const dice = replaceText(element, 0, diceResult2.dice).diceAll;
|
|
301
304
|
results = `${sign} ${dice}: ${diceResult2.result.split(":").splice(1).join(":").trim()}${invertedSign}${diceResult2.compare.value}`;
|
|
305
|
+
if (diceResult2.compare.trivial) trivial = true;
|
|
302
306
|
}
|
|
303
307
|
}
|
|
304
|
-
return { dice: compareResult.dice, results };
|
|
308
|
+
return { dice: compareResult.dice, results, compare: compareResult.compare, trivial };
|
|
305
309
|
}
|
|
306
310
|
function replaceText(element, total, dice) {
|
|
307
311
|
return {
|
|
@@ -357,6 +361,8 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto, pity) {
|
|
|
357
361
|
} else return void 0;
|
|
358
362
|
}
|
|
359
363
|
if (!diceResult || !diceResult.total) return void 0;
|
|
364
|
+
let aggregatedCompare = diceResult.compare;
|
|
365
|
+
let hasTrivialComparison = diceResult.compare?.trivial === true;
|
|
360
366
|
results.push(`\u203B ${comments}${diceResult.result}`);
|
|
361
367
|
let total = diceResult.total;
|
|
362
368
|
diceResult.comment = mainComment;
|
|
@@ -376,6 +382,8 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto, pity) {
|
|
|
376
382
|
);
|
|
377
383
|
toRoll = compareResult.dice;
|
|
378
384
|
results.push(compareResult.results);
|
|
385
|
+
if (!aggregatedCompare && compareResult.compare) aggregatedCompare = compareResult.compare;
|
|
386
|
+
if (compareResult.trivial) hasTrivialComparison = true;
|
|
379
387
|
} else {
|
|
380
388
|
const { formule, diceAll } = replaceText(
|
|
381
389
|
element,
|
|
@@ -388,11 +396,14 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto, pity) {
|
|
|
388
396
|
total += Number.parseInt(evaluated, 10);
|
|
389
397
|
} catch (error) {
|
|
390
398
|
const evaluated = roll(toRoll, engine, pity);
|
|
391
|
-
if (evaluated)
|
|
399
|
+
if (evaluated) {
|
|
392
400
|
results.push(
|
|
393
401
|
`\u25C8 ${comment}${diceAll}: ${evaluated.result.split(":").slice(1).join(":")}`
|
|
394
402
|
);
|
|
395
|
-
|
|
403
|
+
if (!aggregatedCompare && evaluated.compare)
|
|
404
|
+
aggregatedCompare = evaluated.compare;
|
|
405
|
+
if (evaluated.compare?.trivial) hasTrivialComparison = true;
|
|
406
|
+
} else results.push(`\u25C8 ${comment}${diceAll}: ${formule} = ${evaluated}`);
|
|
396
407
|
total += evaluated?.total ?? 0;
|
|
397
408
|
}
|
|
398
409
|
}
|
|
@@ -403,7 +414,7 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto, pity) {
|
|
|
403
414
|
dice: diceMain,
|
|
404
415
|
result: results.join(";"),
|
|
405
416
|
comment: mainComment,
|
|
406
|
-
compare:
|
|
417
|
+
compare: hasTrivialComparison && aggregatedCompare ? { ...aggregatedCompare, trivial: true } : aggregatedCompare,
|
|
407
418
|
modifier: diceResult.modifier,
|
|
408
419
|
total
|
|
409
420
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dice.ts","../src/errors.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/utils.ts","../src/verify_template.ts"],"sourcesContent":["import { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport {\n\tCOMMENT_REGEX,\n\ttype Compare,\n\ttype ComparedValue,\n\ttype CustomCritical,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tdiceTypeRandomParse,\n\tisNumber,\n\ttype Modifier,\n\tOPTIONAL_COMMENT,\n\ttype Resultat,\n\treplaceFormulaInDice,\n\tSIGN_REGEX,\n\tSIGN_REGEX_SPACE,\n\ttype Sign,\n\ttype StatisticalTemplate,\n\tSYMBOL_DICE,\n\tstandardizeDice,\n} from \".\";\n\n/**\n * Check if a comparison is trivial (always true or always false)\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\n * @param maxValue Maximum possible value from the dice roll\n * @param minValue Minimum possible value from the dice roll\n * @param compare The comparison object\n * @returns true if the comparison is trivial (always true or always false)\n */\nfunction isTrivialComparison(\n\tmaxValue: number,\n\tminValue: number,\n\tcompare: ComparedValue\n): boolean {\n\t// Check if comparison can never succeed (always false)\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\n\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\n\n\t// Trivial if it can never succeed OR can never fail\n\treturn !canSucceed || !canFail;\n}\n\n/**\n * Check if a comparison can theoretically fail given roll bounds\n * @param maxRollValue Maximum possible roll value\n * @param compare The comparison object\n * @param minRollValue Minimum possible roll value (defaults to 1)\n * @returns true if the comparison can fail at least once\n */\nfunction canComparisonFail(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue = 1\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\n\t\tcase \">=\":\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\n\t\tcase \"<\":\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\n\t\tcase \"<=\":\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\n\t\tcase \"!=\":\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; compare: ComparedValue | undefined } {\n\t/**\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\n\t * Some system count the number of a dice that are greater than or equal to a target, and not the \"total\" of rolled dice.\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\n\t * To support this, we use the group notation. It a little different than the notation of dice-roller, but it a sacrifice to not break the current notation.\n\t * @note:\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\n\t * - `{2d3>=4}` will count the total of dice that are greater than or equal to 4, and not the total of the dice.\n\t * - `{2d3,1d4}>=4` won't use the comparison, but will count the number of dice that are greater than or equal to 4. If the total of the dice is needed, just remove the group notation and use `2d3+1d4>=4`.\n\t */\n\tif (\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\n\t)\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\n\tconst calc = compareRegex[2];\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\n\n\tif (sign) {\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\n\t\tconst total = evaluate(rCompare.value.toString());\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: total,\n\t\t\toriginalDice: rCompare.dice,\n\t\t\trollValue: rCompare.diceResult,\n\t\t};\n\t} else {\n\t\tconst rcompare = rollCompare(calc, engine, pity);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: rcompare.value,\n\t\t\toriginalDice: rcompare.dice,\n\t\t\trollValue: rcompare.diceResult,\n\t\t};\n\t}\n\n\treturn { dice, compare };\n}\n\nfunction rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\t// Handle empty value or string - return 0 as default\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n\t\treturn { value: 0, diceResult: value as string };\n\t}\n\tconst rollComp = roll(value as string, engine, pity);\n\tif (!rollComp?.total) {\n\t\t//not a dice throw\n\t\ttry {\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\n\t\t} catch (error) {\n\t\t\t// If evaluate fails, return 0\n\t\t\treturn { value: 0, diceResult: value as string };\n\t\t}\n\t}\n\treturn {\n\t\tdice: value as string,\n\t\tvalue: rollComp.total,\n\t\tdiceResult: rollComp?.result,\n\t};\n}\n\n/**\n * Allow to replace the compare part of a dice and use the critical customized one\n * @example\n * dice = \"1d20=20\";\n * custom critical {sign: \">\", value: \"$/2\"}\n * Random stats = 6\n * result = \"1d20>3\"\n */\nexport function createCriticalCustom(\n\tdice: string,\n\tcustomCritical: CustomCritical,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet customDice = dice;\n\tconst compareValue = diceTypeRandomParse(customCritical.value, template, engine);\n\tif (compareValue.includes(\"$\"))\n\t\tthrow new DiceTypeError(compareValue, \"createCriticalCustom\");\n\tconst comparaison = `${customCritical.sign}${compareValue}`;\n\tif (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);\n\telse customDice += comparaison;\n\treturn diceTypeRandomParse(customDice, template, engine);\n}\n\nfunction getModifier(dice: string) {\n\tconst modifier = dice.matchAll(/(\\+|-|%|\\/|\\^|\\*|\\*{2})(\\d+)/gi);\n\tlet modificator: Modifier | undefined;\n\tfor (const mod of modifier) {\n\t\t//calculate the modifier if multiple\n\t\tif (modificator) {\n\t\t\tconst sign = modificator.sign;\n\t\t\tlet value = modificator.value;\n\t\t\tif (sign) value = calculator(sign, value, Number.parseInt(mod[2], 10));\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue,\n\t\t\t};\n\t\t} else {\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue: Number.parseInt(mod[2], 10),\n\t\t\t};\n\t\t}\n\t}\n\treturn modificator;\n}\n\n/**\n * Parse the string provided and turn it as a readable dice for dice parser\n * @param dice {string}\n * @param engine\n * @param pity\n */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\t//parse dice string\n\tdice = standardizeDice(replaceFormulaInDice(dice))\n\t\t.replace(/^\\+/, \"\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimStart();\n\tif (!dice.includes(\"d\")) return undefined;\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet compare: ComparedValue | undefined;\n\tif (dice.includes(\";\")) return sharedRolls(dice, engine);\n\n\tdice = fixParenthesis(dice);\n\tconst modificator = getModifier(dice);\n\n\t// Extract compare BEFORE rolling to remove it from the dice notation\n\tif (compareRegex) {\n\t\tconst compareResult = getCompare(dice, compareRegex, engine, pity);\n\t\tdice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\n\tif (dice.match(/\\d+?#(.*)/)) {\n\t\tconst diceArray = dice.split(\"#\");\n\t\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\n\t\tconst diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\n\t\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\n\t\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\n\t\tconst roller = new DiceRoller();\n\t\tNumberGenerator.generator.engine = engine;\n\t\t//remove comments if any\n\t\tfor (let i = 0; i < numberOfDice; i++) {\n\t\t\ttry {\n\t\t\t\troller.roll(diceToRoll);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdice: diceToRoll,\n\t\t\tresult: roller.output,\n\t\t\tcomment: comments,\n\t\t\tcompare: compare ? compare : undefined,\n\t\t\tmodifier: modificator,\n\t\t\ttotal: roller.total,\n\t\t};\n\t}\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tconst diceWithoutComment = dice.replace(COMMENT_REGEX, \"\").trimEnd();\n\n\tlet diceRoll: DiceRoll | DiceRoll[];\n\ttry {\n\t\tdiceRoll = roller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\n\t// Update compare.trivial after rolling to get access to diceRoll for trivial detection\n\tif (compare && diceRoll) {\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxDiceValue = currentRoll.maxTotal;\n\t\tconst minDiceValue = currentRoll.minTotal;\n\t\tconst trivial = isTrivialComparison(maxDiceValue, minDiceValue, compare);\n\t\tcompare.trivial = trivial ? true : undefined;\n\t}\n\n\tconst commentMatch = dice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\n\tlet rerollCount = 0;\n\tlet res: Resultat | undefined;\n\tif (pity && compare) {\n\t\t// Vérifier si la comparaison est théoriquement possible\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\n\t\tconst isComparisonPossible =\n\t\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\n\n\t\tif (isComparisonPossible) {\n\t\t\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\n\t\t\tif (!isFail) {\n\t\t\t\t//reroll until success\n\t\t\t\tconst maxReroll = 100;\n\t\t\t\twhile (!isFail && rerollCount < maxReroll) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tres = roll(diceWithoutComment, engine, false); // désactiver pity pour éviter la récursion infinie\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t\t\t\t\t}\n\t\t\t\t\trerollCount++;\n\t\t\t\t\tif (res && res.total !== undefined)\n\t\t\t\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\n\t\t\t\t}\n\t\t\t\tif (res) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...res,\n\t\t\t\t\t\tdice,\n\t\t\t\t\t\tcomment,\n\t\t\t\t\t\tcompare: compare,\n\t\t\t\t\t\tmodifier: modificator,\n\t\t\t\t\t\tpityLogs: rerollCount,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t} else console.log(\"Comparison impossible, pity ignored\");\n\t}\n\treturn {\n\t\tdice,\n\t\tresult: roller.output,\n\t\tcomment,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t};\n}\n\n/**\n * Check if a comparison can theoretically succeed given a maximum roll value\n * @example\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\n */\nfunction canComparisonSucceed(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue?: number\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn maxRollValue > compare.value;\n\t\tcase \">=\":\n\t\t\treturn maxRollValue >= compare.value;\n\t\tcase \"<\":\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"<=\":\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\n\t\tcase \"!=\":\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction fixParenthesis(dice: string) {\n\t//dice with like 1d(20) are not valid, we need to remove the parenthesis\n\t//warning: the 1d(20+5) is valid and should not be changed\n\tconst parenthesisRegex = /d\\((\\d+)\\)/g;\n\treturn dice.replaceAll(parenthesisRegex, (_match, p1) => `d${p1}`);\n}\n\n/**\n * Evaluate a formula and replace \"^\" by \"**\" if any\n * @param {Sign} sign\n * @param {number} value\n * @param {number} total\n * @returns\n */\nexport function calculator(sign: Sign, value: number, total: number): number {\n\tif (sign === \"^\") sign = \"**\";\n\treturn evaluate(`${total} ${sign} ${value}`);\n}\n\nfunction inverseSign(\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\"\n): \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\" {\n\tswitch (sign) {\n\t\tcase \"<\":\n\t\t\treturn \">\";\n\t\tcase \">\":\n\t\t\treturn \"<\";\n\t\tcase \"<=\":\n\t\t\treturn \">=\";\n\t\tcase \">=\":\n\t\t\treturn \"<=\";\n\t\tcase \"=\":\n\t\t\treturn \"!=\";\n\t\tcase \"==\":\n\t\t\treturn \"!=\";\n\t\tcase \"!=\":\n\t\t\treturn \"==\";\n\t}\n}\n\nfunction replaceInFormula(\n\telement: string,\n\tdiceResult: Resultat,\n\tcompareResult: { dice: string; compare: Compare | undefined },\n\tres: boolean,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tconst { formule, diceAll } = replaceText(\n\t\telement,\n\t\tdiceResult.total ?? 0,\n\t\tdiceResult.dice\n\t);\n\tconst validSign = res ? \"✓\" : \"✕\";\n\tconst invertedSign = res\n\t\t? compareResult.compare!.sign\n\t\t: inverseSign(compareResult.compare!.sign);\n\tlet evaluateRoll: unknown;\n\ttry {\n\t\tevaluateRoll = evaluate(compareResult.dice);\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t} catch (error) {\n\t\tconst evaluateRoll = roll(compareResult.dice, engine, pity) as Resultat | undefined;\n\t\tif (evaluateRoll)\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\n\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t}\n}\n\nfunction compareSignFormule(\n\ttoRoll: string,\n\tcompareRegex: RegExpMatchArray,\n\telement: string,\n\tdiceResult: Resultat,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet results = \"\";\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\n\tlet res: unknown;\n\ttry {\n\t\tres = evaluate(toCompare);\n\t} catch (error) {\n\t\tres = roll(toCompare, engine, pity);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\n\t} else if (res instanceof Object) {\n\t\tconst diceResult = res as Resultat;\n\t\tif (diceResult.compare) {\n\t\t\tconst toEvaluate = evaluate(\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\n\t\t\t);\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\n\t\t\tconst invertedSign = toEvaluate\n\t\t\t\t? diceResult.compare.sign\n\t\t\t\t: inverseSign(diceResult.compare.sign);\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\n\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\n\t\t}\n\t}\n\treturn { dice: compareResult.dice, results };\n}\n\nfunction replaceText(element: string, total: number, dice: string) {\n\treturn {\n\t\tformule: element.replace(SYMBOL_DICE, `[${total}]`).replace(/%.*%/g, \"\").trim(),\n\t\tdiceAll: element\n\t\t\t.replace(SYMBOL_DICE, `[${dice.replace(COMMENT_REGEX, \"\")}]`)\n\t\t\t.replace(/%.*%/g, \"\")\n\t\t\t.trim(),\n\t};\n}\n\nfunction formatComment(dice: string) {\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\n\tconst commentsMatch = commentsRegex.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\n\t// to avoid conflicts with parentheses inside bracket comments\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\n\n\t//fusion of both comments with a space if both exists\n\t//result expected = \"__comment1 comment2__ — \"\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\n\tlet finalComment = \"\";\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\n\telse if (comments) finalComment = `__${comments}__ — `;\n\telse if (optional) finalComment = `__${optional}__ — `;\n\treturn finalComment;\n}\n\nfunction sharedRolls(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\tif (dice.match(/\\d+?#(.*?)/))\n\t\tthrow new DiceTypeError(\n\t\t\tdice,\n\t\t\t\"noBulkRoll\",\n\t\t\t\"bulk roll are not allowed in shared rolls\"\n\t\t);\n\tconst results = [];\n\tconst mainComment =\n\t\t/\\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? undefined;\n\tconst split = dice.split(\";\");\n\tlet diceMain = fixParenthesis(split[0]);\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\t// Remove comments before checking for hidden dice (parentheses)\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\n\tlet hidden = false;\n\tif (toHide?.dice) {\n\t\tdiceMain = toHide.dice;\n\t\thidden = true;\n\t} else if (toHide) {\n\t\tdiceMain = \"1d1\";\n\t\thidden = true;\n\t} else {\n\t\t// No hidden dice, use the dice without comments\n\t\tdiceMain = diceMainWithoutComments;\n\t}\n\tlet diceResult = roll(diceMain, engine, pity);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\n\t\t\thidden = false;\n\t\t} else return undefined;\n\t}\n\tif (!diceResult || !diceResult.total) return undefined;\n\tresults.push(`※ ${comments}${diceResult.result}`);\n\tlet total = diceResult.total;\n\tdiceResult.comment = mainComment;\n\tif (!total) return diceResult;\n\tfor (let element of split.slice(1)) {\n\t\tconst comment = formatComment(element);\n\t\telement = element\n\t\t\t.replaceAll(commentsRegex, \"\")\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\n\t\t\t.trim();\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\n\t\t//remove comments\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\n\t\tif (compareRegex) {\n\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\ttoRoll,\n\t\t\t\tcompareRegex,\n\t\t\t\telement,\n\t\t\t\tdiceResult,\n\t\t\t\tengine\n\t\t\t);\n\t\t\ttoRoll = compareResult.dice;\n\t\t\tresults.push(compareResult.results);\n\t\t} else {\n\t\t\tconst { formule, diceAll } = replaceText(\n\t\t\t\telement,\n\t\t\t\tdiceResult.total,\n\t\t\t\tdiceResult.dice\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\n\t\t\t} catch (error) {\n\t\t\t\tconst evaluated = roll(toRoll, engine, pity);\n\t\t\t\tif (evaluated)\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\n\t\t\t\t\t);\n\t\t\t\telse results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += evaluated?.total ?? 0;\n\t\t\t}\n\t\t}\n\t}\n\tif (hidden)\n\t\t//remove the first in result\n\t\tresults.shift();\n\treturn {\n\t\tdice: diceMain,\n\t\tresult: results.join(\";\"),\n\t\tcomment: mainComment,\n\t\tcompare: diceResult.compare,\n\t\tmodifier: diceResult.modifier,\n\t\ttotal,\n\t};\n}\n","export class DiceTypeError extends Error {\n\tpublic readonly dice: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(dice: string, cause?: string, method?: unknown) {\n\t\tsuper(dice);\n\t\tthis.name = \"Invalid_Dice_Type\";\n\t\tthis.dice = dice;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class FormulaError extends Error {\n\tpublic readonly formula: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(formula: string, cause?: string, method?: unknown) {\n\t\tsuper(formula);\n\t\tthis.name = \"Invalid_Formula\";\n\t\tthis.formula = formula;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class MaxGreater extends Error {\n\tpublic readonly name: string;\n\tpublic readonly value: number;\n\tpublic readonly max: number;\n\n\tconstructor(value: number, max: number) {\n\t\tsuper(value.toString());\n\t\tthis.name = \"Max_Greater\";\n\t\tthis.value = value;\n\t\tthis.max = max;\n\t}\n}\n\nexport class EmptyObjectError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Empty_Object\";\n\t}\n}\n\nexport class TooManyDice extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Dice\";\n\t}\n}\n\nexport class TooManyStats extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Stats\";\n\t}\n}\n\nexport class NoStatisticsError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"No_Statistics\";\n\t}\n}\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\n// Use negative lookbehind to check for ![<>] before any comparison operator\nexport const SIGN_REGEX =\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\nexport const SIGN_REGEX_SPACE =\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\n","/**\n * Definition of the Zod schema for template data\n */\nimport { z } from \"zod\";\n\nconst statisticValueSchema = z\n\t.object({\n\t\tmax: z\n\t\t\t.number()\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t\t.optional(),\n\t\tmin: z\n\t\t\t.number()\n\t\t\t.transform((val) =>\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\n\t\t\t)\n\t\t\t.optional(),\n\t\tcombinaison: z\n\t\t\t.string()\n\t\t\t.transform((str) => str.trim() || undefined)\n\t\t\t.optional(),\n\t\texclude: z.boolean().optional(),\n\t})\n\t.superRefine((data, ctx) => {\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\n\t\t\t\tpath: [\"max\"],\n\t\t\t});\n\t\t}\n\t});\n\nconst statisticSchema = z\n\t.record(z.string(), statisticValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyStats\",\n\t});\n\nconst criticalSchema = z\n\t.object({\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\n\t})\n\t.transform((values) => {\n\t\tif (values.success === \"\") values.success = undefined;\n\t\tif (values.failure === \"\") values.failure = undefined;\n\t\tif (values.failure === 0) values.failure = undefined;\n\t\tif (values.success === 0) values.success = undefined;\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\n\t\treturn values;\n\t});\n\nconst criticalValueSchema = z.object({\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\n\tvalue: z.string(),\n\tonNaturalDice: z.boolean().optional(),\n\taffectSkill: z.boolean().optional(),\n});\n\nconst damageSchema = z\n\t.record(z.string(), z.string())\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nconst customCriticalSchema = z\n\t.record(z.string(), criticalValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nexport const templateSchema = z.object({\n\tcharName: z.boolean().optional(),\n\tstatistics: statisticSchema,\n\ttotal: z\n\t\t.number()\n\t\t.min(0)\n\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t.optional(),\n\tforceDistrib: z.boolean().optional(),\n\tdiceType: z.string().optional(),\n\tcritical: criticalSchema.optional(),\n\tcustomCritical: customCriticalSchema,\n\tdamage: damageSchema,\n});\n","import { evaluate } from \"mathjs\";\nimport \"uniformize\";\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { type Engine, Random } from \"random-js\";\nimport { FormulaError } from \".\";\n\n/**\n * Escape regex string\n * @param string {string}\n */\nexport function escapeRegex(string: string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Allow to keep the text as if in brackets\n * @param dice {string}\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\n */\nexport function standardizeDice(dice: string): string {\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\n\t);\n}\n\n/**\n * Replace the stat name by their value using stat\n * and after evaluate any formula using `replaceFormulaInDice`\n * @param {string} originalDice\n * @param {Record<string,number>|undefined} stats\n * @param {string|undefined} dollarValue\n */\nexport function generateStatsDice(\n\toriginalDice: string,\n\tstats?: Record<string, number>,\n\tdollarValue?: string\n) {\n\tlet dice = originalDice.standardize();\n\tif (stats && Object.keys(stats).length > 0) {\n\t\tconst statKeys = Object.keys(stats);\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\n\t\tlet result = \"\";\n\t\tlet match: RegExpExecArray | null;\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\n\t\t\tconst insideBrackets = match[1];\n\t\t\tconst outsideText = match[2];\n\t\t\tif (insideBrackets) {\n\t\t\t\tresult += insideBrackets;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!outsideText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\n\t\t\tlet lastIndex = 0;\n\t\t\tlet tokenMatch: RegExpExecArray | null;\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\n\t\t\t\tconst token = tokenMatch[0];\n\t\t\t\tconst tokenStd = token.standardize();\n\t\t\t\tlet bestKey: string | null = null;\n\t\t\t\tlet bestScore = 0;\n\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\tif (\n\t\t\t\t\t\ttokenStd === keyStd ||\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\n\t\t\t\t\t) {\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t\tbestScore = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\n\t\t\t\t\tif (score > bestScore) {\n\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\n\t\t\t\t\tconst statValue = stats[bestKey];\n\t\t\t\t\tresult += statValue.toString();\n\t\t\t\t} else {\n\t\t\t\t\tresult += token;\n\t\t\t\t}\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t}\n\t\t\tresult += outsideText.slice(lastIndex);\n\t\t}\n\t\tdice = result;\n\t}\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\n\treturn replaceFormulaInDice(dice);\n}\n\n/**\n * Replace the {{}} in the dice string and evaluate the interior if any\n * @param dice {string}\n */\nexport function replaceFormulaInDice(dice: string) {\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\n\tlet match;\n\tlet modifiedDice = dice;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\twhile ((match = formula.exec(dice)) !== null) {\n\t\tif (match.groups?.formula) {\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\n\t\t\ttry {\n\t\t\t\tconst result = evaluate(formulae);\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cleanedDice(modifiedDice);\n}\n\n/**\n * Replace the ++ +- -- by their proper value:\n * - `++` = `+`\n * - `+-` = `-`\n * - `--` = `+`\n * @param dice {string}\n */\nfunction cleanedDice(dice: string) {\n\treturn dice\n\t\t.replaceAll(\"+-\", \"-\")\n\t\t.replaceAll(\"--\", \"+\")\n\t\t.replaceAll(\"++\", \"+\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimEnd();\n}\n\n/**\n * Verify if a value is a number, even if it's a \"number\" string\n * @param value {unknown}\n * @returns {boolean}\n */\nexport function isNumber(value: unknown): boolean {\n\treturn (\n\t\tvalue !== undefined &&\n\t\t(typeof value === \"number\" ||\n\t\t\t(!Number.isNaN(Number(value)) &&\n\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\tvalue.trim().length > 0))\n\t);\n}\n\n/**\n * Replace the `{exp}` in the dice.\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\n * @param {string} dice\n * @param engine\n * @returns {string} the dice with the {exp} replaced by a random value\n */\nexport function replaceExpByRandom(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): string {\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\n\t\tconst defaultValue = groups?.default;\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\n\t});\n}\n\n/**\n * Utility function to get a random integer between min and max and using the specified engine\n * @param min {number}\n * @param max {number}\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\n * @returns {number} Random integer between min and max\n */\nexport function randomInt(\n\tmin: number,\n\tmax: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\trng?: Random\n): number {\n\tif (!rng) rng = new Random(engine || undefined);\n\treturn rng.integer(min, max);\n}\n/**\n * Utility function that allow to get the id of an engine\n * @param engine {unknown} Engine to identify\n * @returns {string} Id of the engine or \"unknown\"\n * @private\n */\nexport function getEngineId(engine: unknown): string {\n\t// Comparaisons directes avec les engines exposés par la lib\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\n\t// Fallback: essayer de lire un nom ou le constructeur\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\n\t\tconst e = engine as any;\n\t\tif (e && typeof e === \"object\") {\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\n\t\t\tif (e.constructor?.name) return e.constructor.name;\n\t\t}\n\t} catch {\n\t\t/* ignore */\n\t}\n\treturn \"unknown\";\n}\n\n/**\n * Utility function to get the engine from its name\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\n * @returns {Engine} The engine\n * @public\n */\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\n\tswitch (engine) {\n\t\tcase \"nativeMath\":\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t\tcase \"browserCrypto\":\n\t\t\treturn NumberGenerator.engines.browserCrypto;\n\t\tcase \"nodeCrypto\":\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\n\t\tdefault:\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t}\n}\n\n/**\n * Calcule la distance de Levenshtein entre deux chaînes\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\tif (a === b) return 0;\n\tconst al = a.length;\n\tconst bl = b.length;\n\tif (al === 0) return bl;\n\tif (bl === 0) return al;\n\tconst v0 = new Array<number>(bl + 1);\n\tconst v1 = new Array<number>(bl + 1);\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\n\tfor (let i = 0; i < al; i++) {\n\t\tv1[0] = i + 1;\n\t\tfor (let j = 0; j < bl; j++) {\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n\t\t}\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\n\t}\n\treturn v1[bl];\n}\n\n/**\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\n */\nfunction similarityScore(a: string, b: string): number {\n\tconst la = a.length;\n\tconst lb = b.length;\n\tif (la === 0 && lb === 0) return 1;\n\tconst dist = levenshteinDistance(a, b);\n\tconst max = Math.max(la, lb);\n\treturn 1 - dist / max;\n}\n","import { evaluate } from \"mathjs\";\nimport { type Engine, Random } from \"random-js\";\nimport \"uniformize\";\n\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport {\n\tcreateCriticalCustom,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tEmptyObjectError,\n\tescapeRegex,\n\tFormulaError,\n\tNoStatisticsError,\n\treplaceExpByRandom,\n\treplaceFormulaInDice,\n\troll,\n\ttype StatisticalTemplate,\n\tTooManyDice,\n\ttemplateSchema,\n} from \".\";\nimport { isNumber, randomInt } from \"./utils\";\n\n/**\n * Verify if the provided dice work with random value\n * @param testDice {string}\n * @param allStats {Record<string,number>}\n * @param engine\n * @param pity\n */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet dice = testDice.trimEnd();\n\tif (allStats && Object.keys(allStats).length > 0) {\n\t\tconst names = Object.keys(allStats);\n\t\tfor (const name of names) {\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\t\tif (dice.standardize().match(regex)) {\n\t\t\t\tconst statValue = allStats[name];\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\n\t\t\t}\n\t\t}\n\t}\n\ttry {\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\n\t\treturn testDice;\n\t} catch (error) {\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\n\t}\n}\n\n/**\n * Generate a random dice and remove the formula (+ evaluate it)\n * Used for diceDamage only\n * @param value {string}\n * @param template {StatisticalTemplate}\n * @param engine\n * @returns\n */\nexport function diceRandomParse(\n\tvalue: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\n\tvalue = value.standardize();\n\tconst statNames = Object.keys(template.statistics);\n\tlet newDice = value;\n\tfor (const name of statNames) {\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\tif (value.match(regex)) {\n\t\t\tlet max: undefined | number;\n\t\t\tlet min: undefined | number;\n\t\t\tconst foundStat = template.statistics?.[name];\n\t\t\tif (foundStat) {\n\t\t\t\tmax = foundStat.max;\n\t\t\t\tmin = foundStat.min;\n\t\t\t}\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\n\t\t}\n\t}\n\treturn replaceFormulaInDice(newDice);\n}\n\n/**\n * Same as damageDice but for DiceType\n * @param dice {string}\n * @param template {StatisticalTemplate}\n * @param engine\n */\nexport function diceTypeRandomParse(\n\tdice: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tdice = replaceExpByRandom(dice);\n\tif (!template.statistics) return dice;\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\n\t\t(stat) => !template.statistics?.[stat].combinaison\n\t);\n\tif (!firstStatNotcombinaison) return dice;\n\tconst stats = template.statistics[firstStatNotcombinaison];\n\tconst { min, max } = stats;\n\tconst total = template.total || 100;\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\n}\n\n/**\n * Random the combinaison and evaluate it to check if everything is valid\n * @param combinaison {Record<string,string>}\n * @param stats {Record<string,number|number>}\n */\nexport function evalCombinaison(\n\tcombinaison: Record<string, string>,\n\tstats: Record<string, number | string>\n) {\n\tconst newStats: Record<string, number> = {};\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\n\t\t//replace the stats in formula\n\t\tlet formula = combin.standardize();\n\t\tfor (const [statName, value] of Object.entries(stats)) {\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\t\tformula = formula.replace(regex, value.toString());\n\t\t}\n\t\ttry {\n\t\t\tnewStats[stat] = evaluate(formula);\n\t\t} catch (error) {\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\n\t\t}\n\t}\n\treturn newStats;\n}\n\n/**\n * Evaluate one selected combinaison\n * @param combinaison {string}\n * @param stats {[name: string]: string|number}\n */\nexport function evalOneCombinaison(\n\tcombinaison: string,\n\tstats: Record<string, number | string>\n) {\n\tlet formula = combinaison.standardize();\n\tfor (const [statName, value] of Object.entries(stats)) {\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\tformula = formula.replace(regex, value.toString());\n\t}\n\ttry {\n\t\treturn evaluate(formula);\n\t} catch (error) {\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\n\t}\n}\n\nfunction convertNumber(number: string | number | undefined) {\n\tif (number === undefined || number === null) return undefined;\n\tif (\n\t\tnumber.toString().length === 0 ||\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\n\t)\n\t\treturn undefined;\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\n\treturn undefined;\n}\n\n/**\n * Parse the provided JSON and verify each field to check if everything could work when rolling\n * @param {unknown} template\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\n * @param engine\n * @returns {StatisticalTemplate}\n */\nexport function verifyTemplateValue(\n\ttemplate: unknown,\n\tverify = true,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): StatisticalTemplate {\n\tconst parsedTemplate = templateSchema.parse(template);\n\tconst { success, failure } = parsedTemplate.critical ?? {};\n\tconst criticicalVal = {\n\t\tsuccess: convertNumber(success),\n\t\tfailure: convertNumber(failure),\n\t};\n\tconst statistiqueTemplate: StatisticalTemplate = {\n\t\tdiceType: parsedTemplate.diceType,\n\t\tstatistics: parsedTemplate.statistics,\n\t\tcritical: criticicalVal,\n\t\ttotal: parsedTemplate.total,\n\t\tcharName: parsedTemplate.charName,\n\t\tdamage: parsedTemplate.damage,\n\t\tcustomCritical: parsedTemplate.customCritical,\n\t\tforceDistrib: parsedTemplate.forceDistrib,\n\t};\n\tif (!verify) return statistiqueTemplate;\n\tif (statistiqueTemplate.diceType) {\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\n\t\t\tthrow new DiceTypeError(\n\t\t\t\tstatistiqueTemplate.diceType,\n\t\t\t\t\"critical_dice_type\",\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\n\t\t\t);\n\t\t}\n\t\tconst cleanedDice = diceTypeRandomParse(\n\t\t\tstatistiqueTemplate.diceType,\n\t\t\tstatistiqueTemplate,\n\t\t\tengine\n\t\t);\n\t\tconst rolled = roll(cleanedDice, engine);\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\n\t}\n\tif (statistiqueTemplate.customCritical) {\n\t\tif (!statistiqueTemplate.diceType) {\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\n\t\t}\n\t\tconst customCritical = statistiqueTemplate.customCritical;\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\n\t\t\tconst cleanedDice = createCriticalCustom(\n\t\t\t\tstatistiqueTemplate.diceType!,\n\t\t\t\tcustom,\n\t\t\t\tstatistiqueTemplate,\n\t\t\t\tengine\n\t\t\t);\n\t\t\tconst rolled = roll(cleanedDice, engine);\n\t\t\tif (!rolled)\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\n\t\t}\n\t}\n\ttestDiceRegistered(statistiqueTemplate, engine);\n\ttestStatCombinaison(statistiqueTemplate, engine);\n\treturn statistiqueTemplate;\n}\n\n/**\n * Test each damage roll from the template.damage\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testDiceRegistered(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.damage) return;\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\n\tfor (const [name, dice] of Object.entries(template.damage)) {\n\t\tif (!dice) continue;\n\t\tconst diceReplaced = replaceExpByRandom(dice);\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\n\t\ttry {\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\n\t\t}\n\t}\n}\n\n/**\n * Test all combinaison with generated random value\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testStatCombinaison(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return;\n\tconst onlycombinaisonStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(\n\t\t\t([_, value]) => value.combinaison !== undefined\n\t\t)\n\t);\n\tconst allOtherStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\n\t);\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\n\tconst allStats = Object.keys(template.statistics).filter(\n\t\t(stat) => !template.statistics![stat].combinaison\n\t);\n\tif (allStats.length === 0) throw new NoStatisticsError();\n\tconst error = [];\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\n\t\tlet formula = value.combinaison as string;\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\n\t\t\tconst { max, min } = data;\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tconst regex = new RegExp(other, \"gi\");\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\n\t\t}\n\t\ttry {\n\t\t\tevaluate(formula);\n\t\t} catch (e) {\n\t\t\terror.push(stat);\n\t\t}\n\t}\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\n\treturn;\n}\n\n/**\n * Generate a random stat based on the template and the statistical min and max\n * @param {number|undefined} total\n * @param {number | undefined} max\n * @param {number | undefined} min\n * @param engine\n * @returns\n */\nexport function generateRandomStat(\n\ttotal: number | undefined = 100,\n\tmax?: number,\n\tmin?: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tlet randomStatValue = total + 1;\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\n\twhile (randomStatValue >= total || randomStatValue === 0) {\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\n\t\telse randomStatValue = randomInt(1, total, engine, random);\n\t}\n\treturn randomStatValue;\n}\n"],"mappings":"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","names":["roller","evaluateRoll","diceResult","evaluate","NumberGenerator","evaluate","NumberGenerator","evaluate","Random","NumberGenerator","NumberGenerator","evaluate","cleanedDice","Random"]}
|
|
1
|
+
{"version":3,"sources":["../src/dice.ts","../src/errors.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/utils.ts","../src/verify_template.ts"],"sourcesContent":["import { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport {\n\tCOMMENT_REGEX,\n\ttype Compare,\n\ttype ComparedValue,\n\ttype CustomCritical,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tdiceTypeRandomParse,\n\tisNumber,\n\ttype Modifier,\n\tOPTIONAL_COMMENT,\n\ttype Resultat,\n\treplaceFormulaInDice,\n\tSIGN_REGEX,\n\tSIGN_REGEX_SPACE,\n\ttype Sign,\n\ttype StatisticalTemplate,\n\tSYMBOL_DICE,\n\tstandardizeDice,\n} from \".\";\n\n/**\n * Check if a comparison is trivial (always true or always false)\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\n * @param maxValue Maximum possible value from the dice roll\n * @param minValue Minimum possible value from the dice roll\n * @param compare The comparison object\n * @returns true if the comparison is trivial (always true or always false)\n */\nfunction isTrivialComparison(\n\tmaxValue: number,\n\tminValue: number,\n\tcompare: ComparedValue\n): boolean {\n\t// Check if comparison can never succeed (always false)\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\n\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\n\n\t// Trivial if it can never succeed OR can never fail\n\treturn !canSucceed || !canFail;\n}\n\n/**\n * Check if a comparison can theoretically fail given roll bounds\n * @param maxRollValue Maximum possible roll value\n * @param compare The comparison object\n * @param minRollValue Minimum possible roll value (defaults to 1)\n * @returns true if the comparison can fail at least once\n */\nfunction canComparisonFail(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue = 1\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\n\t\tcase \">=\":\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\n\t\tcase \"<\":\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\n\t\tcase \"<=\":\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\n\t\tcase \"!=\":\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; compare: ComparedValue | undefined } {\n\t/**\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\n\t * Some system count the number of a dice that are greater than or equal to a target, and not the \"total\" of rolled dice.\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\n\t * To support this, we use the group notation. It a little different than the notation of dice-roller, but it a sacrifice to not break the current notation.\n\t * @note:\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\n\t * - `{2d3>=4}` will count the total of dice that are greater than or equal to 4, and not the total of the dice.\n\t * - `{2d3,1d4}>=4` won't use the comparison, but will count the number of dice that are greater than or equal to 4. If the total of the dice is needed, just remove the group notation and use `2d3+1d4>=4`.\n\t */\n\tif (\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\n\t)\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\n\tconst calc = compareRegex[2];\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\n\n\tif (sign) {\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\n\t\tconst total = evaluate(rCompare.value.toString());\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: total,\n\t\t\toriginalDice: rCompare.dice,\n\t\t\trollValue: rCompare.diceResult,\n\t\t};\n\t} else {\n\t\tconst rcompare = rollCompare(calc, engine, pity);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: rcompare.value,\n\t\t\toriginalDice: rcompare.dice,\n\t\t\trollValue: rcompare.diceResult,\n\t\t};\n\t}\n\n\treturn { dice, compare };\n}\n\nfunction rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\t// Handle empty value or string - return 0 as default\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n\t\treturn { value: 0, diceResult: value as string };\n\t}\n\tconst rollComp = roll(value as string, engine, pity);\n\tif (!rollComp?.total) {\n\t\t//not a dice throw\n\t\ttry {\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\n\t\t} catch (error) {\n\t\t\t// If evaluate fails, return 0\n\t\t\treturn { value: 0, diceResult: value as string };\n\t\t}\n\t}\n\treturn {\n\t\tdice: value as string,\n\t\tvalue: rollComp.total,\n\t\tdiceResult: rollComp?.result,\n\t};\n}\n\n/**\n * Allow to replace the compare part of a dice and use the critical customized one\n * @example\n * dice = \"1d20=20\";\n * custom critical {sign: \">\", value: \"$/2\"}\n * Random stats = 6\n * result = \"1d20>3\"\n */\nexport function createCriticalCustom(\n\tdice: string,\n\tcustomCritical: CustomCritical,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet customDice = dice;\n\tconst compareValue = diceTypeRandomParse(customCritical.value, template, engine);\n\tif (compareValue.includes(\"$\"))\n\t\tthrow new DiceTypeError(compareValue, \"createCriticalCustom\");\n\tconst comparaison = `${customCritical.sign}${compareValue}`;\n\tif (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);\n\telse customDice += comparaison;\n\treturn diceTypeRandomParse(customDice, template, engine);\n}\n\nfunction getModifier(dice: string) {\n\tconst modifier = dice.matchAll(/(\\+|-|%|\\/|\\^|\\*|\\*{2})(\\d+)/gi);\n\tlet modificator: Modifier | undefined;\n\tfor (const mod of modifier) {\n\t\t//calculate the modifier if multiple\n\t\tif (modificator) {\n\t\t\tconst sign = modificator.sign;\n\t\t\tlet value = modificator.value;\n\t\t\tif (sign) value = calculator(sign, value, Number.parseInt(mod[2], 10));\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue,\n\t\t\t};\n\t\t} else {\n\t\t\tmodificator = {\n\t\t\t\tsign: mod[1] as Sign,\n\t\t\t\tvalue: Number.parseInt(mod[2], 10),\n\t\t\t};\n\t\t}\n\t}\n\treturn modificator;\n}\n\n/**\n * Parse the string provided and turn it as a readable dice for dice parser\n * @param dice {string}\n * @param engine\n * @param pity\n */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\t//parse dice string\n\tdice = standardizeDice(replaceFormulaInDice(dice))\n\t\t.replace(/^\\+/, \"\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimStart();\n\tif (!dice.includes(\"d\")) return undefined;\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\n\tlet compare: ComparedValue | undefined;\n\tif (dice.includes(\";\")) return sharedRolls(dice, engine);\n\n\tdice = fixParenthesis(dice);\n\tconst modificator = getModifier(dice);\n\n\t// Extract compare BEFORE rolling to remove it from the dice notation\n\tif (compareRegex) {\n\t\tconst compareResult = getCompare(dice, compareRegex, engine, pity);\n\t\tdice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\n\tif (dice.match(/\\d+?#(.*)/)) {\n\t\tconst diceArray = dice.split(\"#\");\n\t\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\n\t\tconst diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\n\t\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\n\t\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\n\t\tconst roller = new DiceRoller();\n\t\tNumberGenerator.generator.engine = engine;\n\t\t//remove comments if any\n\t\tfor (let i = 0; i < numberOfDice; i++) {\n\t\t\ttry {\n\t\t\t\troller.roll(diceToRoll);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdice: diceToRoll,\n\t\t\tresult: roller.output,\n\t\t\tcomment: comments,\n\t\t\tcompare: compare ? compare : undefined,\n\t\t\tmodifier: modificator,\n\t\t\ttotal: roller.total,\n\t\t};\n\t}\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tconst diceWithoutComment = dice.replace(COMMENT_REGEX, \"\").trimEnd();\n\n\tlet diceRoll: DiceRoll | DiceRoll[];\n\ttry {\n\t\tdiceRoll = roller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\n\t// Update compare.trivial after rolling to get access to diceRoll for trivial detection\n\tif (compare && diceRoll) {\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxDiceValue = currentRoll.maxTotal;\n\t\tconst minDiceValue = currentRoll.minTotal;\n\t\tconst trivial = isTrivialComparison(maxDiceValue, minDiceValue, compare);\n\t\tcompare.trivial = trivial ? true : undefined;\n\t}\n\n\tconst commentMatch = dice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\n\tlet rerollCount = 0;\n\tlet res: Resultat | undefined;\n\tif (pity && compare) {\n\t\t// Vérifier si la comparaison est théoriquement possible\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\n\t\tconst isComparisonPossible =\n\t\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\n\n\t\tif (isComparisonPossible) {\n\t\t\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\n\t\t\tif (!isFail) {\n\t\t\t\t//reroll until success\n\t\t\t\tconst maxReroll = 100;\n\t\t\t\twhile (!isFail && rerollCount < maxReroll) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tres = roll(diceWithoutComment, engine, false); // désactiver pity pour éviter la récursion infinie\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t\t\t\t\t}\n\t\t\t\t\trerollCount++;\n\t\t\t\t\tif (res && res.total !== undefined)\n\t\t\t\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\n\t\t\t\t}\n\t\t\t\tif (res) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...res,\n\t\t\t\t\t\tdice,\n\t\t\t\t\t\tcomment,\n\t\t\t\t\t\tcompare: compare,\n\t\t\t\t\t\tmodifier: modificator,\n\t\t\t\t\t\tpityLogs: rerollCount,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t} else console.log(\"Comparison impossible, pity ignored\");\n\t}\n\treturn {\n\t\tdice,\n\t\tresult: roller.output,\n\t\tcomment,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t};\n}\n\n/**\n * Check if a comparison can theoretically succeed given a maximum roll value\n * @example\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\n */\nfunction canComparisonSucceed(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue?: number\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn maxRollValue > compare.value;\n\t\tcase \">=\":\n\t\t\treturn maxRollValue >= compare.value;\n\t\tcase \"<\":\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"<=\":\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\n\t\tcase \"!=\":\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nfunction fixParenthesis(dice: string) {\n\t//dice with like 1d(20) are not valid, we need to remove the parenthesis\n\t//warning: the 1d(20+5) is valid and should not be changed\n\tconst parenthesisRegex = /d\\((\\d+)\\)/g;\n\treturn dice.replaceAll(parenthesisRegex, (_match, p1) => `d${p1}`);\n}\n\n/**\n * Evaluate a formula and replace \"^\" by \"**\" if any\n * @param {Sign} sign\n * @param {number} value\n * @param {number} total\n * @returns\n */\nexport function calculator(sign: Sign, value: number, total: number): number {\n\tif (sign === \"^\") sign = \"**\";\n\treturn evaluate(`${total} ${sign} ${value}`);\n}\n\nfunction inverseSign(\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\"\n): \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\" {\n\tswitch (sign) {\n\t\tcase \"<\":\n\t\t\treturn \">\";\n\t\tcase \">\":\n\t\t\treturn \"<\";\n\t\tcase \"<=\":\n\t\t\treturn \">=\";\n\t\tcase \">=\":\n\t\t\treturn \"<=\";\n\t\tcase \"=\":\n\t\t\treturn \"!=\";\n\t\tcase \"==\":\n\t\t\treturn \"!=\";\n\t\tcase \"!=\":\n\t\t\treturn \"==\";\n\t}\n}\n\nfunction replaceInFormula(\n\telement: string,\n\tdiceResult: Resultat,\n\tcompareResult: { dice: string; compare: Compare | undefined },\n\tres: boolean,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tconst { formule, diceAll } = replaceText(\n\t\telement,\n\t\tdiceResult.total ?? 0,\n\t\tdiceResult.dice\n\t);\n\tconst validSign = res ? \"✓\" : \"✕\";\n\tconst invertedSign = res\n\t\t? compareResult.compare!.sign\n\t\t: inverseSign(compareResult.compare!.sign);\n\tlet evaluateRoll: unknown;\n\ttry {\n\t\tevaluateRoll = evaluate(compareResult.dice);\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t} catch (error) {\n\t\tconst evaluateRoll = roll(compareResult.dice, engine, pity) as Resultat | undefined;\n\t\tif (evaluateRoll)\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\n\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t}\n}\n\nfunction compareSignFormule(\n\ttoRoll: string,\n\tcompareRegex: RegExpMatchArray,\n\telement: string,\n\tdiceResult: Resultat,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; results: string; compare?: Compare; trivial: boolean } {\n\tlet results = \"\";\n\tlet trivial = false;\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\n\tlet res: unknown;\n\ttry {\n\t\tres = evaluate(toCompare);\n\t} catch (error) {\n\t\tres = roll(toCompare, engine, pity);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\ttrivial = true;\n\t\tif (compareResult.compare) compareResult.compare.trivial = true;\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\n\t} else if (res instanceof Object) {\n\t\tconst diceResult = res as Resultat;\n\t\tif (diceResult.compare) {\n\t\t\tconst toEvaluate = evaluate(\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\n\t\t\t);\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\n\t\t\tconst invertedSign = toEvaluate\n\t\t\t\t? diceResult.compare.sign\n\t\t\t\t: inverseSign(diceResult.compare.sign);\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\n\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\n\t\t\tif (diceResult.compare.trivial) trivial = true;\n\t\t}\n\t}\n\treturn { dice: compareResult.dice, results, compare: compareResult.compare, trivial };\n}\n\nfunction replaceText(element: string, total: number, dice: string) {\n\treturn {\n\t\tformule: element.replace(SYMBOL_DICE, `[${total}]`).replace(/%.*%/g, \"\").trim(),\n\t\tdiceAll: element\n\t\t\t.replace(SYMBOL_DICE, `[${dice.replace(COMMENT_REGEX, \"\")}]`)\n\t\t\t.replace(/%.*%/g, \"\")\n\t\t\t.trim(),\n\t};\n}\n\nfunction formatComment(dice: string) {\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\n\tconst commentsMatch = commentsRegex.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\n\t// to avoid conflicts with parentheses inside bracket comments\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\n\n\t//fusion of both comments with a space if both exists\n\t//result expected = \"__comment1 comment2__ — \"\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\n\tlet finalComment = \"\";\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\n\telse if (comments) finalComment = `__${comments}__ — `;\n\telse if (optional) finalComment = `__${optional}__ — `;\n\treturn finalComment;\n}\n\nfunction sharedRolls(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): Resultat | undefined {\n\tif (dice.match(/\\d+?#(.*?)/))\n\t\tthrow new DiceTypeError(\n\t\t\tdice,\n\t\t\t\"noBulkRoll\",\n\t\t\t\"bulk roll are not allowed in shared rolls\"\n\t\t);\n\tconst results = [];\n\tconst mainComment =\n\t\t/\\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? undefined;\n\tconst split = dice.split(\";\");\n\tlet diceMain = fixParenthesis(split[0]);\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\t// Remove comments before checking for hidden dice (parentheses)\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\n\tlet hidden = false;\n\tif (toHide?.dice) {\n\t\tdiceMain = toHide.dice;\n\t\thidden = true;\n\t} else if (toHide) {\n\t\tdiceMain = \"1d1\";\n\t\thidden = true;\n\t} else {\n\t\t// No hidden dice, use the dice without comments\n\t\tdiceMain = diceMainWithoutComments;\n\t}\n\tlet diceResult = roll(diceMain, engine, pity);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\n\t\t\thidden = false;\n\t\t} else return undefined;\n\t}\n\tif (!diceResult || !diceResult.total) return undefined;\n\tlet aggregatedCompare = diceResult.compare;\n\tlet hasTrivialComparison = diceResult.compare?.trivial === true;\n\tresults.push(`※ ${comments}${diceResult.result}`);\n\tlet total = diceResult.total;\n\tdiceResult.comment = mainComment;\n\tif (!total) return diceResult;\n\tfor (let element of split.slice(1)) {\n\t\tconst comment = formatComment(element);\n\t\telement = element\n\t\t\t.replaceAll(commentsRegex, \"\")\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\n\t\t\t.trim();\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\n\t\t//remove comments\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\n\t\tif (compareRegex) {\n\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\ttoRoll,\n\t\t\t\tcompareRegex,\n\t\t\t\telement,\n\t\t\t\tdiceResult,\n\t\t\t\tengine\n\t\t\t);\n\t\t\ttoRoll = compareResult.dice;\n\t\t\tresults.push(compareResult.results);\n\t\t\tif (!aggregatedCompare && compareResult.compare) aggregatedCompare = compareResult.compare;\n\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\n\t\t} else {\n\t\t\tconst { formule, diceAll } = replaceText(\n\t\t\t\telement,\n\t\t\t\tdiceResult.total,\n\t\t\t\tdiceResult.dice\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\n\t\t\t} catch (error) {\n\t\t\t\tconst evaluated = roll(toRoll, engine, pity);\n\t\t\t\tif (evaluated) {\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\n\t\t\t\t\t);\n\t\t\t\t\tif (!aggregatedCompare && evaluated.compare)\n\t\t\t\t\t\taggregatedCompare = evaluated.compare;\n\t\t\t\t\tif (evaluated.compare?.trivial) hasTrivialComparison = true;\n\t\t\t\t} else results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += evaluated?.total ?? 0;\n\t\t\t}\n\t\t}\n\t}\n\tif (hidden)\n\t\t//remove the first in result\n\t\tresults.shift();\n\treturn {\n\t\tdice: diceMain,\n\t\tresult: results.join(\";\"),\n\t\tcomment: mainComment,\n\t\tcompare: hasTrivialComparison && aggregatedCompare\n\t\t\t? { ...aggregatedCompare, trivial: true }\n\t\t\t: aggregatedCompare,\n\t\tmodifier: diceResult.modifier,\n\t\ttotal,\n\t};\n}\n","export class DiceTypeError extends Error {\n\tpublic readonly dice: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(dice: string, cause?: string, method?: unknown) {\n\t\tsuper(dice);\n\t\tthis.name = \"Invalid_Dice_Type\";\n\t\tthis.dice = dice;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class FormulaError extends Error {\n\tpublic readonly formula: string;\n\tpublic readonly cause: string | undefined;\n\tpublic readonly method: unknown;\n\n\tconstructor(formula: string, cause?: string, method?: unknown) {\n\t\tsuper(formula);\n\t\tthis.name = \"Invalid_Formula\";\n\t\tthis.formula = formula;\n\t\tthis.cause = cause;\n\t\tthis.method = method;\n\t}\n}\n\nexport class MaxGreater extends Error {\n\tpublic readonly name: string;\n\tpublic readonly value: number;\n\tpublic readonly max: number;\n\n\tconstructor(value: number, max: number) {\n\t\tsuper(value.toString());\n\t\tthis.name = \"Max_Greater\";\n\t\tthis.value = value;\n\t\tthis.max = max;\n\t}\n}\n\nexport class EmptyObjectError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Empty_Object\";\n\t}\n}\n\nexport class TooManyDice extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Dice\";\n\t}\n}\n\nexport class TooManyStats extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"Too_Many_Stats\";\n\t}\n}\n\nexport class NoStatisticsError extends Error {\n\tpublic readonly name: string;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.name = \"No_Statistics\";\n\t}\n}\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\n// Use negative lookbehind to check for ![<>] before any comparison operator\nexport const SIGN_REGEX =\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\nexport const SIGN_REGEX_SPACE =\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\n","/**\n * Definition of the Zod schema for template data\n */\nimport { z } from \"zod\";\n\nconst statisticValueSchema = z\n\t.object({\n\t\tmax: z\n\t\t\t.number()\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t\t.optional(),\n\t\tmin: z\n\t\t\t.number()\n\t\t\t.transform((val) =>\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\n\t\t\t)\n\t\t\t.optional(),\n\t\tcombinaison: z\n\t\t\t.string()\n\t\t\t.transform((str) => str.trim() || undefined)\n\t\t\t.optional(),\n\t\texclude: z.boolean().optional(),\n\t})\n\t.superRefine((data, ctx) => {\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\n\t\t\t\tpath: [\"max\"],\n\t\t\t});\n\t\t}\n\t});\n\nconst statisticSchema = z\n\t.record(z.string(), statisticValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyStats\",\n\t});\n\nconst criticalSchema = z\n\t.object({\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\n\t})\n\t.transform((values) => {\n\t\tif (values.success === \"\") values.success = undefined;\n\t\tif (values.failure === \"\") values.failure = undefined;\n\t\tif (values.failure === 0) values.failure = undefined;\n\t\tif (values.success === 0) values.success = undefined;\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\n\t\treturn values;\n\t});\n\nconst criticalValueSchema = z.object({\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\n\tvalue: z.string(),\n\tonNaturalDice: z.boolean().optional(),\n\taffectSkill: z.boolean().optional(),\n});\n\nconst damageSchema = z\n\t.record(z.string(), z.string())\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nconst customCriticalSchema = z\n\t.record(z.string(), criticalValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nexport const templateSchema = z.object({\n\tcharName: z.boolean().optional(),\n\tstatistics: statisticSchema,\n\ttotal: z\n\t\t.number()\n\t\t.min(0)\n\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t.optional(),\n\tforceDistrib: z.boolean().optional(),\n\tdiceType: z.string().optional(),\n\tcritical: criticalSchema.optional(),\n\tcustomCritical: customCriticalSchema,\n\tdamage: damageSchema,\n});\n","import { evaluate } from \"mathjs\";\nimport \"uniformize\";\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { type Engine, Random } from \"random-js\";\nimport { FormulaError } from \".\";\n\n/**\n * Escape regex string\n * @param string {string}\n */\nexport function escapeRegex(string: string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Allow to keep the text as if in brackets\n * @param dice {string}\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\n */\nexport function standardizeDice(dice: string): string {\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\n\t);\n}\n\n/**\n * Replace the stat name by their value using stat\n * and after evaluate any formula using `replaceFormulaInDice`\n * @param {string} originalDice\n * @param {Record<string,number>|undefined} stats\n * @param {string|undefined} dollarValue\n */\nexport function generateStatsDice(\n\toriginalDice: string,\n\tstats?: Record<string, number>,\n\tdollarValue?: string\n) {\n\tlet dice = originalDice.standardize();\n\tif (stats && Object.keys(stats).length > 0) {\n\t\tconst statKeys = Object.keys(stats);\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\n\t\tlet result = \"\";\n\t\tlet match: RegExpExecArray | null;\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\n\t\t\tconst insideBrackets = match[1];\n\t\t\tconst outsideText = match[2];\n\t\t\tif (insideBrackets) {\n\t\t\t\tresult += insideBrackets;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!outsideText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\n\t\t\tlet lastIndex = 0;\n\t\t\tlet tokenMatch: RegExpExecArray | null;\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\n\t\t\t\tconst token = tokenMatch[0];\n\t\t\t\tconst tokenStd = token.standardize();\n\t\t\t\tlet bestKey: string | null = null;\n\t\t\t\tlet bestScore = 0;\n\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\tif (\n\t\t\t\t\t\ttokenStd === keyStd ||\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\n\t\t\t\t\t) {\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t\tbestScore = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\n\t\t\t\t\tif (score > bestScore) {\n\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\n\t\t\t\t\tconst statValue = stats[bestKey];\n\t\t\t\t\tresult += statValue.toString();\n\t\t\t\t} else {\n\t\t\t\t\tresult += token;\n\t\t\t\t}\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t}\n\t\t\tresult += outsideText.slice(lastIndex);\n\t\t}\n\t\tdice = result;\n\t}\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\n\treturn replaceFormulaInDice(dice);\n}\n\n/**\n * Replace the {{}} in the dice string and evaluate the interior if any\n * @param dice {string}\n */\nexport function replaceFormulaInDice(dice: string) {\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\n\tlet match;\n\tlet modifiedDice = dice;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\twhile ((match = formula.exec(dice)) !== null) {\n\t\tif (match.groups?.formula) {\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\n\t\t\ttry {\n\t\t\t\tconst result = evaluate(formulae);\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cleanedDice(modifiedDice);\n}\n\n/**\n * Replace the ++ +- -- by their proper value:\n * - `++` = `+`\n * - `+-` = `-`\n * - `--` = `+`\n * @param dice {string}\n */\nfunction cleanedDice(dice: string) {\n\treturn dice\n\t\t.replaceAll(\"+-\", \"-\")\n\t\t.replaceAll(\"--\", \"+\")\n\t\t.replaceAll(\"++\", \"+\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimEnd();\n}\n\n/**\n * Verify if a value is a number, even if it's a \"number\" string\n * @param value {unknown}\n * @returns {boolean}\n */\nexport function isNumber(value: unknown): boolean {\n\treturn (\n\t\tvalue !== undefined &&\n\t\t(typeof value === \"number\" ||\n\t\t\t(!Number.isNaN(Number(value)) &&\n\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\tvalue.trim().length > 0))\n\t);\n}\n\n/**\n * Replace the `{exp}` in the dice.\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\n * @param {string} dice\n * @param engine\n * @returns {string} the dice with the {exp} replaced by a random value\n */\nexport function replaceExpByRandom(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): string {\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\n\t\tconst defaultValue = groups?.default;\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\n\t});\n}\n\n/**\n * Utility function to get a random integer between min and max and using the specified engine\n * @param min {number}\n * @param max {number}\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\n * @returns {number} Random integer between min and max\n */\nexport function randomInt(\n\tmin: number,\n\tmax: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\trng?: Random\n): number {\n\tif (!rng) rng = new Random(engine || undefined);\n\treturn rng.integer(min, max);\n}\n/**\n * Utility function that allow to get the id of an engine\n * @param engine {unknown} Engine to identify\n * @returns {string} Id of the engine or \"unknown\"\n * @private\n */\nexport function getEngineId(engine: unknown): string {\n\t// Comparaisons directes avec les engines exposés par la lib\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\n\t// Fallback: essayer de lire un nom ou le constructeur\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\n\t\tconst e = engine as any;\n\t\tif (e && typeof e === \"object\") {\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\n\t\t\tif (e.constructor?.name) return e.constructor.name;\n\t\t}\n\t} catch {\n\t\t/* ignore */\n\t}\n\treturn \"unknown\";\n}\n\n/**\n * Utility function to get the engine from its name\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\n * @returns {Engine} The engine\n * @public\n */\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\n\tswitch (engine) {\n\t\tcase \"nativeMath\":\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t\tcase \"browserCrypto\":\n\t\t\treturn NumberGenerator.engines.browserCrypto;\n\t\tcase \"nodeCrypto\":\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\n\t\tdefault:\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t}\n}\n\n/**\n * Calcule la distance de Levenshtein entre deux chaînes\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\tif (a === b) return 0;\n\tconst al = a.length;\n\tconst bl = b.length;\n\tif (al === 0) return bl;\n\tif (bl === 0) return al;\n\tconst v0 = new Array<number>(bl + 1);\n\tconst v1 = new Array<number>(bl + 1);\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\n\tfor (let i = 0; i < al; i++) {\n\t\tv1[0] = i + 1;\n\t\tfor (let j = 0; j < bl; j++) {\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n\t\t}\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\n\t}\n\treturn v1[bl];\n}\n\n/**\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\n */\nfunction similarityScore(a: string, b: string): number {\n\tconst la = a.length;\n\tconst lb = b.length;\n\tif (la === 0 && lb === 0) return 1;\n\tconst dist = levenshteinDistance(a, b);\n\tconst max = Math.max(la, lb);\n\treturn 1 - dist / max;\n}\n","import { evaluate } from \"mathjs\";\nimport { type Engine, Random } from \"random-js\";\nimport \"uniformize\";\n\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport {\n\tcreateCriticalCustom,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tEmptyObjectError,\n\tescapeRegex,\n\tFormulaError,\n\tNoStatisticsError,\n\treplaceExpByRandom,\n\treplaceFormulaInDice,\n\troll,\n\ttype StatisticalTemplate,\n\tTooManyDice,\n\ttemplateSchema,\n} from \".\";\nimport { isNumber, randomInt } from \"./utils\";\n\n/**\n * Verify if the provided dice work with random value\n * @param testDice {string}\n * @param allStats {Record<string,number>}\n * @param engine\n * @param pity\n */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet dice = testDice.trimEnd();\n\tif (allStats && Object.keys(allStats).length > 0) {\n\t\tconst names = Object.keys(allStats);\n\t\tfor (const name of names) {\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\t\tif (dice.standardize().match(regex)) {\n\t\t\t\tconst statValue = allStats[name];\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\n\t\t\t}\n\t\t}\n\t}\n\ttry {\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\n\t\treturn testDice;\n\t} catch (error) {\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\n\t}\n}\n\n/**\n * Generate a random dice and remove the formula (+ evaluate it)\n * Used for diceDamage only\n * @param value {string}\n * @param template {StatisticalTemplate}\n * @param engine\n * @returns\n */\nexport function diceRandomParse(\n\tvalue: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\n\tvalue = value.standardize();\n\tconst statNames = Object.keys(template.statistics);\n\tlet newDice = value;\n\tfor (const name of statNames) {\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\tif (value.match(regex)) {\n\t\t\tlet max: undefined | number;\n\t\t\tlet min: undefined | number;\n\t\t\tconst foundStat = template.statistics?.[name];\n\t\t\tif (foundStat) {\n\t\t\t\tmax = foundStat.max;\n\t\t\t\tmin = foundStat.min;\n\t\t\t}\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\n\t\t}\n\t}\n\treturn replaceFormulaInDice(newDice);\n}\n\n/**\n * Same as damageDice but for DiceType\n * @param dice {string}\n * @param template {StatisticalTemplate}\n * @param engine\n */\nexport function diceTypeRandomParse(\n\tdice: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tdice = replaceExpByRandom(dice);\n\tif (!template.statistics) return dice;\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\n\t\t(stat) => !template.statistics?.[stat].combinaison\n\t);\n\tif (!firstStatNotcombinaison) return dice;\n\tconst stats = template.statistics[firstStatNotcombinaison];\n\tconst { min, max } = stats;\n\tconst total = template.total || 100;\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\n}\n\n/**\n * Random the combinaison and evaluate it to check if everything is valid\n * @param combinaison {Record<string,string>}\n * @param stats {Record<string,number|number>}\n */\nexport function evalCombinaison(\n\tcombinaison: Record<string, string>,\n\tstats: Record<string, number | string>\n) {\n\tconst newStats: Record<string, number> = {};\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\n\t\t//replace the stats in formula\n\t\tlet formula = combin.standardize();\n\t\tfor (const [statName, value] of Object.entries(stats)) {\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\t\tformula = formula.replace(regex, value.toString());\n\t\t}\n\t\ttry {\n\t\t\tnewStats[stat] = evaluate(formula);\n\t\t} catch (error) {\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\n\t\t}\n\t}\n\treturn newStats;\n}\n\n/**\n * Evaluate one selected combinaison\n * @param combinaison {string}\n * @param stats {[name: string]: string|number}\n */\nexport function evalOneCombinaison(\n\tcombinaison: string,\n\tstats: Record<string, number | string>\n) {\n\tlet formula = combinaison.standardize();\n\tfor (const [statName, value] of Object.entries(stats)) {\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\tformula = formula.replace(regex, value.toString());\n\t}\n\ttry {\n\t\treturn evaluate(formula);\n\t} catch (error) {\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\n\t}\n}\n\nfunction convertNumber(number: string | number | undefined) {\n\tif (number === undefined || number === null) return undefined;\n\tif (\n\t\tnumber.toString().length === 0 ||\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\n\t)\n\t\treturn undefined;\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\n\treturn undefined;\n}\n\n/**\n * Parse the provided JSON and verify each field to check if everything could work when rolling\n * @param {unknown} template\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\n * @param engine\n * @returns {StatisticalTemplate}\n */\nexport function verifyTemplateValue(\n\ttemplate: unknown,\n\tverify = true,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): StatisticalTemplate {\n\tconst parsedTemplate = templateSchema.parse(template);\n\tconst { success, failure } = parsedTemplate.critical ?? {};\n\tconst criticicalVal = {\n\t\tsuccess: convertNumber(success),\n\t\tfailure: convertNumber(failure),\n\t};\n\tconst statistiqueTemplate: StatisticalTemplate = {\n\t\tdiceType: parsedTemplate.diceType,\n\t\tstatistics: parsedTemplate.statistics,\n\t\tcritical: criticicalVal,\n\t\ttotal: parsedTemplate.total,\n\t\tcharName: parsedTemplate.charName,\n\t\tdamage: parsedTemplate.damage,\n\t\tcustomCritical: parsedTemplate.customCritical,\n\t\tforceDistrib: parsedTemplate.forceDistrib,\n\t};\n\tif (!verify) return statistiqueTemplate;\n\tif (statistiqueTemplate.diceType) {\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\n\t\t\tthrow new DiceTypeError(\n\t\t\t\tstatistiqueTemplate.diceType,\n\t\t\t\t\"critical_dice_type\",\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\n\t\t\t);\n\t\t}\n\t\tconst cleanedDice = diceTypeRandomParse(\n\t\t\tstatistiqueTemplate.diceType,\n\t\t\tstatistiqueTemplate,\n\t\t\tengine\n\t\t);\n\t\tconst rolled = roll(cleanedDice, engine);\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\n\t}\n\tif (statistiqueTemplate.customCritical) {\n\t\tif (!statistiqueTemplate.diceType) {\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\n\t\t}\n\t\tconst customCritical = statistiqueTemplate.customCritical;\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\n\t\t\tconst cleanedDice = createCriticalCustom(\n\t\t\t\tstatistiqueTemplate.diceType!,\n\t\t\t\tcustom,\n\t\t\t\tstatistiqueTemplate,\n\t\t\t\tengine\n\t\t\t);\n\t\t\tconst rolled = roll(cleanedDice, engine);\n\t\t\tif (!rolled)\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\n\t\t}\n\t}\n\ttestDiceRegistered(statistiqueTemplate, engine);\n\ttestStatCombinaison(statistiqueTemplate, engine);\n\treturn statistiqueTemplate;\n}\n\n/**\n * Test each damage roll from the template.damage\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testDiceRegistered(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.damage) return;\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\n\tfor (const [name, dice] of Object.entries(template.damage)) {\n\t\tif (!dice) continue;\n\t\tconst diceReplaced = replaceExpByRandom(dice);\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\n\t\ttry {\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\n\t\t}\n\t}\n}\n\n/**\n * Test all combinaison with generated random value\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testStatCombinaison(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return;\n\tconst onlycombinaisonStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(\n\t\t\t([_, value]) => value.combinaison !== undefined\n\t\t)\n\t);\n\tconst allOtherStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\n\t);\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\n\tconst allStats = Object.keys(template.statistics).filter(\n\t\t(stat) => !template.statistics![stat].combinaison\n\t);\n\tif (allStats.length === 0) throw new NoStatisticsError();\n\tconst error = [];\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\n\t\tlet formula = value.combinaison as string;\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\n\t\t\tconst { max, min } = data;\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tconst regex = new RegExp(other, \"gi\");\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\n\t\t}\n\t\ttry {\n\t\t\tevaluate(formula);\n\t\t} catch (e) {\n\t\t\terror.push(stat);\n\t\t}\n\t}\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\n\treturn;\n}\n\n/**\n * Generate a random stat based on the template and the statistical min and max\n * @param {number|undefined} total\n * @param {number | undefined} max\n * @param {number | undefined} min\n * @param engine\n * @returns\n */\nexport function generateRandomStat(\n\ttotal: number | undefined = 100,\n\tmax?: number,\n\tmin?: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tlet randomStatValue = total + 1;\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\n\twhile (randomStatValue >= total || randomStatValue === 0) {\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\n\t\telse randomStatValue = randomInt(1, total, engine, random);\n\t}\n\treturn randomStatValue;\n}\n"],"mappings":"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","names":["roller","evaluateRoll","diceResult","evaluate","NumberGenerator","evaluate","NumberGenerator","evaluate","Random","NumberGenerator","NumberGenerator","evaluate","cleanedDice","Random"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dicelette/core",
|
|
3
|
-
"version": "1.23.
|
|
3
|
+
"version": "1.23.1",
|
|
4
4
|
"description": "Core library for the Dicelette Discord bot",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"lint": "biome check --write src --unsafe",
|
|
21
21
|
"tsc": "tsc --noEmit --skipLibCheck",
|
|
22
22
|
"release": "commit-and-tag-version",
|
|
23
|
-
"postrelease": "git push --follow-tags origin main && bun publish"
|
|
23
|
+
"postrelease": "git push --follow-tags origin main && bun publish",
|
|
24
|
+
"dev": "tsup --watch"
|
|
24
25
|
},
|
|
25
26
|
"keywords": [
|
|
26
27
|
"discord",
|