@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 +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +15 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dice.ts","../src/errors.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/utils.ts","../src/verify_template.ts"],"sourcesContent":["import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\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"]}
|