@dicelette/core 1.22.1 → 1.22.2

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.d.mts CHANGED
@@ -238,6 +238,7 @@ declare const SIGN_REGEX: RegExp;
238
238
  declare const SIGN_REGEX_SPACE: RegExp;
239
239
  declare const SYMBOL_DICE = "&";
240
240
  declare const DETECT_CRITICAL: RegExp;
241
+ declare const OPTIONAL_COMMENT: RegExp;
241
242
 
242
243
  interface StatisticalSchema extends StatisticalTemplate {
243
244
  /**
@@ -408,4 +409,4 @@ declare function testStatCombinaison(template: StatisticalTemplate, engine?: Eng
408
409
  */
409
410
  declare function generateRandomStat(total?: number | undefined, max?: number, min?: number, engine?: Engine | null): number;
410
411
 
411
- export { COMMENT_REGEX, type Compare, type ComparedValue, type Critical, type CustomCritical, type CustomCriticalMap, DETECT_CRITICAL, DiceTypeError, EmptyObjectError, FormulaError, MaxGreater, type Modifier, NoStatisticsError, type Resultat, SIGN_REGEX, SIGN_REGEX_SPACE, SYMBOL_DICE, type Sign, type Statistic, type StatisticalSchema, type StatisticalTemplate, TooManyDice, TooManyStats, calculator, createCriticalCustom, diceRandomParse, diceTypeRandomParse, escapeRegex, evalCombinaison, evalOneCombinaison, evalStatsDice, generateRandomStat, generateStatsDice, getEngine, getEngineId, isNumber, randomInt, replaceExpByRandom, replaceFormulaInDice, roll, standardizeDice, templateSchema, testDiceRegistered, testStatCombinaison, verifyTemplateValue };
412
+ export { COMMENT_REGEX, type Compare, type ComparedValue, type Critical, type CustomCritical, type CustomCriticalMap, DETECT_CRITICAL, DiceTypeError, EmptyObjectError, FormulaError, MaxGreater, type Modifier, NoStatisticsError, OPTIONAL_COMMENT, type Resultat, SIGN_REGEX, SIGN_REGEX_SPACE, SYMBOL_DICE, type Sign, type Statistic, type StatisticalSchema, type StatisticalTemplate, TooManyDice, TooManyStats, calculator, createCriticalCustom, diceRandomParse, diceTypeRandomParse, escapeRegex, evalCombinaison, evalOneCombinaison, evalStatsDice, generateRandomStat, generateStatsDice, getEngine, getEngineId, isNumber, randomInt, replaceExpByRandom, replaceFormulaInDice, roll, standardizeDice, templateSchema, testDiceRegistered, testStatCombinaison, verifyTemplateValue };
package/dist/index.d.ts CHANGED
@@ -238,6 +238,7 @@ declare const SIGN_REGEX: RegExp;
238
238
  declare const SIGN_REGEX_SPACE: RegExp;
239
239
  declare const SYMBOL_DICE = "&";
240
240
  declare const DETECT_CRITICAL: RegExp;
241
+ declare const OPTIONAL_COMMENT: RegExp;
241
242
 
242
243
  interface StatisticalSchema extends StatisticalTemplate {
243
244
  /**
@@ -408,4 +409,4 @@ declare function testStatCombinaison(template: StatisticalTemplate, engine?: Eng
408
409
  */
409
410
  declare function generateRandomStat(total?: number | undefined, max?: number, min?: number, engine?: Engine | null): number;
410
411
 
411
- export { COMMENT_REGEX, type Compare, type ComparedValue, type Critical, type CustomCritical, type CustomCriticalMap, DETECT_CRITICAL, DiceTypeError, EmptyObjectError, FormulaError, MaxGreater, type Modifier, NoStatisticsError, type Resultat, SIGN_REGEX, SIGN_REGEX_SPACE, SYMBOL_DICE, type Sign, type Statistic, type StatisticalSchema, type StatisticalTemplate, TooManyDice, TooManyStats, calculator, createCriticalCustom, diceRandomParse, diceTypeRandomParse, escapeRegex, evalCombinaison, evalOneCombinaison, evalStatsDice, generateRandomStat, generateStatsDice, getEngine, getEngineId, isNumber, randomInt, replaceExpByRandom, replaceFormulaInDice, roll, standardizeDice, templateSchema, testDiceRegistered, testStatCombinaison, verifyTemplateValue };
412
+ export { COMMENT_REGEX, type Compare, type ComparedValue, type Critical, type CustomCritical, type CustomCriticalMap, DETECT_CRITICAL, DiceTypeError, EmptyObjectError, FormulaError, MaxGreater, type Modifier, NoStatisticsError, OPTIONAL_COMMENT, type Resultat, SIGN_REGEX, SIGN_REGEX_SPACE, SYMBOL_DICE, type Sign, type Statistic, type StatisticalSchema, type StatisticalTemplate, TooManyDice, TooManyStats, calculator, createCriticalCustom, diceRandomParse, diceTypeRandomParse, escapeRegex, evalCombinaison, evalOneCombinaison, evalStatsDice, generateRandomStat, generateStatsDice, getEngine, getEngineId, isNumber, randomInt, replaceExpByRandom, replaceFormulaInDice, roll, standardizeDice, templateSchema, testDiceRegistered, testStatCombinaison, verifyTemplateValue };
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  FormulaError: () => FormulaError,
28
28
  MaxGreater: () => MaxGreater,
29
29
  NoStatisticsError: () => NoStatisticsError,
30
+ OPTIONAL_COMMENT: () => OPTIONAL_COMMENT,
30
31
  SIGN_REGEX: () => SIGN_REGEX,
31
32
  SIGN_REGEX_SPACE: () => SIGN_REGEX_SPACE,
32
33
  SYMBOL_DICE: () => SYMBOL_DICE,
@@ -270,7 +271,15 @@ function replaceText(element, total, dice) {
270
271
  function formatComment(dice) {
271
272
  const commentsRegex = /\[(?<comments>.*?)\]/;
272
273
  const commentsMatch = commentsRegex.exec(dice);
273
- return commentsMatch?.groups?.comments ? `__${commentsMatch.groups.comments}__ \u2014 ` : "";
274
+ const optionalComments = OPTIONAL_COMMENT.exec(dice);
275
+ const comments = commentsMatch?.groups?.comments ? `${commentsMatch.groups.comments}` : "";
276
+ const optional = optionalComments?.groups?.comment ? `${optionalComments.groups.comment.trim()}` : "";
277
+ let finalComment = "";
278
+ if (comments && optional)
279
+ finalComment = `__${commentsMatch?.groups?.comments} ${optionalComments?.groups?.comment.trim()}__ \u2014 `;
280
+ else if (comments) finalComment = `__${comments}__ \u2014 `;
281
+ else if (optional) finalComment = `__${optional}__ \u2014 `;
282
+ return finalComment;
274
283
  }
275
284
  function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engines.nodeCrypto) {
276
285
  if (dice.match(/\d+?#(.*?)/))
@@ -295,7 +304,7 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
295
304
  }
296
305
  const commentsRegex = /\[(?<comments>.*?)\]/gi;
297
306
  const comments = formatComment(diceMain);
298
- diceMain = diceMain.replaceAll(commentsRegex, "").trim();
307
+ diceMain = diceMain.replace(commentsRegex, "").trim();
299
308
  let diceResult = roll(diceMain, engine);
300
309
  if (!diceResult || !diceResult.total) {
301
310
  if (hidden) {
@@ -310,7 +319,7 @@ function sharedRolls(dice, engine = import_rpg_dice_roller.NumberGenerator.engin
310
319
  if (!total) return diceResult;
311
320
  for (let element of split.slice(1)) {
312
321
  const comment = formatComment(element);
313
- element = element.replace(commentsRegex, "").trim();
322
+ element = element.replaceAll(commentsRegex, "").replaceAll(OPTIONAL_COMMENT, "").trim();
314
323
  let toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);
315
324
  const compareRegex = toRoll.match(SIGN_REGEX_SPACE);
316
325
  if (compareRegex) {
@@ -422,11 +431,12 @@ var NoStatisticsError = class extends Error {
422
431
  };
423
432
 
424
433
  // src/interfaces/constant.ts
425
- var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/;
434
+ var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/gi;
426
435
  var SIGN_REGEX = /[><=!]+/;
427
436
  var SIGN_REGEX_SPACE = /[><=!]+(\S+)/;
428
437
  var SYMBOL_DICE = "&";
429
438
  var DETECT_CRITICAL = /\{\*?c[fs]:[<>=!]+(.+?)}/gim;
439
+ var OPTIONAL_COMMENT = /\s+(#|\/{2}|\[|\/\*)?(?<comment>.*)/gi;
430
440
 
431
441
  // src/interfaces/zod.ts
432
442
  var import_zod = require("zod");
@@ -860,6 +870,7 @@ function generateRandomStat(total = 100, max, min, engine = import_rpg_dice_roll
860
870
  FormulaError,
861
871
  MaxGreater,
862
872
  NoStatisticsError,
873
+ OPTIONAL_COMMENT,
863
874
  SIGN_REGEX,
864
875
  SIGN_REGEX_SPACE,
865
876
  SYMBOL_DICE,
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\";\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\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\tconst calc = compareRegex[1];\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\treturn commentsMatch?.groups?.comments ? `__${commentsMatch.groups.comments}__ — ` : \"\";\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\tconst toHideRegex = /(?<!\\[[^\\]]*)\\((?<dice>[^)]+)\\)/;\r\n\tconst toHide = toHideRegex.exec(diceMain)?.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}\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\r\n\tconst comments = formatComment(diceMain);\r\n\tdiceMain = diceMain.replaceAll(commentsRegex, \"\").trim();\r\n\tconsole.log(\"Dice main:\", diceMain);\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.replace(commentsRegex, \"\").trim();\r\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\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>.*)/;\nexport const SIGN_REGEX = /[><=!]+/;\nexport const SIGN_REGEX_SPACE = /[><=!]+(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:[<>=!]+(.+?)}/gim;\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\";\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"]}
package/dist/index.mjs CHANGED
@@ -211,7 +211,15 @@ function replaceText(element, total, dice) {
211
211
  function formatComment(dice) {
212
212
  const commentsRegex = /\[(?<comments>.*?)\]/;
213
213
  const commentsMatch = commentsRegex.exec(dice);
214
- return commentsMatch?.groups?.comments ? `__${commentsMatch.groups.comments}__ \u2014 ` : "";
214
+ const optionalComments = OPTIONAL_COMMENT.exec(dice);
215
+ const comments = commentsMatch?.groups?.comments ? `${commentsMatch.groups.comments}` : "";
216
+ const optional = optionalComments?.groups?.comment ? `${optionalComments.groups.comment.trim()}` : "";
217
+ let finalComment = "";
218
+ if (comments && optional)
219
+ finalComment = `__${commentsMatch?.groups?.comments} ${optionalComments?.groups?.comment.trim()}__ \u2014 `;
220
+ else if (comments) finalComment = `__${comments}__ \u2014 `;
221
+ else if (optional) finalComment = `__${optional}__ \u2014 `;
222
+ return finalComment;
215
223
  }
216
224
  function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto) {
217
225
  if (dice.match(/\d+?#(.*?)/))
@@ -236,7 +244,7 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto) {
236
244
  }
237
245
  const commentsRegex = /\[(?<comments>.*?)\]/gi;
238
246
  const comments = formatComment(diceMain);
239
- diceMain = diceMain.replaceAll(commentsRegex, "").trim();
247
+ diceMain = diceMain.replace(commentsRegex, "").trim();
240
248
  let diceResult = roll(diceMain, engine);
241
249
  if (!diceResult || !diceResult.total) {
242
250
  if (hidden) {
@@ -251,7 +259,7 @@ function sharedRolls(dice, engine = NumberGenerator.engines.nodeCrypto) {
251
259
  if (!total) return diceResult;
252
260
  for (let element of split.slice(1)) {
253
261
  const comment = formatComment(element);
254
- element = element.replace(commentsRegex, "").trim();
262
+ element = element.replaceAll(commentsRegex, "").replaceAll(OPTIONAL_COMMENT, "").trim();
255
263
  let toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);
256
264
  const compareRegex = toRoll.match(SIGN_REGEX_SPACE);
257
265
  if (compareRegex) {
@@ -363,11 +371,12 @@ var NoStatisticsError = class extends Error {
363
371
  };
364
372
 
365
373
  // src/interfaces/constant.ts
366
- var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/;
374
+ var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/gi;
367
375
  var SIGN_REGEX = /[><=!]+/;
368
376
  var SIGN_REGEX_SPACE = /[><=!]+(\S+)/;
369
377
  var SYMBOL_DICE = "&";
370
378
  var DETECT_CRITICAL = /\{\*?c[fs]:[<>=!]+(.+?)}/gim;
379
+ var OPTIONAL_COMMENT = /\s+(#|\/{2}|\[|\/\*)?(?<comment>.*)/gi;
371
380
 
372
381
  // src/interfaces/zod.ts
373
382
  import { z } from "zod";
@@ -800,6 +809,7 @@ export {
800
809
  FormulaError,
801
810
  MaxGreater,
802
811
  NoStatisticsError,
812
+ OPTIONAL_COMMENT,
803
813
  SIGN_REGEX,
804
814
  SIGN_REGEX_SPACE,
805
815
  SYMBOL_DICE,
@@ -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\";\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\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\tconst calc = compareRegex[1];\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\treturn commentsMatch?.groups?.comments ? `__${commentsMatch.groups.comments}__ — ` : \"\";\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\tconst toHideRegex = /(?<!\\[[^\\]]*)\\((?<dice>[^)]+)\\)/;\r\n\tconst toHide = toHideRegex.exec(diceMain)?.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}\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\r\n\tconst comments = formatComment(diceMain);\r\n\tdiceMain = diceMain.replaceAll(commentsRegex, \"\").trim();\r\n\tconsole.log(\"Dice main:\", diceMain);\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.replace(commentsRegex, \"\").trim();\r\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\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>.*)/;\nexport const SIGN_REGEX = /[><=!]+/;\nexport const SIGN_REGEX_SPACE = /[><=!]+(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:[<>=!]+(.+?)}/gim;\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\";\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dicelette/core",
3
- "version": "1.22.1",
3
+ "version": "1.22.2",
4
4
  "description": "Core library for the Dicelette Discord bot",
5
5
  "repository": {
6
6
  "type": "git",