@dicelette/core 1.22.2 → 1.22.3
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 +16 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +59 -59
package/dist/index.js
CHANGED
|
@@ -62,11 +62,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
62
62
|
var import_rpg_dice_roller = require("@dice-roller/rpg-dice-roller");
|
|
63
63
|
var import_mathjs = require("mathjs");
|
|
64
64
|
function getCompare(dice, compareRegex, engine = import_rpg_dice_roller.NumberGenerator.engines.nodeCrypto) {
|
|
65
|
-
if (dice.match(/((\{.*,(.*)+\}|([><=!]+\d+f))[
|
|
65
|
+
if (dice.match(/((\{.*,(.*)+\}|([><=!]+\d+f))([><=]|!=)+\d+\}?)|\{(.*)(([><=]|!=)+).*\}/))
|
|
66
66
|
return { dice, compare: void 0 };
|
|
67
67
|
dice = dice.replace(SIGN_REGEX_SPACE, "");
|
|
68
68
|
let compare;
|
|
69
|
-
const calc = compareRegex[
|
|
69
|
+
const calc = compareRegex[2];
|
|
70
70
|
const sign = calc.match(/[+-/*^]/)?.[0];
|
|
71
71
|
const compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];
|
|
72
72
|
if (sign) {
|
|
@@ -271,12 +271,14 @@ function replaceText(element, total, dice) {
|
|
|
271
271
|
function formatComment(dice) {
|
|
272
272
|
const commentsRegex = /\[(?<comments>.*?)\]/;
|
|
273
273
|
const commentsMatch = commentsRegex.exec(dice);
|
|
274
|
-
const optionalComments = OPTIONAL_COMMENT.exec(dice);
|
|
275
274
|
const comments = commentsMatch?.groups?.comments ? `${commentsMatch.groups.comments}` : "";
|
|
275
|
+
const diceWithoutBrackets = dice.replace(commentsRegex, "");
|
|
276
|
+
const optionalCommentsRegex = /\s+(#|\/\/)(?<comment>.*)/;
|
|
277
|
+
const optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);
|
|
276
278
|
const optional = optionalComments?.groups?.comment ? `${optionalComments.groups.comment.trim()}` : "";
|
|
277
279
|
let finalComment = "";
|
|
278
280
|
if (comments && optional)
|
|
279
|
-
finalComment = `__${
|
|
281
|
+
finalComment = `__${comments} ${optional}__ \u2014 `;
|
|
280
282
|
else if (comments) finalComment = `__${comments}__ \u2014 `;
|
|
281
283
|
else if (optional) finalComment = `__${optional}__ \u2014 `;
|
|
282
284
|
return finalComment;
|
|
@@ -292,8 +294,11 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
|
|
|
292
294
|
const mainComment = /\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? void 0;
|
|
293
295
|
const split = dice.split(";");
|
|
294
296
|
let diceMain = fixParenthesis(split[0]);
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
+
const commentsRegex = /\[(?<comments>.*?)\]/gi;
|
|
298
|
+
const comments = formatComment(diceMain);
|
|
299
|
+
const diceMainWithoutComments = diceMain.replace(commentsRegex, "").trim();
|
|
300
|
+
const toHideRegex = /\((?<dice>[^)]+)\)/;
|
|
301
|
+
const toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;
|
|
297
302
|
let hidden = false;
|
|
298
303
|
if (toHide?.dice) {
|
|
299
304
|
diceMain = toHide.dice;
|
|
@@ -301,10 +306,9 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
|
|
|
301
306
|
} else if (toHide) {
|
|
302
307
|
diceMain = "1d1";
|
|
303
308
|
hidden = true;
|
|
309
|
+
} else {
|
|
310
|
+
diceMain = diceMainWithoutComments;
|
|
304
311
|
}
|
|
305
|
-
const commentsRegex = /\[(?<comments>.*?)\]/gi;
|
|
306
|
-
const comments = formatComment(diceMain);
|
|
307
|
-
diceMain = diceMain.replace(commentsRegex, "").trim();
|
|
308
312
|
let diceResult = roll(diceMain, engine);
|
|
309
313
|
if (!diceResult || !diceResult.total) {
|
|
310
314
|
if (hidden) {
|
|
@@ -432,10 +436,10 @@ var NoStatisticsError = class extends Error {
|
|
|
432
436
|
|
|
433
437
|
// src/interfaces/constant.ts
|
|
434
438
|
var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/gi;
|
|
435
|
-
var SIGN_REGEX =
|
|
436
|
-
var SIGN_REGEX_SPACE = /[
|
|
439
|
+
var SIGN_REGEX = /!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;
|
|
440
|
+
var SIGN_REGEX_SPACE = /(!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\S+)/;
|
|
437
441
|
var SYMBOL_DICE = "&";
|
|
438
|
-
var DETECT_CRITICAL = /\{\*?c[fs]:[
|
|
442
|
+
var DETECT_CRITICAL = /\{\*?c[fs]:([<>=]|!=)+(.+?)}/gim;
|
|
439
443
|
var OPTIONAL_COMMENT = /\s+(#|\/{2}|\[|\/\*)?(?<comment>.*)/gi;
|
|
440
444
|
|
|
441
445
|
// src/interfaces/zod.ts
|
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 { 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\nfunction getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\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 (dice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))[><=!]+\\d+\\}?)|\\{(.*)([><=!]+).*\\}/))\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\tconst calc = compareRegex[1];\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);\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);\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\treturn { dice, compare };\n}\n\nfunction rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\tconst rollComp = roll(value as string, engine);\n\tif (!rollComp?.total)\n\t\t//not a dice throw\n\t\treturn { value: evaluate(value as string), diceResult: value as string };\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 */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\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\tif (compareRegex) {\n\t\tconst compareResult = getCompare(dice, compareRegex, engine);\n\t\tdice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\tdice = fixParenthesis(dice);\n\tconst modificator = getModifier(dice);\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\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\ttry {\n\t\troller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\tconst commentMatch = dice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\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};\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) {\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) 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) {\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);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine);\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\t//search for optional comments too\n\tconst optionalComments = OPTIONAL_COMMENT.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\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)\n\t\tfinalComment = `__${commentsMatch?.groups?.comments} ${optionalComments?.groups?.comment.trim()}__ — `;\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): 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\tconst toHideRegex = /(?<!\\[[^\\]]*)\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMain)?.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}\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\tdiceMain = diceMain.replace(commentsRegex, \"\").trim();\n\tconsole.log(\"Dice main:\", diceMain);\n\tlet diceResult = roll(diceMain, engine);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]));\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\tconsole.log(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\tconsole.log(\"Element to roll:\", element);\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);\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;\nexport const SIGN_REGEX = /[><=!]+/;\nexport const SIGN_REGEX_SPACE = /[><=!]+(\\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\";\r\nimport \"uniformize\";\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport { FormulaError } from \".\";\r\n\r\n/**\r\n * Escape regex string\r\n * @param string {string}\r\n */\r\nexport function escapeRegex(string: string) {\r\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n\r\n/**\r\n * Allow to keep the text as if in brackets\r\n * @param dice {string}\r\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\r\n */\r\nexport function standardizeDice(dice: string): string {\r\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\r\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the stat name by their value using stat\r\n * and after evaluate any formula using `replaceFormulaInDice`\r\n * @param {string} originalDice\r\n * @param {Record<string,number>|undefined} stats\r\n * @param {string|undefined} dollarValue\r\n */\r\nexport function generateStatsDice(\r\n\toriginalDice: string,\r\n\tstats?: Record<string, number>,\r\n\tdollarValue?: string\r\n) {\r\n\tlet dice = originalDice.standardize();\r\n\tif (stats && Object.keys(stats).length > 0) {\r\n\t\tconst statKeys = Object.keys(stats);\r\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\r\n\t\tlet result = \"\";\r\n\t\tlet match: RegExpExecArray | null;\r\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\r\n\t\t\tconst insideBrackets = match[1];\r\n\t\t\tconst outsideText = match[2];\r\n\t\t\tif (insideBrackets) {\r\n\t\t\t\tresult += insideBrackets;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (!outsideText) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\r\n\t\t\tlet lastIndex = 0;\r\n\t\t\tlet tokenMatch: RegExpExecArray | null;\r\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\r\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\r\n\t\t\t\tconst token = tokenMatch[0];\r\n\t\t\t\tconst tokenStd = token.standardize();\r\n\t\t\t\tlet bestKey: string | null = null;\r\n\t\t\t\tlet bestScore = 0;\r\n\t\t\t\tfor (const key of statKeys) {\r\n\t\t\t\t\tconst keyStd = key.standardize();\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttokenStd === keyStd ||\r\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\r\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t\tbestScore = 1;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\r\n\t\t\t\t\tif (score > bestScore) {\r\n\t\t\t\t\t\tbestScore = score;\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\r\n\t\t\t\t\tconst statValue = stats[bestKey];\r\n\t\t\t\t\tresult += statValue.toString();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tresult += token;\r\n\t\t\t\t}\r\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\r\n\t\t\t}\r\n\t\t\tresult += outsideText.slice(lastIndex);\r\n\t\t}\r\n\t\tdice = result;\r\n\t}\r\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\r\n\treturn replaceFormulaInDice(dice);\r\n}\r\n\r\n/**\r\n * Replace the {{}} in the dice string and evaluate the interior if any\r\n * @param dice {string}\r\n */\r\nexport function replaceFormulaInDice(dice: string) {\r\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\r\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\r\n\tlet match;\r\n\tlet modifiedDice = dice;\r\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\twhile ((match = formula.exec(dice)) !== null) {\r\n\t\tif (match.groups?.formula) {\r\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\r\n\t\t\ttry {\r\n\t\t\t\tconst result = evaluate(formulae);\r\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn cleanedDice(modifiedDice);\r\n}\r\n\r\n/**\r\n * Replace the ++ +- -- by their proper value:\r\n * - `++` = `+`\r\n * - `+-` = `-`\r\n * - `--` = `+`\r\n * @param dice {string}\r\n */\r\nfunction cleanedDice(dice: string) {\r\n\treturn dice\r\n\t\t.replaceAll(\"+-\", \"-\")\r\n\t\t.replaceAll(\"--\", \"+\")\r\n\t\t.replaceAll(\"++\", \"+\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimEnd();\r\n}\r\n\r\n/**\r\n * Verify if a value is a number, even if it's a \"number\" string\r\n * @param value {unknown}\r\n * @returns {boolean}\r\n */\r\nexport function isNumber(value: unknown): boolean {\r\n\treturn (\r\n\t\tvalue !== undefined &&\r\n\t\t(typeof value === \"number\" ||\r\n\t\t\t(!Number.isNaN(Number(value)) &&\r\n\t\t\t\ttypeof value === \"string\" &&\r\n\t\t\t\tvalue.trim().length > 0))\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the `{exp}` in the dice.\r\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\r\n * @param {string} dice\r\n * @param engine\r\n * @returns {string} the dice with the {exp} replaced by a random value\r\n */\r\nexport function replaceExpByRandom(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): string {\r\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\r\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\r\n\t\tconst defaultValue = groups?.default;\r\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\r\n\t});\r\n}\r\n\r\n/**\r\n * Utility function to get a random integer between min and max and using the specified engine\r\n * @param min {number}\r\n * @param max {number}\r\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\r\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\r\n * @returns {number} Random integer between min and max\r\n */\r\nexport function randomInt(\r\n\tmin: number,\r\n\tmax: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\trng?: Random\r\n): number {\r\n\tif (!rng) rng = new Random(engine || undefined);\r\n\treturn rng.integer(min, max);\r\n}\r\n/**\r\n * Utility function that allow to get the id of an engine\r\n * @param engine {unknown} Engine to identify\r\n * @returns {string} Id of the engine or \"unknown\"\r\n * @private\r\n */\r\nexport function getEngineId(engine: unknown): string {\r\n\t// Comparaisons directes avec les engines exposés par la lib\r\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\r\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\r\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\r\n\t// Fallback: essayer de lire un nom ou le constructeur\r\n\ttry {\r\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\r\n\t\tconst e = engine as any;\r\n\t\tif (e && typeof e === \"object\") {\r\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\r\n\t\t\tif (e.constructor?.name) return e.constructor.name;\r\n\t\t}\r\n\t} catch {\r\n\t\t/* ignore */\r\n\t}\r\n\treturn \"unknown\";\r\n}\r\n\r\n/**\r\n * Utility function to get the engine from its name\r\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\r\n * @returns {Engine} The engine\r\n * @public\r\n */\r\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\r\n\tswitch (engine) {\r\n\t\tcase \"nativeMath\":\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t\tcase \"browserCrypto\":\r\n\t\t\treturn NumberGenerator.engines.browserCrypto;\r\n\t\tcase \"nodeCrypto\":\r\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\r\n\t\tdefault:\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t}\r\n}\r\n\r\n/**\r\n * Calcule la distance de Levenshtein entre deux chaînes\r\n */\r\nfunction levenshteinDistance(a: string, b: string): number {\r\n\tif (a === b) return 0;\r\n\tconst al = a.length;\r\n\tconst bl = b.length;\r\n\tif (al === 0) return bl;\r\n\tif (bl === 0) return al;\r\n\tconst v0 = new Array<number>(bl + 1);\r\n\tconst v1 = new Array<number>(bl + 1);\r\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\r\n\tfor (let i = 0; i < al; i++) {\r\n\t\tv1[0] = i + 1;\r\n\t\tfor (let j = 0; j < bl; j++) {\r\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\r\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\r\n\t\t}\r\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\r\n\t}\r\n\treturn v1[bl];\r\n}\r\n\r\n/**\r\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\r\n */\r\nfunction similarityScore(a: string, b: string): number {\r\n\tconst la = a.length;\r\n\tconst lb = b.length;\r\n\tif (la === 0 && lb === 0) return 1;\r\n\tconst dist = levenshteinDistance(a, b);\r\n\tconst max = Math.max(la, lb);\r\n\treturn 1 - dist / max;\r\n}\r\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 */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\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))\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 * @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 */\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 * @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\tconsole.log(parsedTemplate);\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 */\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 */\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 * @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\";\r\nexport * from \"./errors\";\r\nexport * from \"./interfaces\";\r\nexport * from \"./interfaces/constant\";\r\nexport * from \"./interfaces/toJsonSchema\";\r\nexport * from \"./interfaces/zod\";\r\nexport * from \"./utils\";\r\nexport * from \"./verify_template\";\r\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport {\r\n\tCOMMENT_REGEX,\r\n\ttype Compare,\r\n\ttype ComparedValue,\r\n\ttype CustomCritical,\r\n\tDETECT_CRITICAL,\r\n\tDiceTypeError,\r\n\tdiceTypeRandomParse,\r\n\tisNumber,\r\n\ttype Modifier,\r\n\tOPTIONAL_COMMENT,\r\n\ttype Resultat,\r\n\treplaceFormulaInDice,\r\n\tSIGN_REGEX,\r\n\tSIGN_REGEX_SPACE,\r\n\ttype Sign,\r\n\ttype StatisticalTemplate,\r\n\tSYMBOL_DICE,\r\n\tstandardizeDice,\r\n} from \".\";\r\n\r\nfunction getCompare(\r\n\tdice: string,\r\n\tcompareRegex: RegExpMatchArray,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): { dice: string; compare: ComparedValue | undefined } {\r\n\t/**\r\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\r\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.\r\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\r\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.\r\n\t * @note:\r\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\r\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.\r\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`.\r\n\t */\r\n\tif (dice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/))\r\n\t\treturn { dice, compare: undefined };\r\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\r\n\tlet compare: ComparedValue;\r\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\r\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\r\n\tconst calc = compareRegex[2];\r\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\r\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\r\n\r\n\tif (sign) {\r\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\r\n\t\tconst rCompare = rollCompare(toCalc, engine);\r\n\t\tconst total = evaluate(rCompare.value.toString());\r\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\r\n\t\tcompare = {\r\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\r\n\t\t\tvalue: total,\r\n\t\t\toriginalDice: rCompare.dice,\r\n\t\t\trollValue: rCompare.diceResult,\r\n\t\t};\r\n\t} else {\r\n\t\tconst rcompare = rollCompare(calc, engine);\r\n\t\tcompare = {\r\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\r\n\t\t\tvalue: rcompare.value,\r\n\t\t\toriginalDice: rcompare.dice,\r\n\t\t\trollValue: rcompare.diceResult,\r\n\t\t};\r\n\t}\r\n\treturn { dice, compare };\r\n}\r\n\r\nfunction rollCompare(\r\n\tvalue: unknown,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\r\n\tconst rollComp = roll(value as string, engine);\r\n\tif (!rollComp?.total)\r\n\t\t//not a dice throw\r\n\t\treturn { value: evaluate(value as string), diceResult: value as string };\r\n\treturn {\r\n\t\tdice: value as string,\r\n\t\tvalue: rollComp.total,\r\n\t\tdiceResult: rollComp?.result,\r\n\t};\r\n}\r\n\r\n/**\r\n * Allow to replace the compare part of a dice and use the critical customized one\r\n * @example\r\n * dice = \"1d20=20\";\r\n * custom critical {sign: \">\", value: \"$/2\"}\r\n * Random stats = 6\r\n * result = \"1d20>3\"\r\n */\r\nexport function createCriticalCustom(\r\n\tdice: string,\r\n\tcustomCritical: CustomCritical,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\r\n\tlet customDice = dice;\r\n\tconst compareValue = diceTypeRandomParse(customCritical.value, template, engine);\r\n\tif (compareValue.includes(\"$\"))\r\n\t\tthrow new DiceTypeError(compareValue, \"createCriticalCustom\");\r\n\tconst comparaison = `${customCritical.sign}${compareValue}`;\r\n\tif (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);\r\n\telse customDice += comparaison;\r\n\treturn diceTypeRandomParse(customDice, template, engine);\r\n}\r\n\r\nfunction getModifier(dice: string) {\r\n\tconst modifier = dice.matchAll(/(\\+|-|%|\\/|\\^|\\*|\\*{2})(\\d+)/gi);\r\n\tlet modificator: Modifier | undefined;\r\n\tfor (const mod of modifier) {\r\n\t\t//calculate the modifier if multiple\r\n\t\tif (modificator) {\r\n\t\t\tconst sign = modificator.sign;\r\n\t\t\tlet value = modificator.value;\r\n\t\t\tif (sign) value = calculator(sign, value, Number.parseInt(mod[2], 10));\r\n\t\t\tmodificator = {\r\n\t\t\t\tsign: mod[1] as Sign,\r\n\t\t\t\tvalue,\r\n\t\t\t};\r\n\t\t} else {\r\n\t\t\tmodificator = {\r\n\t\t\t\tsign: mod[1] as Sign,\r\n\t\t\t\tvalue: Number.parseInt(mod[2], 10),\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\treturn modificator;\r\n}\r\n\r\n/**\r\n * Parse the string provided and turn it as a readable dice for dice parser\r\n * @param dice {string}\r\n */\r\nexport function roll(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): Resultat | undefined {\r\n\t//parse dice string\r\n\tdice = standardizeDice(replaceFormulaInDice(dice))\r\n\t\t.replace(/^\\+/, \"\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimStart();\r\n\tif (!dice.includes(\"d\")) return undefined;\r\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\r\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\r\n\tlet compare: ComparedValue | undefined;\r\n\tif (dice.includes(\";\")) return sharedRolls(dice, engine);\r\n\tif (compareRegex) {\r\n\t\tconst compareResult = getCompare(dice, compareRegex, engine);\r\n\t\tdice = compareResult.dice;\r\n\t\tcompare = compareResult.compare;\r\n\t}\r\n\tdice = fixParenthesis(dice);\r\n\tconst modificator = getModifier(dice);\r\n\tif (dice.match(/\\d+?#(.*)/)) {\r\n\t\tconst diceArray = dice.split(\"#\");\r\n\t\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\r\n\t\tconst diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\r\n\t\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\r\n\t\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\r\n\t\tconst roller = new DiceRoller();\r\n\t\tNumberGenerator.generator.engine = engine;\r\n\t\t//remove comments if any\r\n\t\tfor (let i = 0; i < numberOfDice; i++) {\r\n\t\t\ttry {\r\n\t\t\t\troller.roll(diceToRoll);\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {\r\n\t\t\tdice: diceToRoll,\r\n\t\t\tresult: roller.output,\r\n\t\t\tcomment: comments,\r\n\t\t\tcompare: compare ? compare : undefined,\r\n\t\t\tmodifier: modificator,\r\n\t\t\ttotal: roller.total,\r\n\t\t};\r\n\t}\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\tconst diceWithoutComment = dice.replace(COMMENT_REGEX, \"\").trimEnd();\r\n\r\n\ttry {\r\n\t\troller.roll(diceWithoutComment);\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\r\n\t}\r\n\tconst commentMatch = dice.match(COMMENT_REGEX);\r\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\r\n\treturn {\r\n\t\tdice,\r\n\t\tresult: roller.output,\r\n\t\tcomment,\r\n\t\tcompare: compare ? compare : undefined,\r\n\t\tmodifier: modificator,\r\n\t\ttotal: roller.total,\r\n\t};\r\n}\r\n\r\nfunction fixParenthesis(dice: string) {\r\n\t//dice with like 1d(20) are not valid, we need to remove the parenthesis\r\n\t//warning: the 1d(20+5) is valid and should not be changed\r\n\tconst parenthesisRegex = /d\\((\\d+)\\)/g;\r\n\treturn dice.replaceAll(parenthesisRegex, (_match, p1) => `d${p1}`);\r\n}\r\n\r\n/**\r\n * Evaluate a formula and replace \"^\" by \"**\" if any\r\n * @param {Sign} sign\r\n * @param {number} value\r\n * @param {number} total\r\n * @returns\r\n */\r\nexport function calculator(sign: Sign, value: number, total: number): number {\r\n\tif (sign === \"^\") sign = \"**\";\r\n\treturn evaluate(`${total} ${sign} ${value}`);\r\n}\r\n\r\nfunction inverseSign(\r\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\"\r\n): \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\" {\r\n\tswitch (sign) {\r\n\t\tcase \"<\":\r\n\t\t\treturn \">\";\r\n\t\tcase \">\":\r\n\t\t\treturn \"<\";\r\n\t\tcase \"<=\":\r\n\t\t\treturn \">=\";\r\n\t\tcase \">=\":\r\n\t\t\treturn \"<=\";\r\n\t\tcase \"=\":\r\n\t\t\treturn \"!=\";\r\n\t\tcase \"==\":\r\n\t\t\treturn \"!=\";\r\n\t\tcase \"!=\":\r\n\t\t\treturn \"==\";\r\n\t}\r\n}\r\n\r\nfunction replaceInFormula(\r\n\telement: string,\r\n\tdiceResult: Resultat,\r\n\tcompareResult: { dice: string; compare: Compare | undefined },\r\n\tres: boolean,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tconst { formule, diceAll } = replaceText(\r\n\t\telement,\r\n\t\tdiceResult.total ?? 0,\r\n\t\tdiceResult.dice\r\n\t);\r\n\tconst validSign = res ? \"✓\" : \"✕\";\r\n\tconst invertedSign = res\r\n\t\t? compareResult.compare!.sign\r\n\t\t: inverseSign(compareResult.compare!.sign);\r\n\tlet evaluateRoll: unknown;\r\n\ttry {\r\n\t\tevaluateRoll = evaluate(compareResult.dice);\r\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\r\n\t} catch (error) {\r\n\t\tconst evaluateRoll = roll(compareResult.dice, engine) as Resultat | undefined;\r\n\t\tif (evaluateRoll)\r\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\r\n\r\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\r\n\t}\r\n}\r\n\r\nfunction compareSignFormule(\r\n\ttoRoll: string,\r\n\tcompareRegex: RegExpMatchArray,\r\n\telement: string,\r\n\tdiceResult: Resultat,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet results = \"\";\r\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\r\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\r\n\tlet res: unknown;\r\n\ttry {\r\n\t\tres = evaluate(toCompare);\r\n\t} catch (error) {\r\n\t\tres = roll(toCompare, engine);\r\n\t}\r\n\tif (typeof res === \"boolean\") {\r\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine);\r\n\t} else if (res instanceof Object) {\r\n\t\tconst diceResult = res as Resultat;\r\n\t\tif (diceResult.compare) {\r\n\t\t\tconst toEvaluate = evaluate(\r\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\r\n\t\t\t);\r\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\r\n\t\t\tconst invertedSign = toEvaluate\r\n\t\t\t\t? diceResult.compare.sign\r\n\t\t\t\t: inverseSign(diceResult.compare.sign);\r\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\r\n\r\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\r\n\t\t}\r\n\t}\r\n\treturn { dice: compareResult.dice, results };\r\n}\r\n\r\nfunction replaceText(element: string, total: number, dice: string) {\r\n\treturn {\r\n\t\tformule: element.replace(SYMBOL_DICE, `[${total}]`).replace(/%.*%/g, \"\").trim(),\r\n\t\tdiceAll: element\r\n\t\t\t.replace(SYMBOL_DICE, `[${dice.replace(COMMENT_REGEX, \"\")}]`)\r\n\t\t\t.replace(/%.*%/g, \"\")\r\n\t\t\t.trim(),\r\n\t};\r\n}\r\n\r\nfunction formatComment(dice: string) {\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\r\n\tconst commentsMatch = commentsRegex.exec(dice);\r\n\tconst comments = commentsMatch?.groups?.comments\r\n\t\t? `${commentsMatch.groups.comments}`\r\n\t\t: \"\";\r\n\t\r\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\r\n\t// to avoid conflicts with parentheses inside bracket comments\r\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\r\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\r\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\r\n\tconst optional = optionalComments?.groups?.comment\r\n\t\t? `${optionalComments.groups.comment.trim()}`\r\n\t\t: \"\";\r\n\t\r\n\t//fusion of both comments with a space if both exists\r\n\t//result expected = \"__comment1 comment2__ — \"\r\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\r\n\tlet finalComment = \"\";\r\n\tif (comments && optional)\r\n\t\tfinalComment = `__${comments} ${optional}__ — `;\r\n\telse if (comments) finalComment = `__${comments}__ — `;\r\n\telse if (optional) finalComment = `__${optional}__ — `;\r\n\treturn finalComment;\r\n}\r\n\r\nfunction sharedRolls(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): Resultat | undefined {\r\n\tif (dice.match(/\\d+?#(.*?)/))\r\n\t\tthrow new DiceTypeError(\r\n\t\t\tdice,\r\n\t\t\t\"noBulkRoll\",\r\n\t\t\t\"bulk roll are not allowed in shared rolls\"\r\n\t\t);\r\n\tconst results = [];\r\n\tconst mainComment =\r\n\t\t/\\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? undefined;\r\n\tconst split = dice.split(\";\");\r\n\tlet diceMain = fixParenthesis(split[0]);\r\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\r\n\tconst comments = formatComment(diceMain);\r\n\t// Remove comments before checking for hidden dice (parentheses)\r\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\r\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\r\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\r\n\tlet hidden = false;\r\n\tif (toHide?.dice) {\r\n\t\tdiceMain = toHide.dice;\r\n\t\thidden = true;\r\n\t} else if (toHide) {\r\n\t\tdiceMain = \"1d1\";\r\n\t\thidden = true;\r\n\t} else {\r\n\t\t// No hidden dice, use the dice without comments\r\n\t\tdiceMain = diceMainWithoutComments;\r\n\t}\r\n\tlet diceResult = roll(diceMain, engine);\r\n\tif (!diceResult || !diceResult.total) {\r\n\t\tif (hidden) {\r\n\t\t\tdiceResult = roll(fixParenthesis(split[0]));\r\n\t\t\thidden = false;\r\n\t\t} else return undefined;\r\n\t}\r\n\tif (!diceResult || !diceResult.total) return undefined;\r\n\tresults.push(`※ ${comments}${diceResult.result}`);\r\n\tlet total = diceResult.total;\r\n\tdiceResult.comment = mainComment;\r\n\tif (!total) return diceResult;\r\n\tfor (let element of split.slice(1)) {\r\n\t\tconst comment = formatComment(element);\r\n\t\telement = element\r\n\t\t\t.replaceAll(commentsRegex, \"\")\r\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\r\n\t\t\t.trim();\r\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\r\n\t\t//remove comments\r\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\r\n\t\tif (compareRegex) {\r\n\t\t\tconst compareResult = compareSignFormule(\r\n\t\t\t\ttoRoll,\r\n\t\t\t\tcompareRegex,\r\n\t\t\t\telement,\r\n\t\t\t\tdiceResult,\r\n\t\t\t\tengine\r\n\t\t\t);\r\n\t\t\ttoRoll = compareResult.dice;\r\n\t\t\tresults.push(compareResult.results);\r\n\t\t} else {\r\n\t\t\tconst { formule, diceAll } = replaceText(\r\n\t\t\t\telement,\r\n\t\t\t\tdiceResult.total,\r\n\t\t\t\tdiceResult.dice\r\n\t\t\t);\r\n\r\n\t\t\ttry {\r\n\t\t\t\tconst evaluated = evaluate(toRoll);\r\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\r\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\r\n\t\t\t} catch (error) {\r\n\t\t\t\tconst evaluated = roll(toRoll, engine);\r\n\t\t\t\tif (evaluated)\r\n\t\t\t\t\tresults.push(\r\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\r\n\t\t\t\t\t);\r\n\t\t\t\telse results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\r\n\t\t\t\ttotal += evaluated?.total ?? 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (hidden)\r\n\t\t//remove the first in result\r\n\t\tresults.shift();\r\n\treturn {\r\n\t\tdice: diceMain,\r\n\t\tresult: results.join(\";\"),\r\n\t\tcomment: mainComment,\r\n\t\tcompare: diceResult.compare,\r\n\t\tmodifier: diceResult.modifier,\r\n\t\ttotal,\r\n\t};\r\n}\r\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;\r\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\r\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\r\n// Use negative lookbehind to check for ![<>] before any comparison operator\r\nexport const SIGN_REGEX = /!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\r\nexport const SIGN_REGEX_SPACE = /(!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\r\n\r\nexport const SYMBOL_DICE = \"&\";\r\n\r\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\r\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\r\n","/**\r\n * Definition of the Zod schema for template data\r\n */\r\nimport { z } from \"zod\";\r\n\r\nconst statisticValueSchema = z\r\n\t.object({\r\n\t\tmax: z\r\n\t\t\t.number()\r\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\r\n\t\t\t.optional(),\r\n\t\tmin: z\r\n\t\t\t.number()\r\n\t\t\t.transform((val) =>\r\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\r\n\t\t\t)\r\n\t\t\t.optional(),\r\n\t\tcombinaison: z\r\n\t\t\t.string()\r\n\t\t\t.transform((str) => str.trim() || undefined)\r\n\t\t\t.optional(),\r\n\t\texclude: z.boolean().optional(),\r\n\t})\r\n\t.superRefine((data, ctx) => {\r\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\r\n\t\t\tctx.addIssue({\r\n\t\t\t\tcode: \"custom\",\r\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\r\n\t\t\t\tpath: [\"max\"],\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\nconst statisticSchema = z\r\n\t.record(z.string(), statisticValueSchema)\r\n\t.optional()\r\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\r\n\t\tmessage: \"TooManyStats\",\r\n\t});\r\n\r\nconst criticalSchema = z\r\n\t.object({\r\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\r\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\r\n\t})\r\n\t.transform((values) => {\r\n\t\tif (values.success === \"\") values.success = undefined;\r\n\t\tif (values.failure === \"\") values.failure = undefined;\r\n\t\tif (values.failure === 0) values.failure = undefined;\r\n\t\tif (values.success === 0) values.success = undefined;\r\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\r\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\r\n\t\treturn values;\r\n\t});\r\n\r\nconst criticalValueSchema = z.object({\r\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\r\n\tvalue: z.string(),\r\n\tonNaturalDice: z.boolean().optional(),\r\n\taffectSkill: z.boolean().optional(),\r\n});\r\n\r\nconst damageSchema = z\r\n\t.record(z.string(), z.string())\r\n\t.optional()\r\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\r\n\t\tmessage: \"TooManyDice\",\r\n\t});\r\n\r\nconst customCriticalSchema = z\r\n\t.record(z.string(), criticalValueSchema)\r\n\t.optional()\r\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\r\n\t\tmessage: \"TooManyDice\",\r\n\t});\r\n\r\nexport const templateSchema = z.object({\r\n\tcharName: z.boolean().optional(),\r\n\tstatistics: statisticSchema,\r\n\ttotal: z\r\n\t\t.number()\r\n\t\t.min(0)\r\n\t\t.transform((val) => (val === 0 ? undefined : val))\r\n\t\t.optional(),\r\n\tforceDistrib: z.boolean().optional(),\r\n\tdiceType: z.string().optional(),\r\n\tcritical: criticalSchema.optional(),\r\n\tcustomCritical: customCriticalSchema,\r\n\tdamage: damageSchema,\r\n});\r\n","import { evaluate } from \"mathjs\";\r\nimport \"uniformize\";\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport { FormulaError } from \".\";\r\n\r\n/**\r\n * Escape regex string\r\n * @param string {string}\r\n */\r\nexport function escapeRegex(string: string) {\r\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n\r\n/**\r\n * Allow to keep the text as if in brackets\r\n * @param dice {string}\r\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\r\n */\r\nexport function standardizeDice(dice: string): string {\r\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\r\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the stat name by their value using stat\r\n * and after evaluate any formula using `replaceFormulaInDice`\r\n * @param {string} originalDice\r\n * @param {Record<string,number>|undefined} stats\r\n * @param {string|undefined} dollarValue\r\n */\r\nexport function generateStatsDice(\r\n\toriginalDice: string,\r\n\tstats?: Record<string, number>,\r\n\tdollarValue?: string\r\n) {\r\n\tlet dice = originalDice.standardize();\r\n\tif (stats && Object.keys(stats).length > 0) {\r\n\t\tconst statKeys = Object.keys(stats);\r\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\r\n\t\tlet result = \"\";\r\n\t\tlet match: RegExpExecArray | null;\r\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\r\n\t\t\tconst insideBrackets = match[1];\r\n\t\t\tconst outsideText = match[2];\r\n\t\t\tif (insideBrackets) {\r\n\t\t\t\tresult += insideBrackets;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (!outsideText) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\r\n\t\t\tlet lastIndex = 0;\r\n\t\t\tlet tokenMatch: RegExpExecArray | null;\r\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\r\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\r\n\t\t\t\tconst token = tokenMatch[0];\r\n\t\t\t\tconst tokenStd = token.standardize();\r\n\t\t\t\tlet bestKey: string | null = null;\r\n\t\t\t\tlet bestScore = 0;\r\n\t\t\t\tfor (const key of statKeys) {\r\n\t\t\t\t\tconst keyStd = key.standardize();\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttokenStd === keyStd ||\r\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\r\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t\tbestScore = 1;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\r\n\t\t\t\t\tif (score > bestScore) {\r\n\t\t\t\t\t\tbestScore = score;\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\r\n\t\t\t\t\tconst statValue = stats[bestKey];\r\n\t\t\t\t\tresult += statValue.toString();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tresult += token;\r\n\t\t\t\t}\r\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\r\n\t\t\t}\r\n\t\t\tresult += outsideText.slice(lastIndex);\r\n\t\t}\r\n\t\tdice = result;\r\n\t}\r\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\r\n\treturn replaceFormulaInDice(dice);\r\n}\r\n\r\n/**\r\n * Replace the {{}} in the dice string and evaluate the interior if any\r\n * @param dice {string}\r\n */\r\nexport function replaceFormulaInDice(dice: string) {\r\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\r\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\r\n\tlet match;\r\n\tlet modifiedDice = dice;\r\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\twhile ((match = formula.exec(dice)) !== null) {\r\n\t\tif (match.groups?.formula) {\r\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\r\n\t\t\ttry {\r\n\t\t\t\tconst result = evaluate(formulae);\r\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn cleanedDice(modifiedDice);\r\n}\r\n\r\n/**\r\n * Replace the ++ +- -- by their proper value:\r\n * - `++` = `+`\r\n * - `+-` = `-`\r\n * - `--` = `+`\r\n * @param dice {string}\r\n */\r\nfunction cleanedDice(dice: string) {\r\n\treturn dice\r\n\t\t.replaceAll(\"+-\", \"-\")\r\n\t\t.replaceAll(\"--\", \"+\")\r\n\t\t.replaceAll(\"++\", \"+\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimEnd();\r\n}\r\n\r\n/**\r\n * Verify if a value is a number, even if it's a \"number\" string\r\n * @param value {unknown}\r\n * @returns {boolean}\r\n */\r\nexport function isNumber(value: unknown): boolean {\r\n\treturn (\r\n\t\tvalue !== undefined &&\r\n\t\t(typeof value === \"number\" ||\r\n\t\t\t(!Number.isNaN(Number(value)) &&\r\n\t\t\t\ttypeof value === \"string\" &&\r\n\t\t\t\tvalue.trim().length > 0))\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the `{exp}` in the dice.\r\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\r\n * @param {string} dice\r\n * @param engine\r\n * @returns {string} the dice with the {exp} replaced by a random value\r\n */\r\nexport function replaceExpByRandom(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): string {\r\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\r\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\r\n\t\tconst defaultValue = groups?.default;\r\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\r\n\t});\r\n}\r\n\r\n/**\r\n * Utility function to get a random integer between min and max and using the specified engine\r\n * @param min {number}\r\n * @param max {number}\r\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\r\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\r\n * @returns {number} Random integer between min and max\r\n */\r\nexport function randomInt(\r\n\tmin: number,\r\n\tmax: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\trng?: Random\r\n): number {\r\n\tif (!rng) rng = new Random(engine || undefined);\r\n\treturn rng.integer(min, max);\r\n}\r\n/**\r\n * Utility function that allow to get the id of an engine\r\n * @param engine {unknown} Engine to identify\r\n * @returns {string} Id of the engine or \"unknown\"\r\n * @private\r\n */\r\nexport function getEngineId(engine: unknown): string {\r\n\t// Comparaisons directes avec les engines exposés par la lib\r\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\r\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\r\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\r\n\t// Fallback: essayer de lire un nom ou le constructeur\r\n\ttry {\r\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\r\n\t\tconst e = engine as any;\r\n\t\tif (e && typeof e === \"object\") {\r\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\r\n\t\t\tif (e.constructor?.name) return e.constructor.name;\r\n\t\t}\r\n\t} catch {\r\n\t\t/* ignore */\r\n\t}\r\n\treturn \"unknown\";\r\n}\r\n\r\n/**\r\n * Utility function to get the engine from its name\r\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\r\n * @returns {Engine} The engine\r\n * @public\r\n */\r\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\r\n\tswitch (engine) {\r\n\t\tcase \"nativeMath\":\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t\tcase \"browserCrypto\":\r\n\t\t\treturn NumberGenerator.engines.browserCrypto;\r\n\t\tcase \"nodeCrypto\":\r\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\r\n\t\tdefault:\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t}\r\n}\r\n\r\n/**\r\n * Calcule la distance de Levenshtein entre deux chaînes\r\n */\r\nfunction levenshteinDistance(a: string, b: string): number {\r\n\tif (a === b) return 0;\r\n\tconst al = a.length;\r\n\tconst bl = b.length;\r\n\tif (al === 0) return bl;\r\n\tif (bl === 0) return al;\r\n\tconst v0 = new Array<number>(bl + 1);\r\n\tconst v1 = new Array<number>(bl + 1);\r\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\r\n\tfor (let i = 0; i < al; i++) {\r\n\t\tv1[0] = i + 1;\r\n\t\tfor (let j = 0; j < bl; j++) {\r\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\r\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\r\n\t\t}\r\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\r\n\t}\r\n\treturn v1[bl];\r\n}\r\n\r\n/**\r\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\r\n */\r\nfunction similarityScore(a: string, b: string): number {\r\n\tconst la = a.length;\r\n\tconst lb = b.length;\r\n\tif (la === 0 && lb === 0) return 1;\r\n\tconst dist = levenshteinDistance(a, b);\r\n\tconst max = Math.max(la, lb);\r\n\treturn 1 - dist / max;\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport \"uniformize\";\r\n\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport {\r\n\tcreateCriticalCustom,\r\n\tDETECT_CRITICAL,\r\n\tDiceTypeError,\r\n\tEmptyObjectError,\r\n\tescapeRegex,\r\n\tFormulaError,\r\n\tNoStatisticsError,\r\n\treplaceExpByRandom,\r\n\treplaceFormulaInDice,\r\n\troll,\r\n\ttype StatisticalTemplate,\r\n\tTooManyDice,\r\n\ttemplateSchema,\r\n} from \".\";\r\nimport { isNumber, randomInt } from \"./utils\";\r\n\r\n/**\r\n * Verify if the provided dice work with random value\r\n * @param testDice {string}\r\n * @param allStats {Record<string,number>}\r\n */\r\nexport function evalStatsDice(\r\n\ttestDice: string,\r\n\tallStats?: Record<string, number>,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet dice = testDice.trimEnd();\r\n\tif (allStats && Object.keys(allStats).length > 0) {\r\n\t\tconst names = Object.keys(allStats);\r\n\t\tfor (const name of names) {\r\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\t\tif (dice.standardize().match(regex)) {\r\n\t\t\t\tconst statValue = allStats[name];\r\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttry {\r\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine))\r\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\r\n\t\treturn testDice;\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\r\n\t}\r\n}\r\n\r\n/**\r\n * Generate a random dice and remove the formula (+ evaluate it)\r\n * Used for diceDamage only\r\n * @param value {string}\r\n * @param template {StatisticalTemplate}\r\n * @returns\r\n */\r\nexport function diceRandomParse(\r\n\tvalue: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\r\n\tvalue = value.standardize();\r\n\tconst statNames = Object.keys(template.statistics);\r\n\tlet newDice = value;\r\n\tfor (const name of statNames) {\r\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\tif (value.match(regex)) {\r\n\t\t\tlet max: undefined | number;\r\n\t\t\tlet min: undefined | number;\r\n\t\t\tconst foundStat = template.statistics?.[name];\r\n\t\t\tif (foundStat) {\r\n\t\t\t\tmax = foundStat.max;\r\n\t\t\t\tmin = foundStat.min;\r\n\t\t\t}\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t}\r\n\treturn replaceFormulaInDice(newDice);\r\n}\r\n\r\n/**\r\n * Same as damageDice but for DiceType\r\n * @param dice {string}\r\n * @param template {StatisticalTemplate}\r\n */\r\nexport function diceTypeRandomParse(\r\n\tdice: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tdice = replaceExpByRandom(dice);\r\n\tif (!template.statistics) return dice;\r\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\r\n\t\t(stat) => !template.statistics?.[stat].combinaison\r\n\t);\r\n\tif (!firstStatNotcombinaison) return dice;\r\n\tconst stats = template.statistics[firstStatNotcombinaison];\r\n\tconst { min, max } = stats;\r\n\tconst total = template.total || 100;\r\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\r\n}\r\n\r\n/**\r\n * Random the combinaison and evaluate it to check if everything is valid\r\n * @param combinaison {Record<string,string>}\r\n * @param stats {Record<string,number|number>}\r\n */\r\nexport function evalCombinaison(\r\n\tcombinaison: Record<string, string>,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tconst newStats: Record<string, number> = {};\r\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\r\n\t\t//replace the stats in formula\r\n\t\tlet formula = combin.standardize();\r\n\t\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\t\tformula = formula.replace(regex, value.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tnewStats[stat] = evaluate(formula);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\r\n\t\t}\r\n\t}\r\n\treturn newStats;\r\n}\r\n\r\n/**\r\n * Evaluate one selected combinaison\r\n * @param combinaison {string}\r\n * @param stats {[name: string]: string|number}\r\n */\r\nexport function evalOneCombinaison(\r\n\tcombinaison: string,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tlet formula = combinaison.standardize();\r\n\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\tformula = formula.replace(regex, value.toString());\r\n\t}\r\n\ttry {\r\n\t\treturn evaluate(formula);\r\n\t} catch (error) {\r\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\r\n\t}\r\n}\r\n\r\nfunction convertNumber(number: string | number | undefined) {\r\n\tif (number === undefined || number === null) return undefined;\r\n\tif (\r\n\t\tnumber.toString().length === 0 ||\r\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\r\n\t)\r\n\t\treturn undefined;\r\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\r\n\treturn undefined;\r\n}\r\n\r\n/**\r\n * Parse the provided JSON and verify each field to check if everything could work when rolling\r\n * @param {unknown} template\r\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\r\n * @returns {StatisticalTemplate}\r\n */\r\nexport function verifyTemplateValue(\r\n\ttemplate: unknown,\r\n\tverify = true,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): StatisticalTemplate {\r\n\tconst parsedTemplate = templateSchema.parse(template);\r\n\tconst { success, failure } = parsedTemplate.critical ?? {};\r\n\tconst criticicalVal = {\r\n\t\tsuccess: convertNumber(success),\r\n\t\tfailure: convertNumber(failure),\r\n\t};\r\n\tconst statistiqueTemplate: StatisticalTemplate = {\r\n\t\tdiceType: parsedTemplate.diceType,\r\n\t\tstatistics: parsedTemplate.statistics,\r\n\t\tcritical: criticicalVal,\r\n\t\ttotal: parsedTemplate.total,\r\n\t\tcharName: parsedTemplate.charName,\r\n\t\tdamage: parsedTemplate.damage,\r\n\t\tcustomCritical: parsedTemplate.customCritical,\r\n\t\tforceDistrib: parsedTemplate.forceDistrib,\r\n\t};\r\n\tif (!verify) return statistiqueTemplate;\r\n\tif (statistiqueTemplate.diceType) {\r\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\r\n\t\t\tthrow new DiceTypeError(\r\n\t\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\t\t\"critical_dice_type\",\r\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\r\n\t\t\t);\r\n\t\t}\r\n\t\tconst cleanedDice = diceTypeRandomParse(\r\n\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\tstatistiqueTemplate,\r\n\t\t\tengine\r\n\t\t);\r\n\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\r\n\t}\r\n\tif (statistiqueTemplate.customCritical) {\r\n\t\tif (!statistiqueTemplate.diceType) {\r\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\r\n\t\t}\r\n\t\tconst customCritical = statistiqueTemplate.customCritical;\r\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\r\n\t\t\tconst cleanedDice = createCriticalCustom(\r\n\t\t\t\tstatistiqueTemplate.diceType!,\r\n\t\t\t\tcustom,\r\n\t\t\t\tstatistiqueTemplate,\r\n\t\t\t\tengine\r\n\t\t\t);\r\n\t\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\t\tif (!rolled)\r\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\r\n\t\t}\r\n\t}\r\n\ttestDiceRegistered(statistiqueTemplate, engine);\r\n\ttestStatCombinaison(statistiqueTemplate, engine);\r\n\treturn statistiqueTemplate;\r\n}\r\n\r\n/**\r\n * Test each damage roll from the template.damage\r\n * @param {StatisticalTemplate} template\r\n */\r\nexport function testDiceRegistered(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.damage) return;\r\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\r\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\r\n\tfor (const [name, dice] of Object.entries(template.damage)) {\r\n\t\tif (!dice) continue;\r\n\t\tconst diceReplaced = replaceExpByRandom(dice);\r\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\r\n\t\ttry {\r\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\r\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(error);\r\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Test all combinaison with generated random value\r\n * @param {StatisticalTemplate} template\r\n */\r\nexport function testStatCombinaison(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return;\r\n\tconst onlycombinaisonStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(\r\n\t\t\t([_, value]) => value.combinaison !== undefined\r\n\t\t)\r\n\t);\r\n\tconst allOtherStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\r\n\t);\r\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\r\n\tconst allStats = Object.keys(template.statistics).filter(\r\n\t\t(stat) => !template.statistics![stat].combinaison\r\n\t);\r\n\tif (allStats.length === 0) throw new NoStatisticsError();\r\n\tconst error = [];\r\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\r\n\t\tlet formula = value.combinaison as string;\r\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\r\n\t\t\tconst { max, min } = data;\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tconst regex = new RegExp(other, \"gi\");\r\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tevaluate(formula);\r\n\t\t} catch (e) {\r\n\t\t\terror.push(stat);\r\n\t\t}\r\n\t}\r\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\r\n\treturn;\r\n}\r\n\r\n/**\r\n * Generate a random stat based on the template and the statistical min and max\r\n * @param {number|undefined} total\r\n * @param {number | undefined} max\r\n * @param {number | undefined} min\r\n * @returns\r\n */\r\nexport function generateRandomStat(\r\n\ttotal: number | undefined = 100,\r\n\tmax?: number,\r\n\tmin?: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet randomStatValue = total + 1;\r\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\r\n\twhile (randomStatValue >= total || randomStatValue === 0) {\r\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\r\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\r\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\r\n\t\telse randomStatValue = randomInt(1, total, engine, random);\r\n\t}\r\n\treturn randomStatValue;\r\n}\r\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
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { DiceRoller, NumberGenerator } from "@dice-roller/rpg-dice-roller";
|
|
3
3
|
import { evaluate } from "mathjs";
|
|
4
4
|
function getCompare(dice, compareRegex, engine = NumberGenerator.engines.nodeCrypto) {
|
|
5
|
-
if (dice.match(/((\{.*,(.*)+\}|([><=!]+\d+f))[
|
|
5
|
+
if (dice.match(/((\{.*,(.*)+\}|([><=!]+\d+f))([><=]|!=)+\d+\}?)|\{(.*)(([><=]|!=)+).*\}/))
|
|
6
6
|
return { dice, compare: void 0 };
|
|
7
7
|
dice = dice.replace(SIGN_REGEX_SPACE, "");
|
|
8
8
|
let compare;
|
|
9
|
-
const calc = compareRegex[
|
|
9
|
+
const calc = compareRegex[2];
|
|
10
10
|
const sign = calc.match(/[+-/*^]/)?.[0];
|
|
11
11
|
const compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];
|
|
12
12
|
if (sign) {
|
|
@@ -211,12 +211,14 @@ function replaceText(element, total, dice) {
|
|
|
211
211
|
function formatComment(dice) {
|
|
212
212
|
const commentsRegex = /\[(?<comments>.*?)\]/;
|
|
213
213
|
const commentsMatch = commentsRegex.exec(dice);
|
|
214
|
-
const optionalComments = OPTIONAL_COMMENT.exec(dice);
|
|
215
214
|
const comments = commentsMatch?.groups?.comments ? `${commentsMatch.groups.comments}` : "";
|
|
215
|
+
const diceWithoutBrackets = dice.replace(commentsRegex, "");
|
|
216
|
+
const optionalCommentsRegex = /\s+(#|\/\/)(?<comment>.*)/;
|
|
217
|
+
const optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);
|
|
216
218
|
const optional = optionalComments?.groups?.comment ? `${optionalComments.groups.comment.trim()}` : "";
|
|
217
219
|
let finalComment = "";
|
|
218
220
|
if (comments && optional)
|
|
219
|
-
finalComment = `__${
|
|
221
|
+
finalComment = `__${comments} ${optional}__ \u2014 `;
|
|
220
222
|
else if (comments) finalComment = `__${comments}__ \u2014 `;
|
|
221
223
|
else if (optional) finalComment = `__${optional}__ \u2014 `;
|
|
222
224
|
return finalComment;
|
|
@@ -232,8 +234,11 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto) {
|
|
|
232
234
|
const mainComment = /\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? void 0;
|
|
233
235
|
const split = dice.split(";");
|
|
234
236
|
let diceMain = fixParenthesis(split[0]);
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
+
const commentsRegex = /\[(?<comments>.*?)\]/gi;
|
|
238
|
+
const comments = formatComment(diceMain);
|
|
239
|
+
const diceMainWithoutComments = diceMain.replace(commentsRegex, "").trim();
|
|
240
|
+
const toHideRegex = /\((?<dice>[^)]+)\)/;
|
|
241
|
+
const toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;
|
|
237
242
|
let hidden = false;
|
|
238
243
|
if (toHide?.dice) {
|
|
239
244
|
diceMain = toHide.dice;
|
|
@@ -241,10 +246,9 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto) {
|
|
|
241
246
|
} else if (toHide) {
|
|
242
247
|
diceMain = "1d1";
|
|
243
248
|
hidden = true;
|
|
249
|
+
} else {
|
|
250
|
+
diceMain = diceMainWithoutComments;
|
|
244
251
|
}
|
|
245
|
-
const commentsRegex = /\[(?<comments>.*?)\]/gi;
|
|
246
|
-
const comments = formatComment(diceMain);
|
|
247
|
-
diceMain = diceMain.replace(commentsRegex, "").trim();
|
|
248
252
|
let diceResult = roll(diceMain, engine);
|
|
249
253
|
if (!diceResult || !diceResult.total) {
|
|
250
254
|
if (hidden) {
|
|
@@ -372,10 +376,10 @@ var NoStatisticsError = class extends Error {
|
|
|
372
376
|
|
|
373
377
|
// src/interfaces/constant.ts
|
|
374
378
|
var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/gi;
|
|
375
|
-
var SIGN_REGEX =
|
|
376
|
-
var SIGN_REGEX_SPACE = /[
|
|
379
|
+
var SIGN_REGEX = /!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;
|
|
380
|
+
var SIGN_REGEX_SPACE = /(!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\S+)/;
|
|
377
381
|
var SYMBOL_DICE = "&";
|
|
378
|
-
var DETECT_CRITICAL = /\{\*?c[fs]:[
|
|
382
|
+
var DETECT_CRITICAL = /\{\*?c[fs]:([<>=]|!=)+(.+?)}/gim;
|
|
379
383
|
var OPTIONAL_COMMENT = /\s+(#|\/{2}|\[|\/\*)?(?<comment>.*)/gi;
|
|
380
384
|
|
|
381
385
|
// src/interfaces/zod.ts
|
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 { 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\nfunction getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\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 (dice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))[><=!]+\\d+\\}?)|\\{(.*)([><=!]+).*\\}/))\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\tconst calc = compareRegex[1];\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);\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);\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\treturn { dice, compare };\n}\n\nfunction rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\tconst rollComp = roll(value as string, engine);\n\tif (!rollComp?.total)\n\t\t//not a dice throw\n\t\treturn { value: evaluate(value as string), diceResult: value as string };\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 */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\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\tif (compareRegex) {\n\t\tconst compareResult = getCompare(dice, compareRegex, engine);\n\t\tdice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\tdice = fixParenthesis(dice);\n\tconst modificator = getModifier(dice);\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\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\ttry {\n\t\troller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\tconst commentMatch = dice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\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};\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) {\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) 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) {\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);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine);\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\t//search for optional comments too\n\tconst optionalComments = OPTIONAL_COMMENT.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\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)\n\t\tfinalComment = `__${commentsMatch?.groups?.comments} ${optionalComments?.groups?.comment.trim()}__ — `;\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): 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\tconst toHideRegex = /(?<!\\[[^\\]]*)\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMain)?.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}\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\tdiceMain = diceMain.replace(commentsRegex, \"\").trim();\n\tconsole.log(\"Dice main:\", diceMain);\n\tlet diceResult = roll(diceMain, engine);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]));\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\tconsole.log(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\tconsole.log(\"Element to roll:\", element);\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);\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;\nexport const SIGN_REGEX = /[><=!]+/;\nexport const SIGN_REGEX_SPACE = /[><=!]+(\\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\";\r\nimport \"uniformize\";\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport { FormulaError } from \".\";\r\n\r\n/**\r\n * Escape regex string\r\n * @param string {string}\r\n */\r\nexport function escapeRegex(string: string) {\r\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n\r\n/**\r\n * Allow to keep the text as if in brackets\r\n * @param dice {string}\r\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\r\n */\r\nexport function standardizeDice(dice: string): string {\r\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\r\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the stat name by their value using stat\r\n * and after evaluate any formula using `replaceFormulaInDice`\r\n * @param {string} originalDice\r\n * @param {Record<string,number>|undefined} stats\r\n * @param {string|undefined} dollarValue\r\n */\r\nexport function generateStatsDice(\r\n\toriginalDice: string,\r\n\tstats?: Record<string, number>,\r\n\tdollarValue?: string\r\n) {\r\n\tlet dice = originalDice.standardize();\r\n\tif (stats && Object.keys(stats).length > 0) {\r\n\t\tconst statKeys = Object.keys(stats);\r\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\r\n\t\tlet result = \"\";\r\n\t\tlet match: RegExpExecArray | null;\r\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\r\n\t\t\tconst insideBrackets = match[1];\r\n\t\t\tconst outsideText = match[2];\r\n\t\t\tif (insideBrackets) {\r\n\t\t\t\tresult += insideBrackets;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (!outsideText) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\r\n\t\t\tlet lastIndex = 0;\r\n\t\t\tlet tokenMatch: RegExpExecArray | null;\r\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\r\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\r\n\t\t\t\tconst token = tokenMatch[0];\r\n\t\t\t\tconst tokenStd = token.standardize();\r\n\t\t\t\tlet bestKey: string | null = null;\r\n\t\t\t\tlet bestScore = 0;\r\n\t\t\t\tfor (const key of statKeys) {\r\n\t\t\t\t\tconst keyStd = key.standardize();\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttokenStd === keyStd ||\r\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\r\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t\tbestScore = 1;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\r\n\t\t\t\t\tif (score > bestScore) {\r\n\t\t\t\t\t\tbestScore = score;\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\r\n\t\t\t\t\tconst statValue = stats[bestKey];\r\n\t\t\t\t\tresult += statValue.toString();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tresult += token;\r\n\t\t\t\t}\r\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\r\n\t\t\t}\r\n\t\t\tresult += outsideText.slice(lastIndex);\r\n\t\t}\r\n\t\tdice = result;\r\n\t}\r\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\r\n\treturn replaceFormulaInDice(dice);\r\n}\r\n\r\n/**\r\n * Replace the {{}} in the dice string and evaluate the interior if any\r\n * @param dice {string}\r\n */\r\nexport function replaceFormulaInDice(dice: string) {\r\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\r\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\r\n\tlet match;\r\n\tlet modifiedDice = dice;\r\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\twhile ((match = formula.exec(dice)) !== null) {\r\n\t\tif (match.groups?.formula) {\r\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\r\n\t\t\ttry {\r\n\t\t\t\tconst result = evaluate(formulae);\r\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn cleanedDice(modifiedDice);\r\n}\r\n\r\n/**\r\n * Replace the ++ +- -- by their proper value:\r\n * - `++` = `+`\r\n * - `+-` = `-`\r\n * - `--` = `+`\r\n * @param dice {string}\r\n */\r\nfunction cleanedDice(dice: string) {\r\n\treturn dice\r\n\t\t.replaceAll(\"+-\", \"-\")\r\n\t\t.replaceAll(\"--\", \"+\")\r\n\t\t.replaceAll(\"++\", \"+\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimEnd();\r\n}\r\n\r\n/**\r\n * Verify if a value is a number, even if it's a \"number\" string\r\n * @param value {unknown}\r\n * @returns {boolean}\r\n */\r\nexport function isNumber(value: unknown): boolean {\r\n\treturn (\r\n\t\tvalue !== undefined &&\r\n\t\t(typeof value === \"number\" ||\r\n\t\t\t(!Number.isNaN(Number(value)) &&\r\n\t\t\t\ttypeof value === \"string\" &&\r\n\t\t\t\tvalue.trim().length > 0))\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the `{exp}` in the dice.\r\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\r\n * @param {string} dice\r\n * @param engine\r\n * @returns {string} the dice with the {exp} replaced by a random value\r\n */\r\nexport function replaceExpByRandom(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): string {\r\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\r\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\r\n\t\tconst defaultValue = groups?.default;\r\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\r\n\t});\r\n}\r\n\r\n/**\r\n * Utility function to get a random integer between min and max and using the specified engine\r\n * @param min {number}\r\n * @param max {number}\r\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\r\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\r\n * @returns {number} Random integer between min and max\r\n */\r\nexport function randomInt(\r\n\tmin: number,\r\n\tmax: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\trng?: Random\r\n): number {\r\n\tif (!rng) rng = new Random(engine || undefined);\r\n\treturn rng.integer(min, max);\r\n}\r\n/**\r\n * Utility function that allow to get the id of an engine\r\n * @param engine {unknown} Engine to identify\r\n * @returns {string} Id of the engine or \"unknown\"\r\n * @private\r\n */\r\nexport function getEngineId(engine: unknown): string {\r\n\t// Comparaisons directes avec les engines exposés par la lib\r\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\r\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\r\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\r\n\t// Fallback: essayer de lire un nom ou le constructeur\r\n\ttry {\r\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\r\n\t\tconst e = engine as any;\r\n\t\tif (e && typeof e === \"object\") {\r\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\r\n\t\t\tif (e.constructor?.name) return e.constructor.name;\r\n\t\t}\r\n\t} catch {\r\n\t\t/* ignore */\r\n\t}\r\n\treturn \"unknown\";\r\n}\r\n\r\n/**\r\n * Utility function to get the engine from its name\r\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\r\n * @returns {Engine} The engine\r\n * @public\r\n */\r\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\r\n\tswitch (engine) {\r\n\t\tcase \"nativeMath\":\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t\tcase \"browserCrypto\":\r\n\t\t\treturn NumberGenerator.engines.browserCrypto;\r\n\t\tcase \"nodeCrypto\":\r\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\r\n\t\tdefault:\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t}\r\n}\r\n\r\n/**\r\n * Calcule la distance de Levenshtein entre deux chaînes\r\n */\r\nfunction levenshteinDistance(a: string, b: string): number {\r\n\tif (a === b) return 0;\r\n\tconst al = a.length;\r\n\tconst bl = b.length;\r\n\tif (al === 0) return bl;\r\n\tif (bl === 0) return al;\r\n\tconst v0 = new Array<number>(bl + 1);\r\n\tconst v1 = new Array<number>(bl + 1);\r\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\r\n\tfor (let i = 0; i < al; i++) {\r\n\t\tv1[0] = i + 1;\r\n\t\tfor (let j = 0; j < bl; j++) {\r\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\r\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\r\n\t\t}\r\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\r\n\t}\r\n\treturn v1[bl];\r\n}\r\n\r\n/**\r\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\r\n */\r\nfunction similarityScore(a: string, b: string): number {\r\n\tconst la = a.length;\r\n\tconst lb = b.length;\r\n\tif (la === 0 && lb === 0) return 1;\r\n\tconst dist = levenshteinDistance(a, b);\r\n\tconst max = Math.max(la, lb);\r\n\treturn 1 - dist / max;\r\n}\r\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 */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\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))\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 * @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 */\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 * @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\tconsole.log(parsedTemplate);\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 */\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 */\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 * @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 { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport {\r\n\tCOMMENT_REGEX,\r\n\ttype Compare,\r\n\ttype ComparedValue,\r\n\ttype CustomCritical,\r\n\tDETECT_CRITICAL,\r\n\tDiceTypeError,\r\n\tdiceTypeRandomParse,\r\n\tisNumber,\r\n\ttype Modifier,\r\n\tOPTIONAL_COMMENT,\r\n\ttype Resultat,\r\n\treplaceFormulaInDice,\r\n\tSIGN_REGEX,\r\n\tSIGN_REGEX_SPACE,\r\n\ttype Sign,\r\n\ttype StatisticalTemplate,\r\n\tSYMBOL_DICE,\r\n\tstandardizeDice,\r\n} from \".\";\r\n\r\nfunction getCompare(\r\n\tdice: string,\r\n\tcompareRegex: RegExpMatchArray,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): { dice: string; compare: ComparedValue | undefined } {\r\n\t/**\r\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\r\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.\r\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\r\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.\r\n\t * @note:\r\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\r\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.\r\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`.\r\n\t */\r\n\tif (dice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/))\r\n\t\treturn { dice, compare: undefined };\r\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\r\n\tlet compare: ComparedValue;\r\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\r\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\r\n\tconst calc = compareRegex[2];\r\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\r\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\r\n\r\n\tif (sign) {\r\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\r\n\t\tconst rCompare = rollCompare(toCalc, engine);\r\n\t\tconst total = evaluate(rCompare.value.toString());\r\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\r\n\t\tcompare = {\r\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\r\n\t\t\tvalue: total,\r\n\t\t\toriginalDice: rCompare.dice,\r\n\t\t\trollValue: rCompare.diceResult,\r\n\t\t};\r\n\t} else {\r\n\t\tconst rcompare = rollCompare(calc, engine);\r\n\t\tcompare = {\r\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\r\n\t\t\tvalue: rcompare.value,\r\n\t\t\toriginalDice: rcompare.dice,\r\n\t\t\trollValue: rcompare.diceResult,\r\n\t\t};\r\n\t}\r\n\treturn { dice, compare };\r\n}\r\n\r\nfunction rollCompare(\r\n\tvalue: unknown,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\r\n\tconst rollComp = roll(value as string, engine);\r\n\tif (!rollComp?.total)\r\n\t\t//not a dice throw\r\n\t\treturn { value: evaluate(value as string), diceResult: value as string };\r\n\treturn {\r\n\t\tdice: value as string,\r\n\t\tvalue: rollComp.total,\r\n\t\tdiceResult: rollComp?.result,\r\n\t};\r\n}\r\n\r\n/**\r\n * Allow to replace the compare part of a dice and use the critical customized one\r\n * @example\r\n * dice = \"1d20=20\";\r\n * custom critical {sign: \">\", value: \"$/2\"}\r\n * Random stats = 6\r\n * result = \"1d20>3\"\r\n */\r\nexport function createCriticalCustom(\r\n\tdice: string,\r\n\tcustomCritical: CustomCritical,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\r\n\tlet customDice = dice;\r\n\tconst compareValue = diceTypeRandomParse(customCritical.value, template, engine);\r\n\tif (compareValue.includes(\"$\"))\r\n\t\tthrow new DiceTypeError(compareValue, \"createCriticalCustom\");\r\n\tconst comparaison = `${customCritical.sign}${compareValue}`;\r\n\tif (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);\r\n\telse customDice += comparaison;\r\n\treturn diceTypeRandomParse(customDice, template, engine);\r\n}\r\n\r\nfunction getModifier(dice: string) {\r\n\tconst modifier = dice.matchAll(/(\\+|-|%|\\/|\\^|\\*|\\*{2})(\\d+)/gi);\r\n\tlet modificator: Modifier | undefined;\r\n\tfor (const mod of modifier) {\r\n\t\t//calculate the modifier if multiple\r\n\t\tif (modificator) {\r\n\t\t\tconst sign = modificator.sign;\r\n\t\t\tlet value = modificator.value;\r\n\t\t\tif (sign) value = calculator(sign, value, Number.parseInt(mod[2], 10));\r\n\t\t\tmodificator = {\r\n\t\t\t\tsign: mod[1] as Sign,\r\n\t\t\t\tvalue,\r\n\t\t\t};\r\n\t\t} else {\r\n\t\t\tmodificator = {\r\n\t\t\t\tsign: mod[1] as Sign,\r\n\t\t\t\tvalue: Number.parseInt(mod[2], 10),\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\treturn modificator;\r\n}\r\n\r\n/**\r\n * Parse the string provided and turn it as a readable dice for dice parser\r\n * @param dice {string}\r\n */\r\nexport function roll(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): Resultat | undefined {\r\n\t//parse dice string\r\n\tdice = standardizeDice(replaceFormulaInDice(dice))\r\n\t\t.replace(/^\\+/, \"\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimStart();\r\n\tif (!dice.includes(\"d\")) return undefined;\r\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\r\n\tconst compareRegex = dice.match(SIGN_REGEX_SPACE);\r\n\tlet compare: ComparedValue | undefined;\r\n\tif (dice.includes(\";\")) return sharedRolls(dice, engine);\r\n\tif (compareRegex) {\r\n\t\tconst compareResult = getCompare(dice, compareRegex, engine);\r\n\t\tdice = compareResult.dice;\r\n\t\tcompare = compareResult.compare;\r\n\t}\r\n\tdice = fixParenthesis(dice);\r\n\tconst modificator = getModifier(dice);\r\n\tif (dice.match(/\\d+?#(.*)/)) {\r\n\t\tconst diceArray = dice.split(\"#\");\r\n\t\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\r\n\t\tconst diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\r\n\t\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\r\n\t\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\r\n\t\tconst roller = new DiceRoller();\r\n\t\tNumberGenerator.generator.engine = engine;\r\n\t\t//remove comments if any\r\n\t\tfor (let i = 0; i < numberOfDice; i++) {\r\n\t\t\ttry {\r\n\t\t\t\troller.roll(diceToRoll);\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn {\r\n\t\t\tdice: diceToRoll,\r\n\t\t\tresult: roller.output,\r\n\t\t\tcomment: comments,\r\n\t\t\tcompare: compare ? compare : undefined,\r\n\t\t\tmodifier: modificator,\r\n\t\t\ttotal: roller.total,\r\n\t\t};\r\n\t}\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\tconst diceWithoutComment = dice.replace(COMMENT_REGEX, \"\").trimEnd();\r\n\r\n\ttry {\r\n\t\troller.roll(diceWithoutComment);\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\r\n\t}\r\n\tconst commentMatch = dice.match(COMMENT_REGEX);\r\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\r\n\treturn {\r\n\t\tdice,\r\n\t\tresult: roller.output,\r\n\t\tcomment,\r\n\t\tcompare: compare ? compare : undefined,\r\n\t\tmodifier: modificator,\r\n\t\ttotal: roller.total,\r\n\t};\r\n}\r\n\r\nfunction fixParenthesis(dice: string) {\r\n\t//dice with like 1d(20) are not valid, we need to remove the parenthesis\r\n\t//warning: the 1d(20+5) is valid and should not be changed\r\n\tconst parenthesisRegex = /d\\((\\d+)\\)/g;\r\n\treturn dice.replaceAll(parenthesisRegex, (_match, p1) => `d${p1}`);\r\n}\r\n\r\n/**\r\n * Evaluate a formula and replace \"^\" by \"**\" if any\r\n * @param {Sign} sign\r\n * @param {number} value\r\n * @param {number} total\r\n * @returns\r\n */\r\nexport function calculator(sign: Sign, value: number, total: number): number {\r\n\tif (sign === \"^\") sign = \"**\";\r\n\treturn evaluate(`${total} ${sign} ${value}`);\r\n}\r\n\r\nfunction inverseSign(\r\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\"\r\n): \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\" {\r\n\tswitch (sign) {\r\n\t\tcase \"<\":\r\n\t\t\treturn \">\";\r\n\t\tcase \">\":\r\n\t\t\treturn \"<\";\r\n\t\tcase \"<=\":\r\n\t\t\treturn \">=\";\r\n\t\tcase \">=\":\r\n\t\t\treturn \"<=\";\r\n\t\tcase \"=\":\r\n\t\t\treturn \"!=\";\r\n\t\tcase \"==\":\r\n\t\t\treturn \"!=\";\r\n\t\tcase \"!=\":\r\n\t\t\treturn \"==\";\r\n\t}\r\n}\r\n\r\nfunction replaceInFormula(\r\n\telement: string,\r\n\tdiceResult: Resultat,\r\n\tcompareResult: { dice: string; compare: Compare | undefined },\r\n\tres: boolean,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tconst { formule, diceAll } = replaceText(\r\n\t\telement,\r\n\t\tdiceResult.total ?? 0,\r\n\t\tdiceResult.dice\r\n\t);\r\n\tconst validSign = res ? \"✓\" : \"✕\";\r\n\tconst invertedSign = res\r\n\t\t? compareResult.compare!.sign\r\n\t\t: inverseSign(compareResult.compare!.sign);\r\n\tlet evaluateRoll: unknown;\r\n\ttry {\r\n\t\tevaluateRoll = evaluate(compareResult.dice);\r\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\r\n\t} catch (error) {\r\n\t\tconst evaluateRoll = roll(compareResult.dice, engine) as Resultat | undefined;\r\n\t\tif (evaluateRoll)\r\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\r\n\r\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\r\n\t}\r\n}\r\n\r\nfunction compareSignFormule(\r\n\ttoRoll: string,\r\n\tcompareRegex: RegExpMatchArray,\r\n\telement: string,\r\n\tdiceResult: Resultat,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet results = \"\";\r\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\r\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\r\n\tlet res: unknown;\r\n\ttry {\r\n\t\tres = evaluate(toCompare);\r\n\t} catch (error) {\r\n\t\tres = roll(toCompare, engine);\r\n\t}\r\n\tif (typeof res === \"boolean\") {\r\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine);\r\n\t} else if (res instanceof Object) {\r\n\t\tconst diceResult = res as Resultat;\r\n\t\tif (diceResult.compare) {\r\n\t\t\tconst toEvaluate = evaluate(\r\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\r\n\t\t\t);\r\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\r\n\t\t\tconst invertedSign = toEvaluate\r\n\t\t\t\t? diceResult.compare.sign\r\n\t\t\t\t: inverseSign(diceResult.compare.sign);\r\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\r\n\r\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\r\n\t\t}\r\n\t}\r\n\treturn { dice: compareResult.dice, results };\r\n}\r\n\r\nfunction replaceText(element: string, total: number, dice: string) {\r\n\treturn {\r\n\t\tformule: element.replace(SYMBOL_DICE, `[${total}]`).replace(/%.*%/g, \"\").trim(),\r\n\t\tdiceAll: element\r\n\t\t\t.replace(SYMBOL_DICE, `[${dice.replace(COMMENT_REGEX, \"\")}]`)\r\n\t\t\t.replace(/%.*%/g, \"\")\r\n\t\t\t.trim(),\r\n\t};\r\n}\r\n\r\nfunction formatComment(dice: string) {\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\r\n\tconst commentsMatch = commentsRegex.exec(dice);\r\n\tconst comments = commentsMatch?.groups?.comments\r\n\t\t? `${commentsMatch.groups.comments}`\r\n\t\t: \"\";\r\n\t\r\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\r\n\t// to avoid conflicts with parentheses inside bracket comments\r\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\r\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\r\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\r\n\tconst optional = optionalComments?.groups?.comment\r\n\t\t? `${optionalComments.groups.comment.trim()}`\r\n\t\t: \"\";\r\n\t\r\n\t//fusion of both comments with a space if both exists\r\n\t//result expected = \"__comment1 comment2__ — \"\r\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\r\n\tlet finalComment = \"\";\r\n\tif (comments && optional)\r\n\t\tfinalComment = `__${comments} ${optional}__ — `;\r\n\telse if (comments) finalComment = `__${comments}__ — `;\r\n\telse if (optional) finalComment = `__${optional}__ — `;\r\n\treturn finalComment;\r\n}\r\n\r\nfunction sharedRolls(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): Resultat | undefined {\r\n\tif (dice.match(/\\d+?#(.*?)/))\r\n\t\tthrow new DiceTypeError(\r\n\t\t\tdice,\r\n\t\t\t\"noBulkRoll\",\r\n\t\t\t\"bulk roll are not allowed in shared rolls\"\r\n\t\t);\r\n\tconst results = [];\r\n\tconst mainComment =\r\n\t\t/\\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? undefined;\r\n\tconst split = dice.split(\";\");\r\n\tlet diceMain = fixParenthesis(split[0]);\r\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\r\n\tconst comments = formatComment(diceMain);\r\n\t// Remove comments before checking for hidden dice (parentheses)\r\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\r\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\r\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\r\n\tlet hidden = false;\r\n\tif (toHide?.dice) {\r\n\t\tdiceMain = toHide.dice;\r\n\t\thidden = true;\r\n\t} else if (toHide) {\r\n\t\tdiceMain = \"1d1\";\r\n\t\thidden = true;\r\n\t} else {\r\n\t\t// No hidden dice, use the dice without comments\r\n\t\tdiceMain = diceMainWithoutComments;\r\n\t}\r\n\tlet diceResult = roll(diceMain, engine);\r\n\tif (!diceResult || !diceResult.total) {\r\n\t\tif (hidden) {\r\n\t\t\tdiceResult = roll(fixParenthesis(split[0]));\r\n\t\t\thidden = false;\r\n\t\t} else return undefined;\r\n\t}\r\n\tif (!diceResult || !diceResult.total) return undefined;\r\n\tresults.push(`※ ${comments}${diceResult.result}`);\r\n\tlet total = diceResult.total;\r\n\tdiceResult.comment = mainComment;\r\n\tif (!total) return diceResult;\r\n\tfor (let element of split.slice(1)) {\r\n\t\tconst comment = formatComment(element);\r\n\t\telement = element\r\n\t\t\t.replaceAll(commentsRegex, \"\")\r\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\r\n\t\t\t.trim();\r\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\r\n\t\t//remove comments\r\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\r\n\t\tif (compareRegex) {\r\n\t\t\tconst compareResult = compareSignFormule(\r\n\t\t\t\ttoRoll,\r\n\t\t\t\tcompareRegex,\r\n\t\t\t\telement,\r\n\t\t\t\tdiceResult,\r\n\t\t\t\tengine\r\n\t\t\t);\r\n\t\t\ttoRoll = compareResult.dice;\r\n\t\t\tresults.push(compareResult.results);\r\n\t\t} else {\r\n\t\t\tconst { formule, diceAll } = replaceText(\r\n\t\t\t\telement,\r\n\t\t\t\tdiceResult.total,\r\n\t\t\t\tdiceResult.dice\r\n\t\t\t);\r\n\r\n\t\t\ttry {\r\n\t\t\t\tconst evaluated = evaluate(toRoll);\r\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\r\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\r\n\t\t\t} catch (error) {\r\n\t\t\t\tconst evaluated = roll(toRoll, engine);\r\n\t\t\t\tif (evaluated)\r\n\t\t\t\t\tresults.push(\r\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\r\n\t\t\t\t\t);\r\n\t\t\t\telse results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\r\n\t\t\t\ttotal += evaluated?.total ?? 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif (hidden)\r\n\t\t//remove the first in result\r\n\t\tresults.shift();\r\n\treturn {\r\n\t\tdice: diceMain,\r\n\t\tresult: results.join(\";\"),\r\n\t\tcomment: mainComment,\r\n\t\tcompare: diceResult.compare,\r\n\t\tmodifier: diceResult.modifier,\r\n\t\ttotal,\r\n\t};\r\n}\r\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;\r\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\r\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\r\n// Use negative lookbehind to check for ![<>] before any comparison operator\r\nexport const SIGN_REGEX = /!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\r\nexport const SIGN_REGEX_SPACE = /(!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\r\n\r\nexport const SYMBOL_DICE = \"&\";\r\n\r\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\r\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\r\n","/**\r\n * Definition of the Zod schema for template data\r\n */\r\nimport { z } from \"zod\";\r\n\r\nconst statisticValueSchema = z\r\n\t.object({\r\n\t\tmax: z\r\n\t\t\t.number()\r\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\r\n\t\t\t.optional(),\r\n\t\tmin: z\r\n\t\t\t.number()\r\n\t\t\t.transform((val) =>\r\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\r\n\t\t\t)\r\n\t\t\t.optional(),\r\n\t\tcombinaison: z\r\n\t\t\t.string()\r\n\t\t\t.transform((str) => str.trim() || undefined)\r\n\t\t\t.optional(),\r\n\t\texclude: z.boolean().optional(),\r\n\t})\r\n\t.superRefine((data, ctx) => {\r\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\r\n\t\t\tctx.addIssue({\r\n\t\t\t\tcode: \"custom\",\r\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\r\n\t\t\t\tpath: [\"max\"],\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\nconst statisticSchema = z\r\n\t.record(z.string(), statisticValueSchema)\r\n\t.optional()\r\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\r\n\t\tmessage: \"TooManyStats\",\r\n\t});\r\n\r\nconst criticalSchema = z\r\n\t.object({\r\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\r\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\r\n\t})\r\n\t.transform((values) => {\r\n\t\tif (values.success === \"\") values.success = undefined;\r\n\t\tif (values.failure === \"\") values.failure = undefined;\r\n\t\tif (values.failure === 0) values.failure = undefined;\r\n\t\tif (values.success === 0) values.success = undefined;\r\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\r\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\r\n\t\treturn values;\r\n\t});\r\n\r\nconst criticalValueSchema = z.object({\r\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\r\n\tvalue: z.string(),\r\n\tonNaturalDice: z.boolean().optional(),\r\n\taffectSkill: z.boolean().optional(),\r\n});\r\n\r\nconst damageSchema = z\r\n\t.record(z.string(), z.string())\r\n\t.optional()\r\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\r\n\t\tmessage: \"TooManyDice\",\r\n\t});\r\n\r\nconst customCriticalSchema = z\r\n\t.record(z.string(), criticalValueSchema)\r\n\t.optional()\r\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\r\n\t\tmessage: \"TooManyDice\",\r\n\t});\r\n\r\nexport const templateSchema = z.object({\r\n\tcharName: z.boolean().optional(),\r\n\tstatistics: statisticSchema,\r\n\ttotal: z\r\n\t\t.number()\r\n\t\t.min(0)\r\n\t\t.transform((val) => (val === 0 ? undefined : val))\r\n\t\t.optional(),\r\n\tforceDistrib: z.boolean().optional(),\r\n\tdiceType: z.string().optional(),\r\n\tcritical: criticalSchema.optional(),\r\n\tcustomCritical: customCriticalSchema,\r\n\tdamage: damageSchema,\r\n});\r\n","import { evaluate } from \"mathjs\";\r\nimport \"uniformize\";\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport { FormulaError } from \".\";\r\n\r\n/**\r\n * Escape regex string\r\n * @param string {string}\r\n */\r\nexport function escapeRegex(string: string) {\r\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n\r\n/**\r\n * Allow to keep the text as if in brackets\r\n * @param dice {string}\r\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\r\n */\r\nexport function standardizeDice(dice: string): string {\r\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\r\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the stat name by their value using stat\r\n * and after evaluate any formula using `replaceFormulaInDice`\r\n * @param {string} originalDice\r\n * @param {Record<string,number>|undefined} stats\r\n * @param {string|undefined} dollarValue\r\n */\r\nexport function generateStatsDice(\r\n\toriginalDice: string,\r\n\tstats?: Record<string, number>,\r\n\tdollarValue?: string\r\n) {\r\n\tlet dice = originalDice.standardize();\r\n\tif (stats && Object.keys(stats).length > 0) {\r\n\t\tconst statKeys = Object.keys(stats);\r\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\r\n\t\tlet result = \"\";\r\n\t\tlet match: RegExpExecArray | null;\r\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\r\n\t\t\tconst insideBrackets = match[1];\r\n\t\t\tconst outsideText = match[2];\r\n\t\t\tif (insideBrackets) {\r\n\t\t\t\tresult += insideBrackets;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (!outsideText) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\r\n\t\t\tlet lastIndex = 0;\r\n\t\t\tlet tokenMatch: RegExpExecArray | null;\r\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\r\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\r\n\t\t\t\tconst token = tokenMatch[0];\r\n\t\t\t\tconst tokenStd = token.standardize();\r\n\t\t\t\tlet bestKey: string | null = null;\r\n\t\t\t\tlet bestScore = 0;\r\n\t\t\t\tfor (const key of statKeys) {\r\n\t\t\t\t\tconst keyStd = key.standardize();\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\ttokenStd === keyStd ||\r\n\t\t\t\t\t\tkeyStd.includes(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.includes(keyStd) ||\r\n\t\t\t\t\t\tkeyStd.startsWith(tokenStd) ||\r\n\t\t\t\t\t\ttokenStd.startsWith(keyStd)\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t\tbestScore = 1;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\r\n\t\t\t\t\tif (score > bestScore) {\r\n\t\t\t\t\t\tbestScore = score;\r\n\t\t\t\t\t\tbestKey = key;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\r\n\t\t\t\t\tconst statValue = stats[bestKey];\r\n\t\t\t\t\tresult += statValue.toString();\r\n\t\t\t\t} else {\r\n\t\t\t\t\tresult += token;\r\n\t\t\t\t}\r\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\r\n\t\t\t}\r\n\t\t\tresult += outsideText.slice(lastIndex);\r\n\t\t}\r\n\t\tdice = result;\r\n\t}\r\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\r\n\treturn replaceFormulaInDice(dice);\r\n}\r\n\r\n/**\r\n * Replace the {{}} in the dice string and evaluate the interior if any\r\n * @param dice {string}\r\n */\r\nexport function replaceFormulaInDice(dice: string) {\r\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\r\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\r\n\tlet match;\r\n\tlet modifiedDice = dice;\r\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\r\n\twhile ((match = formula.exec(dice)) !== null) {\r\n\t\tif (match.groups?.formula) {\r\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\r\n\t\t\ttry {\r\n\t\t\t\tconst result = evaluate(formulae);\r\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn cleanedDice(modifiedDice);\r\n}\r\n\r\n/**\r\n * Replace the ++ +- -- by their proper value:\r\n * - `++` = `+`\r\n * - `+-` = `-`\r\n * - `--` = `+`\r\n * @param dice {string}\r\n */\r\nfunction cleanedDice(dice: string) {\r\n\treturn dice\r\n\t\t.replaceAll(\"+-\", \"-\")\r\n\t\t.replaceAll(\"--\", \"+\")\r\n\t\t.replaceAll(\"++\", \"+\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimEnd();\r\n}\r\n\r\n/**\r\n * Verify if a value is a number, even if it's a \"number\" string\r\n * @param value {unknown}\r\n * @returns {boolean}\r\n */\r\nexport function isNumber(value: unknown): boolean {\r\n\treturn (\r\n\t\tvalue !== undefined &&\r\n\t\t(typeof value === \"number\" ||\r\n\t\t\t(!Number.isNaN(Number(value)) &&\r\n\t\t\t\ttypeof value === \"string\" &&\r\n\t\t\t\tvalue.trim().length > 0))\r\n\t);\r\n}\r\n\r\n/**\r\n * Replace the `{exp}` in the dice.\r\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\r\n * @param {string} dice\r\n * @param engine\r\n * @returns {string} the dice with the {exp} replaced by a random value\r\n */\r\nexport function replaceExpByRandom(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): string {\r\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\r\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\r\n\t\tconst defaultValue = groups?.default;\r\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\r\n\t});\r\n}\r\n\r\n/**\r\n * Utility function to get a random integer between min and max and using the specified engine\r\n * @param min {number}\r\n * @param max {number}\r\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\r\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\r\n * @returns {number} Random integer between min and max\r\n */\r\nexport function randomInt(\r\n\tmin: number,\r\n\tmax: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\trng?: Random\r\n): number {\r\n\tif (!rng) rng = new Random(engine || undefined);\r\n\treturn rng.integer(min, max);\r\n}\r\n/**\r\n * Utility function that allow to get the id of an engine\r\n * @param engine {unknown} Engine to identify\r\n * @returns {string} Id of the engine or \"unknown\"\r\n * @private\r\n */\r\nexport function getEngineId(engine: unknown): string {\r\n\t// Comparaisons directes avec les engines exposés par la lib\r\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\r\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\r\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\r\n\t// Fallback: essayer de lire un nom ou le constructeur\r\n\ttry {\r\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\r\n\t\tconst e = engine as any;\r\n\t\tif (e && typeof e === \"object\") {\r\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\r\n\t\t\tif (e.constructor?.name) return e.constructor.name;\r\n\t\t}\r\n\t} catch {\r\n\t\t/* ignore */\r\n\t}\r\n\treturn \"unknown\";\r\n}\r\n\r\n/**\r\n * Utility function to get the engine from its name\r\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\r\n * @returns {Engine} The engine\r\n * @public\r\n */\r\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\r\n\tswitch (engine) {\r\n\t\tcase \"nativeMath\":\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t\tcase \"browserCrypto\":\r\n\t\t\treturn NumberGenerator.engines.browserCrypto;\r\n\t\tcase \"nodeCrypto\":\r\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\r\n\t\tdefault:\r\n\t\t\treturn NumberGenerator.engines.nativeMath;\r\n\t}\r\n}\r\n\r\n/**\r\n * Calcule la distance de Levenshtein entre deux chaînes\r\n */\r\nfunction levenshteinDistance(a: string, b: string): number {\r\n\tif (a === b) return 0;\r\n\tconst al = a.length;\r\n\tconst bl = b.length;\r\n\tif (al === 0) return bl;\r\n\tif (bl === 0) return al;\r\n\tconst v0 = new Array<number>(bl + 1);\r\n\tconst v1 = new Array<number>(bl + 1);\r\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\r\n\tfor (let i = 0; i < al; i++) {\r\n\t\tv1[0] = i + 1;\r\n\t\tfor (let j = 0; j < bl; j++) {\r\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\r\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\r\n\t\t}\r\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\r\n\t}\r\n\treturn v1[bl];\r\n}\r\n\r\n/**\r\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\r\n */\r\nfunction similarityScore(a: string, b: string): number {\r\n\tconst la = a.length;\r\n\tconst lb = b.length;\r\n\tif (la === 0 && lb === 0) return 1;\r\n\tconst dist = levenshteinDistance(a, b);\r\n\tconst max = Math.max(la, lb);\r\n\treturn 1 - dist / max;\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport \"uniformize\";\r\n\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport {\r\n\tcreateCriticalCustom,\r\n\tDETECT_CRITICAL,\r\n\tDiceTypeError,\r\n\tEmptyObjectError,\r\n\tescapeRegex,\r\n\tFormulaError,\r\n\tNoStatisticsError,\r\n\treplaceExpByRandom,\r\n\treplaceFormulaInDice,\r\n\troll,\r\n\ttype StatisticalTemplate,\r\n\tTooManyDice,\r\n\ttemplateSchema,\r\n} from \".\";\r\nimport { isNumber, randomInt } from \"./utils\";\r\n\r\n/**\r\n * Verify if the provided dice work with random value\r\n * @param testDice {string}\r\n * @param allStats {Record<string,number>}\r\n */\r\nexport function evalStatsDice(\r\n\ttestDice: string,\r\n\tallStats?: Record<string, number>,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet dice = testDice.trimEnd();\r\n\tif (allStats && Object.keys(allStats).length > 0) {\r\n\t\tconst names = Object.keys(allStats);\r\n\t\tfor (const name of names) {\r\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\t\tif (dice.standardize().match(regex)) {\r\n\t\t\t\tconst statValue = allStats[name];\r\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttry {\r\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine))\r\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\r\n\t\treturn testDice;\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\r\n\t}\r\n}\r\n\r\n/**\r\n * Generate a random dice and remove the formula (+ evaluate it)\r\n * Used for diceDamage only\r\n * @param value {string}\r\n * @param template {StatisticalTemplate}\r\n * @returns\r\n */\r\nexport function diceRandomParse(\r\n\tvalue: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\r\n\tvalue = value.standardize();\r\n\tconst statNames = Object.keys(template.statistics);\r\n\tlet newDice = value;\r\n\tfor (const name of statNames) {\r\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\tif (value.match(regex)) {\r\n\t\t\tlet max: undefined | number;\r\n\t\t\tlet min: undefined | number;\r\n\t\t\tconst foundStat = template.statistics?.[name];\r\n\t\t\tif (foundStat) {\r\n\t\t\t\tmax = foundStat.max;\r\n\t\t\t\tmin = foundStat.min;\r\n\t\t\t}\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t}\r\n\treturn replaceFormulaInDice(newDice);\r\n}\r\n\r\n/**\r\n * Same as damageDice but for DiceType\r\n * @param dice {string}\r\n * @param template {StatisticalTemplate}\r\n */\r\nexport function diceTypeRandomParse(\r\n\tdice: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tdice = replaceExpByRandom(dice);\r\n\tif (!template.statistics) return dice;\r\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\r\n\t\t(stat) => !template.statistics?.[stat].combinaison\r\n\t);\r\n\tif (!firstStatNotcombinaison) return dice;\r\n\tconst stats = template.statistics[firstStatNotcombinaison];\r\n\tconst { min, max } = stats;\r\n\tconst total = template.total || 100;\r\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\r\n}\r\n\r\n/**\r\n * Random the combinaison and evaluate it to check if everything is valid\r\n * @param combinaison {Record<string,string>}\r\n * @param stats {Record<string,number|number>}\r\n */\r\nexport function evalCombinaison(\r\n\tcombinaison: Record<string, string>,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tconst newStats: Record<string, number> = {};\r\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\r\n\t\t//replace the stats in formula\r\n\t\tlet formula = combin.standardize();\r\n\t\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\t\tformula = formula.replace(regex, value.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tnewStats[stat] = evaluate(formula);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\r\n\t\t}\r\n\t}\r\n\treturn newStats;\r\n}\r\n\r\n/**\r\n * Evaluate one selected combinaison\r\n * @param combinaison {string}\r\n * @param stats {[name: string]: string|number}\r\n */\r\nexport function evalOneCombinaison(\r\n\tcombinaison: string,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tlet formula = combinaison.standardize();\r\n\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\tformula = formula.replace(regex, value.toString());\r\n\t}\r\n\ttry {\r\n\t\treturn evaluate(formula);\r\n\t} catch (error) {\r\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\r\n\t}\r\n}\r\n\r\nfunction convertNumber(number: string | number | undefined) {\r\n\tif (number === undefined || number === null) return undefined;\r\n\tif (\r\n\t\tnumber.toString().length === 0 ||\r\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\r\n\t)\r\n\t\treturn undefined;\r\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\r\n\treturn undefined;\r\n}\r\n\r\n/**\r\n * Parse the provided JSON and verify each field to check if everything could work when rolling\r\n * @param {unknown} template\r\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\r\n * @returns {StatisticalTemplate}\r\n */\r\nexport function verifyTemplateValue(\r\n\ttemplate: unknown,\r\n\tverify = true,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): StatisticalTemplate {\r\n\tconst parsedTemplate = templateSchema.parse(template);\r\n\tconst { success, failure } = parsedTemplate.critical ?? {};\r\n\tconst criticicalVal = {\r\n\t\tsuccess: convertNumber(success),\r\n\t\tfailure: convertNumber(failure),\r\n\t};\r\n\tconst statistiqueTemplate: StatisticalTemplate = {\r\n\t\tdiceType: parsedTemplate.diceType,\r\n\t\tstatistics: parsedTemplate.statistics,\r\n\t\tcritical: criticicalVal,\r\n\t\ttotal: parsedTemplate.total,\r\n\t\tcharName: parsedTemplate.charName,\r\n\t\tdamage: parsedTemplate.damage,\r\n\t\tcustomCritical: parsedTemplate.customCritical,\r\n\t\tforceDistrib: parsedTemplate.forceDistrib,\r\n\t};\r\n\tif (!verify) return statistiqueTemplate;\r\n\tif (statistiqueTemplate.diceType) {\r\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\r\n\t\t\tthrow new DiceTypeError(\r\n\t\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\t\t\"critical_dice_type\",\r\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\r\n\t\t\t);\r\n\t\t}\r\n\t\tconst cleanedDice = diceTypeRandomParse(\r\n\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\tstatistiqueTemplate,\r\n\t\t\tengine\r\n\t\t);\r\n\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\r\n\t}\r\n\tif (statistiqueTemplate.customCritical) {\r\n\t\tif (!statistiqueTemplate.diceType) {\r\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\r\n\t\t}\r\n\t\tconst customCritical = statistiqueTemplate.customCritical;\r\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\r\n\t\t\tconst cleanedDice = createCriticalCustom(\r\n\t\t\t\tstatistiqueTemplate.diceType!,\r\n\t\t\t\tcustom,\r\n\t\t\t\tstatistiqueTemplate,\r\n\t\t\t\tengine\r\n\t\t\t);\r\n\t\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\t\tif (!rolled)\r\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\r\n\t\t}\r\n\t}\r\n\ttestDiceRegistered(statistiqueTemplate, engine);\r\n\ttestStatCombinaison(statistiqueTemplate, engine);\r\n\treturn statistiqueTemplate;\r\n}\r\n\r\n/**\r\n * Test each damage roll from the template.damage\r\n * @param {StatisticalTemplate} template\r\n */\r\nexport function testDiceRegistered(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.damage) return;\r\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\r\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\r\n\tfor (const [name, dice] of Object.entries(template.damage)) {\r\n\t\tif (!dice) continue;\r\n\t\tconst diceReplaced = replaceExpByRandom(dice);\r\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\r\n\t\ttry {\r\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\r\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(error);\r\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Test all combinaison with generated random value\r\n * @param {StatisticalTemplate} template\r\n */\r\nexport function testStatCombinaison(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return;\r\n\tconst onlycombinaisonStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(\r\n\t\t\t([_, value]) => value.combinaison !== undefined\r\n\t\t)\r\n\t);\r\n\tconst allOtherStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\r\n\t);\r\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\r\n\tconst allStats = Object.keys(template.statistics).filter(\r\n\t\t(stat) => !template.statistics![stat].combinaison\r\n\t);\r\n\tif (allStats.length === 0) throw new NoStatisticsError();\r\n\tconst error = [];\r\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\r\n\t\tlet formula = value.combinaison as string;\r\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\r\n\t\t\tconst { max, min } = data;\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tconst regex = new RegExp(other, \"gi\");\r\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tevaluate(formula);\r\n\t\t} catch (e) {\r\n\t\t\terror.push(stat);\r\n\t\t}\r\n\t}\r\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\r\n\treturn;\r\n}\r\n\r\n/**\r\n * Generate a random stat based on the template and the statistical min and max\r\n * @param {number|undefined} total\r\n * @param {number | undefined} max\r\n * @param {number | undefined} min\r\n * @returns\r\n */\r\nexport function generateRandomStat(\r\n\ttotal: number | undefined = 100,\r\n\tmax?: number,\r\n\tmin?: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet randomStatValue = total + 1;\r\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\r\n\twhile (randomStatValue >= total || randomStatValue === 0) {\r\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\r\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\r\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\r\n\t\telse randomStatValue = randomInt(1, total, engine, random);\r\n\t}\r\n\treturn randomStatValue;\r\n}\r\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,59 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@dicelette/core",
|
|
3
|
-
"version": "1.22.
|
|
4
|
-
"description": "Core library for the Dicelette Discord bot",
|
|
5
|
-
"repository": {
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/Dicelette/core.git"
|
|
8
|
-
},
|
|
9
|
-
"type": "commonjs",
|
|
10
|
-
"main": "./dist/index.js",
|
|
11
|
-
"module": "./dist/index.mjs",
|
|
12
|
-
"types": "./dist/index.d.ts",
|
|
13
|
-
"files": [
|
|
14
|
-
"dist"
|
|
15
|
-
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"test": "vitest",
|
|
18
|
-
"build": "tsup",
|
|
19
|
-
"prerelease": "bun run build",
|
|
20
|
-
"lint": "biome format --write src",
|
|
21
|
-
"tsc": "tsc --noEmit --skipLibCheck",
|
|
22
|
-
"release": "commit-and-tag-version",
|
|
23
|
-
"postrelease": "git push --follow-tags origin main && bun publish"
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"discord",
|
|
27
|
-
"roll",
|
|
28
|
-
"library",
|
|
29
|
-
"bot",
|
|
30
|
-
"typescript"
|
|
31
|
-
],
|
|
32
|
-
"author": "Mara-Li",
|
|
33
|
-
"license": "GPL-3.0-only",
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@dice-roller/rpg-dice-roller": "^5.5.1",
|
|
36
|
-
"mathjs": "^15.1.0",
|
|
37
|
-
"moment": "^2.30.1",
|
|
38
|
-
"random-js": "^2.1.0",
|
|
39
|
-
"remove-accents": "^0.5.0",
|
|
40
|
-
"ts-dedent": "^2.2.0",
|
|
41
|
-
"uniformize": "^2.5.0",
|
|
42
|
-
"vite-tsconfig-paths": "^5.1.4",
|
|
43
|
-
"zod": "^4.1.13"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@biomejs/biome": "^2.3.8",
|
|
47
|
-
"@types/bun": "^1.3.3",
|
|
48
|
-
"commit-and-tag-version": "^12.6.1",
|
|
49
|
-
"tslib": "^2.8.1",
|
|
50
|
-
"tsup": "^8.5.1",
|
|
51
|
-
"typescript": "^5.9.3",
|
|
52
|
-
"typescript-json-schema": "^0.67.0",
|
|
53
|
-
"zod-to-json-schema": "^3.25.0"
|
|
54
|
-
},
|
|
55
|
-
"trustedDependencies": [
|
|
56
|
-
"@biomejs/biome",
|
|
57
|
-
"esbuild"
|
|
58
|
-
]
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@dicelette/core",
|
|
3
|
+
"version": "1.22.3",
|
|
4
|
+
"description": "Core library for the Dicelette Discord bot",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Dicelette/core.git"
|
|
8
|
+
},
|
|
9
|
+
"type": "commonjs",
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"module": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "vitest",
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"prerelease": "bun run build",
|
|
20
|
+
"lint": "biome format --write src",
|
|
21
|
+
"tsc": "tsc --noEmit --skipLibCheck",
|
|
22
|
+
"release": "commit-and-tag-version",
|
|
23
|
+
"postrelease": "git push --follow-tags origin main && bun publish"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"discord",
|
|
27
|
+
"roll",
|
|
28
|
+
"library",
|
|
29
|
+
"bot",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"author": "Mara-Li",
|
|
33
|
+
"license": "GPL-3.0-only",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@dice-roller/rpg-dice-roller": "^5.5.1",
|
|
36
|
+
"mathjs": "^15.1.0",
|
|
37
|
+
"moment": "^2.30.1",
|
|
38
|
+
"random-js": "^2.1.0",
|
|
39
|
+
"remove-accents": "^0.5.0",
|
|
40
|
+
"ts-dedent": "^2.2.0",
|
|
41
|
+
"uniformize": "^2.5.0",
|
|
42
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
43
|
+
"zod": "^4.1.13"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@biomejs/biome": "^2.3.8",
|
|
47
|
+
"@types/bun": "^1.3.3",
|
|
48
|
+
"commit-and-tag-version": "^12.6.1",
|
|
49
|
+
"tslib": "^2.8.1",
|
|
50
|
+
"tsup": "^8.5.1",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"typescript-json-schema": "^0.67.0",
|
|
53
|
+
"zod-to-json-schema": "^3.25.0"
|
|
54
|
+
},
|
|
55
|
+
"trustedDependencies": [
|
|
56
|
+
"@biomejs/biome",
|
|
57
|
+
"esbuild"
|
|
58
|
+
]
|
|
59
|
+
}
|