@dicelette/core 1.24.1 → 1.24.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.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -268,7 +268,7 @@ function generateStatsDice(originalDice, stats, dollarValue) {
|
|
|
268
268
|
if (!outsideText) {
|
|
269
269
|
continue;
|
|
270
270
|
}
|
|
271
|
-
const tokenRegex = /([\p{L}\p{N}_]+)/gu;
|
|
271
|
+
const tokenRegex = /(\$?[\p{L}\p{N}_]+)/gu;
|
|
272
272
|
let lastIndex = 0;
|
|
273
273
|
let tokenMatch;
|
|
274
274
|
while ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {
|
|
@@ -320,7 +320,7 @@ function generateStatsDice(originalDice, stats, dollarValue) {
|
|
|
320
320
|
}
|
|
321
321
|
dice = result;
|
|
322
322
|
}
|
|
323
|
-
if (dollarValue) dice = dice.replaceAll(
|
|
323
|
+
if (dollarValue) dice = dice.replaceAll(/\$\B/g, dollarValue);
|
|
324
324
|
return replaceFormulaInDice(dice);
|
|
325
325
|
}
|
|
326
326
|
function replaceFormulaInDice(dice) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/engine.ts","../src/errors.ts","../src/interfaces/index.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/roll.ts","../src/dice/bulk.ts","../src/dice/compare.ts","../src/utils.ts","../src/dice/exploding.ts","../src/dice/signs.ts","../src/dice/replace.ts","../src/dice/extract.ts","../src/dice/calculator.ts","../src/dice/pity.ts","../src/verify_template.ts"],"sourcesContent":["export * from \"./engine\";\nexport * from \"./errors\";\nexport * from \"./interfaces\";\nexport * from \"./interfaces/constant\";\nexport * from \"./interfaces/toJsonSchema\";\nexport * from \"./interfaces/zod\";\nexport * from \"./roll\";\nexport * from \"./utils\";\nexport * from \"./verify_template\";\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport type { Engine } from \"random-js\";\n\n/**\n * Utility function that allow to get the id of an engine\n * @param engine {unknown} Engine to identify\n * @returns {string} Id of the engine or \"unknown\"\n * @private\n */\nexport function getEngineId(engine: unknown): string {\n\t// Comparaisons directes avec les engines exposés par la lib\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\n\t// Fallback: essayer de lire un nom ou le constructeur\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\n\t\tconst e = engine as any;\n\t\tif (e && typeof e === \"object\") {\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\n\t\t\tif (e.constructor?.name) return e.constructor.name;\n\t\t}\n\t} catch {\n\t\t/* ignore */\n\t}\n\treturn \"unknown\";\n}\n\n/**\n * Utility function to get the engine from its name\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\n * @returns {Engine} The engine\n * @public\n */\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\n\tswitch (engine) {\n\t\tcase \"nativeMath\":\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t\tcase \"browserCrypto\":\n\t\t\treturn NumberGenerator.engines.browserCrypto;\n\t\tcase \"nodeCrypto\":\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\n\t\tdefault:\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t}\n}\n","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 interface Resultat {\n\t/**\n\t * Original dice throw\n\t */\n\tdice: string;\n\t/**\n\t * Result of the dice throw\n\t */\n\tresult: string;\n\t/**\n\t * The comment that was added to the dice throw (if any)\n\t */\n\tcomment?: string;\n\t/**\n\t * The comparison made on the dice\n\t */\n\tcompare?: ComparedValue;\n\t/**\n\t * If any value was added to the dice throw\n\t */\n\tmodifier?: Modifier;\n\t/**\n\t * Total of the roll\n\t */\n\ttotal?: number;\n\tpityLogs?: number;\n\ttrivial?: boolean;\n}\n\nexport interface Compare {\n\t/**\n\t * Sign of the comparison\n\t */\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\";\n\t/**\n\t * Value of the comparison\n\t */\n\tvalue: number;\n\t/**\n\t * Indicate if the comparison is \"trivial\"\n\t * aka if the comparaison is always true or always false\n\t */\n\ttrivial?: boolean;\n}\n\n/**\n * Sign format for calculation of modifier\n */\nexport type Sign = \"+\" | \"-\" | \"*\" | \"/\" | \"%\" | \"^\" | \"**\";\n\nexport type ComparedValue = Compare & {\n\t/**\n\t * Original dice if the comparaison is made with a dice throw\n\t */\n\toriginalDice?: string;\n\t/**\n\t * Output of the dice throw\n\t */\n\trollValue?: string;\n};\n\nexport interface Modifier {\n\t/**\n\t * Sign of the modifier\n\t */\n\tsign?: Sign;\n\t/**\n\t * Value of the modifier\n\t * @TJS-type integer\n\t */\n\tvalue: number;\n}\n\n/**\n * Statistic object template\n */\nexport type Statistic = Record<\n\t/**\n\t * The name of the statistic\n\t * @TJS-type string\n\t */\n\tstring,\n\tStatEntry\n>;\n\ntype StatEntry = {\n\t/**\n\t * The value of the statistic that can take the stats\n\t * @TJS-type integer\n\t */\n\tmax?: number;\n\t/**\n\t * The minimal value of the statistic that can take the stats\n\t * @TJS-type integer\n\t */\n\tmin?: number;\n\t/**\n\t * The combinaison that can be made with ANOTHER statistic\n\t * Automatically disable the max/min value\n\t */\n\tcombinaison?: string;\n\t/**\n\t * Allow to exclude from roll selection in /dbroll!\n\t */\n\texclude?: boolean;\n};\n\n/**\n * @example\n * diceType: 1d20+$>=20\n * The dice throw will be 1d20 + statistique that must be >= 20\n * @example\n * diceType: 1d20<=$\n * The dice throw will be 1d20 that must be <= statistique\n */\nexport interface StatisticalTemplate {\n\t/** Allow to force the user to choose a name for them characters */\n\tcharName?: boolean;\n\t/**\n\t * The statistics that can be used in the dice throw\n\t * @maximum 25\n\t */\n\tstatistics?: Statistic;\n\t/**\n\t * A total can be set, it allows to calculate the total value of a future register member\n\t * If the sum of the value > total, the bot will send a message to the user to inform him that the total is exceeded and an error will be thrown\n\t * @note statistique that have a formula will be ignored from the total\n\t * @TJS-type integer\n\t */\n\ttotal?: number;\n\n\t/**\n\t * Force the distribition of all the points\n\t */\n\tforceDistrib?: boolean;\n\t/** A dice type in the notation supported by the bot */\n\tdiceType?: string;\n\t/**\n\t * How the success/echec will be done\n\t */\n\tcritical?: Critical;\n\t/**\n\t * Custom critical, allow to adjust the critical on a statistic, and set multiple critical value\n\t * @maximum 22\n\t */\n\tcustomCritical?: CustomCriticalMap;\n\n\t/** Special dice for damage\n\t * @maximum 25\n\t * */\n\tdamage?: Record<string, string>;\n}\nexport type CustomCriticalMap = Record<string, CustomCritical>;\n\n/**\n * If the result can be considered as a critical\n * Critical is compared to the \"natural\" dice result, so any modifier doesn't count\n */\nexport interface Critical {\n\t/**\n\t * The value that will be considered as a success\n\t * Can only be compared strictly with the natural dice result\n\t * @TJS-type integer\n\t */\n\tsuccess?: number;\n\t/**\n\t * The value that will be considered as a failure.\n\t * Can only be compared strictly with the natural dice result\n\t * @TJS-type integer\n\t */\n\tfailure?: number;\n}\n\nexport interface CustomCritical {\n\t/**\n\t * Sign of the comparison\n\t */\n\tsign: \"<\" | \">\" | \"<=\" | \">=\" | \"!=\" | \"==\";\n\t/**\n\t * Can be a simple value, or a formula, including the statistics with $\n\t * @example round($/2)\n\t */\n\tvalue: string;\n\t/**\n\t * If \"true\", the comparison will be made on the natural dice result, without any modifier, including the statistics bonus if any.\n\t */\n\tonNaturalDice?: boolean;\n\t/**\n\t * Allow to use the custom critical on dbD command (damage)\n\t * @default false\n\t */\n\taffectSkill?: boolean;\n}\n\nexport enum SortOrder {\n\tAscending = \"sa\",\n\tDescending = \"sd\",\n\tNone = \"none\",\n}\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\n// Use negative lookbehind to check for ![<>] before any comparison operator\nexport const SIGN_REGEX =\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\nexport const SIGN_REGEX_SPACE =\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\n","/**\n * Definition of the Zod schema for template data\n */\nimport { z } from \"zod\";\n\nconst statisticValueSchema = z\n\t.object({\n\t\tmax: z\n\t\t\t.number()\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t\t.optional(),\n\t\tmin: z\n\t\t\t.number()\n\t\t\t.transform((val) =>\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\n\t\t\t)\n\t\t\t.optional(),\n\t\tcombinaison: z\n\t\t\t.string()\n\t\t\t.transform((str) => str.trim() || undefined)\n\t\t\t.optional(),\n\t\texclude: z.boolean().optional(),\n\t})\n\t.superRefine((data, ctx) => {\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\n\t\t\t\tpath: [\"max\"],\n\t\t\t});\n\t\t}\n\t});\n\nconst statisticSchema = z\n\t.record(z.string(), statisticValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyStats\",\n\t});\n\nconst criticalSchema = z\n\t.object({\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\n\t})\n\t.transform((values) => {\n\t\tif (values.success === \"\") values.success = undefined;\n\t\tif (values.failure === \"\") values.failure = undefined;\n\t\tif (values.failure === 0) values.failure = undefined;\n\t\tif (values.success === 0) values.success = undefined;\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\n\t\treturn values;\n\t});\n\nconst criticalValueSchema = z.object({\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\n\tvalue: z.string(),\n\tonNaturalDice: z.boolean().optional(),\n\taffectSkill: z.boolean().optional(),\n});\n\nconst damageSchema = z\n\t.record(z.string(), z.string())\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nconst customCriticalSchema = z\n\t.record(z.string(), criticalValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nexport const templateSchema = z.object({\n\tcharName: z.boolean().optional(),\n\tstatistics: statisticSchema,\n\ttotal: z\n\t\t.number()\n\t\t.min(0)\n\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t.optional(),\n\tforceDistrib: z.boolean().optional(),\n\tdiceType: z.string().optional(),\n\tcritical: criticalSchema.optional(),\n\tcustomCritical: customCriticalSchema,\n\tdamage: damageSchema,\n});\n","import { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\n\nimport {\n\tcompareSignFormule,\n\tcountExplodingSuccesses,\n\ttype ExplodingSuccess,\n\textractValuesFromOutput,\n\tfixParenthesis,\n\tformatComment,\n\tgetCompare,\n\tgetModifier,\n\tgetRollBounds,\n\thandleBulkRolls,\n\thandlePitySystem,\n\tinverseSign,\n\tisTrivialComparison,\n\tmatchComparison,\n\tnormalizeExplodingSuccess,\n\tprepareDice,\n\treplaceText,\n\treplaceUnwantedText,\n\tsetSortOrder,\n} from \"./dice\";\nimport { DiceTypeError } from \"./errors\";\nimport { type Compare, type ComparedValue, type Resultat, SortOrder } from \"./interfaces\";\nimport {\n\tCOMMENT_REGEX,\n\tOPTIONAL_COMMENT,\n\tSIGN_REGEX_SPACE,\n\tSYMBOL_DICE,\n} from \"./interfaces/constant\";\n\n/**\n * Parse the string provided and turn it as a readable dice for dice parser\n * @param {string} dice The dice string to parse and roll\n * @param {Engine|null} engine The random engine to use, default to nodeCrypto\n * @param {boolean} pity Whether to enable pity system (reroll on failure) or not\n * @param {boolean} sort Whether to sort the dice results or not\n * @returns {Resultat|undefined} The result of the roll\n */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean,\n\tsort?: SortOrder\n): Resultat | undefined {\n\tif (sort === SortOrder.None) sort = undefined;\n\n\tconst prepared = prepareDice(dice);\n\tif (!prepared.dice.includes(\"d\")) return undefined;\n\n\t// Handle shared rolls\n\tif (prepared.isSharedRoll) {\n\t\treturn sharedRolls(\n\t\t\tprepared.dice,\n\t\t\tengine,\n\t\t\tpity,\n\t\t\tprepared.explodingSuccess,\n\t\t\tprepared.diceDisplay,\n\t\t\tprepared.isSharedCurly\n\t\t);\n\t}\n\n\tlet processedDice = fixParenthesis(prepared.dice);\n\tconst modificator = getModifier(processedDice);\n\n\t// Extract compare BEFORE rolling, but NOT for curly bulk rolls\n\tconst compareRegex = processedDice.match(SIGN_REGEX_SPACE);\n\tlet compare: ComparedValue | undefined;\n\tif (compareRegex && !prepared.isCurlyBulk) {\n\t\tconst compareResult = getCompare(processedDice, compareRegex, engine, pity);\n\t\tprocessedDice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\n\t// For simple curly braces, wrap the diceDisplay with braces\n\tlet finalDiceDisplay = prepared.diceDisplay;\n\tif (prepared.isSimpleCurly && !prepared.diceDisplay.startsWith(\"{\")) {\n\t\tfinalDiceDisplay = `{${prepared.diceDisplay}}`;\n\t}\n\n\t// Handle bulk rolls\n\tconst bulkProcessContent = prepared.isCurlyBulk ? prepared.bulkContent : processedDice;\n\tif (bulkProcessContent.match(/\\d+?#(.*)/)) {\n\t\treturn handleBulkRolls(\n\t\t\tprocessedDice,\n\t\t\tprepared.isCurlyBulk,\n\t\t\tprepared.bulkContent,\n\t\t\tcompare,\n\t\t\tprepared.explodingSuccess,\n\t\t\tprepared.diceDisplay,\n\t\t\tengine,\n\t\t\tsort\n\t\t);\n\t}\n\n\t// Standard roll\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tlet diceWithoutComment = processedDice.replace(COMMENT_REGEX, \"\").trimEnd();\n\tdiceWithoutComment = setSortOrder(diceWithoutComment, sort);\n\n\tlet diceRoll: DiceRoll | DiceRoll[];\n\ttry {\n\t\tdiceRoll = roller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\n\t// Update compare.trivial after rolling\n\tif (compare && diceRoll) {\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst trivial = isTrivialComparison(\n\t\t\tcurrentRoll.maxTotal,\n\t\t\tcurrentRoll.minTotal,\n\t\t\tcompare\n\t\t);\n\t\tcompare.trivial = trivial ? true : undefined;\n\t}\n\n\tconst commentMatch = processedDice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\n\n\t// Handle pity system\n\tlet rerollCount = 0;\n\tlet pityResult: Resultat | undefined;\n\tif (pity && compare) {\n\t\tconst pityData = handlePitySystem(\n\t\t\tdiceWithoutComment,\n\t\t\tcompare,\n\t\t\tdiceRoll,\n\t\t\troller,\n\t\t\tengine\n\t\t);\n\t\trerollCount = pityData.rerollCount;\n\t\tpityResult = pityData.result;\n\t\tif (pityResult) {\n\t\t\treturn {\n\t\t\t\t...pityResult,\n\t\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\n\t\t\t\tcomment,\n\t\t\t\tcompare,\n\t\t\t\tmodifier: modificator,\n\t\t\t\tpityLogs: rerollCount,\n\t\t\t\ttrivial: pityResult.trivial ?? (compare?.trivial ? true : undefined),\n\t\t\t};\n\t\t}\n\t}\n\n\tlet resultOutput = replaceUnwantedText(roller.output);\n\n\t// Handle exploding success\n\tif (prepared.explodingSuccess) {\n\t\tconst successes = countExplodingSuccesses(\n\t\t\tdiceRoll,\n\t\t\tprepared.explodingSuccess.sign,\n\t\t\tprepared.explodingSuccess.value\n\t\t);\n\t\tresultOutput = resultOutput\n\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successes}`)\n\t\t\t.replace(\n\t\t\t\tprepared.explodingSuccess.normalizedSegment,\n\t\t\t\tprepared.explodingSuccess.originalSegment\n\t\t\t);\n\n\t\treturn {\n\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : prepared.diceDisplay,\n\t\t\tresult: resultOutput,\n\t\t\tcomment,\n\t\t\tcompare: compare ? compare : undefined,\n\t\t\tmodifier: modificator,\n\t\t\ttotal: successes,\n\t\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t\t\ttrivial: compare?.trivial ? true : undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\n\t\tresult: resultOutput,\n\t\tcomment,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t\ttrivial: compare?.trivial ? true : undefined,\n\t};\n}\n\nfunction sharedRolls(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean,\n\texplodingSuccessMain?: ExplodingSuccess,\n\tdiceDisplay?: string,\n\tisSharedCurly?: boolean\n): Resultat | undefined {\n\t// If not provided (call from elsewhere), try to detect\n\tif (!explodingSuccessMain)\n\t\texplodingSuccessMain = normalizeExplodingSuccess(dice.split(\";\")[0] ?? dice);\n\n\tif (explodingSuccessMain) {\n\t\t// Use normalized dice for internal processing but keep original for display\n\t\tdice = dice.replace(explodingSuccessMain.originalSegment, \"!\");\n\t}\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\tconst displayDice = diceDisplay ?? explodingSuccessMain?.originalDice ?? split[0];\n\tlet diceMain = fixParenthesis(split[0]);\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\t// Remove comments before checking for hidden dice (parentheses)\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\n\tlet hidden = false;\n\tif (toHide?.dice) {\n\t\tdiceMain = toHide.dice;\n\t\thidden = true;\n\t} else if (toHide) {\n\t\tdiceMain = \"1d1\";\n\t\thidden = true;\n\t} else {\n\t\t// No hidden dice, use the dice without comments\n\t\tdiceMain = diceMainWithoutComments;\n\t}\n\tconst rollBounds = getRollBounds(diceMain, engine);\n\tlet diceResult = roll(diceMain, engine, pity);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\n\t\t\thidden = false;\n\t\t} else return undefined;\n\t}\n\tif (!diceResult || !diceResult.total) return undefined;\n\n\t// If we had a double-sign exploding, recompute successes from the first segment output\n\tif (explodingSuccessMain && diceResult.result) {\n\t\tconst values = extractValuesFromOutput(diceResult.result);\n\t\tdiceResult.total = values.filter((v) =>\n\t\t\tmatchComparison(explodingSuccessMain!.sign, v, explodingSuccessMain!.value)\n\t\t).length;\n\t}\n\tlet aggregatedCompare = diceResult.compare;\n\tlet hasTrivialComparison = diceResult.compare?.trivial === true;\n\tresults.push(`※ ${comments}${diceResult.result}`);\n\tlet total = diceResult.total;\n\tdiceResult.comment = mainComment;\n\tif (!total) {\n\t\treturn {\n\t\t\tdice: displayDice,\n\t\t\tresult: results.join(\";\"),\n\t\t\tcomment: mainComment,\n\t\t\tcompare: aggregatedCompare,\n\t\t\tmodifier: diceResult.modifier,\n\t\t\ttotal,\n\t\t\ttrivial: hasTrivialComparison ? true : undefined,\n\t\t};\n\t}\n\tfor (let element of split.slice(1)) {\n\t\tconst comment = formatComment(element);\n\t\telement = element\n\t\t\t.replaceAll(commentsRegex, \"\")\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\n\t\t\t.trim();\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\n\t\t//remove comments\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\n\t\tif (compareRegex) {\n\t\t\tif (isSharedCurly) {\n\t\t\t\t// For curly braces shared rolls, display success count instead of comparison details\n\t\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\t\ttoRoll,\n\t\t\t\t\tcompareRegex,\n\t\t\t\t\telement,\n\t\t\t\t\tdiceResult,\n\t\t\t\t\tengine,\n\t\t\t\t\tpity,\n\t\t\t\t\trollBounds\n\t\t\t\t);\n\t\t\t\t// Count success: 1 if comparison is true, 0 if false\n\t\t\t\tconst { diceAll } = replaceText(element, diceResult.total, diceResult.dice);\n\t\t\t\tlet successCount = 0;\n\t\t\t\ttry {\n\t\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\t\tsuccessCount = evaluated ? 1 : 0;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// If evaluation fails, try with roll\n\t\t\t\t\tconst evaluated = roll(toRoll, engine, pity) as Resultat | undefined;\n\t\t\t\t\tsuccessCount = (evaluated?.total ?? 0) ? 1 : 0;\n\t\t\t\t}\n\t\t\t\tresults.push(`※ ${comment}${diceAll}: ${successCount}`);\n\t\t\t\ttotal += successCount;\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\n\t\t\t\t\taggregatedCompare = compareResult.compare;\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\n\t\t\t} else {\n\t\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\t\ttoRoll,\n\t\t\t\t\tcompareRegex,\n\t\t\t\t\telement,\n\t\t\t\t\tdiceResult,\n\t\t\t\t\tengine,\n\t\t\t\t\tpity,\n\t\t\t\t\trollBounds\n\t\t\t\t);\n\t\t\t\ttoRoll = compareResult.dice;\n\t\t\t\tresults.push(compareResult.results);\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\n\t\t\t\t\taggregatedCompare = compareResult.compare;\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\n\t\t\t}\n\t\t} else {\n\t\t\tconst { formule, diceAll } = replaceText(\n\t\t\t\telement,\n\t\t\t\tdiceResult.total,\n\t\t\t\tdiceResult.dice\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\n\t\t\t} catch (error) {\n\t\t\t\tconst evaluated = roll(toRoll, engine, pity);\n\t\t\t\tif (evaluated) {\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\n\t\t\t\t\t);\n\t\t\t\t\tif (!aggregatedCompare && evaluated.compare)\n\t\t\t\t\t\taggregatedCompare = evaluated.compare;\n\t\t\t\t\tif (evaluated.compare?.trivial) hasTrivialComparison = true;\n\t\t\t\t} else results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += evaluated?.total ?? 0;\n\t\t\t}\n\t\t}\n\t}\n\tif (hidden)\n\t\t//remove the first in result\n\t\tresults.shift();\n\treturn {\n\t\tdice: displayDice,\n\t\tresult: results.join(\";\"),\n\t\tcomment: mainComment,\n\t\tcompare:\n\t\t\thasTrivialComparison && aggregatedCompare\n\t\t\t\t? { ...aggregatedCompare, trivial: true }\n\t\t\t\t: aggregatedCompare,\n\t\tmodifier: diceResult.modifier,\n\t\ttotal,\n\t\ttrivial: hasTrivialComparison ? true : undefined,\n\t};\n}\n\nexport function replaceInFormula(\n\telement: string,\n\tdiceResult: Resultat,\n\tcompareResult: { dice: string; compare: Compare | undefined },\n\tres: boolean,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tconst { formule, diceAll } = replaceText(\n\t\telement,\n\t\tdiceResult.total ?? 0,\n\t\tdiceResult.dice\n\t);\n\tconst validSign = res ? \"✓\" : \"✕\";\n\tconst invertedSign = res\n\t\t? compareResult.compare!.sign\n\t\t: inverseSign(compareResult.compare!.sign);\n\tlet evaluateRoll: unknown;\n\ttry {\n\t\tevaluateRoll = evaluate(compareResult.dice);\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t} catch (error) {\n\t\tconst evaluateRoll = roll(compareResult.dice, engine, pity) as Resultat | undefined;\n\t\tif (evaluateRoll)\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\n\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t}\n}\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport { DiceTypeError } from \"../errors\";\nimport type { Compare, ComparedValue, Resultat, SortOrder } from \"../interfaces\";\nimport { COMMENT_REGEX, SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\nimport { isTrivialComparison } from \"./compare\";\nimport {\n\tcountExplodingSuccesses,\n\tEXPLODING_SUCCESS_REGEX,\n\ttype ExplodingSuccess,\n} from \"./exploding\";\nimport { extractValuesFromOutput, getModifier, setSortOrder } from \"./extract\";\nimport { replaceUnwantedText } from \"./replace\";\nimport { matchComparison } from \"./signs\";\n\n/**\n * Gère les lancers en masse (bulk rolls)\n */\nexport function handleBulkRolls(\n\tdice: string,\n\tisCurlyBulk: boolean,\n\tbulkContent: string,\n\tcompare: ComparedValue | undefined,\n\texplodingSuccess: ExplodingSuccess | undefined,\n\tdiceDisplay: string,\n\tengine: Engine | null,\n\tsort?: SortOrder\n): Resultat {\n\tconst bulkProcessContent = isCurlyBulk ? bulkContent : dice;\n\tconst diceArray = bulkProcessContent.split(\"#\");\n\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\n\tlet diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\n\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\n\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\n\n\tlet curlyCompare: Compare | undefined;\n\tif (isCurlyBulk) {\n\t\tconst curlyCompareRegex = diceToRoll.match(SIGN_REGEX_SPACE);\n\t\tif (curlyCompareRegex) {\n\t\t\tconst compareSign = curlyCompareRegex[0].match(SIGN_REGEX)?.[0];\n\t\t\tconst compareValue = curlyCompareRegex[2];\n\t\t\tif (compareSign && compareValue) {\n\t\t\t\tcurlyCompare = {\n\t\t\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\t\t\tvalue: Number.parseInt(compareValue, 10),\n\t\t\t\t};\n\t\t\t\tdiceToRoll = diceToRoll.replace(SIGN_REGEX_SPACE, \"\");\n\t\t\t}\n\t\t}\n\t}\n\n\tdiceToRoll = setSortOrder(diceToRoll, sort);\n\n\tconst activeCompare: Compare | undefined =\n\t\tcompare ||\n\t\tcurlyCompare ||\n\t\t(explodingSuccess\n\t\t\t? ({ sign: explodingSuccess.sign, value: explodingSuccess.value } as Compare)\n\t\t\t: undefined);\n\n\tif (activeCompare) {\n\t\treturn handleBulkRollsWithComparison(\n\t\t\tnumberOfDice,\n\t\t\tdiceToRoll,\n\t\t\tcomments,\n\t\t\tactiveCompare,\n\t\t\texplodingSuccess,\n\t\t\tdiceDisplay,\n\t\t\tisCurlyBulk,\n\t\t\tcurlyCompare,\n\t\t\tcompare,\n\t\t\tengine\n\t\t);\n\t}\n\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\n\tfor (let i = 0; i < numberOfDice; i++) {\n\t\ttry {\n\t\t\troller.roll(diceToRoll);\n\t\t} catch (error) {\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t}\n\t}\n\n\tconst finalDice = isCurlyBulk ? `{${diceToRoll}}` : diceToRoll;\n\tconst modificator = getModifier(dice);\n\n\treturn {\n\t\tdice: finalDice,\n\t\tresult: replaceUnwantedText(roller.output),\n\t\tcomment: comments,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t};\n}\n\n/**\n * Gère les lancers en masse avec comparaison\n */\nfunction handleBulkRollsWithComparison(\n\tnumberOfDice: number,\n\tdiceToRoll: string,\n\tcomments: string | undefined,\n\tactiveCompare: Compare,\n\texplodingSuccess: ExplodingSuccess | undefined,\n\tdiceDisplay: string,\n\tisCurlyBulk: boolean,\n\tcurlyCompare: Compare | undefined,\n\tcompare: ComparedValue | undefined,\n\tengine: Engine | null\n): Resultat {\n\tconst results: string[] = [];\n\tlet successCount = 0;\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tlet trivialComparisonDetected = false;\n\n\tconst formatOutput = (output: string, addStar: boolean) => {\n\t\tconst formatted =\n\t\t\taddStar && isCurlyBulk\n\t\t\t\t? output.replace(\n\t\t\t\t\t\t/\\[([^\\]]+)\\]/,\n\t\t\t\t\t\t(_m, content) =>\n\t\t\t\t\t\t\t`[${content\n\t\t\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t\t\t.map((d: string) => `${d.trim()}*`)\n\t\t\t\t\t\t\t\t.join(\", \")}]`\n\t\t\t\t\t)\n\t\t\t\t: output;\n\t\treturn curlyCompare\n\t\t\t? formatted.replace(/^([^:]+):/, `$1${curlyCompare.sign}${curlyCompare.value}:`)\n\t\t\t: formatted;\n\t};\n\n\tfor (let i = 0; i < numberOfDice; i++) {\n\t\ttry {\n\t\t\tconst individualRoll = roller.roll(diceToRoll);\n\t\t\tconst rollInstance = Array.isArray(individualRoll)\n\t\t\t\t? individualRoll[0]\n\t\t\t\t: individualRoll;\n\n\t\t\tif (!trivialComparisonDetected && activeCompare) {\n\t\t\t\tconst { maxTotal, minTotal } = rollInstance;\n\t\t\t\ttrivialComparisonDetected = isTrivialComparison(\n\t\t\t\t\tmaxTotal,\n\t\t\t\t\tminTotal,\n\t\t\t\t\tactiveCompare\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst rollOutput = rollInstance.output;\n\n\t\t\tif (explodingSuccess) {\n\t\t\t\tconst successesForRoll = countExplodingSuccesses(\n\t\t\t\t\trollInstance,\n\t\t\t\t\texplodingSuccess.sign,\n\t\t\t\t\texplodingSuccess.value\n\t\t\t\t);\n\t\t\t\tsuccessCount += successesForRoll;\n\n\t\t\t\tlet formattedRollOutput = rollOutput\n\t\t\t\t\t.replace(explodingSuccess.normalizedSegment, explodingSuccess.originalSegment)\n\t\t\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successesForRoll}`);\n\t\t\t\tformattedRollOutput = formatOutput(formattedRollOutput, false);\n\t\t\t\tresults.push(formattedRollOutput);\n\t\t\t} else {\n\t\t\t\tconst rollTotal = rollInstance.total;\n\t\t\t\tconst isSuccess = evaluate(\n\t\t\t\t\t`${rollTotal}${activeCompare.sign}${activeCompare.value}`\n\t\t\t\t);\n\n\t\t\t\tif (isSuccess) successCount++;\n\t\t\t\tresults.push(formatOutput(rollOutput, isSuccess));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t}\n\t}\n\n\tif (explodingSuccess) {\n\t\tconst signSource = explodingSuccess?.originalDice ?? diceDisplay;\n\t\tconst explodingMatch = signSource.match(EXPLODING_SUCCESS_REGEX);\n\t\tif (explodingMatch) {\n\t\t\tconst [, doubledSignRaw, valueStr] = explodingMatch;\n\t\t\tlet doubledSign: string;\n\t\t\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\n\t\t\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\n\t\t\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\n\n\t\t\tconst signMap: Record<string, Compare[\"sign\"]> = {\n\t\t\t\t\">>\": \">\",\n\t\t\t\t\"<<\": \"<\",\n\t\t\t\t\">=\": \">=\",\n\t\t\t\t\"<=\": \"<=\",\n\t\t\t\t\"==\": \"=\",\n\t\t\t\t\"!==\": \"!=\",\n\t\t\t\t\"!!==\": \"=\",\n\t\t\t};\n\t\t\tconst mappedSign = signMap[doubledSign];\n\t\t\tconst mappedValue = Number.parseFloat(valueStr);\n\n\t\t\tif (mappedSign && !Number.isNaN(mappedValue)) {\n\t\t\t\tconst resultsString = replaceUnwantedText(results.join(\"; \"));\n\t\t\t\tconst flatValues = resultsString\n\t\t\t\t\t.split(\";\")\n\t\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment));\n\n\t\t\t\tif (mappedSign === \"!=\") {\n\t\t\t\t\tconst equalsCount = flatValues.filter((val) => val === mappedValue).length;\n\t\t\t\t\tsuccessCount = flatValues.length - equalsCount;\n\t\t\t\t} else {\n\t\t\t\t\tsuccessCount = flatValues.filter((val) =>\n\t\t\t\t\t\tmatchComparison(mappedSign, val, mappedValue)\n\t\t\t\t\t).length;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (compare && trivialComparisonDetected) compare.trivial = true;\n\n\tconst finalDice = isCurlyBulk\n\t\t? `{${diceToRoll}${curlyCompare?.sign}${curlyCompare?.value}}`\n\t\t: diceToRoll;\n\n\tconst resultOutput = replaceUnwantedText(results.join(\"; \"));\n\tconst finalTotal = explodingSuccess\n\t\t? resultOutput\n\t\t\t\t.split(\";\")\n\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment))\n\t\t\t\t.filter((val) =>\n\t\t\t\t\tmatchComparison(explodingSuccess.sign, val, explodingSuccess.value)\n\t\t\t\t).length\n\t\t: successCount;\n\n\tconst modificator = getModifier(diceDisplay);\n\n\treturn {\n\t\tdice: explodingSuccess ? diceDisplay : finalDice,\n\t\tresult: resultOutput,\n\t\tcomment: comments,\n\t\tcompare: isCurlyBulk ? undefined : compare,\n\t\tmodifier: modificator,\n\t\ttotal: finalTotal,\n\t\ttrivial: trivialComparisonDetected ? true : undefined,\n\t};\n}\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport type { ComparedValue } from \"../interfaces\";\nimport { SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\nimport { roll } from \"../roll\";\nimport { isNumber } from \"../utils\";\n\n/**\n * Check if a comparison is trivial (always true or always false)\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\n * @param maxValue Maximum possible value from the dice roll\n * @param minValue Minimum possible value from the dice roll\n * @param compare The comparison object\n * @returns true if the comparison is trivial (always true or always false)\n */\nexport function isTrivialComparison(\n\tmaxValue: number,\n\tminValue: number,\n\tcompare: ComparedValue\n): boolean {\n\t// Check if comparison can never succeed (always false)\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\n\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\n\n\t// Trivial if it can never succeed OR can never fail\n\treturn !canSucceed || !canFail;\n}\n\n/**\n * Check if a comparison can theoretically fail given roll bounds\n * @param maxRollValue Maximum possible roll value\n * @param compare The comparison object\n * @param minRollValue Minimum possible roll value (defaults to 1)\n * @returns true if the comparison can fail at least once\n */\nexport function canComparisonFail(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue = 1\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\n\t\tcase \">=\":\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\n\t\tcase \"<\":\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\n\t\tcase \"<=\":\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\n\t\tcase \"!=\":\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nexport function rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\t// Handle empty value or string - return 0 as default\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n\t\treturn { value: 0, diceResult: value as string };\n\t}\n\tconst rollComp = roll(value as string, engine, pity);\n\tif (!rollComp?.total) {\n\t\t//not a dice throw\n\t\ttry {\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\n\t\t} catch (error) {\n\t\t\t// If evaluate fails, return 0\n\t\t\treturn { value: 0, diceResult: value as string };\n\t\t}\n\t}\n\treturn {\n\t\tdice: value as string,\n\t\tvalue: rollComp.total,\n\t\tdiceResult: rollComp?.result,\n\t};\n}\n\nexport function getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; compare: ComparedValue | undefined } {\n\t/**\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\n\t * Some system count the number of a dice that are greater than or equal to a target, and not the \"total\" of rolled dice.\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\n\t * To support this, we use the group notation. It a little different than the notation of dice-roller, but it a sacrifice to not break the current notation.\n\t * @note:\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\n\t * - `{2d3>=4}` will count the total of dice that are greater than or equal to 4, and not the total of the dice.\n\t * - `{2d3,1d4}>=4` won't use the comparison, but will count the number of dice that are greater than or equal to 4. If the total of the dice is needed, just remove the group notation and use `2d3+1d4>=4`.\n\t */\n\tif (\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\n\t)\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\n\tconst calc = compareRegex[2];\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\n\n\tif (sign) {\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\n\t\tconst total = evaluate(rCompare.value.toString());\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: total,\n\t\t\toriginalDice: rCompare.dice,\n\t\t\trollValue: rCompare.diceResult,\n\t\t};\n\t} else {\n\t\tconst rcompare = rollCompare(calc, engine, pity);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: rcompare.value,\n\t\t\toriginalDice: rcompare.dice,\n\t\t\trollValue: rcompare.diceResult,\n\t\t};\n\t}\n\n\treturn { dice, compare };\n}\n\n/**\n * Check if a comparison can theoretically succeed given a maximum roll value\n * @example\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\n */\nexport function canComparisonSucceed(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue?: number\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn maxRollValue > compare.value;\n\t\tcase \">=\":\n\t\t\treturn maxRollValue >= compare.value;\n\t\tcase \"<\":\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"<=\":\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\n\t\tcase \"!=\":\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n","import { evaluate } from \"mathjs\";\nimport \"uniformize\";\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { type Engine, Random } from \"random-js\";\nimport {\n\ttype CustomCritical,\n\tDiceTypeError,\n\tdiceTypeRandomParse,\n\tFormulaError,\n\tSIGN_REGEX_SPACE,\n\ttype StatisticalTemplate,\n} from \".\";\n\n/**\n * Escape regex string\n * @param string {string}\n */\nexport function escapeRegex(string: string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Allow to keep the text as if in brackets\n * @param dice {string}\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\n */\nexport function standardizeDice(dice: string): string {\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\n\t);\n}\n\n/**\n * Replace the stat name by their value using stat\n * and after evaluate any formula using `replaceFormulaInDice`\n * @param {string} originalDice\n * @param {Record<string,number>|undefined} stats\n * @param {string|undefined} dollarValue\n */\nexport function generateStatsDice(\n\toriginalDice: string,\n\tstats?: Record<string, number>,\n\tdollarValue?: string\n) {\n\tlet dice = originalDice.standardize();\n\tif (stats && Object.keys(stats).length > 0) {\n\t\tconst statKeys = Object.keys(stats);\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\n\t\tlet result = \"\";\n\t\tlet match: RegExpExecArray | null;\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\n\t\t\tconst insideBrackets = match[1];\n\t\t\tconst outsideText = match[2];\n\t\t\tif (insideBrackets) {\n\t\t\t\tresult += insideBrackets;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!outsideText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\n\t\t\tlet lastIndex = 0;\n\t\t\tlet tokenMatch: RegExpExecArray | null;\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\n\t\t\t\tconst token = tokenMatch[0];\n\t\t\t\tconst tokenStd = token.standardize();\n\n\t\t\t\t// Check for dice notation patterns like \"1dstat1\" or \"dstat1\"\n\t\t\t\tconst diceMatch = /^(\\d*)d(.+)$/i.exec(tokenStd);\n\t\t\t\tif (diceMatch) {\n\t\t\t\t\tconst diceCount = diceMatch[1] || \"\";\n\t\t\t\t\tconst afterD = diceMatch[2];\n\t\t\t\t\tlet foundStatAfterD = false;\n\t\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\t\tif (afterD === keyStd) {\n\t\t\t\t\t\t\tresult += `${diceCount}d${stats[key].toString()}`;\n\t\t\t\t\t\t\tfoundStatAfterD = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (foundStatAfterD) {\n\t\t\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet bestKey: string | null = null;\n\t\t\t\tlet bestScore = 0;\n\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\tif (tokenStd === keyStd) {\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t\tbestScore = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\n\t\t\t\t\tif (score > bestScore) {\n\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\n\t\t\t\t\tconst statValue = stats[bestKey];\n\t\t\t\t\tresult += statValue.toString();\n\t\t\t\t} else {\n\t\t\t\t\tresult += token;\n\t\t\t\t}\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t}\n\t\t\tresult += outsideText.slice(lastIndex);\n\t\t}\n\t\tdice = result;\n\t}\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\n\treturn replaceFormulaInDice(dice);\n}\n\n/**\n * Replace the {{}} in the dice string and evaluate the interior if any\n * @param dice {string}\n */\nexport function replaceFormulaInDice(dice: string) {\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\n\tlet match;\n\tlet modifiedDice = dice;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\twhile ((match = formula.exec(dice)) !== null) {\n\t\tif (match.groups?.formula) {\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\n\t\t\ttry {\n\t\t\t\tconst result = evaluate(formulae);\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cleanedDice(modifiedDice);\n}\n\n/**\n * Replace the ++ +- -- by their proper value:\n * - `++` = `+`\n * - `+-` = `-`\n * - `--` = `+`\n * @param dice {string}\n */\nfunction cleanedDice(dice: string) {\n\treturn dice\n\t\t.replaceAll(\"+-\", \"-\")\n\t\t.replaceAll(\"--\", \"+\")\n\t\t.replaceAll(\"++\", \"+\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimEnd();\n}\n\n/**\n * Verify if a value is a number, even if it's a \"number\" string\n * @param value {unknown}\n * @returns {boolean}\n */\nexport function isNumber(value: unknown): boolean {\n\treturn (\n\t\tvalue !== undefined &&\n\t\t(typeof value === \"number\" ||\n\t\t\t(!Number.isNaN(Number(value)) &&\n\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\tvalue.trim().length > 0))\n\t);\n}\n\n/**\n * Replace the `{exp}` in the dice.\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\n * @param {string} dice\n * @param engine\n * @returns {string} the dice with the {exp} replaced by a random value\n */\nexport function replaceExpByRandom(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): string {\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\n\t\tconst defaultValue = groups?.default;\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\n\t});\n}\n\n/**\n * Utility function to get a random integer between min and max and using the specified engine\n * @param min {number}\n * @param max {number}\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\n * @returns {number} Random integer between min and max\n */\nexport function randomInt(\n\tmin: number,\n\tmax: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\trng?: Random\n): number {\n\tif (!rng) rng = new Random(engine || undefined);\n\treturn rng.integer(min, max);\n}\n\n/**\n * Calcule la distance de Levenshtein entre deux chaînes\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\tif (a === b) return 0;\n\tconst al = a.length;\n\tconst bl = b.length;\n\tif (al === 0) return bl;\n\tif (bl === 0) return al;\n\tconst v0 = new Array<number>(bl + 1);\n\tconst v1 = new Array<number>(bl + 1);\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\n\tfor (let i = 0; i < al; i++) {\n\t\tv1[0] = i + 1;\n\t\tfor (let j = 0; j < bl; j++) {\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n\t\t}\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\n\t}\n\treturn v1[bl];\n}\n\n/**\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\n */\nfunction similarityScore(a: string, b: string): number {\n\tconst la = a.length;\n\tconst lb = b.length;\n\tif (la === 0 && lb === 0) return 1;\n\tconst dist = levenshteinDistance(a, b);\n\tconst max = Math.max(la, lb);\n\treturn 1 - dist / max;\n}\n\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","import type { DiceRoll } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Compare } from \"../interfaces\";\nimport { matchComparison } from \"./signs\";\n\nexport type ExplodingSuccess = {\n\tdice: string;\n\toriginalDice: string;\n\tsign: Compare[\"sign\"];\n\tvalue: number;\n\tnormalizedSegment: string;\n\toriginalSegment: string;\n};\n\nexport const EXPLODING_SUCCESS_REGEX =\n\t/(!(?:>>=|<<=|!==|!!==|>>|<<|==|!=))(-?\\d+(?:\\.\\d+)?)/;\n\nexport function normalizeExplodingSuccess(dice: string): ExplodingSuccess | undefined {\n\tconst match = dice.match(EXPLODING_SUCCESS_REGEX);\n\tif (!match) return undefined;\n\n\tconst [, doubledSignRaw, valueStr] = match;\n\tlet doubledSign: string;\n\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\n\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\n\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\n\tconst signMap: Record<string, Compare[\"sign\"]> = {\n\t\t\">>\": \">\",\n\t\t\"<<\": \"<\",\n\t\t\">>=\": \">=\",\n\t\t\"<<=\": \"<=\",\n\t\t\"==\": \"=\",\n\t\t\"!==\": \"!=\",\n\t\t\"!!==\": \"=\",\n\t};\n\n\tconst normalizedSign = signMap[doubledSign];\n\tif (!normalizedSign) return undefined;\n\tlet parsedValue = Number.parseFloat(valueStr);\n\tif (Number.isNaN(parsedValue)) {\n\t\ttry {\n\t\t\tparsedValue = Number.parseFloat(evaluate(valueStr) as unknown as string);\n\t\t} catch (_error) {\n\t\t\tparsedValue = 0;\n\t\t}\n\t}\n\n\t// Remove comparison for the actual explode mechanic so it uses default explode\n\tconst normalizedSegment = \"!\";\n\tconst replacedDice = dice.replace(match[0], normalizedSegment);\n\n\treturn {\n\t\tdice: replacedDice,\n\t\toriginalDice: dice,\n\t\tsign: normalizedSign,\n\t\tvalue: parsedValue,\n\t\tnormalizedSegment,\n\t\toriginalSegment: match[0],\n\t};\n}\n\nexport function countExplodingSuccesses(\n\tdiceRoll: DiceRoll | DiceRoll[],\n\tsign: Compare[\"sign\"],\n\tvalue: number\n): number {\n\tconst rollsArray = Array.isArray(diceRoll) ? diceRoll : [diceRoll];\n\tconst flatValues: number[] = [];\n\n\tfor (const dr of rollsArray) {\n\t\tconst groups = (dr as DiceRoll).rolls ?? [];\n\t\tfor (const group of groups as unknown as Array<{\n\t\t\trolls?: Array<{ value?: number }>;\n\t\t}>) {\n\t\t\tconst innerRolls = group.rolls ?? [];\n\t\t\tfor (const roll of innerRolls) {\n\t\t\t\tif (typeof roll.value === \"number\") flatValues.push(roll.value);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn flatValues.reduce(\n\t\t(acc, current) => acc + (matchComparison(sign, current, value) ? 1 : 0),\n\t\t0\n\t);\n}\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport type { Compare, Resultat } from \"../interfaces\";\nimport { replaceInFormula, roll } from \"../roll\";\nimport { getCompare, isTrivialComparison } from \"./compare\";\nimport { replaceText } from \"./replace\";\n\nexport function matchComparison(sign: Compare[\"sign\"], val: number, value: number) {\n\tswitch (sign) {\n\t\tcase \">\":\n\t\t\treturn val > value;\n\t\tcase \">=\":\n\t\t\treturn val >= value;\n\t\tcase \"<\":\n\t\t\treturn val < value;\n\t\tcase \"<=\":\n\t\t\treturn val <= value;\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn val === value;\n\t\tcase \"!=\":\n\t\t\treturn val !== value;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function 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\nexport function compareSignFormule(\n\ttoRoll: string,\n\tcompareRegex: RegExpMatchArray,\n\telement: string,\n\tdiceResult: Resultat,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean,\n\trollBounds?: { min: number; max: number }\n): { dice: string; results: string; compare?: Compare; trivial: boolean } {\n\tlet results = \"\";\n\tlet trivial = false;\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\n\tlet res: unknown;\n\ttry {\n\t\tres = evaluate(toCompare);\n\t} catch (error) {\n\t\tres = roll(toCompare, engine, pity);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\tconst detectedTrivial =\n\t\t\trollBounds && compareResult.compare\n\t\t\t\t? isTrivialComparison(rollBounds.max, rollBounds.min, compareResult.compare)\n\t\t\t\t: false;\n\t\tif (detectedTrivial && compareResult.compare) compareResult.compare.trivial = true;\n\t\tif (detectedTrivial) trivial = true;\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\n\t} else if (res instanceof Object) {\n\t\tconst diceResult = res as Resultat;\n\t\tif (diceResult.compare) {\n\t\t\tconst toEvaluate = evaluate(\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\n\t\t\t);\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\n\t\t\tconst invertedSign = toEvaluate\n\t\t\t\t? diceResult.compare.sign\n\t\t\t\t: inverseSign(diceResult.compare.sign);\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\n\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\n\t\t\tif (diceResult.compare.trivial) trivial = true;\n\t\t}\n\t}\n\treturn { dice: compareResult.dice, results, compare: compareResult.compare, trivial };\n}\n","import { COMMENT_REGEX, SYMBOL_DICE } from \"../interfaces/constant\";\n\nexport function replaceUnwantedText(dice: string) {\n\treturn dice.replaceAll(/[{}]/g, \"\").replaceAll(/s[ad]/gi, \"\");\n}\n\nexport function 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\nexport function 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\nexport function formatComment(dice: string) {\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\n\tconst commentsMatch = commentsRegex.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\n\t// to avoid conflicts with parentheses inside bracket comments\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\n\n\t//fusion of both comments with a space if both exists\n\t//result expected = \"__comment1 comment2__ — \"\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\n\tlet finalComment = \"\";\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\n\telse if (comments) finalComment = `__${comments}__ — `;\n\telse if (optional) finalComment = `__${optional}__ — `;\n\treturn finalComment;\n}\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport type { Engine } from \"random-js\";\nimport type { Modifier, Sign, SortOrder } from \"../interfaces\";\nimport { DETECT_CRITICAL } from \"../interfaces/constant\";\nimport { replaceFormulaInDice, standardizeDice } from \"../utils\";\nimport { calculator } from \"./calculator\";\nimport { type ExplodingSuccess, normalizeExplodingSuccess } from \"./exploding\";\n\nexport function 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\nexport function extractValuesFromOutput(output: string): number[] {\n\tconst values: number[] = [];\n\tconst regex = /\\[([^\\]]+)\\]/g;\n\tlet match: RegExpExecArray | null;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best method to extract all matches\n\twhile ((match = regex.exec(output)) !== null) {\n\t\tconst segmentValues = match[1]\n\t\t\t.split(\",\")\n\t\t\t.map((v) => Number.parseInt(v.replace(/[!*]/g, \"\").trim(), 10))\n\t\t\t.filter((v) => !Number.isNaN(v));\n\t\tvalues.push(...segmentValues);\n\t}\n\treturn values;\n}\n\nexport function getRollBounds(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): { min: number; max: number } | undefined {\n\ttry {\n\t\tconst roller = new DiceRoller();\n\t\tNumberGenerator.generator.engine = engine;\n\t\tconst rollResult = roller.roll(dice);\n\t\tconst instance = Array.isArray(rollResult) ? rollResult[0] : rollResult;\n\t\tconst { minTotal, maxTotal } = instance;\n\t\treturn { min: minTotal, max: maxTotal };\n\t} catch (error) {\n\t\t// Ignore bounds computation errors; trivial detection will simply be skipped\n\t}\n\treturn undefined;\n}\n\nexport function setSortOrder(toRoll: string, sort?: SortOrder): string {\n\t//First check if the diceToRoll contains already a sort order\n\tconst sortRegex = /(sa|sd|s)/i;\n\tif (sort && !toRoll.match(sortRegex)) {\n\t\t//we should insert the sort order at the end of the dice string and before the possible modifier or comparison\n\t\tconst modifierComparisonRegex = /([+\\-*/%^]\\d+|([><=!]+\\d+f)|([><=]|!=)+\\d+)$/;\n\t\tconst match = toRoll.match(modifierComparisonRegex);\n\t\tif (match) {\n\t\t\t//Insert before the modifier or comparison\n\t\t\tconst index = match.index!;\n\t\t\ttoRoll = `${toRoll.slice(0, index)}${sort}${toRoll.slice(index)}`;\n\t\t} else {\n\t\t\t//Append at the end\n\t\t\ttoRoll += sort;\n\t\t}\n\t}\n\treturn toRoll;\n}\n\ninterface PreparedDice {\n\tdice: string;\n\tdiceDisplay: string;\n\texplodingSuccess?: ExplodingSuccess;\n\tisSharedRoll: boolean;\n\tisSharedCurly: boolean;\n\tisCurlyBulk: boolean;\n\tbulkContent: string;\n\tisSimpleCurly: boolean;\n}\n\n/**\n * Prépare la chaîne de dés pour le traitement\n */\nexport function prepareDice(diceInput: string): PreparedDice {\n\tlet dice = standardizeDice(replaceFormulaInDice(diceInput))\n\t\t.replace(/^\\+/, \"\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimStart();\n\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\n\n\tconst explodingSuccess = normalizeExplodingSuccess(dice);\n\tif (explodingSuccess) dice = explodingSuccess.dice;\n\n\tlet diceDisplay: string;\n\tif (dice.includes(\";\")) {\n\t\tconst mainDice = dice.split(\";\")[0];\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? mainDice;\n\t} else {\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? dice;\n\t}\n\n\tconst curlyBulkMatch = dice.match(/^\\{(\\d+#.*)\\}$/);\n\tconst isCurlyBulk = !!curlyBulkMatch;\n\tconst bulkContent = isCurlyBulk ? curlyBulkMatch![1] : \"\";\n\n\tconst isSharedRoll = dice.includes(\";\");\n\tlet isSharedCurly = false;\n\n\tif (isSharedRoll && dice.match(/^\\{.*;\\s*.*\\}$/)) {\n\t\tdice = dice.slice(1, -1);\n\t\tisSharedCurly = true;\n\t\tdiceDisplay = diceDisplay.slice(1);\n\t}\n\n\t// Handle simple curly braces like {1d20+5} or {1d20+5>10}\n\t// But NOT dice pool notation like {2d6>4} where the comparison is inside the braces WITHOUT modifiers\n\tlet isSimpleCurly = false;\n\tif (!isCurlyBulk && !isSharedRoll && dice.match(/^\\{.*\\}$/)) {\n\t\t// Check if this is a dice pool (comparison inside the braces WITHOUT modifiers)\n\t\tconst innerContent = dice.slice(1, -1); // Remove outer braces\n\t\tconst hasModifiers = innerContent.match(/[+\\-*/%^]/);\n\t\tconst hasComparison = innerContent.match(/(([><=!]+\\d+f)|([><=]|!=)+\\d+)/);\n\n\t\t// Only remove braces if it's not a dice pool\n\t\t// Dice pool: has comparison inside, NO modifiers (like {2d6>4})\n\t\t// Simple curly: has modifiers before comparison (like {1d20+5>10}) or just plain dice (like {1d20+5})\n\t\tif (!(hasComparison && !hasModifiers)) {\n\t\t\tdice = innerContent;\n\t\t\tisSimpleCurly = true;\n\t\t}\n\t}\n\n\treturn {\n\t\tdice,\n\t\tdiceDisplay,\n\t\texplodingSuccess,\n\t\tisSharedRoll,\n\t\tisSharedCurly,\n\t\tisCurlyBulk,\n\t\tbulkContent,\n\t\tisSimpleCurly,\n\t};\n}\n","import { evaluate } from \"mathjs\";\nimport type { Sign } from \"../interfaces\";\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","import type { DiceRoll, DiceRoller } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport { DiceTypeError } from \"../errors\";\nimport type { Compare, Resultat } from \"../interfaces\";\nimport { roll } from \"../roll\";\nimport { canComparisonSucceed } from \"./compare\";\n\n/**\n * Gère le système de pity (relance en cas d'échec)\n */\nexport function handlePitySystem(\n\tdice: string,\n\tcompare: Compare,\n\tdiceRoll: DiceRoll | DiceRoll[],\n\troller: DiceRoller,\n\tengine: Engine | null\n): { rerollCount: number; result?: Resultat } {\n\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\n\tconst isComparisonPossible =\n\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\n\n\tif (!isComparisonPossible) {\n\t\treturn { rerollCount: 0 };\n\t}\n\n\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\n\tif (isFail) {\n\t\treturn { rerollCount: 0 };\n\t}\n\n\tconst maxReroll = 100;\n\tlet rerollCount = 0;\n\tlet res: Resultat | undefined;\n\n\twhile (!isFail && rerollCount < maxReroll) {\n\t\ttry {\n\t\t\tres = roll(dice, engine, false);\n\t\t} catch (error) {\n\t\t\tthrow new DiceTypeError(dice, \"roll\", error);\n\t\t}\n\t\trerollCount++;\n\t\tif (res && res.total !== undefined) {\n\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\n\t\t}\n\t}\n\n\treturn { rerollCount, result: res };\n}\n","import { evaluate } from \"mathjs\";\nimport { type Engine, Random } from \"random-js\";\nimport \"uniformize\";\n\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport {\n\tcreateCriticalCustom,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tEmptyObjectError,\n\tescapeRegex,\n\tFormulaError,\n\tNoStatisticsError,\n\treplaceExpByRandom,\n\treplaceFormulaInDice,\n\troll,\n\ttype StatisticalTemplate,\n\tTooManyDice,\n\ttemplateSchema,\n} from \".\";\nimport { isNumber, randomInt } from \"./utils\";\n\n/**\n * Verify if the provided dice work with random value\n * @param testDice {string}\n * @param allStats {Record<string,number>}\n * @param engine\n * @param pity\n */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet dice = testDice.trimEnd();\n\tif (allStats && Object.keys(allStats).length > 0) {\n\t\tconst names = Object.keys(allStats);\n\t\tfor (const name of names) {\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\t\tif (dice.standardize().match(regex)) {\n\t\t\t\tconst statValue = allStats[name];\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\n\t\t\t}\n\t\t}\n\t}\n\ttry {\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\n\t\treturn testDice;\n\t} catch (error) {\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\n\t}\n}\n\n/**\n * Generate a random dice and remove the formula (+ evaluate it)\n * Used for diceDamage only\n * @param value {string}\n * @param template {StatisticalTemplate}\n * @param engine\n * @returns\n */\nexport function diceRandomParse(\n\tvalue: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\n\tvalue = value.standardize();\n\tconst statNames = Object.keys(template.statistics);\n\tlet newDice = value;\n\tfor (const name of statNames) {\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\tif (value.match(regex)) {\n\t\t\tlet max: undefined | number;\n\t\t\tlet min: undefined | number;\n\t\t\tconst foundStat = template.statistics?.[name];\n\t\t\tif (foundStat) {\n\t\t\t\tmax = foundStat.max;\n\t\t\t\tmin = foundStat.min;\n\t\t\t}\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\n\t\t}\n\t}\n\treturn replaceFormulaInDice(newDice);\n}\n\n/**\n * Same as damageDice but for DiceType\n * @param dice {string}\n * @param template {StatisticalTemplate}\n * @param engine\n */\nexport function diceTypeRandomParse(\n\tdice: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tdice = replaceExpByRandom(dice);\n\tif (!template.statistics) return dice;\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\n\t\t(stat) => !template.statistics?.[stat].combinaison\n\t);\n\tif (!firstStatNotcombinaison) return dice;\n\tconst stats = template.statistics[firstStatNotcombinaison];\n\tconst { min, max } = stats;\n\tconst total = template.total || 100;\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\n}\n\n/**\n * Random the combinaison and evaluate it to check if everything is valid\n * @param combinaison {Record<string,string>}\n * @param stats {Record<string,number|number>}\n */\nexport function evalCombinaison(\n\tcombinaison: Record<string, string>,\n\tstats: Record<string, number | string>\n) {\n\tconst newStats: Record<string, number> = {};\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\n\t\t//replace the stats in formula\n\t\tlet formula = combin.standardize();\n\t\tfor (const [statName, value] of Object.entries(stats)) {\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\t\tformula = formula.replace(regex, value.toString());\n\t\t}\n\t\ttry {\n\t\t\tnewStats[stat] = evaluate(formula);\n\t\t} catch (error) {\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\n\t\t}\n\t}\n\treturn newStats;\n}\n\n/**\n * Evaluate one selected combinaison\n * @param combinaison {string}\n * @param stats {[name: string]: string|number}\n */\nexport function evalOneCombinaison(\n\tcombinaison: string,\n\tstats: Record<string, number | string>\n) {\n\tlet formula = combinaison.standardize();\n\tfor (const [statName, value] of Object.entries(stats)) {\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\tformula = formula.replace(regex, value.toString());\n\t}\n\ttry {\n\t\treturn evaluate(formula);\n\t} catch (error) {\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\n\t}\n}\n\nfunction convertNumber(number: string | number | undefined) {\n\tif (number === undefined || number === null) return undefined;\n\tif (\n\t\tnumber.toString().length === 0 ||\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\n\t)\n\t\treturn undefined;\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\n\treturn undefined;\n}\n\n/**\n * Parse the provided JSON and verify each field to check if everything could work when rolling\n * @param {unknown} template\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\n * @param engine\n * @returns {StatisticalTemplate}\n */\nexport function verifyTemplateValue(\n\ttemplate: unknown,\n\tverify = true,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): StatisticalTemplate {\n\tconst parsedTemplate = templateSchema.parse(template);\n\tconst { success, failure } = parsedTemplate.critical ?? {};\n\tconst criticicalVal = {\n\t\tsuccess: convertNumber(success),\n\t\tfailure: convertNumber(failure),\n\t};\n\tconst statistiqueTemplate: StatisticalTemplate = {\n\t\tdiceType: parsedTemplate.diceType,\n\t\tstatistics: parsedTemplate.statistics,\n\t\tcritical: criticicalVal,\n\t\ttotal: parsedTemplate.total,\n\t\tcharName: parsedTemplate.charName,\n\t\tdamage: parsedTemplate.damage,\n\t\tcustomCritical: parsedTemplate.customCritical,\n\t\tforceDistrib: parsedTemplate.forceDistrib,\n\t};\n\tif (!verify) return statistiqueTemplate;\n\tif (statistiqueTemplate.diceType) {\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\n\t\t\tthrow new DiceTypeError(\n\t\t\t\tstatistiqueTemplate.diceType,\n\t\t\t\t\"critical_dice_type\",\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\n\t\t\t);\n\t\t}\n\t\tconst cleanedDice = diceTypeRandomParse(\n\t\t\tstatistiqueTemplate.diceType,\n\t\t\tstatistiqueTemplate,\n\t\t\tengine\n\t\t);\n\t\tconst rolled = roll(cleanedDice, engine);\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\n\t}\n\tif (statistiqueTemplate.customCritical) {\n\t\tif (!statistiqueTemplate.diceType) {\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\n\t\t}\n\t\tconst customCritical = statistiqueTemplate.customCritical;\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\n\t\t\tconst cleanedDice = createCriticalCustom(\n\t\t\t\tstatistiqueTemplate.diceType!,\n\t\t\t\tcustom,\n\t\t\t\tstatistiqueTemplate,\n\t\t\t\tengine\n\t\t\t);\n\t\t\tconst rolled = roll(cleanedDice, engine);\n\t\t\tif (!rolled)\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\n\t\t}\n\t}\n\ttestDiceRegistered(statistiqueTemplate, engine);\n\ttestStatCombinaison(statistiqueTemplate, engine);\n\treturn statistiqueTemplate;\n}\n\n/**\n * Test each damage roll from the template.damage\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testDiceRegistered(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.damage) return;\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\n\tfor (const [name, dice] of Object.entries(template.damage)) {\n\t\tif (!dice) continue;\n\t\tconst diceReplaced = replaceExpByRandom(dice);\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\n\t\ttry {\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\n\t\t}\n\t}\n}\n\n/**\n * Test all combinaison with generated random value\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testStatCombinaison(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return;\n\tconst onlycombinaisonStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(\n\t\t\t([_, value]) => value.combinaison !== undefined\n\t\t)\n\t);\n\tconst allOtherStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\n\t);\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\n\tconst allStats = Object.keys(template.statistics).filter(\n\t\t(stat) => !template.statistics![stat].combinaison\n\t);\n\tif (allStats.length === 0) throw new NoStatisticsError();\n\tconst error = [];\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\n\t\tlet formula = value.combinaison as string;\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\n\t\t\tconst { max, min } = data;\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tconst regex = new RegExp(other, \"gi\");\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\n\t\t}\n\t\ttry {\n\t\t\tevaluate(formula);\n\t\t} catch (e) {\n\t\t\terror.push(stat);\n\t\t}\n\t}\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\n\treturn;\n}\n\n/**\n * Generate a random stat based on the template and the statistical min and max\n * @param {number|undefined} total\n * @param {number | undefined} max\n * @param {number | undefined} min\n * @param engine\n * @returns\n */\nexport function generateRandomStat(\n\ttotal: number | undefined = 100,\n\tmax?: number,\n\tmin?: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tlet randomStatValue = total + 1;\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\n\twhile (randomStatValue >= total || randomStatValue === 0) {\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\n\t\telse randomStatValue = randomInt(1, total, engine, random);\n\t}\n\treturn randomStatValue;\n}\n"],"mappings":"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","names":["SortOrder","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","diceResult","roll","import_rpg_dice_roller","import_mathjs","import_mathjs","evaluateRoll","import_mathjs","import_random_js","import_uniformize","import_rpg_dice_roller","cleanedDice"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/engine.ts","../src/errors.ts","../src/interfaces/index.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/roll.ts","../src/dice/bulk.ts","../src/dice/compare.ts","../src/utils.ts","../src/dice/exploding.ts","../src/dice/signs.ts","../src/dice/replace.ts","../src/dice/extract.ts","../src/dice/calculator.ts","../src/dice/pity.ts","../src/verify_template.ts"],"sourcesContent":["export * from \"./engine\";\r\nexport * from \"./errors\";\r\nexport * from \"./interfaces\";\r\nexport * from \"./interfaces/constant\";\r\nexport * from \"./interfaces/toJsonSchema\";\r\nexport * from \"./interfaces/zod\";\r\nexport * from \"./roll\";\r\nexport * from \"./utils\";\r\nexport * from \"./verify_template\";\r\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport type { Engine } from \"random-js\";\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","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 interface Resultat {\r\n\t/**\r\n\t * Original dice throw\r\n\t */\r\n\tdice: string;\r\n\t/**\r\n\t * Result of the dice throw\r\n\t */\r\n\tresult: string;\r\n\t/**\r\n\t * The comment that was added to the dice throw (if any)\r\n\t */\r\n\tcomment?: string;\r\n\t/**\r\n\t * The comparison made on the dice\r\n\t */\r\n\tcompare?: ComparedValue;\r\n\t/**\r\n\t * If any value was added to the dice throw\r\n\t */\r\n\tmodifier?: Modifier;\r\n\t/**\r\n\t * Total of the roll\r\n\t */\r\n\ttotal?: number;\r\n\tpityLogs?: number;\r\n\ttrivial?: boolean;\r\n}\r\n\r\nexport interface Compare {\r\n\t/**\r\n\t * Sign of the comparison\r\n\t */\r\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\";\r\n\t/**\r\n\t * Value of the comparison\r\n\t */\r\n\tvalue: number;\r\n\t/**\r\n\t * Indicate if the comparison is \"trivial\"\r\n\t * aka if the comparaison is always true or always false\r\n\t */\r\n\ttrivial?: boolean;\r\n}\r\n\r\n/**\r\n * Sign format for calculation of modifier\r\n */\r\nexport type Sign = \"+\" | \"-\" | \"*\" | \"/\" | \"%\" | \"^\" | \"**\";\r\n\r\nexport type ComparedValue = Compare & {\r\n\t/**\r\n\t * Original dice if the comparaison is made with a dice throw\r\n\t */\r\n\toriginalDice?: string;\r\n\t/**\r\n\t * Output of the dice throw\r\n\t */\r\n\trollValue?: string;\r\n};\r\n\r\nexport interface Modifier {\r\n\t/**\r\n\t * Sign of the modifier\r\n\t */\r\n\tsign?: Sign;\r\n\t/**\r\n\t * Value of the modifier\r\n\t * @TJS-type integer\r\n\t */\r\n\tvalue: number;\r\n}\r\n\r\n/**\r\n * Statistic object template\r\n */\r\nexport type Statistic = Record<\r\n\t/**\r\n\t * The name of the statistic\r\n\t * @TJS-type string\r\n\t */\r\n\tstring,\r\n\tStatEntry\r\n>;\r\n\r\ntype StatEntry = {\r\n\t/**\r\n\t * The value of the statistic that can take the stats\r\n\t * @TJS-type integer\r\n\t */\r\n\tmax?: number;\r\n\t/**\r\n\t * The minimal value of the statistic that can take the stats\r\n\t * @TJS-type integer\r\n\t */\r\n\tmin?: number;\r\n\t/**\r\n\t * The combinaison that can be made with ANOTHER statistic\r\n\t * Automatically disable the max/min value\r\n\t */\r\n\tcombinaison?: string;\r\n\t/**\r\n\t * Allow to exclude from roll selection in /dbroll!\r\n\t */\r\n\texclude?: boolean;\r\n};\r\n\r\n/**\r\n * @example\r\n * diceType: 1d20+$>=20\r\n * The dice throw will be 1d20 + statistique that must be >= 20\r\n * @example\r\n * diceType: 1d20<=$\r\n * The dice throw will be 1d20 that must be <= statistique\r\n */\r\nexport interface StatisticalTemplate {\r\n\t/** Allow to force the user to choose a name for them characters */\r\n\tcharName?: boolean;\r\n\t/**\r\n\t * The statistics that can be used in the dice throw\r\n\t * @maximum 25\r\n\t */\r\n\tstatistics?: Statistic;\r\n\t/**\r\n\t * A total can be set, it allows to calculate the total value of a future register member\r\n\t * If the sum of the value > total, the bot will send a message to the user to inform him that the total is exceeded and an error will be thrown\r\n\t * @note statistique that have a formula will be ignored from the total\r\n\t * @TJS-type integer\r\n\t */\r\n\ttotal?: number;\r\n\r\n\t/**\r\n\t * Force the distribition of all the points\r\n\t */\r\n\tforceDistrib?: boolean;\r\n\t/** A dice type in the notation supported by the bot */\r\n\tdiceType?: string;\r\n\t/**\r\n\t * How the success/echec will be done\r\n\t */\r\n\tcritical?: Critical;\r\n\t/**\r\n\t * Custom critical, allow to adjust the critical on a statistic, and set multiple critical value\r\n\t * @maximum 22\r\n\t */\r\n\tcustomCritical?: CustomCriticalMap;\r\n\r\n\t/** Special dice for damage\r\n\t * @maximum 25\r\n\t * */\r\n\tdamage?: Record<string, string>;\r\n}\r\nexport type CustomCriticalMap = Record<string, CustomCritical>;\r\n\r\n/**\r\n * If the result can be considered as a critical\r\n * Critical is compared to the \"natural\" dice result, so any modifier doesn't count\r\n */\r\nexport interface Critical {\r\n\t/**\r\n\t * The value that will be considered as a success\r\n\t * Can only be compared strictly with the natural dice result\r\n\t * @TJS-type integer\r\n\t */\r\n\tsuccess?: number;\r\n\t/**\r\n\t * The value that will be considered as a failure.\r\n\t * Can only be compared strictly with the natural dice result\r\n\t * @TJS-type integer\r\n\t */\r\n\tfailure?: number;\r\n}\r\n\r\nexport interface CustomCritical {\r\n\t/**\r\n\t * Sign of the comparison\r\n\t */\r\n\tsign: \"<\" | \">\" | \"<=\" | \">=\" | \"!=\" | \"==\";\r\n\t/**\r\n\t * Can be a simple value, or a formula, including the statistics with $\r\n\t * @example round($/2)\r\n\t */\r\n\tvalue: string;\r\n\t/**\r\n\t * If \"true\", the comparison will be made on the natural dice result, without any modifier, including the statistics bonus if any.\r\n\t */\r\n\tonNaturalDice?: boolean;\r\n\t/**\r\n\t * Allow to use the custom critical on dbD command (damage)\r\n\t * @default false\r\n\t */\r\n\taffectSkill?: boolean;\r\n}\r\n\r\nexport enum SortOrder {\r\n\tAscending = \"sa\",\r\n\tDescending = \"sd\",\r\n\tNone = \"none\",\r\n}\r\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\r\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\r\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\r\n// Use negative lookbehind to check for ![<>] before any comparison operator\r\nexport const SIGN_REGEX =\r\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\r\nexport const SIGN_REGEX_SPACE =\r\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\r\n\r\nexport const SYMBOL_DICE = \"&\";\r\n\r\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\r\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\r\n","/**\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 { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\n\r\nimport {\r\n\tcompareSignFormule,\r\n\tcountExplodingSuccesses,\r\n\ttype ExplodingSuccess,\r\n\textractValuesFromOutput,\r\n\tfixParenthesis,\r\n\tformatComment,\r\n\tgetCompare,\r\n\tgetModifier,\r\n\tgetRollBounds,\r\n\thandleBulkRolls,\r\n\thandlePitySystem,\r\n\tinverseSign,\r\n\tisTrivialComparison,\r\n\tmatchComparison,\r\n\tnormalizeExplodingSuccess,\r\n\tprepareDice,\r\n\treplaceText,\r\n\treplaceUnwantedText,\r\n\tsetSortOrder,\r\n} from \"./dice\";\r\nimport { DiceTypeError } from \"./errors\";\r\nimport { type Compare, type ComparedValue, type Resultat, SortOrder } from \"./interfaces\";\r\nimport {\r\n\tCOMMENT_REGEX,\r\n\tOPTIONAL_COMMENT,\r\n\tSIGN_REGEX_SPACE,\r\n\tSYMBOL_DICE,\r\n} from \"./interfaces/constant\";\r\n\r\n/**\r\n * Parse the string provided and turn it as a readable dice for dice parser\r\n * @param {string} dice The dice string to parse and roll\r\n * @param {Engine|null} engine The random engine to use, default to nodeCrypto\r\n * @param {boolean} pity Whether to enable pity system (reroll on failure) or not\r\n * @param {boolean} sort Whether to sort the dice results or not\r\n * @returns {Resultat|undefined} The result of the roll\r\n */\r\nexport function roll(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean,\r\n\tsort?: SortOrder\r\n): Resultat | undefined {\r\n\tif (sort === SortOrder.None) sort = undefined;\r\n\r\n\tconst prepared = prepareDice(dice);\r\n\tif (!prepared.dice.includes(\"d\")) return undefined;\r\n\r\n\t// Handle shared rolls\r\n\tif (prepared.isSharedRoll) {\r\n\t\treturn sharedRolls(\r\n\t\t\tprepared.dice,\r\n\t\t\tengine,\r\n\t\t\tpity,\r\n\t\t\tprepared.explodingSuccess,\r\n\t\t\tprepared.diceDisplay,\r\n\t\t\tprepared.isSharedCurly\r\n\t\t);\r\n\t}\r\n\r\n\tlet processedDice = fixParenthesis(prepared.dice);\r\n\tconst modificator = getModifier(processedDice);\r\n\r\n\t// Extract compare BEFORE rolling, but NOT for curly bulk rolls\r\n\tconst compareRegex = processedDice.match(SIGN_REGEX_SPACE);\r\n\tlet compare: ComparedValue | undefined;\r\n\tif (compareRegex && !prepared.isCurlyBulk) {\r\n\t\tconst compareResult = getCompare(processedDice, compareRegex, engine, pity);\r\n\t\tprocessedDice = compareResult.dice;\r\n\t\tcompare = compareResult.compare;\r\n\t}\r\n\r\n\t// For simple curly braces, wrap the diceDisplay with braces\r\n\tlet finalDiceDisplay = prepared.diceDisplay;\r\n\tif (prepared.isSimpleCurly && !prepared.diceDisplay.startsWith(\"{\")) {\r\n\t\tfinalDiceDisplay = `{${prepared.diceDisplay}}`;\r\n\t}\r\n\r\n\t// Handle bulk rolls\r\n\tconst bulkProcessContent = prepared.isCurlyBulk ? prepared.bulkContent : processedDice;\r\n\tif (bulkProcessContent.match(/\\d+?#(.*)/)) {\r\n\t\treturn handleBulkRolls(\r\n\t\t\tprocessedDice,\r\n\t\t\tprepared.isCurlyBulk,\r\n\t\t\tprepared.bulkContent,\r\n\t\t\tcompare,\r\n\t\t\tprepared.explodingSuccess,\r\n\t\t\tprepared.diceDisplay,\r\n\t\t\tengine,\r\n\t\t\tsort\r\n\t\t);\r\n\t}\r\n\r\n\t// Standard roll\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\tlet diceWithoutComment = processedDice.replace(COMMENT_REGEX, \"\").trimEnd();\r\n\tdiceWithoutComment = setSortOrder(diceWithoutComment, sort);\r\n\r\n\tlet diceRoll: DiceRoll | DiceRoll[];\r\n\ttry {\r\n\t\tdiceRoll = roller.roll(diceWithoutComment);\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\r\n\t}\r\n\r\n\t// Update compare.trivial after rolling\r\n\tif (compare && diceRoll) {\r\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\r\n\t\tconst trivial = isTrivialComparison(\r\n\t\t\tcurrentRoll.maxTotal,\r\n\t\t\tcurrentRoll.minTotal,\r\n\t\t\tcompare\r\n\t\t);\r\n\t\tcompare.trivial = trivial ? true : undefined;\r\n\t}\r\n\r\n\tconst commentMatch = processedDice.match(COMMENT_REGEX);\r\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\r\n\r\n\t// Handle pity system\r\n\tlet rerollCount = 0;\r\n\tlet pityResult: Resultat | undefined;\r\n\tif (pity && compare) {\r\n\t\tconst pityData = handlePitySystem(\r\n\t\t\tdiceWithoutComment,\r\n\t\t\tcompare,\r\n\t\t\tdiceRoll,\r\n\t\t\troller,\r\n\t\t\tengine\r\n\t\t);\r\n\t\trerollCount = pityData.rerollCount;\r\n\t\tpityResult = pityData.result;\r\n\t\tif (pityResult) {\r\n\t\t\treturn {\r\n\t\t\t\t...pityResult,\r\n\t\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\r\n\t\t\t\tcomment,\r\n\t\t\t\tcompare,\r\n\t\t\t\tmodifier: modificator,\r\n\t\t\t\tpityLogs: rerollCount,\r\n\t\t\t\ttrivial: pityResult.trivial ?? (compare?.trivial ? true : undefined),\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\tlet resultOutput = replaceUnwantedText(roller.output);\r\n\r\n\t// Handle exploding success\r\n\tif (prepared.explodingSuccess) {\r\n\t\tconst successes = countExplodingSuccesses(\r\n\t\t\tdiceRoll,\r\n\t\t\tprepared.explodingSuccess.sign,\r\n\t\t\tprepared.explodingSuccess.value\r\n\t\t);\r\n\t\tresultOutput = resultOutput\r\n\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successes}`)\r\n\t\t\t.replace(\r\n\t\t\t\tprepared.explodingSuccess.normalizedSegment,\r\n\t\t\t\tprepared.explodingSuccess.originalSegment\r\n\t\t\t);\r\n\r\n\t\treturn {\r\n\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : prepared.diceDisplay,\r\n\t\t\tresult: resultOutput,\r\n\t\t\tcomment,\r\n\t\t\tcompare: compare ? compare : undefined,\r\n\t\t\tmodifier: modificator,\r\n\t\t\ttotal: successes,\r\n\t\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\r\n\t\t\ttrivial: compare?.trivial ? true : undefined,\r\n\t\t};\r\n\t}\r\n\r\n\treturn {\r\n\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\r\n\t\tresult: resultOutput,\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\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\r\n\t\ttrivial: compare?.trivial ? true : undefined,\r\n\t};\r\n}\r\n\r\nfunction sharedRolls(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean,\r\n\texplodingSuccessMain?: ExplodingSuccess,\r\n\tdiceDisplay?: string,\r\n\tisSharedCurly?: boolean\r\n): Resultat | undefined {\r\n\t// If not provided (call from elsewhere), try to detect\r\n\tif (!explodingSuccessMain)\r\n\t\texplodingSuccessMain = normalizeExplodingSuccess(dice.split(\";\")[0] ?? dice);\r\n\r\n\tif (explodingSuccessMain) {\r\n\t\t// Use normalized dice for internal processing but keep original for display\r\n\t\tdice = dice.replace(explodingSuccessMain.originalSegment, \"!\");\r\n\t}\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\tconst displayDice = diceDisplay ?? explodingSuccessMain?.originalDice ?? split[0];\r\n\tlet diceMain = fixParenthesis(split[0]);\r\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\r\n\tconst comments = formatComment(diceMain);\r\n\t// Remove comments before checking for hidden dice (parentheses)\r\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\r\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\r\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\r\n\tlet hidden = false;\r\n\tif (toHide?.dice) {\r\n\t\tdiceMain = toHide.dice;\r\n\t\thidden = true;\r\n\t} else if (toHide) {\r\n\t\tdiceMain = \"1d1\";\r\n\t\thidden = true;\r\n\t} else {\r\n\t\t// No hidden dice, use the dice without comments\r\n\t\tdiceMain = diceMainWithoutComments;\r\n\t}\r\n\tconst rollBounds = getRollBounds(diceMain, engine);\r\n\tlet diceResult = roll(diceMain, engine, pity);\r\n\tif (!diceResult || !diceResult.total) {\r\n\t\tif (hidden) {\r\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\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\r\n\t// If we had a double-sign exploding, recompute successes from the first segment output\r\n\tif (explodingSuccessMain && diceResult.result) {\r\n\t\tconst values = extractValuesFromOutput(diceResult.result);\r\n\t\tdiceResult.total = values.filter((v) =>\r\n\t\t\tmatchComparison(explodingSuccessMain!.sign, v, explodingSuccessMain!.value)\r\n\t\t).length;\r\n\t}\r\n\tlet aggregatedCompare = diceResult.compare;\r\n\tlet hasTrivialComparison = diceResult.compare?.trivial === true;\r\n\tresults.push(`※ ${comments}${diceResult.result}`);\r\n\tlet total = diceResult.total;\r\n\tdiceResult.comment = mainComment;\r\n\tif (!total) {\r\n\t\treturn {\r\n\t\t\tdice: displayDice,\r\n\t\t\tresult: results.join(\";\"),\r\n\t\t\tcomment: mainComment,\r\n\t\t\tcompare: aggregatedCompare,\r\n\t\t\tmodifier: diceResult.modifier,\r\n\t\t\ttotal,\r\n\t\t\ttrivial: hasTrivialComparison ? true : undefined,\r\n\t\t};\r\n\t}\r\n\tfor (let element of split.slice(1)) {\r\n\t\tconst comment = formatComment(element);\r\n\t\telement = element\r\n\t\t\t.replaceAll(commentsRegex, \"\")\r\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\r\n\t\t\t.trim();\r\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\r\n\t\t//remove comments\r\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\r\n\t\tif (compareRegex) {\r\n\t\t\tif (isSharedCurly) {\r\n\t\t\t\t// For curly braces shared rolls, display success count instead of comparison details\r\n\t\t\t\tconst compareResult = compareSignFormule(\r\n\t\t\t\t\ttoRoll,\r\n\t\t\t\t\tcompareRegex,\r\n\t\t\t\t\telement,\r\n\t\t\t\t\tdiceResult,\r\n\t\t\t\t\tengine,\r\n\t\t\t\t\tpity,\r\n\t\t\t\t\trollBounds\r\n\t\t\t\t);\r\n\t\t\t\t// Count success: 1 if comparison is true, 0 if false\r\n\t\t\t\tconst { diceAll } = replaceText(element, diceResult.total, diceResult.dice);\r\n\t\t\t\tlet successCount = 0;\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconst evaluated = evaluate(toRoll);\r\n\t\t\t\t\tsuccessCount = evaluated ? 1 : 0;\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\t// If evaluation fails, try with roll\r\n\t\t\t\t\tconst evaluated = roll(toRoll, engine, pity) as Resultat | undefined;\r\n\t\t\t\t\tsuccessCount = (evaluated?.total ?? 0) ? 1 : 0;\r\n\t\t\t\t}\r\n\t\t\t\tresults.push(`※ ${comment}${diceAll}: ${successCount}`);\r\n\t\t\t\ttotal += successCount;\r\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\r\n\t\t\t\t\taggregatedCompare = compareResult.compare;\r\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\r\n\t\t\t} else {\r\n\t\t\t\tconst compareResult = compareSignFormule(\r\n\t\t\t\t\ttoRoll,\r\n\t\t\t\t\tcompareRegex,\r\n\t\t\t\t\telement,\r\n\t\t\t\t\tdiceResult,\r\n\t\t\t\t\tengine,\r\n\t\t\t\t\tpity,\r\n\t\t\t\t\trollBounds\r\n\t\t\t\t);\r\n\t\t\t\ttoRoll = compareResult.dice;\r\n\t\t\t\tresults.push(compareResult.results);\r\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\r\n\t\t\t\t\taggregatedCompare = compareResult.compare;\r\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\r\n\t\t\t}\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, pity);\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\t\tif (!aggregatedCompare && evaluated.compare)\r\n\t\t\t\t\t\taggregatedCompare = evaluated.compare;\r\n\t\t\t\t\tif (evaluated.compare?.trivial) hasTrivialComparison = true;\r\n\t\t\t\t} else 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: displayDice,\r\n\t\tresult: results.join(\";\"),\r\n\t\tcomment: mainComment,\r\n\t\tcompare:\r\n\t\t\thasTrivialComparison && aggregatedCompare\r\n\t\t\t\t? { ...aggregatedCompare, trivial: true }\r\n\t\t\t\t: aggregatedCompare,\r\n\t\tmodifier: diceResult.modifier,\r\n\t\ttotal,\r\n\t\ttrivial: hasTrivialComparison ? true : undefined,\r\n\t};\r\n}\r\n\r\nexport function 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\tpity?: boolean\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, pity) 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","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport { DiceTypeError } from \"../errors\";\r\nimport type { Compare, ComparedValue, Resultat, SortOrder } from \"../interfaces\";\r\nimport { COMMENT_REGEX, SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\r\nimport { isTrivialComparison } from \"./compare\";\r\nimport {\r\n\tcountExplodingSuccesses,\r\n\tEXPLODING_SUCCESS_REGEX,\r\n\ttype ExplodingSuccess,\r\n} from \"./exploding\";\r\nimport { extractValuesFromOutput, getModifier, setSortOrder } from \"./extract\";\r\nimport { replaceUnwantedText } from \"./replace\";\r\nimport { matchComparison } from \"./signs\";\r\n\r\n/**\r\n * Gère les lancers en masse (bulk rolls)\r\n */\r\nexport function handleBulkRolls(\r\n\tdice: string,\r\n\tisCurlyBulk: boolean,\r\n\tbulkContent: string,\r\n\tcompare: ComparedValue | undefined,\r\n\texplodingSuccess: ExplodingSuccess | undefined,\r\n\tdiceDisplay: string,\r\n\tengine: Engine | null,\r\n\tsort?: SortOrder\r\n): Resultat {\r\n\tconst bulkProcessContent = isCurlyBulk ? bulkContent : dice;\r\n\tconst diceArray = bulkProcessContent.split(\"#\");\r\n\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\r\n\tlet diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\r\n\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\r\n\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\r\n\r\n\tlet curlyCompare: Compare | undefined;\r\n\tif (isCurlyBulk) {\r\n\t\tconst curlyCompareRegex = diceToRoll.match(SIGN_REGEX_SPACE);\r\n\t\tif (curlyCompareRegex) {\r\n\t\t\tconst compareSign = curlyCompareRegex[0].match(SIGN_REGEX)?.[0];\r\n\t\t\tconst compareValue = curlyCompareRegex[2];\r\n\t\t\tif (compareSign && compareValue) {\r\n\t\t\t\tcurlyCompare = {\r\n\t\t\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\r\n\t\t\t\t\tvalue: Number.parseInt(compareValue, 10),\r\n\t\t\t\t};\r\n\t\t\t\tdiceToRoll = diceToRoll.replace(SIGN_REGEX_SPACE, \"\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tdiceToRoll = setSortOrder(diceToRoll, sort);\r\n\r\n\tconst activeCompare: Compare | undefined =\r\n\t\tcompare ||\r\n\t\tcurlyCompare ||\r\n\t\t(explodingSuccess\r\n\t\t\t? ({ sign: explodingSuccess.sign, value: explodingSuccess.value } as Compare)\r\n\t\t\t: undefined);\r\n\r\n\tif (activeCompare) {\r\n\t\treturn handleBulkRollsWithComparison(\r\n\t\t\tnumberOfDice,\r\n\t\t\tdiceToRoll,\r\n\t\t\tcomments,\r\n\t\t\tactiveCompare,\r\n\t\t\texplodingSuccess,\r\n\t\t\tdiceDisplay,\r\n\t\t\tisCurlyBulk,\r\n\t\t\tcurlyCompare,\r\n\t\t\tcompare,\r\n\t\t\tengine\r\n\t\t);\r\n\t}\r\n\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\r\n\tfor (let i = 0; i < numberOfDice; i++) {\r\n\t\ttry {\r\n\t\t\troller.roll(diceToRoll);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\r\n\t\t}\r\n\t}\r\n\r\n\tconst finalDice = isCurlyBulk ? `{${diceToRoll}}` : diceToRoll;\r\n\tconst modificator = getModifier(dice);\r\n\r\n\treturn {\r\n\t\tdice: finalDice,\r\n\t\tresult: replaceUnwantedText(roller.output),\r\n\t\tcomment: comments,\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\n/**\r\n * Gère les lancers en masse avec comparaison\r\n */\r\nfunction handleBulkRollsWithComparison(\r\n\tnumberOfDice: number,\r\n\tdiceToRoll: string,\r\n\tcomments: string | undefined,\r\n\tactiveCompare: Compare,\r\n\texplodingSuccess: ExplodingSuccess | undefined,\r\n\tdiceDisplay: string,\r\n\tisCurlyBulk: boolean,\r\n\tcurlyCompare: Compare | undefined,\r\n\tcompare: ComparedValue | undefined,\r\n\tengine: Engine | null\r\n): Resultat {\r\n\tconst results: string[] = [];\r\n\tlet successCount = 0;\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\tlet trivialComparisonDetected = false;\r\n\r\n\tconst formatOutput = (output: string, addStar: boolean) => {\r\n\t\tconst formatted =\r\n\t\t\taddStar && isCurlyBulk\r\n\t\t\t\t? output.replace(\r\n\t\t\t\t\t\t/\\[([^\\]]+)\\]/,\r\n\t\t\t\t\t\t(_m, content) =>\r\n\t\t\t\t\t\t\t`[${content\r\n\t\t\t\t\t\t\t\t.split(\",\")\r\n\t\t\t\t\t\t\t\t.map((d: string) => `${d.trim()}*`)\r\n\t\t\t\t\t\t\t\t.join(\", \")}]`\r\n\t\t\t\t\t)\r\n\t\t\t\t: output;\r\n\t\treturn curlyCompare\r\n\t\t\t? formatted.replace(/^([^:]+):/, `$1${curlyCompare.sign}${curlyCompare.value}:`)\r\n\t\t\t: formatted;\r\n\t};\r\n\r\n\tfor (let i = 0; i < numberOfDice; i++) {\r\n\t\ttry {\r\n\t\t\tconst individualRoll = roller.roll(diceToRoll);\r\n\t\t\tconst rollInstance = Array.isArray(individualRoll)\r\n\t\t\t\t? individualRoll[0]\r\n\t\t\t\t: individualRoll;\r\n\r\n\t\t\tif (!trivialComparisonDetected && activeCompare) {\r\n\t\t\t\tconst { maxTotal, minTotal } = rollInstance;\r\n\t\t\t\ttrivialComparisonDetected = isTrivialComparison(\r\n\t\t\t\t\tmaxTotal,\r\n\t\t\t\t\tminTotal,\r\n\t\t\t\t\tactiveCompare\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tconst rollOutput = rollInstance.output;\r\n\r\n\t\t\tif (explodingSuccess) {\r\n\t\t\t\tconst successesForRoll = countExplodingSuccesses(\r\n\t\t\t\t\trollInstance,\r\n\t\t\t\t\texplodingSuccess.sign,\r\n\t\t\t\t\texplodingSuccess.value\r\n\t\t\t\t);\r\n\t\t\t\tsuccessCount += successesForRoll;\r\n\r\n\t\t\t\tlet formattedRollOutput = rollOutput\r\n\t\t\t\t\t.replace(explodingSuccess.normalizedSegment, explodingSuccess.originalSegment)\r\n\t\t\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successesForRoll}`);\r\n\t\t\t\tformattedRollOutput = formatOutput(formattedRollOutput, false);\r\n\t\t\t\tresults.push(formattedRollOutput);\r\n\t\t\t} else {\r\n\t\t\t\tconst rollTotal = rollInstance.total;\r\n\t\t\t\tconst isSuccess = evaluate(\r\n\t\t\t\t\t`${rollTotal}${activeCompare.sign}${activeCompare.value}`\r\n\t\t\t\t);\r\n\r\n\t\t\t\tif (isSuccess) successCount++;\r\n\t\t\t\tresults.push(formatOutput(rollOutput, isSuccess));\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\r\n\t\t}\r\n\t}\r\n\r\n\tif (explodingSuccess) {\r\n\t\tconst signSource = explodingSuccess?.originalDice ?? diceDisplay;\r\n\t\tconst explodingMatch = signSource.match(EXPLODING_SUCCESS_REGEX);\r\n\t\tif (explodingMatch) {\r\n\t\t\tconst [, doubledSignRaw, valueStr] = explodingMatch;\r\n\t\t\tlet doubledSign: string;\r\n\t\t\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\r\n\t\t\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\r\n\t\t\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\r\n\r\n\t\t\tconst signMap: Record<string, Compare[\"sign\"]> = {\r\n\t\t\t\t\">>\": \">\",\r\n\t\t\t\t\"<<\": \"<\",\r\n\t\t\t\t\">=\": \">=\",\r\n\t\t\t\t\"<=\": \"<=\",\r\n\t\t\t\t\"==\": \"=\",\r\n\t\t\t\t\"!==\": \"!=\",\r\n\t\t\t\t\"!!==\": \"=\",\r\n\t\t\t};\r\n\t\t\tconst mappedSign = signMap[doubledSign];\r\n\t\t\tconst mappedValue = Number.parseFloat(valueStr);\r\n\r\n\t\t\tif (mappedSign && !Number.isNaN(mappedValue)) {\r\n\t\t\t\tconst resultsString = replaceUnwantedText(results.join(\"; \"));\r\n\t\t\t\tconst flatValues = resultsString\r\n\t\t\t\t\t.split(\";\")\r\n\t\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment));\r\n\r\n\t\t\t\tif (mappedSign === \"!=\") {\r\n\t\t\t\t\tconst equalsCount = flatValues.filter((val) => val === mappedValue).length;\r\n\t\t\t\t\tsuccessCount = flatValues.length - equalsCount;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tsuccessCount = flatValues.filter((val) =>\r\n\t\t\t\t\t\tmatchComparison(mappedSign, val, mappedValue)\r\n\t\t\t\t\t).length;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (compare && trivialComparisonDetected) compare.trivial = true;\r\n\r\n\tconst finalDice = isCurlyBulk\r\n\t\t? `{${diceToRoll}${curlyCompare?.sign}${curlyCompare?.value}}`\r\n\t\t: diceToRoll;\r\n\r\n\tconst resultOutput = replaceUnwantedText(results.join(\"; \"));\r\n\tconst finalTotal = explodingSuccess\r\n\t\t? resultOutput\r\n\t\t\t\t.split(\";\")\r\n\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment))\r\n\t\t\t\t.filter((val) =>\r\n\t\t\t\t\tmatchComparison(explodingSuccess.sign, val, explodingSuccess.value)\r\n\t\t\t\t).length\r\n\t\t: successCount;\r\n\r\n\tconst modificator = getModifier(diceDisplay);\r\n\r\n\treturn {\r\n\t\tdice: explodingSuccess ? diceDisplay : finalDice,\r\n\t\tresult: resultOutput,\r\n\t\tcomment: comments,\r\n\t\tcompare: isCurlyBulk ? undefined : compare,\r\n\t\tmodifier: modificator,\r\n\t\ttotal: finalTotal,\r\n\t\ttrivial: trivialComparisonDetected ? true : undefined,\r\n\t};\r\n}\r\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport type { ComparedValue } from \"../interfaces\";\r\nimport { SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\r\nimport { roll } from \"../roll\";\r\nimport { isNumber } from \"../utils\";\r\n\r\n/**\r\n * Check if a comparison is trivial (always true or always false)\r\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\r\n * @param maxValue Maximum possible value from the dice roll\r\n * @param minValue Minimum possible value from the dice roll\r\n * @param compare The comparison object\r\n * @returns true if the comparison is trivial (always true or always false)\r\n */\r\nexport function isTrivialComparison(\r\n\tmaxValue: number,\r\n\tminValue: number,\r\n\tcompare: ComparedValue\r\n): boolean {\r\n\t// Check if comparison can never succeed (always false)\r\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\r\n\r\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\r\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\r\n\r\n\t// Trivial if it can never succeed OR can never fail\r\n\treturn !canSucceed || !canFail;\r\n}\r\n\r\n/**\r\n * Check if a comparison can theoretically fail given roll bounds\r\n * @param maxRollValue Maximum possible roll value\r\n * @param compare The comparison object\r\n * @param minRollValue Minimum possible roll value (defaults to 1)\r\n * @returns true if the comparison can fail at least once\r\n */\r\nexport function canComparisonFail(\r\n\tmaxRollValue: number,\r\n\tcompare: ComparedValue,\r\n\tminRollValue = 1\r\n): boolean {\r\n\tswitch (compare.sign) {\r\n\t\tcase \">\":\r\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\r\n\t\tcase \">=\":\r\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\r\n\t\tcase \"<\":\r\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\r\n\t\tcase \"<=\":\r\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\r\n\t\tcase \"=\":\r\n\t\tcase \"==\":\r\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\r\n\t\tcase \"!=\":\r\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\r\n\t\tdefault:\r\n\t\t\treturn true;\r\n\t}\r\n}\r\n\r\nexport function rollCompare(\r\n\tvalue: unknown,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean\r\n) {\r\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\r\n\t// Handle empty value or string - return 0 as default\r\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\r\n\t\treturn { value: 0, diceResult: value as string };\r\n\t}\r\n\tconst rollComp = roll(value as string, engine, pity);\r\n\tif (!rollComp?.total) {\r\n\t\t//not a dice throw\r\n\t\ttry {\r\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\r\n\t\t} catch (error) {\r\n\t\t\t// If evaluate fails, return 0\r\n\t\t\treturn { value: 0, diceResult: value as string };\r\n\t\t}\r\n\t}\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\nexport function getCompare(\r\n\tdice: string,\r\n\tcompareRegex: RegExpMatchArray,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean\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 (\r\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\r\n\t)\r\n\t\treturn { dice, compare: undefined };\r\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\r\n\tlet compare: ComparedValue;\r\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\r\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\r\n\tconst calc = compareRegex[2];\r\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\r\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\r\n\r\n\tif (sign) {\r\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\r\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\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, pity);\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\r\n\treturn { dice, compare };\r\n}\r\n\r\n/**\r\n * Check if a comparison can theoretically succeed given a maximum roll value\r\n * @example\r\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\r\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\r\n */\r\nexport function canComparisonSucceed(\r\n\tmaxRollValue: number,\r\n\tcompare: ComparedValue,\r\n\tminRollValue?: number\r\n): boolean {\r\n\tswitch (compare.sign) {\r\n\t\tcase \">\":\r\n\t\t\treturn maxRollValue > compare.value;\r\n\t\tcase \">=\":\r\n\t\t\treturn maxRollValue >= compare.value;\r\n\t\tcase \"<\":\r\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\r\n\t\tcase \"<=\":\r\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\r\n\t\tcase \"=\":\r\n\t\tcase \"==\":\r\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\r\n\t\tcase \"!=\":\r\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\r\n\t\tdefault:\r\n\t\t\treturn true;\r\n\t}\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport \"uniformize\";\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport {\r\n\ttype CustomCritical,\r\n\tDiceTypeError,\r\n\tdiceTypeRandomParse,\r\n\tFormulaError,\r\n\tSIGN_REGEX_SPACE,\r\n\ttype StatisticalTemplate,\r\n} 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\r\n\t\t\t\t// Check for dice notation patterns like \"1dstat1\" or \"dstat1\"\r\n\t\t\t\tconst diceMatch = /^(\\d*)d(.+)$/i.exec(tokenStd);\r\n\t\t\t\tif (diceMatch) {\r\n\t\t\t\t\tconst diceCount = diceMatch[1] || \"\";\r\n\t\t\t\t\tconst afterD = diceMatch[2];\r\n\t\t\t\t\tlet foundStatAfterD = false;\r\n\t\t\t\t\tfor (const key of statKeys) {\r\n\t\t\t\t\t\tconst keyStd = key.standardize();\r\n\t\t\t\t\t\tif (afterD === keyStd) {\r\n\t\t\t\t\t\t\tresult += `${diceCount}d${stats[key].toString()}`;\r\n\t\t\t\t\t\t\tfoundStatAfterD = true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (foundStatAfterD) {\r\n\t\t\t\t\t\tlastIndex = tokenRegex.lastIndex;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\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 (tokenStd === keyStd) {\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(/\\$\\B/g, 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/**\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\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","import type { DiceRoll } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Compare } from \"../interfaces\";\r\nimport { matchComparison } from \"./signs\";\r\n\r\nexport type ExplodingSuccess = {\r\n\tdice: string;\r\n\toriginalDice: string;\r\n\tsign: Compare[\"sign\"];\r\n\tvalue: number;\r\n\tnormalizedSegment: string;\r\n\toriginalSegment: string;\r\n};\r\n\r\nexport const EXPLODING_SUCCESS_REGEX =\r\n\t/(!(?:>>=|<<=|!==|!!==|>>|<<|==|!=))(-?\\d+(?:\\.\\d+)?)/;\r\n\r\nexport function normalizeExplodingSuccess(dice: string): ExplodingSuccess | undefined {\r\n\tconst match = dice.match(EXPLODING_SUCCESS_REGEX);\r\n\tif (!match) return undefined;\r\n\r\n\tconst [, doubledSignRaw, valueStr] = match;\r\n\tlet doubledSign: string;\r\n\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\r\n\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\r\n\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\r\n\tconst signMap: Record<string, Compare[\"sign\"]> = {\r\n\t\t\">>\": \">\",\r\n\t\t\"<<\": \"<\",\r\n\t\t\">>=\": \">=\",\r\n\t\t\"<<=\": \"<=\",\r\n\t\t\"==\": \"=\",\r\n\t\t\"!==\": \"!=\",\r\n\t\t\"!!==\": \"=\",\r\n\t};\r\n\r\n\tconst normalizedSign = signMap[doubledSign];\r\n\tif (!normalizedSign) return undefined;\r\n\tlet parsedValue = Number.parseFloat(valueStr);\r\n\tif (Number.isNaN(parsedValue)) {\r\n\t\ttry {\r\n\t\t\tparsedValue = Number.parseFloat(evaluate(valueStr) as unknown as string);\r\n\t\t} catch (_error) {\r\n\t\t\tparsedValue = 0;\r\n\t\t}\r\n\t}\r\n\r\n\t// Remove comparison for the actual explode mechanic so it uses default explode\r\n\tconst normalizedSegment = \"!\";\r\n\tconst replacedDice = dice.replace(match[0], normalizedSegment);\r\n\r\n\treturn {\r\n\t\tdice: replacedDice,\r\n\t\toriginalDice: dice,\r\n\t\tsign: normalizedSign,\r\n\t\tvalue: parsedValue,\r\n\t\tnormalizedSegment,\r\n\t\toriginalSegment: match[0],\r\n\t};\r\n}\r\n\r\nexport function countExplodingSuccesses(\r\n\tdiceRoll: DiceRoll | DiceRoll[],\r\n\tsign: Compare[\"sign\"],\r\n\tvalue: number\r\n): number {\r\n\tconst rollsArray = Array.isArray(diceRoll) ? diceRoll : [diceRoll];\r\n\tconst flatValues: number[] = [];\r\n\r\n\tfor (const dr of rollsArray) {\r\n\t\tconst groups = (dr as DiceRoll).rolls ?? [];\r\n\t\tfor (const group of groups as unknown as Array<{\r\n\t\t\trolls?: Array<{ value?: number }>;\r\n\t\t}>) {\r\n\t\t\tconst innerRolls = group.rolls ?? [];\r\n\t\t\tfor (const roll of innerRolls) {\r\n\t\t\t\tif (typeof roll.value === \"number\") flatValues.push(roll.value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn flatValues.reduce(\r\n\t\t(acc, current) => acc + (matchComparison(sign, current, value) ? 1 : 0),\r\n\t\t0\r\n\t);\r\n}\r\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport type { Compare, Resultat } from \"../interfaces\";\r\nimport { replaceInFormula, roll } from \"../roll\";\r\nimport { getCompare, isTrivialComparison } from \"./compare\";\r\nimport { replaceText } from \"./replace\";\r\n\r\nexport function matchComparison(sign: Compare[\"sign\"], val: number, value: number) {\r\n\tswitch (sign) {\r\n\t\tcase \">\":\r\n\t\t\treturn val > value;\r\n\t\tcase \">=\":\r\n\t\t\treturn val >= value;\r\n\t\tcase \"<\":\r\n\t\t\treturn val < value;\r\n\t\tcase \"<=\":\r\n\t\t\treturn val <= value;\r\n\t\tcase \"=\":\r\n\t\tcase \"==\":\r\n\t\t\treturn val === value;\r\n\t\tcase \"!=\":\r\n\t\t\treturn val !== value;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport function 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\nexport function 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\tpity?: boolean,\r\n\trollBounds?: { min: number; max: number }\r\n): { dice: string; results: string; compare?: Compare; trivial: boolean } {\r\n\tlet results = \"\";\r\n\tlet trivial = false;\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, pity);\r\n\t}\r\n\tif (typeof res === \"boolean\") {\r\n\t\tconst detectedTrivial =\r\n\t\t\trollBounds && compareResult.compare\r\n\t\t\t\t? isTrivialComparison(rollBounds.max, rollBounds.min, compareResult.compare)\r\n\t\t\t\t: false;\r\n\t\tif (detectedTrivial && compareResult.compare) compareResult.compare.trivial = true;\r\n\t\tif (detectedTrivial) trivial = true;\r\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\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\tif (diceResult.compare.trivial) trivial = true;\r\n\t\t}\r\n\t}\r\n\treturn { dice: compareResult.dice, results, compare: compareResult.compare, trivial };\r\n}\r\n","import { COMMENT_REGEX, SYMBOL_DICE } from \"../interfaces/constant\";\r\n\r\nexport function replaceUnwantedText(dice: string) {\r\n\treturn dice.replaceAll(/[{}]/g, \"\").replaceAll(/s[ad]/gi, \"\");\r\n}\r\n\r\nexport function 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\nexport function 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\nexport function formatComment(dice: string) {\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\r\n\tconst commentsMatch = commentsRegex.exec(dice);\r\n\tconst comments = commentsMatch?.groups?.comments\r\n\t\t? `${commentsMatch.groups.comments}`\r\n\t\t: \"\";\r\n\r\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\r\n\t// to avoid conflicts with parentheses inside bracket comments\r\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\r\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\r\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\r\n\tconst optional = optionalComments?.groups?.comment\r\n\t\t? `${optionalComments.groups.comment.trim()}`\r\n\t\t: \"\";\r\n\r\n\t//fusion of both comments with a space if both exists\r\n\t//result expected = \"__comment1 comment2__ — \"\r\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\r\n\tlet finalComment = \"\";\r\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\r\n\telse if (comments) finalComment = `__${comments}__ — `;\r\n\telse if (optional) finalComment = `__${optional}__ — `;\r\n\treturn finalComment;\r\n}\r\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport type { Engine } from \"random-js\";\r\nimport type { Modifier, Sign, SortOrder } from \"../interfaces\";\r\nimport { DETECT_CRITICAL } from \"../interfaces/constant\";\r\nimport { replaceFormulaInDice, standardizeDice } from \"../utils\";\r\nimport { calculator } from \"./calculator\";\r\nimport { type ExplodingSuccess, normalizeExplodingSuccess } from \"./exploding\";\r\n\r\nexport function 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\nexport function extractValuesFromOutput(output: string): number[] {\r\n\tconst values: number[] = [];\r\n\tconst regex = /\\[([^\\]]+)\\]/g;\r\n\tlet match: RegExpExecArray | null;\r\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best method to extract all matches\r\n\twhile ((match = regex.exec(output)) !== null) {\r\n\t\tconst segmentValues = match[1]\r\n\t\t\t.split(\",\")\r\n\t\t\t.map((v) => Number.parseInt(v.replace(/[!*]/g, \"\").trim(), 10))\r\n\t\t\t.filter((v) => !Number.isNaN(v));\r\n\t\tvalues.push(...segmentValues);\r\n\t}\r\n\treturn values;\r\n}\r\n\r\nexport function getRollBounds(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): { min: number; max: number } | undefined {\r\n\ttry {\r\n\t\tconst roller = new DiceRoller();\r\n\t\tNumberGenerator.generator.engine = engine;\r\n\t\tconst rollResult = roller.roll(dice);\r\n\t\tconst instance = Array.isArray(rollResult) ? rollResult[0] : rollResult;\r\n\t\tconst { minTotal, maxTotal } = instance;\r\n\t\treturn { min: minTotal, max: maxTotal };\r\n\t} catch (error) {\r\n\t\t// Ignore bounds computation errors; trivial detection will simply be skipped\r\n\t}\r\n\treturn undefined;\r\n}\r\n\r\nexport function setSortOrder(toRoll: string, sort?: SortOrder): string {\r\n\t//First check if the diceToRoll contains already a sort order\r\n\tconst sortRegex = /(sa|sd|s)/i;\r\n\tif (sort && !toRoll.match(sortRegex)) {\r\n\t\t//we should insert the sort order at the end of the dice string and before the possible modifier or comparison\r\n\t\tconst modifierComparisonRegex = /([+\\-*/%^]\\d+|([><=!]+\\d+f)|([><=]|!=)+\\d+)$/;\r\n\t\tconst match = toRoll.match(modifierComparisonRegex);\r\n\t\tif (match) {\r\n\t\t\t//Insert before the modifier or comparison\r\n\t\t\tconst index = match.index!;\r\n\t\t\ttoRoll = `${toRoll.slice(0, index)}${sort}${toRoll.slice(index)}`;\r\n\t\t} else {\r\n\t\t\t//Append at the end\r\n\t\t\ttoRoll += sort;\r\n\t\t}\r\n\t}\r\n\treturn toRoll;\r\n}\r\n\r\ninterface PreparedDice {\r\n\tdice: string;\r\n\tdiceDisplay: string;\r\n\texplodingSuccess?: ExplodingSuccess;\r\n\tisSharedRoll: boolean;\r\n\tisSharedCurly: boolean;\r\n\tisCurlyBulk: boolean;\r\n\tbulkContent: string;\r\n\tisSimpleCurly: boolean;\r\n}\r\n\r\n/**\r\n * Prépare la chaîne de dés pour le traitement\r\n */\r\nexport function prepareDice(diceInput: string): PreparedDice {\r\n\tlet dice = standardizeDice(replaceFormulaInDice(diceInput))\r\n\t\t.replace(/^\\+/, \"\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimStart();\r\n\r\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\r\n\r\n\tconst explodingSuccess = normalizeExplodingSuccess(dice);\r\n\tif (explodingSuccess) dice = explodingSuccess.dice;\r\n\r\n\tlet diceDisplay: string;\r\n\tif (dice.includes(\";\")) {\r\n\t\tconst mainDice = dice.split(\";\")[0];\r\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? mainDice;\r\n\t} else {\r\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? dice;\r\n\t}\r\n\r\n\tconst curlyBulkMatch = dice.match(/^\\{(\\d+#.*)\\}$/);\r\n\tconst isCurlyBulk = !!curlyBulkMatch;\r\n\tconst bulkContent = isCurlyBulk ? curlyBulkMatch![1] : \"\";\r\n\r\n\tconst isSharedRoll = dice.includes(\";\");\r\n\tlet isSharedCurly = false;\r\n\r\n\tif (isSharedRoll && dice.match(/^\\{.*;\\s*.*\\}$/)) {\r\n\t\tdice = dice.slice(1, -1);\r\n\t\tisSharedCurly = true;\r\n\t\tdiceDisplay = diceDisplay.slice(1);\r\n\t}\r\n\r\n\t// Handle simple curly braces like {1d20+5} or {1d20+5>10}\r\n\t// But NOT dice pool notation like {2d6>4} where the comparison is inside the braces WITHOUT modifiers\r\n\tlet isSimpleCurly = false;\r\n\tif (!isCurlyBulk && !isSharedRoll && dice.match(/^\\{.*\\}$/)) {\r\n\t\t// Check if this is a dice pool (comparison inside the braces WITHOUT modifiers)\r\n\t\tconst innerContent = dice.slice(1, -1); // Remove outer braces\r\n\t\tconst hasModifiers = innerContent.match(/[+\\-*/%^]/);\r\n\t\tconst hasComparison = innerContent.match(/(([><=!]+\\d+f)|([><=]|!=)+\\d+)/);\r\n\r\n\t\t// Only remove braces if it's not a dice pool\r\n\t\t// Dice pool: has comparison inside, NO modifiers (like {2d6>4})\r\n\t\t// Simple curly: has modifiers before comparison (like {1d20+5>10}) or just plain dice (like {1d20+5})\r\n\t\tif (!(hasComparison && !hasModifiers)) {\r\n\t\t\tdice = innerContent;\r\n\t\t\tisSimpleCurly = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\tdice,\r\n\t\tdiceDisplay,\r\n\t\texplodingSuccess,\r\n\t\tisSharedRoll,\r\n\t\tisSharedCurly,\r\n\t\tisCurlyBulk,\r\n\t\tbulkContent,\r\n\t\tisSimpleCurly,\r\n\t};\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport type { Sign } from \"../interfaces\";\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","import type { DiceRoll, DiceRoller } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport { DiceTypeError } from \"../errors\";\r\nimport type { Compare, Resultat } from \"../interfaces\";\r\nimport { roll } from \"../roll\";\r\nimport { canComparisonSucceed } from \"./compare\";\r\n\r\n/**\r\n * Gère le système de pity (relance en cas d'échec)\r\n */\r\nexport function handlePitySystem(\r\n\tdice: string,\r\n\tcompare: Compare,\r\n\tdiceRoll: DiceRoll | DiceRoll[],\r\n\troller: DiceRoller,\r\n\tengine: Engine | null\r\n): { rerollCount: number; result?: Resultat } {\r\n\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\r\n\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\r\n\tconst isComparisonPossible =\r\n\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\r\n\r\n\tif (!isComparisonPossible) {\r\n\t\treturn { rerollCount: 0 };\r\n\t}\r\n\r\n\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\r\n\tif (isFail) {\r\n\t\treturn { rerollCount: 0 };\r\n\t}\r\n\r\n\tconst maxReroll = 100;\r\n\tlet rerollCount = 0;\r\n\tlet res: Resultat | undefined;\r\n\r\n\twhile (!isFail && rerollCount < maxReroll) {\r\n\t\ttry {\r\n\t\t\tres = roll(dice, engine, false);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new DiceTypeError(dice, \"roll\", error);\r\n\t\t}\r\n\t\trerollCount++;\r\n\t\tif (res && res.total !== undefined) {\r\n\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { rerollCount, result: res };\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport \"uniformize\";\r\n\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport {\r\n\tcreateCriticalCustom,\r\n\tDETECT_CRITICAL,\r\n\tDiceTypeError,\r\n\tEmptyObjectError,\r\n\tescapeRegex,\r\n\tFormulaError,\r\n\tNoStatisticsError,\r\n\treplaceExpByRandom,\r\n\treplaceFormulaInDice,\r\n\troll,\r\n\ttype StatisticalTemplate,\r\n\tTooManyDice,\r\n\ttemplateSchema,\r\n} from \".\";\r\nimport { isNumber, randomInt } from \"./utils\";\r\n\r\n/**\r\n * Verify if the provided dice work with random value\r\n * @param testDice {string}\r\n * @param allStats {Record<string,number>}\r\n * @param engine\r\n * @param pity\r\n */\r\nexport function evalStatsDice(\r\n\ttestDice: string,\r\n\tallStats?: Record<string, number>,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean\r\n) {\r\n\tlet dice = testDice.trimEnd();\r\n\tif (allStats && Object.keys(allStats).length > 0) {\r\n\t\tconst names = Object.keys(allStats);\r\n\t\tfor (const name of names) {\r\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\t\tif (dice.standardize().match(regex)) {\r\n\t\t\t\tconst statValue = allStats[name];\r\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttry {\r\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\r\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\r\n\t\treturn testDice;\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\r\n\t}\r\n}\r\n\r\n/**\r\n * Generate a random dice and remove the formula (+ evaluate it)\r\n * Used for diceDamage only\r\n * @param value {string}\r\n * @param template {StatisticalTemplate}\r\n * @param engine\r\n * @returns\r\n */\r\nexport function diceRandomParse(\r\n\tvalue: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\r\n\tvalue = value.standardize();\r\n\tconst statNames = Object.keys(template.statistics);\r\n\tlet newDice = value;\r\n\tfor (const name of statNames) {\r\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\tif (value.match(regex)) {\r\n\t\t\tlet max: undefined | number;\r\n\t\t\tlet min: undefined | number;\r\n\t\t\tconst foundStat = template.statistics?.[name];\r\n\t\t\tif (foundStat) {\r\n\t\t\t\tmax = foundStat.max;\r\n\t\t\t\tmin = foundStat.min;\r\n\t\t\t}\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t}\r\n\treturn replaceFormulaInDice(newDice);\r\n}\r\n\r\n/**\r\n * Same as damageDice but for DiceType\r\n * @param dice {string}\r\n * @param template {StatisticalTemplate}\r\n * @param engine\r\n */\r\nexport function diceTypeRandomParse(\r\n\tdice: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tdice = replaceExpByRandom(dice);\r\n\tif (!template.statistics) return dice;\r\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\r\n\t\t(stat) => !template.statistics?.[stat].combinaison\r\n\t);\r\n\tif (!firstStatNotcombinaison) return dice;\r\n\tconst stats = template.statistics[firstStatNotcombinaison];\r\n\tconst { min, max } = stats;\r\n\tconst total = template.total || 100;\r\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\r\n}\r\n\r\n/**\r\n * Random the combinaison and evaluate it to check if everything is valid\r\n * @param combinaison {Record<string,string>}\r\n * @param stats {Record<string,number|number>}\r\n */\r\nexport function evalCombinaison(\r\n\tcombinaison: Record<string, string>,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tconst newStats: Record<string, number> = {};\r\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\r\n\t\t//replace the stats in formula\r\n\t\tlet formula = combin.standardize();\r\n\t\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\t\tformula = formula.replace(regex, value.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tnewStats[stat] = evaluate(formula);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\r\n\t\t}\r\n\t}\r\n\treturn newStats;\r\n}\r\n\r\n/**\r\n * Evaluate one selected combinaison\r\n * @param combinaison {string}\r\n * @param stats {[name: string]: string|number}\r\n */\r\nexport function evalOneCombinaison(\r\n\tcombinaison: string,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tlet formula = combinaison.standardize();\r\n\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\tformula = formula.replace(regex, value.toString());\r\n\t}\r\n\ttry {\r\n\t\treturn evaluate(formula);\r\n\t} catch (error) {\r\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\r\n\t}\r\n}\r\n\r\nfunction convertNumber(number: string | number | undefined) {\r\n\tif (number === undefined || number === null) return undefined;\r\n\tif (\r\n\t\tnumber.toString().length === 0 ||\r\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\r\n\t)\r\n\t\treturn undefined;\r\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\r\n\treturn undefined;\r\n}\r\n\r\n/**\r\n * Parse the provided JSON and verify each field to check if everything could work when rolling\r\n * @param {unknown} template\r\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\r\n * @param engine\r\n * @returns {StatisticalTemplate}\r\n */\r\nexport function verifyTemplateValue(\r\n\ttemplate: unknown,\r\n\tverify = true,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): StatisticalTemplate {\r\n\tconst parsedTemplate = templateSchema.parse(template);\r\n\tconst { success, failure } = parsedTemplate.critical ?? {};\r\n\tconst criticicalVal = {\r\n\t\tsuccess: convertNumber(success),\r\n\t\tfailure: convertNumber(failure),\r\n\t};\r\n\tconst statistiqueTemplate: StatisticalTemplate = {\r\n\t\tdiceType: parsedTemplate.diceType,\r\n\t\tstatistics: parsedTemplate.statistics,\r\n\t\tcritical: criticicalVal,\r\n\t\ttotal: parsedTemplate.total,\r\n\t\tcharName: parsedTemplate.charName,\r\n\t\tdamage: parsedTemplate.damage,\r\n\t\tcustomCritical: parsedTemplate.customCritical,\r\n\t\tforceDistrib: parsedTemplate.forceDistrib,\r\n\t};\r\n\tif (!verify) return statistiqueTemplate;\r\n\tif (statistiqueTemplate.diceType) {\r\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\r\n\t\t\tthrow new DiceTypeError(\r\n\t\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\t\t\"critical_dice_type\",\r\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\r\n\t\t\t);\r\n\t\t}\r\n\t\tconst cleanedDice = diceTypeRandomParse(\r\n\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\tstatistiqueTemplate,\r\n\t\t\tengine\r\n\t\t);\r\n\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\r\n\t}\r\n\tif (statistiqueTemplate.customCritical) {\r\n\t\tif (!statistiqueTemplate.diceType) {\r\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\r\n\t\t}\r\n\t\tconst customCritical = statistiqueTemplate.customCritical;\r\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\r\n\t\t\tconst cleanedDice = createCriticalCustom(\r\n\t\t\t\tstatistiqueTemplate.diceType!,\r\n\t\t\t\tcustom,\r\n\t\t\t\tstatistiqueTemplate,\r\n\t\t\t\tengine\r\n\t\t\t);\r\n\t\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\t\tif (!rolled)\r\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\r\n\t\t}\r\n\t}\r\n\ttestDiceRegistered(statistiqueTemplate, engine);\r\n\ttestStatCombinaison(statistiqueTemplate, engine);\r\n\treturn statistiqueTemplate;\r\n}\r\n\r\n/**\r\n * Test each damage roll from the template.damage\r\n * @param {StatisticalTemplate} template\r\n * @param engine\r\n */\r\nexport function testDiceRegistered(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.damage) return;\r\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\r\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\r\n\tfor (const [name, dice] of Object.entries(template.damage)) {\r\n\t\tif (!dice) continue;\r\n\t\tconst diceReplaced = replaceExpByRandom(dice);\r\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\r\n\t\ttry {\r\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\r\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(error);\r\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Test all combinaison with generated random value\r\n * @param {StatisticalTemplate} template\r\n * @param engine\r\n */\r\nexport function testStatCombinaison(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return;\r\n\tconst onlycombinaisonStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(\r\n\t\t\t([_, value]) => value.combinaison !== undefined\r\n\t\t)\r\n\t);\r\n\tconst allOtherStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\r\n\t);\r\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\r\n\tconst allStats = Object.keys(template.statistics).filter(\r\n\t\t(stat) => !template.statistics![stat].combinaison\r\n\t);\r\n\tif (allStats.length === 0) throw new NoStatisticsError();\r\n\tconst error = [];\r\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\r\n\t\tlet formula = value.combinaison as string;\r\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\r\n\t\t\tconst { max, min } = data;\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tconst regex = new RegExp(other, \"gi\");\r\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tevaluate(formula);\r\n\t\t} catch (e) {\r\n\t\t\terror.push(stat);\r\n\t\t}\r\n\t}\r\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\r\n\treturn;\r\n}\r\n\r\n/**\r\n * Generate a random stat based on the template and the statistical min and max\r\n * @param {number|undefined} total\r\n * @param {number | undefined} max\r\n * @param {number | undefined} min\r\n * @param engine\r\n * @returns\r\n */\r\nexport function generateRandomStat(\r\n\ttotal: number | undefined = 100,\r\n\tmax?: number,\r\n\tmin?: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet randomStatValue = total + 1;\r\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\r\n\twhile (randomStatValue >= total || randomStatValue === 0) {\r\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\r\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\r\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\r\n\t\telse randomStatValue = randomInt(1, total, engine, random);\r\n\t}\r\n\treturn randomStatValue;\r\n}\r\n"],"mappings":"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","names":["SortOrder","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","import_rpg_dice_roller","import_mathjs","diceResult","roll","import_rpg_dice_roller","import_mathjs","import_mathjs","evaluateRoll","import_mathjs","import_random_js","import_uniformize","import_rpg_dice_roller","cleanedDice"]}
|
package/dist/index.mjs
CHANGED
|
@@ -207,7 +207,7 @@ function generateStatsDice(originalDice, stats, dollarValue) {
|
|
|
207
207
|
if (!outsideText) {
|
|
208
208
|
continue;
|
|
209
209
|
}
|
|
210
|
-
const tokenRegex = /([\p{L}\p{N}_]+)/gu;
|
|
210
|
+
const tokenRegex = /(\$?[\p{L}\p{N}_]+)/gu;
|
|
211
211
|
let lastIndex = 0;
|
|
212
212
|
let tokenMatch;
|
|
213
213
|
while ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {
|
|
@@ -259,7 +259,7 @@ function generateStatsDice(originalDice, stats, dollarValue) {
|
|
|
259
259
|
}
|
|
260
260
|
dice = result;
|
|
261
261
|
}
|
|
262
|
-
if (dollarValue) dice = dice.replaceAll(
|
|
262
|
+
if (dollarValue) dice = dice.replaceAll(/\$\B/g, dollarValue);
|
|
263
263
|
return replaceFormulaInDice(dice);
|
|
264
264
|
}
|
|
265
265
|
function replaceFormulaInDice(dice) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine.ts","../src/errors.ts","../src/interfaces/index.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/roll.ts","../src/dice/bulk.ts","../src/dice/compare.ts","../src/utils.ts","../src/dice/exploding.ts","../src/dice/signs.ts","../src/dice/replace.ts","../src/dice/extract.ts","../src/dice/calculator.ts","../src/dice/pity.ts","../src/verify_template.ts"],"sourcesContent":["import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport type { Engine } from \"random-js\";\n\n/**\n * Utility function that allow to get the id of an engine\n * @param engine {unknown} Engine to identify\n * @returns {string} Id of the engine or \"unknown\"\n * @private\n */\nexport function getEngineId(engine: unknown): string {\n\t// Comparaisons directes avec les engines exposés par la lib\n\tif (engine === NumberGenerator.engines.nodeCrypto) return \"nodeCrypto\";\n\tif (engine === NumberGenerator.engines.nativeMath) return \"nativeMath\";\n\tif (engine === NumberGenerator.engines.browserCrypto) return \"browserCrypto\";\n\t// Fallback: essayer de lire un nom ou le constructeur\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: needed for dynamic access\n\t\tconst e = engine as any;\n\t\tif (e && typeof e === \"object\") {\n\t\t\tif (typeof e.name === \"string\" && e.name) return e.name;\n\t\t\tif (e.constructor?.name) return e.constructor.name;\n\t\t}\n\t} catch {\n\t\t/* ignore */\n\t}\n\treturn \"unknown\";\n}\n\n/**\n * Utility function to get the engine from its name\n * @param engine {\"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"} The engine name\n * @returns {Engine} The engine\n * @public\n */\nexport function getEngine(engine: \"nativeMath\" | \"browserCrypto\" | \"nodeCrypto\"): Engine {\n\tswitch (engine) {\n\t\tcase \"nativeMath\":\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t\tcase \"browserCrypto\":\n\t\t\treturn NumberGenerator.engines.browserCrypto;\n\t\tcase \"nodeCrypto\":\n\t\t\treturn NumberGenerator.engines.nodeCrypto;\n\t\tdefault:\n\t\t\treturn NumberGenerator.engines.nativeMath;\n\t}\n}\n","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 interface Resultat {\n\t/**\n\t * Original dice throw\n\t */\n\tdice: string;\n\t/**\n\t * Result of the dice throw\n\t */\n\tresult: string;\n\t/**\n\t * The comment that was added to the dice throw (if any)\n\t */\n\tcomment?: string;\n\t/**\n\t * The comparison made on the dice\n\t */\n\tcompare?: ComparedValue;\n\t/**\n\t * If any value was added to the dice throw\n\t */\n\tmodifier?: Modifier;\n\t/**\n\t * Total of the roll\n\t */\n\ttotal?: number;\n\tpityLogs?: number;\n\ttrivial?: boolean;\n}\n\nexport interface Compare {\n\t/**\n\t * Sign of the comparison\n\t */\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\";\n\t/**\n\t * Value of the comparison\n\t */\n\tvalue: number;\n\t/**\n\t * Indicate if the comparison is \"trivial\"\n\t * aka if the comparaison is always true or always false\n\t */\n\ttrivial?: boolean;\n}\n\n/**\n * Sign format for calculation of modifier\n */\nexport type Sign = \"+\" | \"-\" | \"*\" | \"/\" | \"%\" | \"^\" | \"**\";\n\nexport type ComparedValue = Compare & {\n\t/**\n\t * Original dice if the comparaison is made with a dice throw\n\t */\n\toriginalDice?: string;\n\t/**\n\t * Output of the dice throw\n\t */\n\trollValue?: string;\n};\n\nexport interface Modifier {\n\t/**\n\t * Sign of the modifier\n\t */\n\tsign?: Sign;\n\t/**\n\t * Value of the modifier\n\t * @TJS-type integer\n\t */\n\tvalue: number;\n}\n\n/**\n * Statistic object template\n */\nexport type Statistic = Record<\n\t/**\n\t * The name of the statistic\n\t * @TJS-type string\n\t */\n\tstring,\n\tStatEntry\n>;\n\ntype StatEntry = {\n\t/**\n\t * The value of the statistic that can take the stats\n\t * @TJS-type integer\n\t */\n\tmax?: number;\n\t/**\n\t * The minimal value of the statistic that can take the stats\n\t * @TJS-type integer\n\t */\n\tmin?: number;\n\t/**\n\t * The combinaison that can be made with ANOTHER statistic\n\t * Automatically disable the max/min value\n\t */\n\tcombinaison?: string;\n\t/**\n\t * Allow to exclude from roll selection in /dbroll!\n\t */\n\texclude?: boolean;\n};\n\n/**\n * @example\n * diceType: 1d20+$>=20\n * The dice throw will be 1d20 + statistique that must be >= 20\n * @example\n * diceType: 1d20<=$\n * The dice throw will be 1d20 that must be <= statistique\n */\nexport interface StatisticalTemplate {\n\t/** Allow to force the user to choose a name for them characters */\n\tcharName?: boolean;\n\t/**\n\t * The statistics that can be used in the dice throw\n\t * @maximum 25\n\t */\n\tstatistics?: Statistic;\n\t/**\n\t * A total can be set, it allows to calculate the total value of a future register member\n\t * If the sum of the value > total, the bot will send a message to the user to inform him that the total is exceeded and an error will be thrown\n\t * @note statistique that have a formula will be ignored from the total\n\t * @TJS-type integer\n\t */\n\ttotal?: number;\n\n\t/**\n\t * Force the distribition of all the points\n\t */\n\tforceDistrib?: boolean;\n\t/** A dice type in the notation supported by the bot */\n\tdiceType?: string;\n\t/**\n\t * How the success/echec will be done\n\t */\n\tcritical?: Critical;\n\t/**\n\t * Custom critical, allow to adjust the critical on a statistic, and set multiple critical value\n\t * @maximum 22\n\t */\n\tcustomCritical?: CustomCriticalMap;\n\n\t/** Special dice for damage\n\t * @maximum 25\n\t * */\n\tdamage?: Record<string, string>;\n}\nexport type CustomCriticalMap = Record<string, CustomCritical>;\n\n/**\n * If the result can be considered as a critical\n * Critical is compared to the \"natural\" dice result, so any modifier doesn't count\n */\nexport interface Critical {\n\t/**\n\t * The value that will be considered as a success\n\t * Can only be compared strictly with the natural dice result\n\t * @TJS-type integer\n\t */\n\tsuccess?: number;\n\t/**\n\t * The value that will be considered as a failure.\n\t * Can only be compared strictly with the natural dice result\n\t * @TJS-type integer\n\t */\n\tfailure?: number;\n}\n\nexport interface CustomCritical {\n\t/**\n\t * Sign of the comparison\n\t */\n\tsign: \"<\" | \">\" | \"<=\" | \">=\" | \"!=\" | \"==\";\n\t/**\n\t * Can be a simple value, or a formula, including the statistics with $\n\t * @example round($/2)\n\t */\n\tvalue: string;\n\t/**\n\t * If \"true\", the comparison will be made on the natural dice result, without any modifier, including the statistics bonus if any.\n\t */\n\tonNaturalDice?: boolean;\n\t/**\n\t * Allow to use the custom critical on dbD command (damage)\n\t * @default false\n\t */\n\taffectSkill?: boolean;\n}\n\nexport enum SortOrder {\n\tAscending = \"sa\",\n\tDescending = \"sd\",\n\tNone = \"none\",\n}\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\n// Use negative lookbehind to check for ![<>] before any comparison operator\nexport const SIGN_REGEX =\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\nexport const SIGN_REGEX_SPACE =\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\n\nexport const SYMBOL_DICE = \"&\";\n\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\n","/**\n * Definition of the Zod schema for template data\n */\nimport { z } from \"zod\";\n\nconst statisticValueSchema = z\n\t.object({\n\t\tmax: z\n\t\t\t.number()\n\t\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t\t.optional(),\n\t\tmin: z\n\t\t\t.number()\n\t\t\t.transform((val) =>\n\t\t\t\tNumber.isNaN(Number.parseInt(val as unknown as string, 10)) ? undefined : val\n\t\t\t)\n\t\t\t.optional(),\n\t\tcombinaison: z\n\t\t\t.string()\n\t\t\t.transform((str) => str.trim() || undefined)\n\t\t\t.optional(),\n\t\texclude: z.boolean().optional(),\n\t})\n\t.superRefine((data, ctx) => {\n\t\tif (data.max !== undefined && data.min !== undefined && data.max <= data.min) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tmessage: `Max_Greater; ${data.min}; ${data.max}`,\n\t\t\t\tpath: [\"max\"],\n\t\t\t});\n\t\t}\n\t});\n\nconst statisticSchema = z\n\t.record(z.string(), statisticValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyStats\",\n\t});\n\nconst criticalSchema = z\n\t.object({\n\t\tsuccess: z.string().or(z.number().min(0)).optional(),\n\t\tfailure: z.string().or(z.number().min(0)).optional(),\n\t})\n\t.transform((values) => {\n\t\tif (values.success === \"\") values.success = undefined;\n\t\tif (values.failure === \"\") values.failure = undefined;\n\t\tif (values.failure === 0) values.failure = undefined;\n\t\tif (values.success === 0) values.success = undefined;\n\t\tvalues.success = Number.parseInt(values.success as string, 10);\n\t\tvalues.failure = Number.parseInt(values.failure as string, 10);\n\t\treturn values;\n\t});\n\nconst criticalValueSchema = z.object({\n\tsign: z.enum([\"<\", \">\", \"<=\", \">=\", \"!=\", \"==\"]),\n\tvalue: z.string(),\n\tonNaturalDice: z.boolean().optional(),\n\taffectSkill: z.boolean().optional(),\n});\n\nconst damageSchema = z\n\t.record(z.string(), z.string())\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 25, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nconst customCriticalSchema = z\n\t.record(z.string(), criticalValueSchema)\n\t.optional()\n\t.refine((stats) => !stats || Object.keys(stats).length <= 22, {\n\t\tmessage: \"TooManyDice\",\n\t});\n\nexport const templateSchema = z.object({\n\tcharName: z.boolean().optional(),\n\tstatistics: statisticSchema,\n\ttotal: z\n\t\t.number()\n\t\t.min(0)\n\t\t.transform((val) => (val === 0 ? undefined : val))\n\t\t.optional(),\n\tforceDistrib: z.boolean().optional(),\n\tdiceType: z.string().optional(),\n\tcritical: criticalSchema.optional(),\n\tcustomCritical: customCriticalSchema,\n\tdamage: damageSchema,\n});\n","import { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\n\nimport {\n\tcompareSignFormule,\n\tcountExplodingSuccesses,\n\ttype ExplodingSuccess,\n\textractValuesFromOutput,\n\tfixParenthesis,\n\tformatComment,\n\tgetCompare,\n\tgetModifier,\n\tgetRollBounds,\n\thandleBulkRolls,\n\thandlePitySystem,\n\tinverseSign,\n\tisTrivialComparison,\n\tmatchComparison,\n\tnormalizeExplodingSuccess,\n\tprepareDice,\n\treplaceText,\n\treplaceUnwantedText,\n\tsetSortOrder,\n} from \"./dice\";\nimport { DiceTypeError } from \"./errors\";\nimport { type Compare, type ComparedValue, type Resultat, SortOrder } from \"./interfaces\";\nimport {\n\tCOMMENT_REGEX,\n\tOPTIONAL_COMMENT,\n\tSIGN_REGEX_SPACE,\n\tSYMBOL_DICE,\n} from \"./interfaces/constant\";\n\n/**\n * Parse the string provided and turn it as a readable dice for dice parser\n * @param {string} dice The dice string to parse and roll\n * @param {Engine|null} engine The random engine to use, default to nodeCrypto\n * @param {boolean} pity Whether to enable pity system (reroll on failure) or not\n * @param {boolean} sort Whether to sort the dice results or not\n * @returns {Resultat|undefined} The result of the roll\n */\nexport function roll(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean,\n\tsort?: SortOrder\n): Resultat | undefined {\n\tif (sort === SortOrder.None) sort = undefined;\n\n\tconst prepared = prepareDice(dice);\n\tif (!prepared.dice.includes(\"d\")) return undefined;\n\n\t// Handle shared rolls\n\tif (prepared.isSharedRoll) {\n\t\treturn sharedRolls(\n\t\t\tprepared.dice,\n\t\t\tengine,\n\t\t\tpity,\n\t\t\tprepared.explodingSuccess,\n\t\t\tprepared.diceDisplay,\n\t\t\tprepared.isSharedCurly\n\t\t);\n\t}\n\n\tlet processedDice = fixParenthesis(prepared.dice);\n\tconst modificator = getModifier(processedDice);\n\n\t// Extract compare BEFORE rolling, but NOT for curly bulk rolls\n\tconst compareRegex = processedDice.match(SIGN_REGEX_SPACE);\n\tlet compare: ComparedValue | undefined;\n\tif (compareRegex && !prepared.isCurlyBulk) {\n\t\tconst compareResult = getCompare(processedDice, compareRegex, engine, pity);\n\t\tprocessedDice = compareResult.dice;\n\t\tcompare = compareResult.compare;\n\t}\n\n\t// For simple curly braces, wrap the diceDisplay with braces\n\tlet finalDiceDisplay = prepared.diceDisplay;\n\tif (prepared.isSimpleCurly && !prepared.diceDisplay.startsWith(\"{\")) {\n\t\tfinalDiceDisplay = `{${prepared.diceDisplay}}`;\n\t}\n\n\t// Handle bulk rolls\n\tconst bulkProcessContent = prepared.isCurlyBulk ? prepared.bulkContent : processedDice;\n\tif (bulkProcessContent.match(/\\d+?#(.*)/)) {\n\t\treturn handleBulkRolls(\n\t\t\tprocessedDice,\n\t\t\tprepared.isCurlyBulk,\n\t\t\tprepared.bulkContent,\n\t\t\tcompare,\n\t\t\tprepared.explodingSuccess,\n\t\t\tprepared.diceDisplay,\n\t\t\tengine,\n\t\t\tsort\n\t\t);\n\t}\n\n\t// Standard roll\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tlet diceWithoutComment = processedDice.replace(COMMENT_REGEX, \"\").trimEnd();\n\tdiceWithoutComment = setSortOrder(diceWithoutComment, sort);\n\n\tlet diceRoll: DiceRoll | DiceRoll[];\n\ttry {\n\t\tdiceRoll = roller.roll(diceWithoutComment);\n\t} catch (error) {\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\n\t}\n\n\t// Update compare.trivial after rolling\n\tif (compare && diceRoll) {\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\t\tconst trivial = isTrivialComparison(\n\t\t\tcurrentRoll.maxTotal,\n\t\t\tcurrentRoll.minTotal,\n\t\t\tcompare\n\t\t);\n\t\tcompare.trivial = trivial ? true : undefined;\n\t}\n\n\tconst commentMatch = processedDice.match(COMMENT_REGEX);\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\n\n\t// Handle pity system\n\tlet rerollCount = 0;\n\tlet pityResult: Resultat | undefined;\n\tif (pity && compare) {\n\t\tconst pityData = handlePitySystem(\n\t\t\tdiceWithoutComment,\n\t\t\tcompare,\n\t\t\tdiceRoll,\n\t\t\troller,\n\t\t\tengine\n\t\t);\n\t\trerollCount = pityData.rerollCount;\n\t\tpityResult = pityData.result;\n\t\tif (pityResult) {\n\t\t\treturn {\n\t\t\t\t...pityResult,\n\t\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\n\t\t\t\tcomment,\n\t\t\t\tcompare,\n\t\t\t\tmodifier: modificator,\n\t\t\t\tpityLogs: rerollCount,\n\t\t\t\ttrivial: pityResult.trivial ?? (compare?.trivial ? true : undefined),\n\t\t\t};\n\t\t}\n\t}\n\n\tlet resultOutput = replaceUnwantedText(roller.output);\n\n\t// Handle exploding success\n\tif (prepared.explodingSuccess) {\n\t\tconst successes = countExplodingSuccesses(\n\t\t\tdiceRoll,\n\t\t\tprepared.explodingSuccess.sign,\n\t\t\tprepared.explodingSuccess.value\n\t\t);\n\t\tresultOutput = resultOutput\n\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successes}`)\n\t\t\t.replace(\n\t\t\t\tprepared.explodingSuccess.normalizedSegment,\n\t\t\t\tprepared.explodingSuccess.originalSegment\n\t\t\t);\n\n\t\treturn {\n\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : prepared.diceDisplay,\n\t\t\tresult: resultOutput,\n\t\t\tcomment,\n\t\t\tcompare: compare ? compare : undefined,\n\t\t\tmodifier: modificator,\n\t\t\ttotal: successes,\n\t\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t\t\ttrivial: compare?.trivial ? true : undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\n\t\tresult: resultOutput,\n\t\tcomment,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\n\t\ttrivial: compare?.trivial ? true : undefined,\n\t};\n}\n\nfunction sharedRolls(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean,\n\texplodingSuccessMain?: ExplodingSuccess,\n\tdiceDisplay?: string,\n\tisSharedCurly?: boolean\n): Resultat | undefined {\n\t// If not provided (call from elsewhere), try to detect\n\tif (!explodingSuccessMain)\n\t\texplodingSuccessMain = normalizeExplodingSuccess(dice.split(\";\")[0] ?? dice);\n\n\tif (explodingSuccessMain) {\n\t\t// Use normalized dice for internal processing but keep original for display\n\t\tdice = dice.replace(explodingSuccessMain.originalSegment, \"!\");\n\t}\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\tconst displayDice = diceDisplay ?? explodingSuccessMain?.originalDice ?? split[0];\n\tlet diceMain = fixParenthesis(split[0]);\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\n\tconst comments = formatComment(diceMain);\n\t// Remove comments before checking for hidden dice (parentheses)\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\n\tlet hidden = false;\n\tif (toHide?.dice) {\n\t\tdiceMain = toHide.dice;\n\t\thidden = true;\n\t} else if (toHide) {\n\t\tdiceMain = \"1d1\";\n\t\thidden = true;\n\t} else {\n\t\t// No hidden dice, use the dice without comments\n\t\tdiceMain = diceMainWithoutComments;\n\t}\n\tconst rollBounds = getRollBounds(diceMain, engine);\n\tlet diceResult = roll(diceMain, engine, pity);\n\tif (!diceResult || !diceResult.total) {\n\t\tif (hidden) {\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\n\t\t\thidden = false;\n\t\t} else return undefined;\n\t}\n\tif (!diceResult || !diceResult.total) return undefined;\n\n\t// If we had a double-sign exploding, recompute successes from the first segment output\n\tif (explodingSuccessMain && diceResult.result) {\n\t\tconst values = extractValuesFromOutput(diceResult.result);\n\t\tdiceResult.total = values.filter((v) =>\n\t\t\tmatchComparison(explodingSuccessMain!.sign, v, explodingSuccessMain!.value)\n\t\t).length;\n\t}\n\tlet aggregatedCompare = diceResult.compare;\n\tlet hasTrivialComparison = diceResult.compare?.trivial === true;\n\tresults.push(`※ ${comments}${diceResult.result}`);\n\tlet total = diceResult.total;\n\tdiceResult.comment = mainComment;\n\tif (!total) {\n\t\treturn {\n\t\t\tdice: displayDice,\n\t\t\tresult: results.join(\";\"),\n\t\t\tcomment: mainComment,\n\t\t\tcompare: aggregatedCompare,\n\t\t\tmodifier: diceResult.modifier,\n\t\t\ttotal,\n\t\t\ttrivial: hasTrivialComparison ? true : undefined,\n\t\t};\n\t}\n\tfor (let element of split.slice(1)) {\n\t\tconst comment = formatComment(element);\n\t\telement = element\n\t\t\t.replaceAll(commentsRegex, \"\")\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\n\t\t\t.trim();\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\n\t\t//remove comments\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\n\t\tif (compareRegex) {\n\t\t\tif (isSharedCurly) {\n\t\t\t\t// For curly braces shared rolls, display success count instead of comparison details\n\t\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\t\ttoRoll,\n\t\t\t\t\tcompareRegex,\n\t\t\t\t\telement,\n\t\t\t\t\tdiceResult,\n\t\t\t\t\tengine,\n\t\t\t\t\tpity,\n\t\t\t\t\trollBounds\n\t\t\t\t);\n\t\t\t\t// Count success: 1 if comparison is true, 0 if false\n\t\t\t\tconst { diceAll } = replaceText(element, diceResult.total, diceResult.dice);\n\t\t\t\tlet successCount = 0;\n\t\t\t\ttry {\n\t\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\t\tsuccessCount = evaluated ? 1 : 0;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// If evaluation fails, try with roll\n\t\t\t\t\tconst evaluated = roll(toRoll, engine, pity) as Resultat | undefined;\n\t\t\t\t\tsuccessCount = (evaluated?.total ?? 0) ? 1 : 0;\n\t\t\t\t}\n\t\t\t\tresults.push(`※ ${comment}${diceAll}: ${successCount}`);\n\t\t\t\ttotal += successCount;\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\n\t\t\t\t\taggregatedCompare = compareResult.compare;\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\n\t\t\t} else {\n\t\t\t\tconst compareResult = compareSignFormule(\n\t\t\t\t\ttoRoll,\n\t\t\t\t\tcompareRegex,\n\t\t\t\t\telement,\n\t\t\t\t\tdiceResult,\n\t\t\t\t\tengine,\n\t\t\t\t\tpity,\n\t\t\t\t\trollBounds\n\t\t\t\t);\n\t\t\t\ttoRoll = compareResult.dice;\n\t\t\t\tresults.push(compareResult.results);\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\n\t\t\t\t\taggregatedCompare = compareResult.compare;\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\n\t\t\t}\n\t\t} else {\n\t\t\tconst { formule, diceAll } = replaceText(\n\t\t\t\telement,\n\t\t\t\tdiceResult.total,\n\t\t\t\tdiceResult.dice\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst evaluated = evaluate(toRoll);\n\t\t\t\tresults.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += Number.parseInt(evaluated, 10);\n\t\t\t} catch (error) {\n\t\t\t\tconst evaluated = roll(toRoll, engine, pity);\n\t\t\t\tif (evaluated) {\n\t\t\t\t\tresults.push(\n\t\t\t\t\t\t`◈ ${comment}${diceAll}: ${evaluated.result.split(\":\").slice(1).join(\":\")}`\n\t\t\t\t\t);\n\t\t\t\t\tif (!aggregatedCompare && evaluated.compare)\n\t\t\t\t\t\taggregatedCompare = evaluated.compare;\n\t\t\t\t\tif (evaluated.compare?.trivial) hasTrivialComparison = true;\n\t\t\t\t} else results.push(`◈ ${comment}${diceAll}: ${formule} = ${evaluated}`);\n\t\t\t\ttotal += evaluated?.total ?? 0;\n\t\t\t}\n\t\t}\n\t}\n\tif (hidden)\n\t\t//remove the first in result\n\t\tresults.shift();\n\treturn {\n\t\tdice: displayDice,\n\t\tresult: results.join(\";\"),\n\t\tcomment: mainComment,\n\t\tcompare:\n\t\t\thasTrivialComparison && aggregatedCompare\n\t\t\t\t? { ...aggregatedCompare, trivial: true }\n\t\t\t\t: aggregatedCompare,\n\t\tmodifier: diceResult.modifier,\n\t\ttotal,\n\t\ttrivial: hasTrivialComparison ? true : undefined,\n\t};\n}\n\nexport function replaceInFormula(\n\telement: string,\n\tdiceResult: Resultat,\n\tcompareResult: { dice: string; compare: Compare | undefined },\n\tres: boolean,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tconst { formule, diceAll } = replaceText(\n\t\telement,\n\t\tdiceResult.total ?? 0,\n\t\tdiceResult.dice\n\t);\n\tconst validSign = res ? \"✓\" : \"✕\";\n\tconst invertedSign = res\n\t\t? compareResult.compare!.sign\n\t\t: inverseSign(compareResult.compare!.sign);\n\tlet evaluateRoll: unknown;\n\ttry {\n\t\tevaluateRoll = evaluate(compareResult.dice);\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t} catch (error) {\n\t\tconst evaluateRoll = roll(compareResult.dice, engine, pity) as Resultat | undefined;\n\t\tif (evaluateRoll)\n\t\t\treturn `${validSign} ${diceAll}: ${evaluateRoll.result.split(\":\").splice(1).join(\":\")}`;\n\n\t\treturn `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;\n\t}\n}\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport { DiceTypeError } from \"../errors\";\nimport type { Compare, ComparedValue, Resultat, SortOrder } from \"../interfaces\";\nimport { COMMENT_REGEX, SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\nimport { isTrivialComparison } from \"./compare\";\nimport {\n\tcountExplodingSuccesses,\n\tEXPLODING_SUCCESS_REGEX,\n\ttype ExplodingSuccess,\n} from \"./exploding\";\nimport { extractValuesFromOutput, getModifier, setSortOrder } from \"./extract\";\nimport { replaceUnwantedText } from \"./replace\";\nimport { matchComparison } from \"./signs\";\n\n/**\n * Gère les lancers en masse (bulk rolls)\n */\nexport function handleBulkRolls(\n\tdice: string,\n\tisCurlyBulk: boolean,\n\tbulkContent: string,\n\tcompare: ComparedValue | undefined,\n\texplodingSuccess: ExplodingSuccess | undefined,\n\tdiceDisplay: string,\n\tengine: Engine | null,\n\tsort?: SortOrder\n): Resultat {\n\tconst bulkProcessContent = isCurlyBulk ? bulkContent : dice;\n\tconst diceArray = bulkProcessContent.split(\"#\");\n\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\n\tlet diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\n\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\n\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\n\n\tlet curlyCompare: Compare | undefined;\n\tif (isCurlyBulk) {\n\t\tconst curlyCompareRegex = diceToRoll.match(SIGN_REGEX_SPACE);\n\t\tif (curlyCompareRegex) {\n\t\t\tconst compareSign = curlyCompareRegex[0].match(SIGN_REGEX)?.[0];\n\t\t\tconst compareValue = curlyCompareRegex[2];\n\t\t\tif (compareSign && compareValue) {\n\t\t\t\tcurlyCompare = {\n\t\t\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\t\t\tvalue: Number.parseInt(compareValue, 10),\n\t\t\t\t};\n\t\t\t\tdiceToRoll = diceToRoll.replace(SIGN_REGEX_SPACE, \"\");\n\t\t\t}\n\t\t}\n\t}\n\n\tdiceToRoll = setSortOrder(diceToRoll, sort);\n\n\tconst activeCompare: Compare | undefined =\n\t\tcompare ||\n\t\tcurlyCompare ||\n\t\t(explodingSuccess\n\t\t\t? ({ sign: explodingSuccess.sign, value: explodingSuccess.value } as Compare)\n\t\t\t: undefined);\n\n\tif (activeCompare) {\n\t\treturn handleBulkRollsWithComparison(\n\t\t\tnumberOfDice,\n\t\t\tdiceToRoll,\n\t\t\tcomments,\n\t\t\tactiveCompare,\n\t\t\texplodingSuccess,\n\t\t\tdiceDisplay,\n\t\t\tisCurlyBulk,\n\t\t\tcurlyCompare,\n\t\t\tcompare,\n\t\t\tengine\n\t\t);\n\t}\n\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\n\tfor (let i = 0; i < numberOfDice; i++) {\n\t\ttry {\n\t\t\troller.roll(diceToRoll);\n\t\t} catch (error) {\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t}\n\t}\n\n\tconst finalDice = isCurlyBulk ? `{${diceToRoll}}` : diceToRoll;\n\tconst modificator = getModifier(dice);\n\n\treturn {\n\t\tdice: finalDice,\n\t\tresult: replaceUnwantedText(roller.output),\n\t\tcomment: comments,\n\t\tcompare: compare ? compare : undefined,\n\t\tmodifier: modificator,\n\t\ttotal: roller.total,\n\t};\n}\n\n/**\n * Gère les lancers en masse avec comparaison\n */\nfunction handleBulkRollsWithComparison(\n\tnumberOfDice: number,\n\tdiceToRoll: string,\n\tcomments: string | undefined,\n\tactiveCompare: Compare,\n\texplodingSuccess: ExplodingSuccess | undefined,\n\tdiceDisplay: string,\n\tisCurlyBulk: boolean,\n\tcurlyCompare: Compare | undefined,\n\tcompare: ComparedValue | undefined,\n\tengine: Engine | null\n): Resultat {\n\tconst results: string[] = [];\n\tlet successCount = 0;\n\tconst roller = new DiceRoller();\n\tNumberGenerator.generator.engine = engine;\n\tlet trivialComparisonDetected = false;\n\n\tconst formatOutput = (output: string, addStar: boolean) => {\n\t\tconst formatted =\n\t\t\taddStar && isCurlyBulk\n\t\t\t\t? output.replace(\n\t\t\t\t\t\t/\\[([^\\]]+)\\]/,\n\t\t\t\t\t\t(_m, content) =>\n\t\t\t\t\t\t\t`[${content\n\t\t\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t\t\t.map((d: string) => `${d.trim()}*`)\n\t\t\t\t\t\t\t\t.join(\", \")}]`\n\t\t\t\t\t)\n\t\t\t\t: output;\n\t\treturn curlyCompare\n\t\t\t? formatted.replace(/^([^:]+):/, `$1${curlyCompare.sign}${curlyCompare.value}:`)\n\t\t\t: formatted;\n\t};\n\n\tfor (let i = 0; i < numberOfDice; i++) {\n\t\ttry {\n\t\t\tconst individualRoll = roller.roll(diceToRoll);\n\t\t\tconst rollInstance = Array.isArray(individualRoll)\n\t\t\t\t? individualRoll[0]\n\t\t\t\t: individualRoll;\n\n\t\t\tif (!trivialComparisonDetected && activeCompare) {\n\t\t\t\tconst { maxTotal, minTotal } = rollInstance;\n\t\t\t\ttrivialComparisonDetected = isTrivialComparison(\n\t\t\t\t\tmaxTotal,\n\t\t\t\t\tminTotal,\n\t\t\t\t\tactiveCompare\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst rollOutput = rollInstance.output;\n\n\t\t\tif (explodingSuccess) {\n\t\t\t\tconst successesForRoll = countExplodingSuccesses(\n\t\t\t\t\trollInstance,\n\t\t\t\t\texplodingSuccess.sign,\n\t\t\t\t\texplodingSuccess.value\n\t\t\t\t);\n\t\t\t\tsuccessCount += successesForRoll;\n\n\t\t\t\tlet formattedRollOutput = rollOutput\n\t\t\t\t\t.replace(explodingSuccess.normalizedSegment, explodingSuccess.originalSegment)\n\t\t\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successesForRoll}`);\n\t\t\t\tformattedRollOutput = formatOutput(formattedRollOutput, false);\n\t\t\t\tresults.push(formattedRollOutput);\n\t\t\t} else {\n\t\t\t\tconst rollTotal = rollInstance.total;\n\t\t\t\tconst isSuccess = evaluate(\n\t\t\t\t\t`${rollTotal}${activeCompare.sign}${activeCompare.value}`\n\t\t\t\t);\n\n\t\t\t\tif (isSuccess) successCount++;\n\t\t\t\tresults.push(formatOutput(rollOutput, isSuccess));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\n\t\t}\n\t}\n\n\tif (explodingSuccess) {\n\t\tconst signSource = explodingSuccess?.originalDice ?? diceDisplay;\n\t\tconst explodingMatch = signSource.match(EXPLODING_SUCCESS_REGEX);\n\t\tif (explodingMatch) {\n\t\t\tconst [, doubledSignRaw, valueStr] = explodingMatch;\n\t\t\tlet doubledSign: string;\n\t\t\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\n\t\t\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\n\t\t\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\n\n\t\t\tconst signMap: Record<string, Compare[\"sign\"]> = {\n\t\t\t\t\">>\": \">\",\n\t\t\t\t\"<<\": \"<\",\n\t\t\t\t\">=\": \">=\",\n\t\t\t\t\"<=\": \"<=\",\n\t\t\t\t\"==\": \"=\",\n\t\t\t\t\"!==\": \"!=\",\n\t\t\t\t\"!!==\": \"=\",\n\t\t\t};\n\t\t\tconst mappedSign = signMap[doubledSign];\n\t\t\tconst mappedValue = Number.parseFloat(valueStr);\n\n\t\t\tif (mappedSign && !Number.isNaN(mappedValue)) {\n\t\t\t\tconst resultsString = replaceUnwantedText(results.join(\"; \"));\n\t\t\t\tconst flatValues = resultsString\n\t\t\t\t\t.split(\";\")\n\t\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment));\n\n\t\t\t\tif (mappedSign === \"!=\") {\n\t\t\t\t\tconst equalsCount = flatValues.filter((val) => val === mappedValue).length;\n\t\t\t\t\tsuccessCount = flatValues.length - equalsCount;\n\t\t\t\t} else {\n\t\t\t\t\tsuccessCount = flatValues.filter((val) =>\n\t\t\t\t\t\tmatchComparison(mappedSign, val, mappedValue)\n\t\t\t\t\t).length;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (compare && trivialComparisonDetected) compare.trivial = true;\n\n\tconst finalDice = isCurlyBulk\n\t\t? `{${diceToRoll}${curlyCompare?.sign}${curlyCompare?.value}}`\n\t\t: diceToRoll;\n\n\tconst resultOutput = replaceUnwantedText(results.join(\"; \"));\n\tconst finalTotal = explodingSuccess\n\t\t? resultOutput\n\t\t\t\t.split(\";\")\n\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment))\n\t\t\t\t.filter((val) =>\n\t\t\t\t\tmatchComparison(explodingSuccess.sign, val, explodingSuccess.value)\n\t\t\t\t).length\n\t\t: successCount;\n\n\tconst modificator = getModifier(diceDisplay);\n\n\treturn {\n\t\tdice: explodingSuccess ? diceDisplay : finalDice,\n\t\tresult: resultOutput,\n\t\tcomment: comments,\n\t\tcompare: isCurlyBulk ? undefined : compare,\n\t\tmodifier: modificator,\n\t\ttotal: finalTotal,\n\t\ttrivial: trivialComparisonDetected ? true : undefined,\n\t};\n}\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport type { ComparedValue } from \"../interfaces\";\nimport { SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\nimport { roll } from \"../roll\";\nimport { isNumber } from \"../utils\";\n\n/**\n * Check if a comparison is trivial (always true or always false)\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\n * @param maxValue Maximum possible value from the dice roll\n * @param minValue Minimum possible value from the dice roll\n * @param compare The comparison object\n * @returns true if the comparison is trivial (always true or always false)\n */\nexport function isTrivialComparison(\n\tmaxValue: number,\n\tminValue: number,\n\tcompare: ComparedValue\n): boolean {\n\t// Check if comparison can never succeed (always false)\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\n\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\n\n\t// Trivial if it can never succeed OR can never fail\n\treturn !canSucceed || !canFail;\n}\n\n/**\n * Check if a comparison can theoretically fail given roll bounds\n * @param maxRollValue Maximum possible roll value\n * @param compare The comparison object\n * @param minRollValue Minimum possible roll value (defaults to 1)\n * @returns true if the comparison can fail at least once\n */\nexport function canComparisonFail(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue = 1\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\n\t\tcase \">=\":\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\n\t\tcase \"<\":\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\n\t\tcase \"<=\":\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\n\t\tcase \"!=\":\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\nexport function rollCompare(\n\tvalue: unknown,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\n\t// Handle empty value or string - return 0 as default\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\n\t\treturn { value: 0, diceResult: value as string };\n\t}\n\tconst rollComp = roll(value as string, engine, pity);\n\tif (!rollComp?.total) {\n\t\t//not a dice throw\n\t\ttry {\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\n\t\t} catch (error) {\n\t\t\t// If evaluate fails, return 0\n\t\t\treturn { value: 0, diceResult: value as string };\n\t\t}\n\t}\n\treturn {\n\t\tdice: value as string,\n\t\tvalue: rollComp.total,\n\t\tdiceResult: rollComp?.result,\n\t};\n}\n\nexport function getCompare(\n\tdice: string,\n\tcompareRegex: RegExpMatchArray,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n): { dice: string; compare: ComparedValue | undefined } {\n\t/**\n\t * @source: https://dice-roller.github.io/documentation/guide/notation/modifiers.html#target-success-dice-pool\n\t * Some system count the number of a dice that are greater than or equal to a target, and not the \"total\" of rolled dice.\n\t * We \"count\" the number of dice that meet a criterion, and not the total of the dice.\n\t * To support this, we use the group notation. It a little different than the notation of dice-roller, but it a sacrifice to not break the current notation.\n\t * @note:\n\t * - `{2d3}>=4` will be the same as `2d3>=4` and thus keep the comparaison.\n\t * - `{2d3>=4}` will count the total of dice that are greater than or equal to 4, and not the total of the dice.\n\t * - `{2d3,1d4}>=4` won't use the comparison, but will count the number of dice that are greater than or equal to 4. If the total of the dice is needed, just remove the group notation and use `2d3+1d4>=4`.\n\t */\n\tif (\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\n\t)\n\t\treturn { dice, compare: undefined };\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\n\tlet compare: ComparedValue;\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\n\tconst calc = compareRegex[2];\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\n\n\tif (sign) {\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\n\t\tconst total = evaluate(rCompare.value.toString());\n\t\tdice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: total,\n\t\t\toriginalDice: rCompare.dice,\n\t\t\trollValue: rCompare.diceResult,\n\t\t};\n\t} else {\n\t\tconst rcompare = rollCompare(calc, engine, pity);\n\t\tcompare = {\n\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\n\t\t\tvalue: rcompare.value,\n\t\t\toriginalDice: rcompare.dice,\n\t\t\trollValue: rcompare.diceResult,\n\t\t};\n\t}\n\n\treturn { dice, compare };\n}\n\n/**\n * Check if a comparison can theoretically succeed given a maximum roll value\n * @example\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\n */\nexport function canComparisonSucceed(\n\tmaxRollValue: number,\n\tcompare: ComparedValue,\n\tminRollValue?: number\n): boolean {\n\tswitch (compare.sign) {\n\t\tcase \">\":\n\t\t\treturn maxRollValue > compare.value;\n\t\tcase \">=\":\n\t\t\treturn maxRollValue >= compare.value;\n\t\tcase \"<\":\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"<=\":\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\n\t\tcase \"!=\":\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n","import { evaluate } from \"mathjs\";\nimport \"uniformize\";\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { type Engine, Random } from \"random-js\";\nimport {\n\ttype CustomCritical,\n\tDiceTypeError,\n\tdiceTypeRandomParse,\n\tFormulaError,\n\tSIGN_REGEX_SPACE,\n\ttype StatisticalTemplate,\n} from \".\";\n\n/**\n * Escape regex string\n * @param string {string}\n */\nexport function escapeRegex(string: string) {\n\treturn string.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Allow to keep the text as if in brackets\n * @param dice {string}\n * @return {string} the dice with the text in brackets as if, but the dice (not in brackets) is standardized\n */\nexport function standardizeDice(dice: string): string {\n\treturn dice.replace(/(\\[[^\\]]+])|([^[]+)/g, (_match, insideBrackets, outsideText) =>\n\t\tinsideBrackets ? insideBrackets : outsideText.standardize().replaceAll(\"df\", \"dF\")\n\t);\n}\n\n/**\n * Replace the stat name by their value using stat\n * and after evaluate any formula using `replaceFormulaInDice`\n * @param {string} originalDice\n * @param {Record<string,number>|undefined} stats\n * @param {string|undefined} dollarValue\n */\nexport function generateStatsDice(\n\toriginalDice: string,\n\tstats?: Record<string, number>,\n\tdollarValue?: string\n) {\n\tlet dice = originalDice.standardize();\n\tif (stats && Object.keys(stats).length > 0) {\n\t\tconst statKeys = Object.keys(stats);\n\t\tconst partsRegex = /(\\[[^\\]]+])|([^[]+)/g;\n\t\tlet result = \"\";\n\t\tlet match: RegExpExecArray | null;\n\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\twhile ((match = partsRegex.exec(dice)) !== null) {\n\t\t\tconst insideBrackets = match[1];\n\t\t\tconst outsideText = match[2];\n\t\t\tif (insideBrackets) {\n\t\t\t\tresult += insideBrackets;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!outsideText) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst tokenRegex = /([\\p{L}\\p{N}_]+)/gu;\n\t\t\tlet lastIndex = 0;\n\t\t\tlet tokenMatch: RegExpExecArray | null;\n\t\t\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\t\t\twhile ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {\n\t\t\t\tresult += outsideText.slice(lastIndex, tokenMatch.index);\n\t\t\t\tconst token = tokenMatch[0];\n\t\t\t\tconst tokenStd = token.standardize();\n\n\t\t\t\t// Check for dice notation patterns like \"1dstat1\" or \"dstat1\"\n\t\t\t\tconst diceMatch = /^(\\d*)d(.+)$/i.exec(tokenStd);\n\t\t\t\tif (diceMatch) {\n\t\t\t\t\tconst diceCount = diceMatch[1] || \"\";\n\t\t\t\t\tconst afterD = diceMatch[2];\n\t\t\t\t\tlet foundStatAfterD = false;\n\t\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\t\tif (afterD === keyStd) {\n\t\t\t\t\t\t\tresult += `${diceCount}d${stats[key].toString()}`;\n\t\t\t\t\t\t\tfoundStatAfterD = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (foundStatAfterD) {\n\t\t\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlet bestKey: string | null = null;\n\t\t\t\tlet bestScore = 0;\n\t\t\t\tfor (const key of statKeys) {\n\t\t\t\t\tconst keyStd = key.standardize();\n\t\t\t\t\tif (tokenStd === keyStd) {\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t\tbestScore = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst score = similarityScore(tokenStd, keyStd);\n\t\t\t\t\tif (score > bestScore) {\n\t\t\t\t\t\tbestScore = score;\n\t\t\t\t\t\tbestKey = key;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (bestKey && bestScore >= 0.6) {\n\t\t\t\t\tconst statValue = stats[bestKey];\n\t\t\t\t\tresult += statValue.toString();\n\t\t\t\t} else {\n\t\t\t\t\tresult += token;\n\t\t\t\t}\n\t\t\t\tlastIndex = tokenRegex.lastIndex;\n\t\t\t}\n\t\t\tresult += outsideText.slice(lastIndex);\n\t\t}\n\t\tdice = result;\n\t}\n\tif (dollarValue) dice = dice.replaceAll(\"$\", dollarValue);\n\treturn replaceFormulaInDice(dice);\n}\n\n/**\n * Replace the {{}} in the dice string and evaluate the interior if any\n * @param dice {string}\n */\nexport function replaceFormulaInDice(dice: string) {\n\tconst formula = /(?<formula>\\{{2}(.+?)}{2})/gim;\n\t// biome-ignore lint/suspicious/noImplicitAnyLet: needed for regex loop\n\tlet match;\n\tlet modifiedDice = dice;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best way to regex in a loop\n\twhile ((match = formula.exec(dice)) !== null) {\n\t\tif (match.groups?.formula) {\n\t\t\tconst formulae = match.groups.formula.replaceAll(\"{{\", \"\").replaceAll(\"}}\", \"\");\n\t\t\ttry {\n\t\t\t\tconst result = evaluate(formulae);\n\t\t\t\tmodifiedDice = modifiedDice.replace(match.groups.formula, result.toString());\n\t\t\t} catch (error) {\n\t\t\t\tthrow new FormulaError(match.groups.formula, \"replaceFormulasInDice\", error);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cleanedDice(modifiedDice);\n}\n\n/**\n * Replace the ++ +- -- by their proper value:\n * - `++` = `+`\n * - `+-` = `-`\n * - `--` = `+`\n * @param dice {string}\n */\nfunction cleanedDice(dice: string) {\n\treturn dice\n\t\t.replaceAll(\"+-\", \"-\")\n\t\t.replaceAll(\"--\", \"+\")\n\t\t.replaceAll(\"++\", \"+\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimEnd();\n}\n\n/**\n * Verify if a value is a number, even if it's a \"number\" string\n * @param value {unknown}\n * @returns {boolean}\n */\nexport function isNumber(value: unknown): boolean {\n\treturn (\n\t\tvalue !== undefined &&\n\t\t(typeof value === \"number\" ||\n\t\t\t(!Number.isNaN(Number(value)) &&\n\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\tvalue.trim().length > 0))\n\t);\n}\n\n/**\n * Replace the `{exp}` in the dice.\n * If the `{exp}` has a default value in the form of `{exp || defaultValue}`, it will be replaced by the default value.\n * @param {string} dice\n * @param engine\n * @returns {string} the dice with the {exp} replaced by a random value\n */\nexport function replaceExpByRandom(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): string {\n\tconst diceRegex = /\\{exp( ?\\|\\| ?(?<default>\\d+))?}/gi;\n\treturn dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {\n\t\tconst defaultValue = groups?.default;\n\t\treturn defaultValue ?? randomInt(1, 999, engine).toString();\n\t});\n}\n\n/**\n * Utility function to get a random integer between min and max and using the specified engine\n * @param min {number}\n * @param max {number}\n * @param engine {Engine | null} Engine to use, default to nodeCrypto\n * @param rng {Random | undefined} Random instance to use, see https://www.npmjs.com/package/random-js#usage\n * @returns {number} Random integer between min and max\n */\nexport function randomInt(\n\tmin: number,\n\tmax: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\trng?: Random\n): number {\n\tif (!rng) rng = new Random(engine || undefined);\n\treturn rng.integer(min, max);\n}\n\n/**\n * Calcule la distance de Levenshtein entre deux chaînes\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\tif (a === b) return 0;\n\tconst al = a.length;\n\tconst bl = b.length;\n\tif (al === 0) return bl;\n\tif (bl === 0) return al;\n\tconst v0 = new Array<number>(bl + 1);\n\tconst v1 = new Array<number>(bl + 1);\n\tfor (let i = 0; i <= bl; i++) v0[i] = i;\n\tfor (let i = 0; i < al; i++) {\n\t\tv1[0] = i + 1;\n\t\tfor (let j = 0; j < bl; j++) {\n\t\t\tconst cost = a[i] === b[j] ? 0 : 1;\n\t\t\tv1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);\n\t\t}\n\t\tfor (let j = 0; j <= bl; j++) v0[j] = v1[j];\n\t}\n\treturn v1[bl];\n}\n\n/**\n * Score de similarité normalisé entre 0 et 1 (1 = identique)\n */\nfunction similarityScore(a: string, b: string): number {\n\tconst la = a.length;\n\tconst lb = b.length;\n\tif (la === 0 && lb === 0) return 1;\n\tconst dist = levenshteinDistance(a, b);\n\tconst max = Math.max(la, lb);\n\treturn 1 - dist / max;\n}\n\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","import type { DiceRoll } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Compare } from \"../interfaces\";\nimport { matchComparison } from \"./signs\";\n\nexport type ExplodingSuccess = {\n\tdice: string;\n\toriginalDice: string;\n\tsign: Compare[\"sign\"];\n\tvalue: number;\n\tnormalizedSegment: string;\n\toriginalSegment: string;\n};\n\nexport const EXPLODING_SUCCESS_REGEX =\n\t/(!(?:>>=|<<=|!==|!!==|>>|<<|==|!=))(-?\\d+(?:\\.\\d+)?)/;\n\nexport function normalizeExplodingSuccess(dice: string): ExplodingSuccess | undefined {\n\tconst match = dice.match(EXPLODING_SUCCESS_REGEX);\n\tif (!match) return undefined;\n\n\tconst [, doubledSignRaw, valueStr] = match;\n\tlet doubledSign: string;\n\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\n\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\n\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\n\tconst signMap: Record<string, Compare[\"sign\"]> = {\n\t\t\">>\": \">\",\n\t\t\"<<\": \"<\",\n\t\t\">>=\": \">=\",\n\t\t\"<<=\": \"<=\",\n\t\t\"==\": \"=\",\n\t\t\"!==\": \"!=\",\n\t\t\"!!==\": \"=\",\n\t};\n\n\tconst normalizedSign = signMap[doubledSign];\n\tif (!normalizedSign) return undefined;\n\tlet parsedValue = Number.parseFloat(valueStr);\n\tif (Number.isNaN(parsedValue)) {\n\t\ttry {\n\t\t\tparsedValue = Number.parseFloat(evaluate(valueStr) as unknown as string);\n\t\t} catch (_error) {\n\t\t\tparsedValue = 0;\n\t\t}\n\t}\n\n\t// Remove comparison for the actual explode mechanic so it uses default explode\n\tconst normalizedSegment = \"!\";\n\tconst replacedDice = dice.replace(match[0], normalizedSegment);\n\n\treturn {\n\t\tdice: replacedDice,\n\t\toriginalDice: dice,\n\t\tsign: normalizedSign,\n\t\tvalue: parsedValue,\n\t\tnormalizedSegment,\n\t\toriginalSegment: match[0],\n\t};\n}\n\nexport function countExplodingSuccesses(\n\tdiceRoll: DiceRoll | DiceRoll[],\n\tsign: Compare[\"sign\"],\n\tvalue: number\n): number {\n\tconst rollsArray = Array.isArray(diceRoll) ? diceRoll : [diceRoll];\n\tconst flatValues: number[] = [];\n\n\tfor (const dr of rollsArray) {\n\t\tconst groups = (dr as DiceRoll).rolls ?? [];\n\t\tfor (const group of groups as unknown as Array<{\n\t\t\trolls?: Array<{ value?: number }>;\n\t\t}>) {\n\t\t\tconst innerRolls = group.rolls ?? [];\n\t\t\tfor (const roll of innerRolls) {\n\t\t\t\tif (typeof roll.value === \"number\") flatValues.push(roll.value);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn flatValues.reduce(\n\t\t(acc, current) => acc + (matchComparison(sign, current, value) ? 1 : 0),\n\t\t0\n\t);\n}\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport type { Compare, Resultat } from \"../interfaces\";\nimport { replaceInFormula, roll } from \"../roll\";\nimport { getCompare, isTrivialComparison } from \"./compare\";\nimport { replaceText } from \"./replace\";\n\nexport function matchComparison(sign: Compare[\"sign\"], val: number, value: number) {\n\tswitch (sign) {\n\t\tcase \">\":\n\t\t\treturn val > value;\n\t\tcase \">=\":\n\t\t\treturn val >= value;\n\t\tcase \"<\":\n\t\t\treturn val < value;\n\t\tcase \"<=\":\n\t\t\treturn val <= value;\n\t\tcase \"=\":\n\t\tcase \"==\":\n\t\t\treturn val === value;\n\t\tcase \"!=\":\n\t\t\treturn val !== value;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nexport function 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\nexport function compareSignFormule(\n\ttoRoll: string,\n\tcompareRegex: RegExpMatchArray,\n\telement: string,\n\tdiceResult: Resultat,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean,\n\trollBounds?: { min: number; max: number }\n): { dice: string; results: string; compare?: Compare; trivial: boolean } {\n\tlet results = \"\";\n\tlet trivial = false;\n\tconst compareResult = getCompare(toRoll, compareRegex, engine);\n\tconst toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;\n\tlet res: unknown;\n\ttry {\n\t\tres = evaluate(toCompare);\n\t} catch (error) {\n\t\tres = roll(toCompare, engine, pity);\n\t}\n\tif (typeof res === \"boolean\") {\n\t\tconst detectedTrivial =\n\t\t\trollBounds && compareResult.compare\n\t\t\t\t? isTrivialComparison(rollBounds.max, rollBounds.min, compareResult.compare)\n\t\t\t\t: false;\n\t\tif (detectedTrivial && compareResult.compare) compareResult.compare.trivial = true;\n\t\tif (detectedTrivial) trivial = true;\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\n\t} else if (res instanceof Object) {\n\t\tconst diceResult = res as Resultat;\n\t\tif (diceResult.compare) {\n\t\t\tconst toEvaluate = evaluate(\n\t\t\t\t`${diceResult.total}${diceResult.compare.sign}${diceResult.compare.value}`\n\t\t\t);\n\t\t\tconst sign = toEvaluate ? \"✓\" : \"✕\";\n\t\t\tconst invertedSign = toEvaluate\n\t\t\t\t? diceResult.compare.sign\n\t\t\t\t: inverseSign(diceResult.compare.sign);\n\t\t\tconst dice = replaceText(element, 0, diceResult.dice).diceAll;\n\n\t\t\tresults = `${sign} ${dice}: ${diceResult.result.split(\":\").splice(1).join(\":\").trim()}${invertedSign}${diceResult.compare.value}`;\n\t\t\tif (diceResult.compare.trivial) trivial = true;\n\t\t}\n\t}\n\treturn { dice: compareResult.dice, results, compare: compareResult.compare, trivial };\n}\n","import { COMMENT_REGEX, SYMBOL_DICE } from \"../interfaces/constant\";\n\nexport function replaceUnwantedText(dice: string) {\n\treturn dice.replaceAll(/[{}]/g, \"\").replaceAll(/s[ad]/gi, \"\");\n}\n\nexport function 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\nexport function 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\nexport function formatComment(dice: string) {\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\n\tconst commentsMatch = commentsRegex.exec(dice);\n\tconst comments = commentsMatch?.groups?.comments\n\t\t? `${commentsMatch.groups.comments}`\n\t\t: \"\";\n\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\n\t// to avoid conflicts with parentheses inside bracket comments\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\n\tconst optional = optionalComments?.groups?.comment\n\t\t? `${optionalComments.groups.comment.trim()}`\n\t\t: \"\";\n\n\t//fusion of both comments with a space if both exists\n\t//result expected = \"__comment1 comment2__ — \"\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\n\tlet finalComment = \"\";\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\n\telse if (comments) finalComment = `__${comments}__ — `;\n\telse if (optional) finalComment = `__${optional}__ — `;\n\treturn finalComment;\n}\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport type { Engine } from \"random-js\";\nimport type { Modifier, Sign, SortOrder } from \"../interfaces\";\nimport { DETECT_CRITICAL } from \"../interfaces/constant\";\nimport { replaceFormulaInDice, standardizeDice } from \"../utils\";\nimport { calculator } from \"./calculator\";\nimport { type ExplodingSuccess, normalizeExplodingSuccess } from \"./exploding\";\n\nexport function 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\nexport function extractValuesFromOutput(output: string): number[] {\n\tconst values: number[] = [];\n\tconst regex = /\\[([^\\]]+)\\]/g;\n\tlet match: RegExpExecArray | null;\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best method to extract all matches\n\twhile ((match = regex.exec(output)) !== null) {\n\t\tconst segmentValues = match[1]\n\t\t\t.split(\",\")\n\t\t\t.map((v) => Number.parseInt(v.replace(/[!*]/g, \"\").trim(), 10))\n\t\t\t.filter((v) => !Number.isNaN(v));\n\t\tvalues.push(...segmentValues);\n\t}\n\treturn values;\n}\n\nexport function getRollBounds(\n\tdice: string,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): { min: number; max: number } | undefined {\n\ttry {\n\t\tconst roller = new DiceRoller();\n\t\tNumberGenerator.generator.engine = engine;\n\t\tconst rollResult = roller.roll(dice);\n\t\tconst instance = Array.isArray(rollResult) ? rollResult[0] : rollResult;\n\t\tconst { minTotal, maxTotal } = instance;\n\t\treturn { min: minTotal, max: maxTotal };\n\t} catch (error) {\n\t\t// Ignore bounds computation errors; trivial detection will simply be skipped\n\t}\n\treturn undefined;\n}\n\nexport function setSortOrder(toRoll: string, sort?: SortOrder): string {\n\t//First check if the diceToRoll contains already a sort order\n\tconst sortRegex = /(sa|sd|s)/i;\n\tif (sort && !toRoll.match(sortRegex)) {\n\t\t//we should insert the sort order at the end of the dice string and before the possible modifier or comparison\n\t\tconst modifierComparisonRegex = /([+\\-*/%^]\\d+|([><=!]+\\d+f)|([><=]|!=)+\\d+)$/;\n\t\tconst match = toRoll.match(modifierComparisonRegex);\n\t\tif (match) {\n\t\t\t//Insert before the modifier or comparison\n\t\t\tconst index = match.index!;\n\t\t\ttoRoll = `${toRoll.slice(0, index)}${sort}${toRoll.slice(index)}`;\n\t\t} else {\n\t\t\t//Append at the end\n\t\t\ttoRoll += sort;\n\t\t}\n\t}\n\treturn toRoll;\n}\n\ninterface PreparedDice {\n\tdice: string;\n\tdiceDisplay: string;\n\texplodingSuccess?: ExplodingSuccess;\n\tisSharedRoll: boolean;\n\tisSharedCurly: boolean;\n\tisCurlyBulk: boolean;\n\tbulkContent: string;\n\tisSimpleCurly: boolean;\n}\n\n/**\n * Prépare la chaîne de dés pour le traitement\n */\nexport function prepareDice(diceInput: string): PreparedDice {\n\tlet dice = standardizeDice(replaceFormulaInDice(diceInput))\n\t\t.replace(/^\\+/, \"\")\n\t\t.replaceAll(\"=>\", \">=\")\n\t\t.replaceAll(\"=<\", \"<=\")\n\t\t.trimStart();\n\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\n\n\tconst explodingSuccess = normalizeExplodingSuccess(dice);\n\tif (explodingSuccess) dice = explodingSuccess.dice;\n\n\tlet diceDisplay: string;\n\tif (dice.includes(\";\")) {\n\t\tconst mainDice = dice.split(\";\")[0];\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? mainDice;\n\t} else {\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? dice;\n\t}\n\n\tconst curlyBulkMatch = dice.match(/^\\{(\\d+#.*)\\}$/);\n\tconst isCurlyBulk = !!curlyBulkMatch;\n\tconst bulkContent = isCurlyBulk ? curlyBulkMatch![1] : \"\";\n\n\tconst isSharedRoll = dice.includes(\";\");\n\tlet isSharedCurly = false;\n\n\tif (isSharedRoll && dice.match(/^\\{.*;\\s*.*\\}$/)) {\n\t\tdice = dice.slice(1, -1);\n\t\tisSharedCurly = true;\n\t\tdiceDisplay = diceDisplay.slice(1);\n\t}\n\n\t// Handle simple curly braces like {1d20+5} or {1d20+5>10}\n\t// But NOT dice pool notation like {2d6>4} where the comparison is inside the braces WITHOUT modifiers\n\tlet isSimpleCurly = false;\n\tif (!isCurlyBulk && !isSharedRoll && dice.match(/^\\{.*\\}$/)) {\n\t\t// Check if this is a dice pool (comparison inside the braces WITHOUT modifiers)\n\t\tconst innerContent = dice.slice(1, -1); // Remove outer braces\n\t\tconst hasModifiers = innerContent.match(/[+\\-*/%^]/);\n\t\tconst hasComparison = innerContent.match(/(([><=!]+\\d+f)|([><=]|!=)+\\d+)/);\n\n\t\t// Only remove braces if it's not a dice pool\n\t\t// Dice pool: has comparison inside, NO modifiers (like {2d6>4})\n\t\t// Simple curly: has modifiers before comparison (like {1d20+5>10}) or just plain dice (like {1d20+5})\n\t\tif (!(hasComparison && !hasModifiers)) {\n\t\t\tdice = innerContent;\n\t\t\tisSimpleCurly = true;\n\t\t}\n\t}\n\n\treturn {\n\t\tdice,\n\t\tdiceDisplay,\n\t\texplodingSuccess,\n\t\tisSharedRoll,\n\t\tisSharedCurly,\n\t\tisCurlyBulk,\n\t\tbulkContent,\n\t\tisSimpleCurly,\n\t};\n}\n","import { evaluate } from \"mathjs\";\nimport type { Sign } from \"../interfaces\";\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","import type { DiceRoll, DiceRoller } from \"@dice-roller/rpg-dice-roller\";\nimport { evaluate } from \"mathjs\";\nimport type { Engine } from \"random-js\";\nimport { DiceTypeError } from \"../errors\";\nimport type { Compare, Resultat } from \"../interfaces\";\nimport { roll } from \"../roll\";\nimport { canComparisonSucceed } from \"./compare\";\n\n/**\n * Gère le système de pity (relance en cas d'échec)\n */\nexport function handlePitySystem(\n\tdice: string,\n\tcompare: Compare,\n\tdiceRoll: DiceRoll | DiceRoll[],\n\troller: DiceRoller,\n\tengine: Engine | null\n): { rerollCount: number; result?: Resultat } {\n\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\n\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\n\tconst isComparisonPossible =\n\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\n\n\tif (!isComparisonPossible) {\n\t\treturn { rerollCount: 0 };\n\t}\n\n\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\n\tif (isFail) {\n\t\treturn { rerollCount: 0 };\n\t}\n\n\tconst maxReroll = 100;\n\tlet rerollCount = 0;\n\tlet res: Resultat | undefined;\n\n\twhile (!isFail && rerollCount < maxReroll) {\n\t\ttry {\n\t\t\tres = roll(dice, engine, false);\n\t\t} catch (error) {\n\t\t\tthrow new DiceTypeError(dice, \"roll\", error);\n\t\t}\n\t\trerollCount++;\n\t\tif (res && res.total !== undefined) {\n\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\n\t\t}\n\t}\n\n\treturn { rerollCount, result: res };\n}\n","import { evaluate } from \"mathjs\";\nimport { type Engine, Random } from \"random-js\";\nimport \"uniformize\";\n\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\nimport {\n\tcreateCriticalCustom,\n\tDETECT_CRITICAL,\n\tDiceTypeError,\n\tEmptyObjectError,\n\tescapeRegex,\n\tFormulaError,\n\tNoStatisticsError,\n\treplaceExpByRandom,\n\treplaceFormulaInDice,\n\troll,\n\ttype StatisticalTemplate,\n\tTooManyDice,\n\ttemplateSchema,\n} from \".\";\nimport { isNumber, randomInt } from \"./utils\";\n\n/**\n * Verify if the provided dice work with random value\n * @param testDice {string}\n * @param allStats {Record<string,number>}\n * @param engine\n * @param pity\n */\nexport function evalStatsDice(\n\ttestDice: string,\n\tallStats?: Record<string, number>,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\n\tpity?: boolean\n) {\n\tlet dice = testDice.trimEnd();\n\tif (allStats && Object.keys(allStats).length > 0) {\n\t\tconst names = Object.keys(allStats);\n\t\tfor (const name of names) {\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\t\tif (dice.standardize().match(regex)) {\n\t\t\t\tconst statValue = allStats[name];\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\n\t\t\t}\n\t\t}\n\t}\n\ttry {\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\n\t\treturn testDice;\n\t} catch (error) {\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\n\t}\n}\n\n/**\n * Generate a random dice and remove the formula (+ evaluate it)\n * Used for diceDamage only\n * @param value {string}\n * @param template {StatisticalTemplate}\n * @param engine\n * @returns\n */\nexport function diceRandomParse(\n\tvalue: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\n\tvalue = value.standardize();\n\tconst statNames = Object.keys(template.statistics);\n\tlet newDice = value;\n\tfor (const name of statNames) {\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\n\t\tif (value.match(regex)) {\n\t\t\tlet max: undefined | number;\n\t\t\tlet min: undefined | number;\n\t\t\tconst foundStat = template.statistics?.[name];\n\t\t\tif (foundStat) {\n\t\t\t\tmax = foundStat.max;\n\t\t\t\tmin = foundStat.min;\n\t\t\t}\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\n\t\t}\n\t}\n\treturn replaceFormulaInDice(newDice);\n}\n\n/**\n * Same as damageDice but for DiceType\n * @param dice {string}\n * @param template {StatisticalTemplate}\n * @param engine\n */\nexport function diceTypeRandomParse(\n\tdice: string,\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tdice = replaceExpByRandom(dice);\n\tif (!template.statistics) return dice;\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\n\t\t(stat) => !template.statistics?.[stat].combinaison\n\t);\n\tif (!firstStatNotcombinaison) return dice;\n\tconst stats = template.statistics[firstStatNotcombinaison];\n\tconst { min, max } = stats;\n\tconst total = template.total || 100;\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\n}\n\n/**\n * Random the combinaison and evaluate it to check if everything is valid\n * @param combinaison {Record<string,string>}\n * @param stats {Record<string,number|number>}\n */\nexport function evalCombinaison(\n\tcombinaison: Record<string, string>,\n\tstats: Record<string, number | string>\n) {\n\tconst newStats: Record<string, number> = {};\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\n\t\t//replace the stats in formula\n\t\tlet formula = combin.standardize();\n\t\tfor (const [statName, value] of Object.entries(stats)) {\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\t\tformula = formula.replace(regex, value.toString());\n\t\t}\n\t\ttry {\n\t\t\tnewStats[stat] = evaluate(formula);\n\t\t} catch (error) {\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\n\t\t}\n\t}\n\treturn newStats;\n}\n\n/**\n * Evaluate one selected combinaison\n * @param combinaison {string}\n * @param stats {[name: string]: string|number}\n */\nexport function evalOneCombinaison(\n\tcombinaison: string,\n\tstats: Record<string, number | string>\n) {\n\tlet formula = combinaison.standardize();\n\tfor (const [statName, value] of Object.entries(stats)) {\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\n\t\tformula = formula.replace(regex, value.toString());\n\t}\n\ttry {\n\t\treturn evaluate(formula);\n\t} catch (error) {\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\n\t}\n}\n\nfunction convertNumber(number: string | number | undefined) {\n\tif (number === undefined || number === null) return undefined;\n\tif (\n\t\tnumber.toString().length === 0 ||\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\n\t)\n\t\treturn undefined;\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\n\treturn undefined;\n}\n\n/**\n * Parse the provided JSON and verify each field to check if everything could work when rolling\n * @param {unknown} template\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\n * @param engine\n * @returns {StatisticalTemplate}\n */\nexport function verifyTemplateValue(\n\ttemplate: unknown,\n\tverify = true,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n): StatisticalTemplate {\n\tconst parsedTemplate = templateSchema.parse(template);\n\tconst { success, failure } = parsedTemplate.critical ?? {};\n\tconst criticicalVal = {\n\t\tsuccess: convertNumber(success),\n\t\tfailure: convertNumber(failure),\n\t};\n\tconst statistiqueTemplate: StatisticalTemplate = {\n\t\tdiceType: parsedTemplate.diceType,\n\t\tstatistics: parsedTemplate.statistics,\n\t\tcritical: criticicalVal,\n\t\ttotal: parsedTemplate.total,\n\t\tcharName: parsedTemplate.charName,\n\t\tdamage: parsedTemplate.damage,\n\t\tcustomCritical: parsedTemplate.customCritical,\n\t\tforceDistrib: parsedTemplate.forceDistrib,\n\t};\n\tif (!verify) return statistiqueTemplate;\n\tif (statistiqueTemplate.diceType) {\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\n\t\t\tthrow new DiceTypeError(\n\t\t\t\tstatistiqueTemplate.diceType,\n\t\t\t\t\"critical_dice_type\",\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\n\t\t\t);\n\t\t}\n\t\tconst cleanedDice = diceTypeRandomParse(\n\t\t\tstatistiqueTemplate.diceType,\n\t\t\tstatistiqueTemplate,\n\t\t\tengine\n\t\t);\n\t\tconst rolled = roll(cleanedDice, engine);\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\n\t}\n\tif (statistiqueTemplate.customCritical) {\n\t\tif (!statistiqueTemplate.diceType) {\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\n\t\t}\n\t\tconst customCritical = statistiqueTemplate.customCritical;\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\n\t\t\tconst cleanedDice = createCriticalCustom(\n\t\t\t\tstatistiqueTemplate.diceType!,\n\t\t\t\tcustom,\n\t\t\t\tstatistiqueTemplate,\n\t\t\t\tengine\n\t\t\t);\n\t\t\tconst rolled = roll(cleanedDice, engine);\n\t\t\tif (!rolled)\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\n\t\t}\n\t}\n\ttestDiceRegistered(statistiqueTemplate, engine);\n\ttestStatCombinaison(statistiqueTemplate, engine);\n\treturn statistiqueTemplate;\n}\n\n/**\n * Test each damage roll from the template.damage\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testDiceRegistered(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.damage) return;\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\n\tfor (const [name, dice] of Object.entries(template.damage)) {\n\t\tif (!dice) continue;\n\t\tconst diceReplaced = replaceExpByRandom(dice);\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\n\t\ttry {\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\n\t\t}\n\t}\n}\n\n/**\n * Test all combinaison with generated random value\n * @param {StatisticalTemplate} template\n * @param engine\n */\nexport function testStatCombinaison(\n\ttemplate: StatisticalTemplate,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tif (!template.statistics) return;\n\tconst onlycombinaisonStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(\n\t\t\t([_, value]) => value.combinaison !== undefined\n\t\t)\n\t);\n\tconst allOtherStats = Object.fromEntries(\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\n\t);\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\n\tconst allStats = Object.keys(template.statistics).filter(\n\t\t(stat) => !template.statistics![stat].combinaison\n\t);\n\tif (allStats.length === 0) throw new NoStatisticsError();\n\tconst error = [];\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\n\t\tlet formula = value.combinaison as string;\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\n\t\t\tconst { max, min } = data;\n\t\t\tconst total = template.total || 100;\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\n\t\t\tconst regex = new RegExp(other, \"gi\");\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\n\t\t}\n\t\ttry {\n\t\t\tevaluate(formula);\n\t\t} catch (e) {\n\t\t\terror.push(stat);\n\t\t}\n\t}\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\n\treturn;\n}\n\n/**\n * Generate a random stat based on the template and the statistical min and max\n * @param {number|undefined} total\n * @param {number | undefined} max\n * @param {number | undefined} min\n * @param engine\n * @returns\n */\nexport function generateRandomStat(\n\ttotal: number | undefined = 100,\n\tmax?: number,\n\tmin?: number,\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\n) {\n\tlet randomStatValue = total + 1;\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\n\twhile (randomStatValue >= total || randomStatValue === 0) {\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\n\t\telse randomStatValue = randomInt(1, total, engine, random);\n\t}\n\treturn randomStatValue;\n}\n"],"mappings":";AAAA,SAAS,uBAAuB;AASzB,SAAS,YAAY,QAAyB;AAEpD,MAAI,WAAW,gBAAgB,QAAQ,WAAY,QAAO;AAC1D,MAAI,WAAW,gBAAgB,QAAQ,WAAY,QAAO;AAC1D,MAAI,WAAW,gBAAgB,QAAQ,cAAe,QAAO;AAE7D,MAAI;AAEH,UAAM,IAAI;AACV,QAAI,KAAK,OAAO,MAAM,UAAU;AAC/B,UAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAM,QAAO,EAAE;AACnD,UAAI,EAAE,aAAa,KAAM,QAAO,EAAE,YAAY;AAAA,IAC/C;AAAA,EACD,QAAQ;AAAA,EAER;AACA,SAAO;AACR;AAQO,SAAS,UAAU,QAA+D;AACxF,UAAQ,QAAQ;AAAA,IACf,KAAK;AACJ,aAAO,gBAAgB,QAAQ;AAAA,IAChC,KAAK;AACJ,aAAO,gBAAgB,QAAQ;AAAA,IAChC,KAAK;AACJ,aAAO,gBAAgB,QAAQ;AAAA,IAChC;AACC,aAAO,gBAAgB,QAAQ;AAAA,EACjC;AACD;;;AC7CO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAY,MAAc,OAAgB,QAAkB;AAC3D,UAAM,IAAI;AACV,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EACf;AACD;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAY,SAAiB,OAAgB,QAAkB;AAC9D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EACf;AACD;AAEO,IAAM,aAAN,cAAyB,MAAM;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YAAY,OAAe,KAAa;AACvC,UAAM,MAAM,SAAS,CAAC;AACtB,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,MAAM;AAAA,EACZ;AACD;AAEO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC3B;AAAA,EAEhB,cAAc;AACb,UAAM;AACN,SAAK,OAAO;AAAA,EACb;AACD;AAEO,IAAM,cAAN,cAA0B,MAAM;AAAA,EACtB;AAAA,EAEhB,cAAc;AACb,UAAM;AACN,SAAK,OAAO;AAAA,EACb;AACD;AAEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACvB;AAAA,EAEhB,cAAc;AACb,UAAM;AACN,SAAK,OAAO;AAAA,EACb;AACD;AAEO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC5B;AAAA,EAEhB,cAAc;AACb,UAAM;AACN,SAAK,OAAO;AAAA,EACb;AACD;;;ACuHO,IAAK,YAAL,kBAAKA,eAAL;AACN,EAAAA,WAAA,eAAY;AACZ,EAAAA,WAAA,gBAAa;AACb,EAAAA,WAAA,UAAO;AAHI,SAAAA;AAAA,GAAA;;;AClML,IAAM,gBAAgB;AAItB,IAAM,aACZ;AACM,IAAM,mBACZ;AAEM,IAAM,cAAc;AAEpB,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;;;ACThC,SAAS,SAAS;AAElB,IAAM,uBAAuB,EAC3B,OAAO;AAAA,EACP,KAAK,EACH,OAAO,EACP,UAAU,CAAC,QAAS,QAAQ,IAAI,SAAY,GAAI,EAChD,SAAS;AAAA,EACX,KAAK,EACH,OAAO,EACP;AAAA,IAAU,CAAC,QACX,OAAO,MAAM,OAAO,SAAS,KAA0B,EAAE,CAAC,IAAI,SAAY;AAAA,EAC3E,EACC,SAAS;AAAA,EACX,aAAa,EACX,OAAO,EACP,UAAU,CAAC,QAAQ,IAAI,KAAK,KAAK,MAAS,EAC1C,SAAS;AAAA,EACX,SAAS,EAAE,QAAQ,EAAE,SAAS;AAC/B,CAAC,EACA,YAAY,CAAC,MAAM,QAAQ;AAC3B,MAAI,KAAK,QAAQ,UAAa,KAAK,QAAQ,UAAa,KAAK,OAAO,KAAK,KAAK;AAC7E,QAAI,SAAS;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,gBAAgB,KAAK,GAAG,KAAK,KAAK,GAAG;AAAA,MAC9C,MAAM,CAAC,KAAK;AAAA,IACb,CAAC;AAAA,EACF;AACD,CAAC;AAEF,IAAM,kBAAkB,EACtB,OAAO,EAAE,OAAO,GAAG,oBAAoB,EACvC,SAAS,EACT,OAAO,CAAC,UAAU,CAAC,SAAS,OAAO,KAAK,KAAK,EAAE,UAAU,IAAI;AAAA,EAC7D,SAAS;AACV,CAAC;AAEF,IAAM,iBAAiB,EACrB,OAAO;AAAA,EACP,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACnD,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AACpD,CAAC,EACA,UAAU,CAAC,WAAW;AACtB,MAAI,OAAO,YAAY,GAAI,QAAO,UAAU;AAC5C,MAAI,OAAO,YAAY,GAAI,QAAO,UAAU;AAC5C,MAAI,OAAO,YAAY,EAAG,QAAO,UAAU;AAC3C,MAAI,OAAO,YAAY,EAAG,QAAO,UAAU;AAC3C,SAAO,UAAU,OAAO,SAAS,OAAO,SAAmB,EAAE;AAC7D,SAAO,UAAU,OAAO,SAAS,OAAO,SAAmB,EAAE;AAC7D,SAAO;AACR,CAAC;AAEF,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACpC,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK,MAAM,MAAM,MAAM,IAAI,CAAC;AAAA,EAC/C,OAAO,EAAE,OAAO;AAAA,EAChB,eAAe,EAAE,QAAQ,EAAE,SAAS;AAAA,EACpC,aAAa,EAAE,QAAQ,EAAE,SAAS;AACnC,CAAC;AAED,IAAM,eAAe,EACnB,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAC7B,SAAS,EACT,OAAO,CAAC,UAAU,CAAC,SAAS,OAAO,KAAK,KAAK,EAAE,UAAU,IAAI;AAAA,EAC7D,SAAS;AACV,CAAC;AAEF,IAAM,uBAAuB,EAC3B,OAAO,EAAE,OAAO,GAAG,mBAAmB,EACtC,SAAS,EACT,OAAO,CAAC,UAAU,CAAC,SAAS,OAAO,KAAK,KAAK,EAAE,UAAU,IAAI;AAAA,EAC7D,SAAS;AACV,CAAC;AAEK,IAAM,iBAAiB,EAAE,OAAO;AAAA,EACtC,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC/B,YAAY;AAAA,EACZ,OAAO,EACL,OAAO,EACP,IAAI,CAAC,EACL,UAAU,CAAC,QAAS,QAAQ,IAAI,SAAY,GAAI,EAChD,SAAS;AAAA,EACX,cAAc,EAAE,QAAQ,EAAE,SAAS;AAAA,EACnC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,UAAU,eAAe,SAAS;AAAA,EAClC,gBAAgB;AAAA,EAChB,QAAQ;AACT,CAAC;;;ACzFD,SAAwB,cAAAC,aAAY,mBAAAC,wBAAuB;AAC3D,SAAS,YAAAC,iBAAgB;;;ACDzB,SAAS,cAAAC,aAAY,mBAAAC,wBAAuB;AAC5C,SAAS,YAAAC,iBAAgB;;;ACDzB,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,YAAAC,iBAAgB;;;ACDzB,SAAS,gBAAgB;AACzB,OAAO;AACP,SAAS,mBAAAC,wBAAuB;AAChC,SAAsB,cAAc;AAc7B,SAAS,YAAY,QAAgB;AAC3C,SAAO,OAAO,QAAQ,uBAAuB,MAAM;AACpD;AAOO,SAAS,gBAAgB,MAAsB;AACrD,SAAO,KAAK;AAAA,IAAQ;AAAA,IAAwB,CAAC,QAAQ,gBAAgB,gBACpE,iBAAiB,iBAAiB,YAAY,YAAY,EAAE,WAAW,MAAM,IAAI;AAAA,EAClF;AACD;AASO,SAAS,kBACf,cACA,OACA,aACC;AACD,MAAI,OAAO,aAAa,YAAY;AACpC,MAAI,SAAS,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AAC3C,UAAM,WAAW,OAAO,KAAK,KAAK;AAClC,UAAM,aAAa;AACnB,QAAI,SAAS;AACb,QAAI;AAEJ,YAAQ,QAAQ,WAAW,KAAK,IAAI,OAAO,MAAM;AAChD,YAAM,iBAAiB,MAAM,CAAC;AAC9B,YAAM,cAAc,MAAM,CAAC;AAC3B,UAAI,gBAAgB;AACnB,kBAAU;AACV;AAAA,MACD;AACA,UAAI,CAAC,aAAa;AACjB;AAAA,MACD;AACA,YAAM,aAAa;AACnB,UAAI,YAAY;AAChB,UAAI;AAEJ,cAAQ,aAAa,WAAW,KAAK,WAAW,OAAO,MAAM;AAC5D,kBAAU,YAAY,MAAM,WAAW,WAAW,KAAK;AACvD,cAAM,QAAQ,WAAW,CAAC;AAC1B,cAAM,WAAW,MAAM,YAAY;AAGnC,cAAM,YAAY,gBAAgB,KAAK,QAAQ;AAC/C,YAAI,WAAW;AACd,gBAAM,YAAY,UAAU,CAAC,KAAK;AAClC,gBAAM,SAAS,UAAU,CAAC;AAC1B,cAAI,kBAAkB;AACtB,qBAAW,OAAO,UAAU;AAC3B,kBAAM,SAAS,IAAI,YAAY;AAC/B,gBAAI,WAAW,QAAQ;AACtB,wBAAU,GAAG,SAAS,IAAI,MAAM,GAAG,EAAE,SAAS,CAAC;AAC/C,gCAAkB;AAClB;AAAA,YACD;AAAA,UACD;AACA,cAAI,iBAAiB;AACpB,wBAAY,WAAW;AACvB;AAAA,UACD;AAAA,QACD;AAEA,YAAI,UAAyB;AAC7B,YAAI,YAAY;AAChB,mBAAW,OAAO,UAAU;AAC3B,gBAAM,SAAS,IAAI,YAAY;AAC/B,cAAI,aAAa,QAAQ;AACxB,sBAAU;AACV,wBAAY;AACZ;AAAA,UACD;AACA,gBAAM,QAAQ,gBAAgB,UAAU,MAAM;AAC9C,cAAI,QAAQ,WAAW;AACtB,wBAAY;AACZ,sBAAU;AAAA,UACX;AAAA,QACD;AACA,YAAI,WAAW,aAAa,KAAK;AAChC,gBAAM,YAAY,MAAM,OAAO;AAC/B,oBAAU,UAAU,SAAS;AAAA,QAC9B,OAAO;AACN,oBAAU;AAAA,QACX;AACA,oBAAY,WAAW;AAAA,MACxB;AACA,gBAAU,YAAY,MAAM,SAAS;AAAA,IACtC;AACA,WAAO;AAAA,EACR;AACA,MAAI,YAAa,QAAO,KAAK,WAAW,KAAK,WAAW;AACxD,SAAO,qBAAqB,IAAI;AACjC;AAMO,SAAS,qBAAqB,MAAc;AAClD,QAAM,UAAU;AAEhB,MAAI;AACJ,MAAI,eAAe;AAEnB,UAAQ,QAAQ,QAAQ,KAAK,IAAI,OAAO,MAAM;AAC7C,QAAI,MAAM,QAAQ,SAAS;AAC1B,YAAM,WAAW,MAAM,OAAO,QAAQ,WAAW,MAAM,EAAE,EAAE,WAAW,MAAM,EAAE;AAC9E,UAAI;AACH,cAAM,SAAS,SAAS,QAAQ;AAChC,uBAAe,aAAa,QAAQ,MAAM,OAAO,SAAS,OAAO,SAAS,CAAC;AAAA,MAC5E,SAAS,OAAO;AACf,cAAM,IAAI,aAAa,MAAM,OAAO,SAAS,yBAAyB,KAAK;AAAA,MAC5E;AAAA,IACD;AAAA,EACD;AAEA,SAAO,YAAY,YAAY;AAChC;AASA,SAAS,YAAY,MAAc;AAClC,SAAO,KACL,WAAW,MAAM,GAAG,EACpB,WAAW,MAAM,GAAG,EACpB,WAAW,MAAM,GAAG,EACpB,WAAW,MAAM,IAAI,EACrB,WAAW,MAAM,IAAI,EACrB,QAAQ;AACX;AAOO,SAAS,SAAS,OAAyB;AACjD,SACC,UAAU,WACT,OAAO,UAAU,YAChB,CAAC,OAAO,MAAM,OAAO,KAAK,CAAC,KAC3B,OAAO,UAAU,YACjB,MAAM,KAAK,EAAE,SAAS;AAE1B;AASO,SAAS,mBACf,MACA,SAAwBC,iBAAgB,QAAQ,YACvC;AACT,QAAM,YAAY;AAClB,SAAO,KAAK,QAAQ,WAAW,CAAC,QAAQ,KAAK,KAAK,SAAS,SAAS,WAAW;AAC9E,UAAM,eAAe,QAAQ;AAC7B,WAAO,gBAAgB,UAAU,GAAG,KAAK,MAAM,EAAE,SAAS;AAAA,EAC3D,CAAC;AACF;AAUO,SAAS,UACf,KACA,KACA,SAAwBA,iBAAgB,QAAQ,YAChD,KACS;AACT,MAAI,CAAC,IAAK,OAAM,IAAI,OAAO,UAAU,MAAS;AAC9C,SAAO,IAAI,QAAQ,KAAK,GAAG;AAC5B;AAKA,SAAS,oBAAoB,GAAW,GAAmB;AAC1D,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,EAAE;AACb,MAAI,OAAO,EAAG,QAAO;AACrB,MAAI,OAAO,EAAG,QAAO;AACrB,QAAM,KAAK,IAAI,MAAc,KAAK,CAAC;AACnC,QAAM,KAAK,IAAI,MAAc,KAAK,CAAC;AACnC,WAAS,IAAI,GAAG,KAAK,IAAI,IAAK,IAAG,CAAC,IAAI;AACtC,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC5B,OAAG,CAAC,IAAI,IAAI;AACZ,aAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC5B,YAAM,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI;AACjC,SAAG,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI;AAAA,IAC5D;AACA,aAAS,IAAI,GAAG,KAAK,IAAI,IAAK,IAAG,CAAC,IAAI,GAAG,CAAC;AAAA,EAC3C;AACA,SAAO,GAAG,EAAE;AACb;AAKA,SAAS,gBAAgB,GAAW,GAAmB;AACtD,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,EAAE;AACb,MAAI,OAAO,KAAK,OAAO,EAAG,QAAO;AACjC,QAAM,OAAO,oBAAoB,GAAG,CAAC;AACrC,QAAM,MAAM,KAAK,IAAI,IAAI,EAAE;AAC3B,SAAO,IAAI,OAAO;AACnB;AAUO,SAAS,qBACf,MACA,gBACA,UACA,SAAwBA,iBAAgB,QAAQ,YAC/C;AACD,QAAM,eAAe,KAAK,MAAM,gBAAgB;AAChD,MAAI,aAAa;AACjB,QAAM,eAAe,oBAAoB,eAAe,OAAO,UAAU,MAAM;AAC/E,MAAI,aAAa,SAAS,GAAG;AAC5B,UAAM,IAAI,cAAc,cAAc,sBAAsB;AAC7D,QAAM,cAAc,GAAG,eAAe,IAAI,GAAG,YAAY;AACzD,MAAI,aAAc,cAAa,WAAW,QAAQ,kBAAkB,WAAW;AAAA,MAC1E,eAAc;AACnB,SAAO,oBAAoB,YAAY,UAAU,MAAM;AACxD;;;ADhQO,SAAS,oBACf,UACA,UACA,SACU;AAEV,QAAM,aAAa,qBAAqB,UAAU,SAAS,QAAQ;AAGnE,QAAM,UAAU,kBAAkB,UAAU,SAAS,QAAQ;AAG7D,SAAO,CAAC,cAAc,CAAC;AACxB;AASO,SAAS,kBACf,cACA,SACA,eAAe,GACL;AACV,UAAQ,QAAQ,MAAM;AAAA,IACrB,KAAK;AACJ,aAAO,gBAAgB,QAAQ;AAAA;AAAA,IAChC,KAAK;AACJ,aAAO,eAAe,QAAQ;AAAA;AAAA,IAC/B,KAAK;AACJ,aAAO,gBAAgB,QAAQ;AAAA;AAAA,IAChC,KAAK;AACJ,aAAO,eAAe,QAAQ;AAAA;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,iBAAiB,QAAQ,SAAS,iBAAiB,QAAQ;AAAA;AAAA,IACnE,KAAK;AACJ,aAAO,gBAAgB,QAAQ,SAAS,QAAQ,SAAS;AAAA;AAAA,IAC1D;AACC,aAAO;AAAA,EACT;AACD;AAEO,SAAS,YACf,OACA,SAAwBC,iBAAgB,QAAQ,YAChD,MACC;AACD,MAAI,SAAS,KAAK,EAAG,QAAO,EAAE,OAAO,OAAO,SAAS,OAAiB,EAAE,EAAE;AAE1E,MAAI,CAAC,SAAU,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,IAAK;AACjE,WAAO,EAAE,OAAO,GAAG,YAAY,MAAgB;AAAA,EAChD;AACA,QAAM,WAAW,KAAK,OAAiB,QAAQ,IAAI;AACnD,MAAI,CAAC,UAAU,OAAO;AAErB,QAAI;AACH,aAAO,EAAE,OAAOC,UAAS,KAAe,GAAG,YAAY,MAAgB;AAAA,IACxE,SAAS,OAAO;AAEf,aAAO,EAAE,OAAO,GAAG,YAAY,MAAgB;AAAA,IAChD;AAAA,EACD;AACA,SAAO;AAAA,IACN,MAAM;AAAA,IACN,OAAO,SAAS;AAAA,IAChB,YAAY,UAAU;AAAA,EACvB;AACD;AAEO,SAAS,WACf,MACA,cACA,SAAwBD,iBAAgB,QAAQ,YAChD,MACuD;AAWvD,MACC,KAAK,MAAM,yEAAyE;AAEpF,WAAO,EAAE,MAAM,SAAS,OAAU;AACnC,SAAO,KAAK,QAAQ,kBAAkB,EAAE;AACxC,MAAI;AAGJ,QAAM,OAAO,aAAa,CAAC;AAC3B,QAAM,OAAO,KAAK,MAAM,SAAS,IAAI,CAAC;AACtC,QAAM,cAAc,aAAa,CAAC,EAAE,MAAM,UAAU,IAAI,CAAC;AAEzD,MAAI,MAAM;AACT,UAAM,SAAS,KAAK,QAAQ,YAAY,EAAE,EAAE,QAAQ,OAAO,EAAE,EAAE,QAAQ,SAAS,EAAE;AAClF,UAAM,WAAW,YAAY,QAAQ,QAAQ,IAAI;AACjD,UAAM,QAAQC,UAAS,SAAS,MAAM,SAAS,CAAC;AAChD,WAAO,KAAK,QAAQ,kBAAkB,GAAG,WAAW,GAAG,KAAK,EAAE;AAC9D,cAAU;AAAA,MACT,MAAM;AAAA,MACN,OAAO;AAAA,MACP,cAAc,SAAS;AAAA,MACvB,WAAW,SAAS;AAAA,IACrB;AAAA,EACD,OAAO;AACN,UAAM,WAAW,YAAY,MAAM,QAAQ,IAAI;AAC/C,cAAU;AAAA,MACT,MAAM;AAAA,MACN,OAAO,SAAS;AAAA,MAChB,cAAc,SAAS;AAAA,MACvB,WAAW,SAAS;AAAA,IACrB;AAAA,EACD;AAEA,SAAO,EAAE,MAAM,QAAQ;AACxB;AAQO,SAAS,qBACf,cACA,SACA,cACU;AACV,UAAQ,QAAQ,MAAM;AAAA,IACrB,KAAK;AACJ,aAAO,eAAe,QAAQ;AAAA,IAC/B,KAAK;AACJ,aAAO,gBAAgB,QAAQ;AAAA,IAChC,KAAK;AACJ,aAAO,QAAQ,SAAS,gBAAgB;AAAA;AAAA,IACzC,KAAK;AACJ,aAAO,QAAQ,UAAU,gBAAgB;AAAA;AAAA,IAC1C,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,gBAAgB,QAAQ,SAAS,QAAQ,UAAU,gBAAgB;AAAA,IAC3E,KAAK;AACJ,aAAO,iBAAiB,QAAQ,UAAU,gBAAgB,OAAO,QAAQ;AAAA,IAC1E;AACC,aAAO;AAAA,EACT;AACD;;;AExKA,SAAS,YAAAC,iBAAgB;;;ACDzB,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,YAAAC,iBAAgB;;;ACClB,SAAS,oBAAoB,MAAc;AACjD,SAAO,KAAK,WAAW,SAAS,EAAE,EAAE,WAAW,WAAW,EAAE;AAC7D;AAEO,SAAS,eAAe,MAAc;AAG5C,QAAM,mBAAmB;AACzB,SAAO,KAAK,WAAW,kBAAkB,CAAC,QAAQ,OAAO,IAAI,EAAE,EAAE;AAClE;AAEO,SAAS,YAAY,SAAiB,OAAe,MAAc;AACzE,SAAO;AAAA,IACN,SAAS,QAAQ,QAAQ,aAAa,IAAI,KAAK,GAAG,EAAE,QAAQ,SAAS,EAAE,EAAE,KAAK;AAAA,IAC9E,SAAS,QACP,QAAQ,aAAa,IAAI,KAAK,QAAQ,eAAe,EAAE,CAAC,GAAG,EAC3D,QAAQ,SAAS,EAAE,EACnB,KAAK;AAAA,EACR;AACD;AAEO,SAAS,cAAc,MAAc;AAC3C,QAAM,gBAAgB;AACtB,QAAM,gBAAgB,cAAc,KAAK,IAAI;AAC7C,QAAM,WAAW,eAAe,QAAQ,WACrC,GAAG,cAAc,OAAO,QAAQ,KAChC;AAIH,QAAM,sBAAsB,KAAK,QAAQ,eAAe,EAAE;AAC1D,QAAM,wBAAwB;AAC9B,QAAM,mBAAmB,sBAAsB,KAAK,mBAAmB;AACvE,QAAM,WAAW,kBAAkB,QAAQ,UACxC,GAAG,iBAAiB,OAAO,QAAQ,KAAK,CAAC,KACzC;AAKH,MAAI,eAAe;AACnB,MAAI,YAAY,SAAU,gBAAe,KAAK,QAAQ,IAAI,QAAQ;AAAA,WACzD,SAAU,gBAAe,KAAK,QAAQ;AAAA,WACtC,SAAU,gBAAe,KAAK,QAAQ;AAC/C,SAAO;AACR;;;ADvCO,SAAS,gBAAgB,MAAuB,KAAa,OAAe;AAClF,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,aAAO,MAAM;AAAA,IACd,KAAK;AACJ,aAAO,OAAO;AAAA,IACf,KAAK;AACJ,aAAO,MAAM;AAAA,IACd,KAAK;AACJ,aAAO,OAAO;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,QAAQ;AAAA,IAChB,KAAK;AACJ,aAAO,QAAQ;AAAA,IAChB;AACC,aAAO;AAAA,EACT;AACD;AAEO,SAAS,YACf,MAC8C;AAC9C,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAEO,SAAS,mBACf,QACA,cACA,SACA,YACA,SAAwBC,iBAAgB,QAAQ,YAChD,MACA,YACyE;AACzE,MAAI,UAAU;AACd,MAAI,UAAU;AACd,QAAM,gBAAgB,WAAW,QAAQ,cAAc,MAAM;AAC7D,QAAM,YAAY,GAAG,cAAc,IAAI,GAAG,cAAc,SAAS,IAAI,GAAG,cAAc,SAAS,KAAK;AACpG,MAAI;AACJ,MAAI;AACH,UAAMC,UAAS,SAAS;AAAA,EACzB,SAAS,OAAO;AACf,UAAM,KAAK,WAAW,QAAQ,IAAI;AAAA,EACnC;AACA,MAAI,OAAO,QAAQ,WAAW;AAC7B,UAAM,kBACL,cAAc,cAAc,UACzB,oBAAoB,WAAW,KAAK,WAAW,KAAK,cAAc,OAAO,IACzE;AACJ,QAAI,mBAAmB,cAAc,QAAS,eAAc,QAAQ,UAAU;AAC9E,QAAI,gBAAiB,WAAU;AAC/B,cAAU,iBAAiB,SAAS,YAAY,eAAe,KAAK,QAAQ,IAAI;AAAA,EACjF,WAAW,eAAe,QAAQ;AACjC,UAAMC,cAAa;AACnB,QAAIA,YAAW,SAAS;AACvB,YAAM,aAAaD;AAAA,QAClB,GAAGC,YAAW,KAAK,GAAGA,YAAW,QAAQ,IAAI,GAAGA,YAAW,QAAQ,KAAK;AAAA,MACzE;AACA,YAAM,OAAO,aAAa,WAAM;AAChC,YAAM,eAAe,aAClBA,YAAW,QAAQ,OACnB,YAAYA,YAAW,QAAQ,IAAI;AACtC,YAAM,OAAO,YAAY,SAAS,GAAGA,YAAW,IAAI,EAAE;AAEtD,gBAAU,GAAG,IAAI,IAAI,IAAI,KAAKA,YAAW,OAAO,MAAM,GAAG,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC,GAAG,YAAY,GAAGA,YAAW,QAAQ,KAAK;AAC/H,UAAIA,YAAW,QAAQ,QAAS,WAAU;AAAA,IAC3C;AAAA,EACD;AACA,SAAO,EAAE,MAAM,cAAc,MAAM,SAAS,SAAS,cAAc,SAAS,QAAQ;AACrF;;;AD/EO,IAAM,0BACZ;AAEM,SAAS,0BAA0B,MAA4C;AACrF,QAAM,QAAQ,KAAK,MAAM,uBAAuB;AAChD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,CAAC,EAAE,gBAAgB,QAAQ,IAAI;AACrC,MAAI;AACJ,MAAI,mBAAmB,OAAQ,eAAc;AAAA,WACpC,mBAAmB,MAAO,eAAc;AAAA,MAC5C,eAAc,eAAe,QAAQ,MAAM,EAAE;AAClD,QAAM,UAA2C;AAAA,IAChD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,EACT;AAEA,QAAM,iBAAiB,QAAQ,WAAW;AAC1C,MAAI,CAAC,eAAgB,QAAO;AAC5B,MAAI,cAAc,OAAO,WAAW,QAAQ;AAC5C,MAAI,OAAO,MAAM,WAAW,GAAG;AAC9B,QAAI;AACH,oBAAc,OAAO,WAAWC,UAAS,QAAQ,CAAsB;AAAA,IACxE,SAAS,QAAQ;AAChB,oBAAc;AAAA,IACf;AAAA,EACD;AAGA,QAAM,oBAAoB;AAC1B,QAAM,eAAe,KAAK,QAAQ,MAAM,CAAC,GAAG,iBAAiB;AAE7D,SAAO;AAAA,IACN,MAAM;AAAA,IACN,cAAc;AAAA,IACd,MAAM;AAAA,IACN,OAAO;AAAA,IACP;AAAA,IACA,iBAAiB,MAAM,CAAC;AAAA,EACzB;AACD;AAEO,SAAS,wBACf,UACA,MACA,OACS;AACT,QAAM,aAAa,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;AACjE,QAAM,aAAuB,CAAC;AAE9B,aAAW,MAAM,YAAY;AAC5B,UAAM,SAAU,GAAgB,SAAS,CAAC;AAC1C,eAAW,SAAS,QAEhB;AACH,YAAM,aAAa,MAAM,SAAS,CAAC;AACnC,iBAAWC,SAAQ,YAAY;AAC9B,YAAI,OAAOA,MAAK,UAAU,SAAU,YAAW,KAAKA,MAAK,KAAK;AAAA,MAC/D;AAAA,IACD;AAAA,EACD;AAEA,SAAO,WAAW;AAAA,IACjB,CAAC,KAAK,YAAY,OAAO,gBAAgB,MAAM,SAAS,KAAK,IAAI,IAAI;AAAA,IACrE;AAAA,EACD;AACD;;;AGrFA,SAAS,YAAY,mBAAAC,wBAAuB;;;ACA5C,SAAS,YAAAC,iBAAgB;AAUlB,SAAS,WAAW,MAAY,OAAe,OAAuB;AAC5E,MAAI,SAAS,IAAK,QAAO;AACzB,SAAOA,UAAS,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;AAC5C;;;ADLO,SAAS,YAAY,MAAc;AACzC,QAAM,WAAW,KAAK,SAAS,gCAAgC;AAC/D,MAAI;AACJ,aAAW,OAAO,UAAU;AAE3B,QAAI,aAAa;AAChB,YAAM,OAAO,YAAY;AACzB,UAAI,QAAQ,YAAY;AACxB,UAAI,KAAM,SAAQ,WAAW,MAAM,OAAO,OAAO,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC;AACrE,oBAAc;AAAA,QACb,MAAM,IAAI,CAAC;AAAA,QACX;AAAA,MACD;AAAA,IACD,OAAO;AACN,oBAAc;AAAA,QACb,MAAM,IAAI,CAAC;AAAA,QACX,OAAO,OAAO,SAAS,IAAI,CAAC,GAAG,EAAE;AAAA,MAClC;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAEO,SAAS,wBAAwB,QAA0B;AACjE,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAQ;AACd,MAAI;AAEJ,UAAQ,QAAQ,MAAM,KAAK,MAAM,OAAO,MAAM;AAC7C,UAAM,gBAAgB,MAAM,CAAC,EAC3B,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,OAAO,SAAS,EAAE,QAAQ,SAAS,EAAE,EAAE,KAAK,GAAG,EAAE,CAAC,EAC7D,OAAO,CAAC,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC;AAChC,WAAO,KAAK,GAAG,aAAa;AAAA,EAC7B;AACA,SAAO;AACR;AAEO,SAAS,cACf,MACA,SAAwBC,iBAAgB,QAAQ,YACL;AAC3C,MAAI;AACH,UAAM,SAAS,IAAI,WAAW;AAC9B,IAAAA,iBAAgB,UAAU,SAAS;AACnC,UAAM,aAAa,OAAO,KAAK,IAAI;AACnC,UAAM,WAAW,MAAM,QAAQ,UAAU,IAAI,WAAW,CAAC,IAAI;AAC7D,UAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,WAAO,EAAE,KAAK,UAAU,KAAK,SAAS;AAAA,EACvC,SAAS,OAAO;AAAA,EAEhB;AACA,SAAO;AACR;AAEO,SAAS,aAAa,QAAgB,MAA0B;AAEtE,QAAM,YAAY;AAClB,MAAI,QAAQ,CAAC,OAAO,MAAM,SAAS,GAAG;AAErC,UAAM,0BAA0B;AAChC,UAAM,QAAQ,OAAO,MAAM,uBAAuB;AAClD,QAAI,OAAO;AAEV,YAAM,QAAQ,MAAM;AACpB,eAAS,GAAG,OAAO,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,MAAM,KAAK,CAAC;AAAA,IAChE,OAAO;AAEN,gBAAU;AAAA,IACX;AAAA,EACD;AACA,SAAO;AACR;AAgBO,SAAS,YAAY,WAAiC;AAC5D,MAAI,OAAO,gBAAgB,qBAAqB,SAAS,CAAC,EACxD,QAAQ,OAAO,EAAE,EACjB,WAAW,MAAM,IAAI,EACrB,WAAW,MAAM,IAAI,EACrB,UAAU;AAEZ,SAAO,KAAK,WAAW,iBAAiB,EAAE,EAAE,QAAQ;AAEpD,QAAM,mBAAmB,0BAA0B,IAAI;AACvD,MAAI,iBAAkB,QAAO,iBAAiB;AAE9C,MAAI;AACJ,MAAI,KAAK,SAAS,GAAG,GAAG;AACvB,UAAM,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC;AAClC,kBAAc,kBAAkB,gBAAgB;AAAA,EACjD,OAAO;AACN,kBAAc,kBAAkB,gBAAgB;AAAA,EACjD;AAEA,QAAM,iBAAiB,KAAK,MAAM,gBAAgB;AAClD,QAAM,cAAc,CAAC,CAAC;AACtB,QAAM,cAAc,cAAc,eAAgB,CAAC,IAAI;AAEvD,QAAM,eAAe,KAAK,SAAS,GAAG;AACtC,MAAI,gBAAgB;AAEpB,MAAI,gBAAgB,KAAK,MAAM,gBAAgB,GAAG;AACjD,WAAO,KAAK,MAAM,GAAG,EAAE;AACvB,oBAAgB;AAChB,kBAAc,YAAY,MAAM,CAAC;AAAA,EAClC;AAIA,MAAI,gBAAgB;AACpB,MAAI,CAAC,eAAe,CAAC,gBAAgB,KAAK,MAAM,UAAU,GAAG;AAE5D,UAAM,eAAe,KAAK,MAAM,GAAG,EAAE;AACrC,UAAM,eAAe,aAAa,MAAM,WAAW;AACnD,UAAM,gBAAgB,aAAa,MAAM,gCAAgC;AAKzE,QAAI,EAAE,iBAAiB,CAAC,eAAe;AACtC,aAAO;AACP,sBAAgB;AAAA,IACjB;AAAA,EACD;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;;;AN1IO,SAAS,gBACf,MACA,aACA,aACA,SACA,kBACA,aACA,QACA,MACW;AACX,QAAM,qBAAqB,cAAc,cAAc;AACvD,QAAM,YAAY,mBAAmB,MAAM,GAAG;AAC9C,QAAM,eAAe,OAAO,SAAS,UAAU,CAAC,GAAG,EAAE;AACrD,MAAI,aAAa,UAAU,CAAC,EAAE,QAAQ,eAAe,EAAE;AACvD,QAAM,gBAAgB,UAAU,CAAC,EAAE,MAAM,aAAa;AACtD,QAAM,WAAW,gBAAgB,cAAc,CAAC,IAAI;AAEpD,MAAI;AACJ,MAAI,aAAa;AAChB,UAAM,oBAAoB,WAAW,MAAM,gBAAgB;AAC3D,QAAI,mBAAmB;AACtB,YAAM,cAAc,kBAAkB,CAAC,EAAE,MAAM,UAAU,IAAI,CAAC;AAC9D,YAAM,eAAe,kBAAkB,CAAC;AACxC,UAAI,eAAe,cAAc;AAChC,uBAAe;AAAA,UACd,MAAM;AAAA,UACN,OAAO,OAAO,SAAS,cAAc,EAAE;AAAA,QACxC;AACA,qBAAa,WAAW,QAAQ,kBAAkB,EAAE;AAAA,MACrD;AAAA,IACD;AAAA,EACD;AAEA,eAAa,aAAa,YAAY,IAAI;AAE1C,QAAM,gBACL,WACA,iBACC,mBACG,EAAE,MAAM,iBAAiB,MAAM,OAAO,iBAAiB,MAAM,IAC9D;AAEJ,MAAI,eAAe;AAClB,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,QAAM,SAAS,IAAIC,YAAW;AAC9B,EAAAC,iBAAgB,UAAU,SAAS;AAEnC,WAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACtC,QAAI;AACH,aAAO,KAAK,UAAU;AAAA,IACvB,SAAS,OAAO;AACf,YAAM,IAAI,cAAc,YAAY,QAAQ,KAAK;AAAA,IAClD;AAAA,EACD;AAEA,QAAM,YAAY,cAAc,IAAI,UAAU,MAAM;AACpD,QAAM,cAAc,YAAY,IAAI;AAEpC,SAAO;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,oBAAoB,OAAO,MAAM;AAAA,IACzC,SAAS;AAAA,IACT,SAAS,UAAU,UAAU;AAAA,IAC7B,UAAU;AAAA,IACV,OAAO,OAAO;AAAA,EACf;AACD;AAKA,SAAS,8BACR,cACA,YACA,UACA,eACA,kBACA,aACA,aACA,cACA,SACA,QACW;AACX,QAAM,UAAoB,CAAC;AAC3B,MAAI,eAAe;AACnB,QAAM,SAAS,IAAID,YAAW;AAC9B,EAAAC,iBAAgB,UAAU,SAAS;AACnC,MAAI,4BAA4B;AAEhC,QAAM,eAAe,CAAC,QAAgB,YAAqB;AAC1D,UAAM,YACL,WAAW,cACR,OAAO;AAAA,MACP;AAAA,MACA,CAAC,IAAI,YACJ,IAAI,QACF,MAAM,GAAG,EACT,IAAI,CAAC,MAAc,GAAG,EAAE,KAAK,CAAC,GAAG,EACjC,KAAK,IAAI,CAAC;AAAA,IACd,IACC;AACJ,WAAO,eACJ,UAAU,QAAQ,aAAa,KAAK,aAAa,IAAI,GAAG,aAAa,KAAK,GAAG,IAC7E;AAAA,EACJ;AAEA,WAAS,IAAI,GAAG,IAAI,cAAc,KAAK;AACtC,QAAI;AACH,YAAM,iBAAiB,OAAO,KAAK,UAAU;AAC7C,YAAM,eAAe,MAAM,QAAQ,cAAc,IAC9C,eAAe,CAAC,IAChB;AAEH,UAAI,CAAC,6BAA6B,eAAe;AAChD,cAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,oCAA4B;AAAA,UAC3B;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAEA,YAAM,aAAa,aAAa;AAEhC,UAAI,kBAAkB;AACrB,cAAM,mBAAmB;AAAA,UACxB;AAAA,UACA,iBAAiB;AAAA,UACjB,iBAAiB;AAAA,QAClB;AACA,wBAAgB;AAEhB,YAAI,sBAAsB,WACxB,QAAQ,iBAAiB,mBAAmB,iBAAiB,eAAe,EAC5E,QAAQ,wBAAwB,KAAK,gBAAgB,EAAE;AACzD,8BAAsB,aAAa,qBAAqB,KAAK;AAC7D,gBAAQ,KAAK,mBAAmB;AAAA,MACjC,OAAO;AACN,cAAM,YAAY,aAAa;AAC/B,cAAM,YAAYC;AAAA,UACjB,GAAG,SAAS,GAAG,cAAc,IAAI,GAAG,cAAc,KAAK;AAAA,QACxD;AAEA,YAAI,UAAW;AACf,gBAAQ,KAAK,aAAa,YAAY,SAAS,CAAC;AAAA,MACjD;AAAA,IACD,SAAS,OAAO;AACf,YAAM,IAAI,cAAc,YAAY,QAAQ,KAAK;AAAA,IAClD;AAAA,EACD;AAEA,MAAI,kBAAkB;AACrB,UAAM,aAAa,kBAAkB,gBAAgB;AACrD,UAAM,iBAAiB,WAAW,MAAM,uBAAuB;AAC/D,QAAI,gBAAgB;AACnB,YAAM,CAAC,EAAE,gBAAgB,QAAQ,IAAI;AACrC,UAAI;AACJ,UAAI,mBAAmB,OAAQ,eAAc;AAAA,eACpC,mBAAmB,MAAO,eAAc;AAAA,UAC5C,eAAc,eAAe,QAAQ,MAAM,EAAE;AAElD,YAAM,UAA2C;AAAA,QAChD,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,MACT;AACA,YAAM,aAAa,QAAQ,WAAW;AACtC,YAAM,cAAc,OAAO,WAAW,QAAQ;AAE9C,UAAI,cAAc,CAAC,OAAO,MAAM,WAAW,GAAG;AAC7C,cAAM,gBAAgB,oBAAoB,QAAQ,KAAK,IAAI,CAAC;AAC5D,cAAM,aAAa,cACjB,MAAM,GAAG,EACT,QAAQ,CAAC,YAAY,wBAAwB,OAAO,CAAC;AAEvD,YAAI,eAAe,MAAM;AACxB,gBAAM,cAAc,WAAW,OAAO,CAAC,QAAQ,QAAQ,WAAW,EAAE;AACpE,yBAAe,WAAW,SAAS;AAAA,QACpC,OAAO;AACN,yBAAe,WAAW;AAAA,YAAO,CAAC,QACjC,gBAAgB,YAAY,KAAK,WAAW;AAAA,UAC7C,EAAE;AAAA,QACH;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,MAAI,WAAW,0BAA2B,SAAQ,UAAU;AAE5D,QAAM,YAAY,cACf,IAAI,UAAU,GAAG,cAAc,IAAI,GAAG,cAAc,KAAK,MACzD;AAEH,QAAM,eAAe,oBAAoB,QAAQ,KAAK,IAAI,CAAC;AAC3D,QAAM,aAAa,mBAChB,aACC,MAAM,GAAG,EACT,QAAQ,CAAC,YAAY,wBAAwB,OAAO,CAAC,EACrD;AAAA,IAAO,CAAC,QACR,gBAAgB,iBAAiB,MAAM,KAAK,iBAAiB,KAAK;AAAA,EACnE,EAAE,SACF;AAEH,QAAM,cAAc,YAAY,WAAW;AAE3C,SAAO;AAAA,IACN,MAAM,mBAAmB,cAAc;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS,cAAc,SAAY;AAAA,IACnC,UAAU;AAAA,IACV,OAAO;AAAA,IACP,SAAS,4BAA4B,OAAO;AAAA,EAC7C;AACD;;;AQzPA,SAAS,YAAAC,iBAAgB;AAUlB,SAAS,iBACf,MACA,SACA,UACA,QACA,QAC6C;AAC7C,QAAM,cAAc,MAAM,QAAQ,QAAQ,IAAI,SAAS,CAAC,IAAI;AAC5D,QAAM,cAAc,cAAc,YAAY,WAAW;AACzD,QAAM,uBACL,gBAAgB,QAAQ,qBAAqB,aAAa,OAAO;AAElE,MAAI,CAAC,sBAAsB;AAC1B,WAAO,EAAE,aAAa,EAAE;AAAA,EACzB;AAEA,MAAI,SAASC,UAAS,GAAG,OAAO,KAAK,GAAG,QAAQ,IAAI,GAAG,QAAQ,KAAK,EAAE;AACtE,MAAI,QAAQ;AACX,WAAO,EAAE,aAAa,EAAE;AAAA,EACzB;AAEA,QAAM,YAAY;AAClB,MAAI,cAAc;AAClB,MAAI;AAEJ,SAAO,CAAC,UAAU,cAAc,WAAW;AAC1C,QAAI;AACH,YAAM,KAAK,MAAM,QAAQ,KAAK;AAAA,IAC/B,SAAS,OAAO;AACf,YAAM,IAAI,cAAc,MAAM,QAAQ,KAAK;AAAA,IAC5C;AACA;AACA,QAAI,OAAO,IAAI,UAAU,QAAW;AACnC,eAASA,UAAS,GAAG,IAAI,KAAK,GAAG,QAAQ,IAAI,GAAG,QAAQ,KAAK,EAAE;AAAA,IAChE;AAAA,EACD;AAEA,SAAO,EAAE,aAAa,QAAQ,IAAI;AACnC;;;ATPO,SAAS,KACf,MACA,SAAwBC,iBAAgB,QAAQ,YAChD,MACA,MACuB;AACvB,MAAI,2BAAyB,QAAO;AAEpC,QAAM,WAAW,YAAY,IAAI;AACjC,MAAI,CAAC,SAAS,KAAK,SAAS,GAAG,EAAG,QAAO;AAGzC,MAAI,SAAS,cAAc;AAC1B,WAAO;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,IACV;AAAA,EACD;AAEA,MAAI,gBAAgB,eAAe,SAAS,IAAI;AAChD,QAAM,cAAc,YAAY,aAAa;AAG7C,QAAM,eAAe,cAAc,MAAM,gBAAgB;AACzD,MAAI;AACJ,MAAI,gBAAgB,CAAC,SAAS,aAAa;AAC1C,UAAM,gBAAgB,WAAW,eAAe,cAAc,QAAQ,IAAI;AAC1E,oBAAgB,cAAc;AAC9B,cAAU,cAAc;AAAA,EACzB;AAGA,MAAI,mBAAmB,SAAS;AAChC,MAAI,SAAS,iBAAiB,CAAC,SAAS,YAAY,WAAW,GAAG,GAAG;AACpE,uBAAmB,IAAI,SAAS,WAAW;AAAA,EAC5C;AAGA,QAAM,qBAAqB,SAAS,cAAc,SAAS,cAAc;AACzE,MAAI,mBAAmB,MAAM,WAAW,GAAG;AAC1C,WAAO;AAAA,MACN;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,QAAM,SAAS,IAAIC,YAAW;AAC9B,EAAAD,iBAAgB,UAAU,SAAS;AACnC,MAAI,qBAAqB,cAAc,QAAQ,eAAe,EAAE,EAAE,QAAQ;AAC1E,uBAAqB,aAAa,oBAAoB,IAAI;AAE1D,MAAI;AACJ,MAAI;AACH,eAAW,OAAO,KAAK,kBAAkB;AAAA,EAC1C,SAAS,OAAO;AACf,UAAM,IAAI,cAAc,oBAAoB,QAAQ,KAAK;AAAA,EAC1D;AAGA,MAAI,WAAW,UAAU;AACxB,UAAM,cAAc,MAAM,QAAQ,QAAQ,IAAI,SAAS,CAAC,IAAI;AAC5D,UAAM,UAAU;AAAA,MACf,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ;AAAA,IACD;AACA,YAAQ,UAAU,UAAU,OAAO;AAAA,EACpC;AAEA,QAAM,eAAe,cAAc,MAAM,aAAa;AACtD,QAAM,UAAU,eAAe,aAAa,CAAC,IAAI;AAGjD,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI,QAAQ,SAAS;AACpB,UAAM,WAAW;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,kBAAc,SAAS;AACvB,iBAAa,SAAS;AACtB,QAAI,YAAY;AACf,aAAO;AAAA,QACN,GAAG;AAAA,QACH,MAAM,SAAS,gBAAgB,mBAAmB;AAAA,QAClD;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,UAAU;AAAA,QACV,SAAS,WAAW,YAAY,SAAS,UAAU,OAAO;AAAA,MAC3D;AAAA,IACD;AAAA,EACD;AAEA,MAAI,eAAe,oBAAoB,OAAO,MAAM;AAGpD,MAAI,SAAS,kBAAkB;AAC9B,UAAM,YAAY;AAAA,MACjB;AAAA,MACA,SAAS,iBAAiB;AAAA,MAC1B,SAAS,iBAAiB;AAAA,IAC3B;AACA,mBAAe,aACb,QAAQ,wBAAwB,KAAK,SAAS,EAAE,EAChD;AAAA,MACA,SAAS,iBAAiB;AAAA,MAC1B,SAAS,iBAAiB;AAAA,IAC3B;AAED,WAAO;AAAA,MACN,MAAM,SAAS,gBAAgB,mBAAmB,SAAS;AAAA,MAC3D,QAAQ;AAAA,MACR;AAAA,MACA,SAAS,UAAU,UAAU;AAAA,MAC7B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU,cAAc,IAAI,cAAc;AAAA,MAC1C,SAAS,SAAS,UAAU,OAAO;AAAA,IACpC;AAAA,EACD;AAEA,SAAO;AAAA,IACN,MAAM,SAAS,gBAAgB,mBAAmB;AAAA,IAClD,QAAQ;AAAA,IACR;AAAA,IACA,SAAS,UAAU,UAAU;AAAA,IAC7B,UAAU;AAAA,IACV,OAAO,OAAO;AAAA,IACd,UAAU,cAAc,IAAI,cAAc;AAAA,IAC1C,SAAS,SAAS,UAAU,OAAO;AAAA,EACpC;AACD;AAEA,SAAS,YACR,MACA,SAAwBA,iBAAgB,QAAQ,YAChD,MACA,sBACA,aACA,eACuB;AAEvB,MAAI,CAAC;AACJ,2BAAuB,0BAA0B,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI;AAE5E,MAAI,sBAAsB;AAEzB,WAAO,KAAK,QAAQ,qBAAqB,iBAAiB,GAAG;AAAA,EAC9D;AACA,MAAI,KAAK,MAAM,YAAY;AAC1B,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACD,QAAM,UAAU,CAAC;AACjB,QAAM,cACL,qBAAqB,KAAK,IAAI,GAAG,QAAQ,SAAS,QAAQ,KAAK;AAChE,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,QAAM,cAAc,eAAe,sBAAsB,gBAAgB,MAAM,CAAC;AAChF,MAAI,WAAW,eAAe,MAAM,CAAC,CAAC;AAEtC,QAAM,gBAAgB;AACtB,QAAM,WAAW,cAAc,QAAQ;AAEvC,QAAM,0BAA0B,SAAS,QAAQ,eAAe,EAAE,EAAE,KAAK;AACzE,QAAM,cAAc;AACpB,QAAM,SAAS,YAAY,KAAK,uBAAuB,GAAG;AAC1D,MAAI,SAAS;AACb,MAAI,QAAQ,MAAM;AACjB,eAAW,OAAO;AAClB,aAAS;AAAA,EACV,WAAW,QAAQ;AAClB,eAAW;AACX,aAAS;AAAA,EACV,OAAO;AAEN,eAAW;AAAA,EACZ;AACA,QAAM,aAAa,cAAc,UAAU,MAAM;AACjD,MAAI,aAAa,KAAK,UAAU,QAAQ,IAAI;AAC5C,MAAI,CAAC,cAAc,CAAC,WAAW,OAAO;AACrC,QAAI,QAAQ;AACX,mBAAa,KAAK,eAAe,MAAM,CAAC,CAAC,GAAG,QAAQ,IAAI;AACxD,eAAS;AAAA,IACV,MAAO,QAAO;AAAA,EACf;AACA,MAAI,CAAC,cAAc,CAAC,WAAW,MAAO,QAAO;AAG7C,MAAI,wBAAwB,WAAW,QAAQ;AAC9C,UAAM,SAAS,wBAAwB,WAAW,MAAM;AACxD,eAAW,QAAQ,OAAO;AAAA,MAAO,CAAC,MACjC,gBAAgB,qBAAsB,MAAM,GAAG,qBAAsB,KAAK;AAAA,IAC3E,EAAE;AAAA,EACH;AACA,MAAI,oBAAoB,WAAW;AACnC,MAAI,uBAAuB,WAAW,SAAS,YAAY;AAC3D,UAAQ,KAAK,UAAK,QAAQ,GAAG,WAAW,MAAM,EAAE;AAChD,MAAI,QAAQ,WAAW;AACvB,aAAW,UAAU;AACrB,MAAI,CAAC,OAAO;AACX,WAAO;AAAA,MACN,MAAM;AAAA,MACN,QAAQ,QAAQ,KAAK,GAAG;AAAA,MACxB,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU,WAAW;AAAA,MACrB;AAAA,MACA,SAAS,uBAAuB,OAAO;AAAA,IACxC;AAAA,EACD;AACA,WAAS,WAAW,MAAM,MAAM,CAAC,GAAG;AACnC,UAAM,UAAU,cAAc,OAAO;AACrC,cAAU,QACR,WAAW,eAAe,EAAE,EAC5B,WAAW,kBAAkB,EAAE,EAC/B,KAAK;AACP,QAAI,SAAS,QAAQ,QAAQ,aAAa,GAAG,WAAW,KAAK,EAAE;AAE/D,UAAM,eAAe,OAAO,MAAM,gBAAgB;AAClD,QAAI,cAAc;AACjB,UAAI,eAAe;AAElB,cAAM,gBAAgB;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAEA,cAAM,EAAE,QAAQ,IAAI,YAAY,SAAS,WAAW,OAAO,WAAW,IAAI;AAC1E,YAAI,eAAe;AACnB,YAAI;AACH,gBAAM,YAAYE,UAAS,MAAM;AACjC,yBAAe,YAAY,IAAI;AAAA,QAChC,SAAS,OAAO;AAEf,gBAAM,YAAY,KAAK,QAAQ,QAAQ,IAAI;AAC3C,yBAAgB,WAAW,SAAS,IAAK,IAAI;AAAA,QAC9C;AACA,gBAAQ,KAAK,UAAK,OAAO,GAAG,OAAO,KAAK,YAAY,EAAE;AACtD,iBAAS;AACT,YAAI,CAAC,qBAAqB,cAAc;AACvC,8BAAoB,cAAc;AACnC,YAAI,cAAc,QAAS,wBAAuB;AAAA,MACnD,OAAO;AACN,cAAM,gBAAgB;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,iBAAS,cAAc;AACvB,gBAAQ,KAAK,cAAc,OAAO;AAClC,YAAI,CAAC,qBAAqB,cAAc;AACvC,8BAAoB,cAAc;AACnC,YAAI,cAAc,QAAS,wBAAuB;AAAA,MACnD;AAAA,IACD,OAAO;AACN,YAAM,EAAE,SAAS,QAAQ,IAAI;AAAA,QAC5B;AAAA,QACA,WAAW;AAAA,QACX,WAAW;AAAA,MACZ;AAEA,UAAI;AACH,cAAM,YAAYA,UAAS,MAAM;AACjC,gBAAQ,KAAK,UAAK,OAAO,GAAG,OAAO,KAAK,OAAO,MAAM,SAAS,EAAE;AAChE,iBAAS,OAAO,SAAS,WAAW,EAAE;AAAA,MACvC,SAAS,OAAO;AACf,cAAM,YAAY,KAAK,QAAQ,QAAQ,IAAI;AAC3C,YAAI,WAAW;AACd,kBAAQ;AAAA,YACP,UAAK,OAAO,GAAG,OAAO,KAAK,UAAU,OAAO,MAAM,GAAG,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,CAAC;AAAA,UAC1E;AACA,cAAI,CAAC,qBAAqB,UAAU;AACnC,gCAAoB,UAAU;AAC/B,cAAI,UAAU,SAAS,QAAS,wBAAuB;AAAA,QACxD,MAAO,SAAQ,KAAK,UAAK,OAAO,GAAG,OAAO,KAAK,OAAO,MAAM,SAAS,EAAE;AACvE,iBAAS,WAAW,SAAS;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AACA,MAAI;AAEH,YAAQ,MAAM;AACf,SAAO;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,QAAQ,KAAK,GAAG;AAAA,IACxB,SAAS;AAAA,IACT,SACC,wBAAwB,oBACrB,EAAE,GAAG,mBAAmB,SAAS,KAAK,IACtC;AAAA,IACJ,UAAU,WAAW;AAAA,IACrB;AAAA,IACA,SAAS,uBAAuB,OAAO;AAAA,EACxC;AACD;AAEO,SAAS,iBACf,SACA,YACA,eACA,KACA,SAAwBF,iBAAgB,QAAQ,YAChD,MACC;AACD,QAAM,EAAE,SAAS,QAAQ,IAAI;AAAA,IAC5B;AAAA,IACA,WAAW,SAAS;AAAA,IACpB,WAAW;AAAA,EACZ;AACA,QAAM,YAAY,MAAM,WAAM;AAC9B,QAAM,eAAe,MAClB,cAAc,QAAS,OACvB,YAAY,cAAc,QAAS,IAAI;AAC1C,MAAI;AACJ,MAAI;AACH,mBAAeE,UAAS,cAAc,IAAI;AAC1C,WAAO,GAAG,SAAS,IAAI,OAAO,KAAK,OAAO,MAAM,YAAY,GAAG,YAAY,GAAG,cAAc,SAAS,KAAK;AAAA,EAC3G,SAAS,OAAO;AACf,UAAMC,gBAAe,KAAK,cAAc,MAAM,QAAQ,IAAI;AAC1D,QAAIA;AACH,aAAO,GAAG,SAAS,IAAI,OAAO,KAAKA,cAAa,OAAO,MAAM,GAAG,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG,CAAC;AAEtF,WAAO,GAAG,SAAS,IAAI,OAAO,KAAK,OAAO,MAAMA,aAAY,GAAG,YAAY,GAAG,cAAc,SAAS,KAAK;AAAA,EAC3G;AACD;;;AUzYA,SAAS,YAAAC,iBAAgB;AACzB,SAAsB,UAAAC,eAAc;AACpC,OAAO;AAEP,SAAS,mBAAAC,wBAAuB;AAyBzB,SAAS,cACf,UACA,UACA,SAAwBC,iBAAgB,QAAQ,YAChD,MACC;AACD,MAAI,OAAO,SAAS,QAAQ;AAC5B,MAAI,YAAY,OAAO,KAAK,QAAQ,EAAE,SAAS,GAAG;AACjD,UAAM,QAAQ,OAAO,KAAK,QAAQ;AAClC,eAAW,QAAQ,OAAO;AACzB,YAAM,QAAQ,IAAI,OAAO,YAAY,KAAK,YAAY,CAAC,GAAG,IAAI;AAC9D,UAAI,KAAK,YAAY,EAAE,MAAM,KAAK,GAAG;AACpC,cAAM,YAAY,SAAS,IAAI;AAC/B,eAAO,KAAK,YAAY,EAAE,QAAQ,OAAO,UAAU,SAAS,CAAC,EAAE,QAAQ;AAAA,MACxE;AAAA,IACD;AAAA,EACD;AACA,MAAI;AACH,QAAI,CAAC,KAAK,qBAAqB,mBAAmB,IAAI,CAAC,GAAG,QAAQ,IAAI;AACrE,YAAM,IAAI,cAAc,MAAM,iBAAiB,gBAAgB;AAChE,WAAO;AAAA,EACR,SAAS,OAAO;AACf,UAAM,IAAI,cAAc,MAAM,iBAAiB,KAAK;AAAA,EACrD;AACD;AAUO,SAAS,gBACf,OACA,UACA,SAAwBA,iBAAgB,QAAQ,YAC/C;AACD,MAAI,CAAC,SAAS,WAAY,QAAO,qBAAqB,MAAM,YAAY,CAAC;AACzE,UAAQ,MAAM,YAAY;AAC1B,QAAM,YAAY,OAAO,KAAK,SAAS,UAAU;AACjD,MAAI,UAAU;AACd,aAAW,QAAQ,WAAW;AAC7B,UAAM,QAAQ,IAAI,OAAO,YAAY,KAAK,YAAY,CAAC,GAAG,IAAI;AAC9D,QAAI,MAAM,MAAM,KAAK,GAAG;AACvB,UAAI;AACJ,UAAI;AACJ,YAAM,YAAY,SAAS,aAAa,IAAI;AAC5C,UAAI,WAAW;AACd,cAAM,UAAU;AAChB,cAAM,UAAU;AAAA,MACjB;AACA,YAAM,QAAQ,SAAS,SAAS;AAChC,YAAM,kBAAkB,mBAAmB,OAAO,KAAK,KAAK,MAAM;AAClE,gBAAU,MAAM,QAAQ,OAAO,gBAAgB,SAAS,CAAC;AAAA,IAC1D;AAAA,EACD;AACA,SAAO,qBAAqB,OAAO;AACpC;AAQO,SAAS,oBACf,MACA,UACA,SAAwBA,iBAAgB,QAAQ,YAC/C;AACD,SAAO,mBAAmB,IAAI;AAC9B,MAAI,CAAC,SAAS,WAAY,QAAO;AACjC,QAAM,0BAA0B,OAAO,KAAK,SAAS,UAAU,EAAE;AAAA,IAChE,CAAC,SAAS,CAAC,SAAS,aAAa,IAAI,EAAE;AAAA,EACxC;AACA,MAAI,CAAC,wBAAyB,QAAO;AACrC,QAAM,QAAQ,SAAS,WAAW,uBAAuB;AACzD,QAAM,EAAE,KAAK,IAAI,IAAI;AACrB,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,kBAAkB,mBAAmB,OAAO,KAAK,KAAK,MAAM;AAClE,SAAO,qBAAqB,KAAK,WAAW,KAAK,gBAAgB,SAAS,CAAC,CAAC;AAC7E;AAOO,SAAS,gBACf,aACA,OACC;AACD,QAAM,WAAmC,CAAC;AAC1C,aAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,WAAW,GAAG;AAEzD,QAAI,UAAU,OAAO,YAAY;AACjC,eAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACtD,YAAM,QAAQ,IAAI,OAAO,SAAS,YAAY,GAAG,IAAI;AACrD,gBAAU,QAAQ,QAAQ,OAAO,MAAM,SAAS,CAAC;AAAA,IAClD;AACA,QAAI;AACH,eAAS,IAAI,IAAIC,UAAS,OAAO;AAAA,IAClC,SAAS,OAAO;AACf,YAAM,IAAI,aAAa,MAAM,mBAAmB,KAAK;AAAA,IACtD;AAAA,EACD;AACA,SAAO;AACR;AAOO,SAAS,mBACf,aACA,OACC;AACD,MAAI,UAAU,YAAY,YAAY;AACtC,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACtD,UAAM,QAAQ,IAAI,OAAO,SAAS,YAAY,GAAG,IAAI;AACrD,cAAU,QAAQ,QAAQ,OAAO,MAAM,SAAS,CAAC;AAAA,EAClD;AACA,MAAI;AACH,WAAOA,UAAS,OAAO;AAAA,EACxB,SAAS,OAAO;AACf,UAAM,IAAI,aAAa,aAAa,sBAAsB,KAAK;AAAA,EAChE;AACD;AAEA,SAAS,cAAc,QAAqC;AAC3D,MAAI,WAAW,UAAa,WAAW,KAAM,QAAO;AACpD,MACC,OAAO,SAAS,EAAE,WAAW,KAC7B,OAAO,MAAM,OAAO,SAAS,OAAO,SAAS,GAAG,EAAE,CAAC;AAEnD,WAAO;AACR,MAAI,SAAS,MAAM,EAAG,QAAO,OAAO,SAAS,OAAO,SAAS,GAAG,EAAE;AAClE,SAAO;AACR;AASO,SAAS,oBACf,UACA,SAAS,MACT,SAAwBD,iBAAgB,QAAQ,YAC1B;AACtB,QAAM,iBAAiB,eAAe,MAAM,QAAQ;AACpD,QAAM,EAAE,SAAS,QAAQ,IAAI,eAAe,YAAY,CAAC;AACzD,QAAM,gBAAgB;AAAA,IACrB,SAAS,cAAc,OAAO;AAAA,IAC9B,SAAS,cAAc,OAAO;AAAA,EAC/B;AACA,QAAM,sBAA2C;AAAA,IAChD,UAAU,eAAe;AAAA,IACzB,YAAY,eAAe;AAAA,IAC3B,UAAU;AAAA,IACV,OAAO,eAAe;AAAA,IACtB,UAAU,eAAe;AAAA,IACzB,QAAQ,eAAe;AAAA,IACvB,gBAAgB,eAAe;AAAA,IAC/B,cAAc,eAAe;AAAA,EAC9B;AACA,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,oBAAoB,UAAU;AACjC,QAAI,oBAAoB,SAAS,MAAM,eAAe,GAAG;AACxD,YAAM,IAAI;AAAA,QACT,oBAAoB;AAAA,QACpB;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,UAAME,eAAc;AAAA,MACnB,oBAAoB;AAAA,MACpB;AAAA,MACA;AAAA,IACD;AACA,UAAM,SAAS,KAAKA,cAAa,MAAM;AACvC,QAAI,CAAC,OAAQ,OAAM,IAAI,cAAcA,cAAa,kBAAkB,gBAAgB;AAAA,EACrF;AACA,MAAI,oBAAoB,gBAAgB;AACvC,QAAI,CAAC,oBAAoB,UAAU;AAClC,YAAM,IAAI,cAAc,gBAAgB,gBAAgB,cAAc;AAAA,IACvE;AACA,UAAM,iBAAiB,oBAAoB;AAC3C,eAAW,CAAC,EAAE,MAAM,KAAK,OAAO,QAAQ,cAAc,GAAG;AACxD,YAAMA,eAAc;AAAA,QACnB,oBAAoB;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA,YAAM,SAAS,KAAKA,cAAa,MAAM;AACvC,UAAI,CAAC;AACJ,cAAM,IAAI,cAAcA,cAAa,uBAAuB,gBAAgB;AAAA,IAC9E;AAAA,EACD;AACA,qBAAmB,qBAAqB,MAAM;AAC9C,sBAAoB,qBAAqB,MAAM;AAC/C,SAAO;AACR;AAOO,SAAS,mBACf,UACA,SAAwBF,iBAAgB,QAAQ,YAC/C;AACD,MAAI,CAAC,SAAS,OAAQ;AACtB,MAAI,OAAO,KAAK,SAAS,MAAM,EAAE,WAAW,EAAG,OAAM,IAAI,iBAAiB;AAC1E,MAAI,OAAO,KAAK,SAAS,MAAM,EAAE,SAAS,GAAI,OAAM,IAAI,YAAY;AACpE,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,SAAS,MAAM,GAAG;AAC3D,QAAI,CAAC,KAAM;AACX,UAAM,eAAe,mBAAmB,IAAI;AAC5C,UAAM,mBAAmB,gBAAgB,cAAc,UAAU,MAAM;AACvE,QAAI;AACH,YAAM,SAAS,KAAK,kBAAkB,MAAM;AAC5C,UAAI,CAAC,OAAQ,OAAM,IAAI,cAAc,MAAM,kBAAkB,IAAI;AAAA,IAClE,SAAS,OAAO;AAEf,YAAM,IAAI,cAAc,MAAM,sBAAsB,KAAK;AAAA,IAC1D;AAAA,EACD;AACD;AAOO,SAAS,oBACf,UACA,SAAwBA,iBAAgB,QAAQ,YAC/C;AACD,MAAI,CAAC,SAAS,WAAY;AAC1B,QAAM,uBAAuB,OAAO;AAAA,IACnC,OAAO,QAAQ,SAAS,UAAU,EAAE;AAAA,MACnC,CAAC,CAAC,GAAG,KAAK,MAAM,MAAM,gBAAgB;AAAA,IACvC;AAAA,EACD;AACA,QAAM,gBAAgB,OAAO;AAAA,IAC5B,OAAO,QAAQ,SAAS,UAAU,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,MAAM,WAAW;AAAA,EAC9E;AACA,MAAI,OAAO,KAAK,oBAAoB,EAAE,WAAW,EAAG;AACpD,QAAM,WAAW,OAAO,KAAK,SAAS,UAAU,EAAE;AAAA,IACjD,CAAC,SAAS,CAAC,SAAS,WAAY,IAAI,EAAE;AAAA,EACvC;AACA,MAAI,SAAS,WAAW,EAAG,OAAM,IAAI,kBAAkB;AACvD,QAAM,QAAQ,CAAC;AACf,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,oBAAoB,GAAG;AACjE,QAAI,UAAU,MAAM;AACpB,eAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,aAAa,GAAG;AAC1D,YAAM,EAAE,KAAK,IAAI,IAAI;AACrB,YAAM,QAAQ,SAAS,SAAS;AAChC,YAAM,kBAAkB,mBAAmB,OAAO,KAAK,KAAK,MAAM;AAClE,YAAM,QAAQ,IAAI,OAAO,OAAO,IAAI;AACpC,gBAAU,QAAQ,QAAQ,OAAO,gBAAgB,SAAS,CAAC;AAAA,IAC5D;AACA,QAAI;AACH,MAAAC,UAAS,OAAO;AAAA,IACjB,SAAS,GAAG;AACX,YAAM,KAAK,IAAI;AAAA,IAChB;AAAA,EACD;AACA,MAAI,MAAM,SAAS,EAAG,OAAM,IAAI,aAAa,MAAM,KAAK,IAAI,GAAG,qBAAqB;AACpF;AACD;AAUO,SAAS,mBACf,QAA4B,KAC5B,KACA,KACA,SAAwBD,iBAAgB,QAAQ,YAC/C;AACD,MAAI,kBAAkB,QAAQ;AAC9B,QAAM,SAAS,IAAIG,QAAO,UAAUH,iBAAgB,QAAQ,UAAU;AACtE,SAAO,mBAAmB,SAAS,oBAAoB,GAAG;AACzD,QAAI,OAAO,IAAK,mBAAkB,UAAU,KAAK,KAAK,QAAQ,MAAM;AAAA,aAC3D,IAAK,mBAAkB,UAAU,GAAG,KAAK,QAAQ,MAAM;AAAA,aACvD,IAAK,mBAAkB,UAAU,KAAK,OAAO,QAAQ,MAAM;AAAA,QAC/D,mBAAkB,UAAU,GAAG,OAAO,QAAQ,MAAM;AAAA,EAC1D;AACA,SAAO;AACR;","names":["SortOrder","DiceRoller","NumberGenerator","evaluate","DiceRoller","NumberGenerator","evaluate","NumberGenerator","evaluate","NumberGenerator","NumberGenerator","NumberGenerator","evaluate","evaluate","NumberGenerator","evaluate","NumberGenerator","evaluate","diceResult","evaluate","roll","NumberGenerator","evaluate","NumberGenerator","DiceRoller","NumberGenerator","evaluate","evaluate","evaluate","NumberGenerator","DiceRoller","evaluate","evaluateRoll","evaluate","Random","NumberGenerator","NumberGenerator","evaluate","cleanedDice","Random"]}
|
|
1
|
+
{"version":3,"sources":["../src/engine.ts","../src/errors.ts","../src/interfaces/index.ts","../src/interfaces/constant.ts","../src/interfaces/zod.ts","../src/roll.ts","../src/dice/bulk.ts","../src/dice/compare.ts","../src/utils.ts","../src/dice/exploding.ts","../src/dice/signs.ts","../src/dice/replace.ts","../src/dice/extract.ts","../src/dice/calculator.ts","../src/dice/pity.ts","../src/verify_template.ts"],"sourcesContent":["import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport type { Engine } from \"random-js\";\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","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 interface Resultat {\r\n\t/**\r\n\t * Original dice throw\r\n\t */\r\n\tdice: string;\r\n\t/**\r\n\t * Result of the dice throw\r\n\t */\r\n\tresult: string;\r\n\t/**\r\n\t * The comment that was added to the dice throw (if any)\r\n\t */\r\n\tcomment?: string;\r\n\t/**\r\n\t * The comparison made on the dice\r\n\t */\r\n\tcompare?: ComparedValue;\r\n\t/**\r\n\t * If any value was added to the dice throw\r\n\t */\r\n\tmodifier?: Modifier;\r\n\t/**\r\n\t * Total of the roll\r\n\t */\r\n\ttotal?: number;\r\n\tpityLogs?: number;\r\n\ttrivial?: boolean;\r\n}\r\n\r\nexport interface Compare {\r\n\t/**\r\n\t * Sign of the comparison\r\n\t */\r\n\tsign: \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\";\r\n\t/**\r\n\t * Value of the comparison\r\n\t */\r\n\tvalue: number;\r\n\t/**\r\n\t * Indicate if the comparison is \"trivial\"\r\n\t * aka if the comparaison is always true or always false\r\n\t */\r\n\ttrivial?: boolean;\r\n}\r\n\r\n/**\r\n * Sign format for calculation of modifier\r\n */\r\nexport type Sign = \"+\" | \"-\" | \"*\" | \"/\" | \"%\" | \"^\" | \"**\";\r\n\r\nexport type ComparedValue = Compare & {\r\n\t/**\r\n\t * Original dice if the comparaison is made with a dice throw\r\n\t */\r\n\toriginalDice?: string;\r\n\t/**\r\n\t * Output of the dice throw\r\n\t */\r\n\trollValue?: string;\r\n};\r\n\r\nexport interface Modifier {\r\n\t/**\r\n\t * Sign of the modifier\r\n\t */\r\n\tsign?: Sign;\r\n\t/**\r\n\t * Value of the modifier\r\n\t * @TJS-type integer\r\n\t */\r\n\tvalue: number;\r\n}\r\n\r\n/**\r\n * Statistic object template\r\n */\r\nexport type Statistic = Record<\r\n\t/**\r\n\t * The name of the statistic\r\n\t * @TJS-type string\r\n\t */\r\n\tstring,\r\n\tStatEntry\r\n>;\r\n\r\ntype StatEntry = {\r\n\t/**\r\n\t * The value of the statistic that can take the stats\r\n\t * @TJS-type integer\r\n\t */\r\n\tmax?: number;\r\n\t/**\r\n\t * The minimal value of the statistic that can take the stats\r\n\t * @TJS-type integer\r\n\t */\r\n\tmin?: number;\r\n\t/**\r\n\t * The combinaison that can be made with ANOTHER statistic\r\n\t * Automatically disable the max/min value\r\n\t */\r\n\tcombinaison?: string;\r\n\t/**\r\n\t * Allow to exclude from roll selection in /dbroll!\r\n\t */\r\n\texclude?: boolean;\r\n};\r\n\r\n/**\r\n * @example\r\n * diceType: 1d20+$>=20\r\n * The dice throw will be 1d20 + statistique that must be >= 20\r\n * @example\r\n * diceType: 1d20<=$\r\n * The dice throw will be 1d20 that must be <= statistique\r\n */\r\nexport interface StatisticalTemplate {\r\n\t/** Allow to force the user to choose a name for them characters */\r\n\tcharName?: boolean;\r\n\t/**\r\n\t * The statistics that can be used in the dice throw\r\n\t * @maximum 25\r\n\t */\r\n\tstatistics?: Statistic;\r\n\t/**\r\n\t * A total can be set, it allows to calculate the total value of a future register member\r\n\t * If the sum of the value > total, the bot will send a message to the user to inform him that the total is exceeded and an error will be thrown\r\n\t * @note statistique that have a formula will be ignored from the total\r\n\t * @TJS-type integer\r\n\t */\r\n\ttotal?: number;\r\n\r\n\t/**\r\n\t * Force the distribition of all the points\r\n\t */\r\n\tforceDistrib?: boolean;\r\n\t/** A dice type in the notation supported by the bot */\r\n\tdiceType?: string;\r\n\t/**\r\n\t * How the success/echec will be done\r\n\t */\r\n\tcritical?: Critical;\r\n\t/**\r\n\t * Custom critical, allow to adjust the critical on a statistic, and set multiple critical value\r\n\t * @maximum 22\r\n\t */\r\n\tcustomCritical?: CustomCriticalMap;\r\n\r\n\t/** Special dice for damage\r\n\t * @maximum 25\r\n\t * */\r\n\tdamage?: Record<string, string>;\r\n}\r\nexport type CustomCriticalMap = Record<string, CustomCritical>;\r\n\r\n/**\r\n * If the result can be considered as a critical\r\n * Critical is compared to the \"natural\" dice result, so any modifier doesn't count\r\n */\r\nexport interface Critical {\r\n\t/**\r\n\t * The value that will be considered as a success\r\n\t * Can only be compared strictly with the natural dice result\r\n\t * @TJS-type integer\r\n\t */\r\n\tsuccess?: number;\r\n\t/**\r\n\t * The value that will be considered as a failure.\r\n\t * Can only be compared strictly with the natural dice result\r\n\t * @TJS-type integer\r\n\t */\r\n\tfailure?: number;\r\n}\r\n\r\nexport interface CustomCritical {\r\n\t/**\r\n\t * Sign of the comparison\r\n\t */\r\n\tsign: \"<\" | \">\" | \"<=\" | \">=\" | \"!=\" | \"==\";\r\n\t/**\r\n\t * Can be a simple value, or a formula, including the statistics with $\r\n\t * @example round($/2)\r\n\t */\r\n\tvalue: string;\r\n\t/**\r\n\t * If \"true\", the comparison will be made on the natural dice result, without any modifier, including the statistics bonus if any.\r\n\t */\r\n\tonNaturalDice?: boolean;\r\n\t/**\r\n\t * Allow to use the custom critical on dbD command (damage)\r\n\t * @default false\r\n\t */\r\n\taffectSkill?: boolean;\r\n}\r\n\r\nexport enum SortOrder {\r\n\tAscending = \"sa\",\r\n\tDescending = \"sd\",\r\n\tNone = \"none\",\r\n}\r\n","export const COMMENT_REGEX = /\\s+(#|\\/{2}|\\[|\\/\\*)(?<comment>.*)/gi;\r\n// Match comparison operators but exclude explosive dice (!>, !<, !<=, !>=)\r\n// Accept != as a valid comparison, but not !> or !< (which are explosive dice)\r\n// Use negative lookbehind to check for ![<>] before any comparison operator\r\nexport const SIGN_REGEX =\r\n\t/==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=/;\r\nexport const SIGN_REGEX_SPACE =\r\n\t/(==|!=|(?<![!<>])>=|(?<![!<>])<=|(?<!!)(?<![<>])>|(?<!!)(?<![<>])<|(?<!!)(?<![<>])=)(\\S+)/;\r\n\r\nexport const SYMBOL_DICE = \"&\";\r\n\r\nexport const DETECT_CRITICAL = /\\{\\*?c[fs]:([<>=]|!=)+(.+?)}/gim;\r\nexport const OPTIONAL_COMMENT = /\\s+(#|\\/{2}|\\[|\\/\\*)?(?<comment>.*)/gi;\r\n","/**\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 { type DiceRoll, DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\n\r\nimport {\r\n\tcompareSignFormule,\r\n\tcountExplodingSuccesses,\r\n\ttype ExplodingSuccess,\r\n\textractValuesFromOutput,\r\n\tfixParenthesis,\r\n\tformatComment,\r\n\tgetCompare,\r\n\tgetModifier,\r\n\tgetRollBounds,\r\n\thandleBulkRolls,\r\n\thandlePitySystem,\r\n\tinverseSign,\r\n\tisTrivialComparison,\r\n\tmatchComparison,\r\n\tnormalizeExplodingSuccess,\r\n\tprepareDice,\r\n\treplaceText,\r\n\treplaceUnwantedText,\r\n\tsetSortOrder,\r\n} from \"./dice\";\r\nimport { DiceTypeError } from \"./errors\";\r\nimport { type Compare, type ComparedValue, type Resultat, SortOrder } from \"./interfaces\";\r\nimport {\r\n\tCOMMENT_REGEX,\r\n\tOPTIONAL_COMMENT,\r\n\tSIGN_REGEX_SPACE,\r\n\tSYMBOL_DICE,\r\n} from \"./interfaces/constant\";\r\n\r\n/**\r\n * Parse the string provided and turn it as a readable dice for dice parser\r\n * @param {string} dice The dice string to parse and roll\r\n * @param {Engine|null} engine The random engine to use, default to nodeCrypto\r\n * @param {boolean} pity Whether to enable pity system (reroll on failure) or not\r\n * @param {boolean} sort Whether to sort the dice results or not\r\n * @returns {Resultat|undefined} The result of the roll\r\n */\r\nexport function roll(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean,\r\n\tsort?: SortOrder\r\n): Resultat | undefined {\r\n\tif (sort === SortOrder.None) sort = undefined;\r\n\r\n\tconst prepared = prepareDice(dice);\r\n\tif (!prepared.dice.includes(\"d\")) return undefined;\r\n\r\n\t// Handle shared rolls\r\n\tif (prepared.isSharedRoll) {\r\n\t\treturn sharedRolls(\r\n\t\t\tprepared.dice,\r\n\t\t\tengine,\r\n\t\t\tpity,\r\n\t\t\tprepared.explodingSuccess,\r\n\t\t\tprepared.diceDisplay,\r\n\t\t\tprepared.isSharedCurly\r\n\t\t);\r\n\t}\r\n\r\n\tlet processedDice = fixParenthesis(prepared.dice);\r\n\tconst modificator = getModifier(processedDice);\r\n\r\n\t// Extract compare BEFORE rolling, but NOT for curly bulk rolls\r\n\tconst compareRegex = processedDice.match(SIGN_REGEX_SPACE);\r\n\tlet compare: ComparedValue | undefined;\r\n\tif (compareRegex && !prepared.isCurlyBulk) {\r\n\t\tconst compareResult = getCompare(processedDice, compareRegex, engine, pity);\r\n\t\tprocessedDice = compareResult.dice;\r\n\t\tcompare = compareResult.compare;\r\n\t}\r\n\r\n\t// For simple curly braces, wrap the diceDisplay with braces\r\n\tlet finalDiceDisplay = prepared.diceDisplay;\r\n\tif (prepared.isSimpleCurly && !prepared.diceDisplay.startsWith(\"{\")) {\r\n\t\tfinalDiceDisplay = `{${prepared.diceDisplay}}`;\r\n\t}\r\n\r\n\t// Handle bulk rolls\r\n\tconst bulkProcessContent = prepared.isCurlyBulk ? prepared.bulkContent : processedDice;\r\n\tif (bulkProcessContent.match(/\\d+?#(.*)/)) {\r\n\t\treturn handleBulkRolls(\r\n\t\t\tprocessedDice,\r\n\t\t\tprepared.isCurlyBulk,\r\n\t\t\tprepared.bulkContent,\r\n\t\t\tcompare,\r\n\t\t\tprepared.explodingSuccess,\r\n\t\t\tprepared.diceDisplay,\r\n\t\t\tengine,\r\n\t\t\tsort\r\n\t\t);\r\n\t}\r\n\r\n\t// Standard roll\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\tlet diceWithoutComment = processedDice.replace(COMMENT_REGEX, \"\").trimEnd();\r\n\tdiceWithoutComment = setSortOrder(diceWithoutComment, sort);\r\n\r\n\tlet diceRoll: DiceRoll | DiceRoll[];\r\n\ttry {\r\n\t\tdiceRoll = roller.roll(diceWithoutComment);\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(diceWithoutComment, \"roll\", error);\r\n\t}\r\n\r\n\t// Update compare.trivial after rolling\r\n\tif (compare && diceRoll) {\r\n\t\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\r\n\t\tconst trivial = isTrivialComparison(\r\n\t\t\tcurrentRoll.maxTotal,\r\n\t\t\tcurrentRoll.minTotal,\r\n\t\t\tcompare\r\n\t\t);\r\n\t\tcompare.trivial = trivial ? true : undefined;\r\n\t}\r\n\r\n\tconst commentMatch = processedDice.match(COMMENT_REGEX);\r\n\tconst comment = commentMatch ? commentMatch[2] : undefined;\r\n\r\n\t// Handle pity system\r\n\tlet rerollCount = 0;\r\n\tlet pityResult: Resultat | undefined;\r\n\tif (pity && compare) {\r\n\t\tconst pityData = handlePitySystem(\r\n\t\t\tdiceWithoutComment,\r\n\t\t\tcompare,\r\n\t\t\tdiceRoll,\r\n\t\t\troller,\r\n\t\t\tengine\r\n\t\t);\r\n\t\trerollCount = pityData.rerollCount;\r\n\t\tpityResult = pityData.result;\r\n\t\tif (pityResult) {\r\n\t\t\treturn {\r\n\t\t\t\t...pityResult,\r\n\t\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\r\n\t\t\t\tcomment,\r\n\t\t\t\tcompare,\r\n\t\t\t\tmodifier: modificator,\r\n\t\t\t\tpityLogs: rerollCount,\r\n\t\t\t\ttrivial: pityResult.trivial ?? (compare?.trivial ? true : undefined),\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\r\n\tlet resultOutput = replaceUnwantedText(roller.output);\r\n\r\n\t// Handle exploding success\r\n\tif (prepared.explodingSuccess) {\r\n\t\tconst successes = countExplodingSuccesses(\r\n\t\t\tdiceRoll,\r\n\t\t\tprepared.explodingSuccess.sign,\r\n\t\t\tprepared.explodingSuccess.value\r\n\t\t);\r\n\t\tresultOutput = resultOutput\r\n\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successes}`)\r\n\t\t\t.replace(\r\n\t\t\t\tprepared.explodingSuccess.normalizedSegment,\r\n\t\t\t\tprepared.explodingSuccess.originalSegment\r\n\t\t\t);\r\n\r\n\t\treturn {\r\n\t\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : prepared.diceDisplay,\r\n\t\t\tresult: resultOutput,\r\n\t\t\tcomment,\r\n\t\t\tcompare: compare ? compare : undefined,\r\n\t\t\tmodifier: modificator,\r\n\t\t\ttotal: successes,\r\n\t\t\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\r\n\t\t\ttrivial: compare?.trivial ? true : undefined,\r\n\t\t};\r\n\t}\r\n\r\n\treturn {\r\n\t\tdice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,\r\n\t\tresult: resultOutput,\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\tpityLogs: rerollCount > 0 ? rerollCount : undefined,\r\n\t\ttrivial: compare?.trivial ? true : undefined,\r\n\t};\r\n}\r\n\r\nfunction sharedRolls(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean,\r\n\texplodingSuccessMain?: ExplodingSuccess,\r\n\tdiceDisplay?: string,\r\n\tisSharedCurly?: boolean\r\n): Resultat | undefined {\r\n\t// If not provided (call from elsewhere), try to detect\r\n\tif (!explodingSuccessMain)\r\n\t\texplodingSuccessMain = normalizeExplodingSuccess(dice.split(\";\")[0] ?? dice);\r\n\r\n\tif (explodingSuccessMain) {\r\n\t\t// Use normalized dice for internal processing but keep original for display\r\n\t\tdice = dice.replace(explodingSuccessMain.originalSegment, \"!\");\r\n\t}\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\tconst displayDice = diceDisplay ?? explodingSuccessMain?.originalDice ?? split[0];\r\n\tlet diceMain = fixParenthesis(split[0]);\r\n\t// Extract and save the comments first to avoid conflicts with parentheses detection\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/gi;\r\n\tconst comments = formatComment(diceMain);\r\n\t// Remove comments before checking for hidden dice (parentheses)\r\n\tconst diceMainWithoutComments = diceMain.replace(commentsRegex, \"\").trim();\r\n\tconst toHideRegex = /\\((?<dice>[^)]+)\\)/;\r\n\tconst toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;\r\n\tlet hidden = false;\r\n\tif (toHide?.dice) {\r\n\t\tdiceMain = toHide.dice;\r\n\t\thidden = true;\r\n\t} else if (toHide) {\r\n\t\tdiceMain = \"1d1\";\r\n\t\thidden = true;\r\n\t} else {\r\n\t\t// No hidden dice, use the dice without comments\r\n\t\tdiceMain = diceMainWithoutComments;\r\n\t}\r\n\tconst rollBounds = getRollBounds(diceMain, engine);\r\n\tlet diceResult = roll(diceMain, engine, pity);\r\n\tif (!diceResult || !diceResult.total) {\r\n\t\tif (hidden) {\r\n\t\t\tdiceResult = roll(fixParenthesis(split[0]), engine, pity);\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\r\n\t// If we had a double-sign exploding, recompute successes from the first segment output\r\n\tif (explodingSuccessMain && diceResult.result) {\r\n\t\tconst values = extractValuesFromOutput(diceResult.result);\r\n\t\tdiceResult.total = values.filter((v) =>\r\n\t\t\tmatchComparison(explodingSuccessMain!.sign, v, explodingSuccessMain!.value)\r\n\t\t).length;\r\n\t}\r\n\tlet aggregatedCompare = diceResult.compare;\r\n\tlet hasTrivialComparison = diceResult.compare?.trivial === true;\r\n\tresults.push(`※ ${comments}${diceResult.result}`);\r\n\tlet total = diceResult.total;\r\n\tdiceResult.comment = mainComment;\r\n\tif (!total) {\r\n\t\treturn {\r\n\t\t\tdice: displayDice,\r\n\t\t\tresult: results.join(\";\"),\r\n\t\t\tcomment: mainComment,\r\n\t\t\tcompare: aggregatedCompare,\r\n\t\t\tmodifier: diceResult.modifier,\r\n\t\t\ttotal,\r\n\t\t\ttrivial: hasTrivialComparison ? true : undefined,\r\n\t\t};\r\n\t}\r\n\tfor (let element of split.slice(1)) {\r\n\t\tconst comment = formatComment(element);\r\n\t\telement = element\r\n\t\t\t.replaceAll(commentsRegex, \"\")\r\n\t\t\t.replaceAll(OPTIONAL_COMMENT, \"\")\r\n\t\t\t.trim();\r\n\t\tlet toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);\r\n\t\t//remove comments\r\n\t\tconst compareRegex = toRoll.match(SIGN_REGEX_SPACE);\r\n\t\tif (compareRegex) {\r\n\t\t\tif (isSharedCurly) {\r\n\t\t\t\t// For curly braces shared rolls, display success count instead of comparison details\r\n\t\t\t\tconst compareResult = compareSignFormule(\r\n\t\t\t\t\ttoRoll,\r\n\t\t\t\t\tcompareRegex,\r\n\t\t\t\t\telement,\r\n\t\t\t\t\tdiceResult,\r\n\t\t\t\t\tengine,\r\n\t\t\t\t\tpity,\r\n\t\t\t\t\trollBounds\r\n\t\t\t\t);\r\n\t\t\t\t// Count success: 1 if comparison is true, 0 if false\r\n\t\t\t\tconst { diceAll } = replaceText(element, diceResult.total, diceResult.dice);\r\n\t\t\t\tlet successCount = 0;\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconst evaluated = evaluate(toRoll);\r\n\t\t\t\t\tsuccessCount = evaluated ? 1 : 0;\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\t// If evaluation fails, try with roll\r\n\t\t\t\t\tconst evaluated = roll(toRoll, engine, pity) as Resultat | undefined;\r\n\t\t\t\t\tsuccessCount = (evaluated?.total ?? 0) ? 1 : 0;\r\n\t\t\t\t}\r\n\t\t\t\tresults.push(`※ ${comment}${diceAll}: ${successCount}`);\r\n\t\t\t\ttotal += successCount;\r\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\r\n\t\t\t\t\taggregatedCompare = compareResult.compare;\r\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\r\n\t\t\t} else {\r\n\t\t\t\tconst compareResult = compareSignFormule(\r\n\t\t\t\t\ttoRoll,\r\n\t\t\t\t\tcompareRegex,\r\n\t\t\t\t\telement,\r\n\t\t\t\t\tdiceResult,\r\n\t\t\t\t\tengine,\r\n\t\t\t\t\tpity,\r\n\t\t\t\t\trollBounds\r\n\t\t\t\t);\r\n\t\t\t\ttoRoll = compareResult.dice;\r\n\t\t\t\tresults.push(compareResult.results);\r\n\t\t\t\tif (!aggregatedCompare && compareResult.compare)\r\n\t\t\t\t\taggregatedCompare = compareResult.compare;\r\n\t\t\t\tif (compareResult.trivial) hasTrivialComparison = true;\r\n\t\t\t}\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, pity);\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\t\tif (!aggregatedCompare && evaluated.compare)\r\n\t\t\t\t\t\taggregatedCompare = evaluated.compare;\r\n\t\t\t\t\tif (evaluated.compare?.trivial) hasTrivialComparison = true;\r\n\t\t\t\t} else 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: displayDice,\r\n\t\tresult: results.join(\";\"),\r\n\t\tcomment: mainComment,\r\n\t\tcompare:\r\n\t\t\thasTrivialComparison && aggregatedCompare\r\n\t\t\t\t? { ...aggregatedCompare, trivial: true }\r\n\t\t\t\t: aggregatedCompare,\r\n\t\tmodifier: diceResult.modifier,\r\n\t\ttotal,\r\n\t\ttrivial: hasTrivialComparison ? true : undefined,\r\n\t};\r\n}\r\n\r\nexport function 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\tpity?: boolean\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, pity) 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","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport { DiceTypeError } from \"../errors\";\r\nimport type { Compare, ComparedValue, Resultat, SortOrder } from \"../interfaces\";\r\nimport { COMMENT_REGEX, SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\r\nimport { isTrivialComparison } from \"./compare\";\r\nimport {\r\n\tcountExplodingSuccesses,\r\n\tEXPLODING_SUCCESS_REGEX,\r\n\ttype ExplodingSuccess,\r\n} from \"./exploding\";\r\nimport { extractValuesFromOutput, getModifier, setSortOrder } from \"./extract\";\r\nimport { replaceUnwantedText } from \"./replace\";\r\nimport { matchComparison } from \"./signs\";\r\n\r\n/**\r\n * Gère les lancers en masse (bulk rolls)\r\n */\r\nexport function handleBulkRolls(\r\n\tdice: string,\r\n\tisCurlyBulk: boolean,\r\n\tbulkContent: string,\r\n\tcompare: ComparedValue | undefined,\r\n\texplodingSuccess: ExplodingSuccess | undefined,\r\n\tdiceDisplay: string,\r\n\tengine: Engine | null,\r\n\tsort?: SortOrder\r\n): Resultat {\r\n\tconst bulkProcessContent = isCurlyBulk ? bulkContent : dice;\r\n\tconst diceArray = bulkProcessContent.split(\"#\");\r\n\tconst numberOfDice = Number.parseInt(diceArray[0], 10);\r\n\tlet diceToRoll = diceArray[1].replace(COMMENT_REGEX, \"\");\r\n\tconst commentsMatch = diceArray[1].match(COMMENT_REGEX);\r\n\tconst comments = commentsMatch ? commentsMatch[2] : undefined;\r\n\r\n\tlet curlyCompare: Compare | undefined;\r\n\tif (isCurlyBulk) {\r\n\t\tconst curlyCompareRegex = diceToRoll.match(SIGN_REGEX_SPACE);\r\n\t\tif (curlyCompareRegex) {\r\n\t\t\tconst compareSign = curlyCompareRegex[0].match(SIGN_REGEX)?.[0];\r\n\t\t\tconst compareValue = curlyCompareRegex[2];\r\n\t\t\tif (compareSign && compareValue) {\r\n\t\t\t\tcurlyCompare = {\r\n\t\t\t\t\tsign: compareSign as \"<\" | \">\" | \">=\" | \"<=\" | \"=\" | \"!=\" | \"==\",\r\n\t\t\t\t\tvalue: Number.parseInt(compareValue, 10),\r\n\t\t\t\t};\r\n\t\t\t\tdiceToRoll = diceToRoll.replace(SIGN_REGEX_SPACE, \"\");\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tdiceToRoll = setSortOrder(diceToRoll, sort);\r\n\r\n\tconst activeCompare: Compare | undefined =\r\n\t\tcompare ||\r\n\t\tcurlyCompare ||\r\n\t\t(explodingSuccess\r\n\t\t\t? ({ sign: explodingSuccess.sign, value: explodingSuccess.value } as Compare)\r\n\t\t\t: undefined);\r\n\r\n\tif (activeCompare) {\r\n\t\treturn handleBulkRollsWithComparison(\r\n\t\t\tnumberOfDice,\r\n\t\t\tdiceToRoll,\r\n\t\t\tcomments,\r\n\t\t\tactiveCompare,\r\n\t\t\texplodingSuccess,\r\n\t\t\tdiceDisplay,\r\n\t\t\tisCurlyBulk,\r\n\t\t\tcurlyCompare,\r\n\t\t\tcompare,\r\n\t\t\tengine\r\n\t\t);\r\n\t}\r\n\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\r\n\tfor (let i = 0; i < numberOfDice; i++) {\r\n\t\ttry {\r\n\t\t\troller.roll(diceToRoll);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\r\n\t\t}\r\n\t}\r\n\r\n\tconst finalDice = isCurlyBulk ? `{${diceToRoll}}` : diceToRoll;\r\n\tconst modificator = getModifier(dice);\r\n\r\n\treturn {\r\n\t\tdice: finalDice,\r\n\t\tresult: replaceUnwantedText(roller.output),\r\n\t\tcomment: comments,\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\n/**\r\n * Gère les lancers en masse avec comparaison\r\n */\r\nfunction handleBulkRollsWithComparison(\r\n\tnumberOfDice: number,\r\n\tdiceToRoll: string,\r\n\tcomments: string | undefined,\r\n\tactiveCompare: Compare,\r\n\texplodingSuccess: ExplodingSuccess | undefined,\r\n\tdiceDisplay: string,\r\n\tisCurlyBulk: boolean,\r\n\tcurlyCompare: Compare | undefined,\r\n\tcompare: ComparedValue | undefined,\r\n\tengine: Engine | null\r\n): Resultat {\r\n\tconst results: string[] = [];\r\n\tlet successCount = 0;\r\n\tconst roller = new DiceRoller();\r\n\tNumberGenerator.generator.engine = engine;\r\n\tlet trivialComparisonDetected = false;\r\n\r\n\tconst formatOutput = (output: string, addStar: boolean) => {\r\n\t\tconst formatted =\r\n\t\t\taddStar && isCurlyBulk\r\n\t\t\t\t? output.replace(\r\n\t\t\t\t\t\t/\\[([^\\]]+)\\]/,\r\n\t\t\t\t\t\t(_m, content) =>\r\n\t\t\t\t\t\t\t`[${content\r\n\t\t\t\t\t\t\t\t.split(\",\")\r\n\t\t\t\t\t\t\t\t.map((d: string) => `${d.trim()}*`)\r\n\t\t\t\t\t\t\t\t.join(\", \")}]`\r\n\t\t\t\t\t)\r\n\t\t\t\t: output;\r\n\t\treturn curlyCompare\r\n\t\t\t? formatted.replace(/^([^:]+):/, `$1${curlyCompare.sign}${curlyCompare.value}:`)\r\n\t\t\t: formatted;\r\n\t};\r\n\r\n\tfor (let i = 0; i < numberOfDice; i++) {\r\n\t\ttry {\r\n\t\t\tconst individualRoll = roller.roll(diceToRoll);\r\n\t\t\tconst rollInstance = Array.isArray(individualRoll)\r\n\t\t\t\t? individualRoll[0]\r\n\t\t\t\t: individualRoll;\r\n\r\n\t\t\tif (!trivialComparisonDetected && activeCompare) {\r\n\t\t\t\tconst { maxTotal, minTotal } = rollInstance;\r\n\t\t\t\ttrivialComparisonDetected = isTrivialComparison(\r\n\t\t\t\t\tmaxTotal,\r\n\t\t\t\t\tminTotal,\r\n\t\t\t\t\tactiveCompare\r\n\t\t\t\t);\r\n\t\t\t}\r\n\r\n\t\t\tconst rollOutput = rollInstance.output;\r\n\r\n\t\t\tif (explodingSuccess) {\r\n\t\t\t\tconst successesForRoll = countExplodingSuccesses(\r\n\t\t\t\t\trollInstance,\r\n\t\t\t\t\texplodingSuccess.sign,\r\n\t\t\t\t\texplodingSuccess.value\r\n\t\t\t\t);\r\n\t\t\t\tsuccessCount += successesForRoll;\r\n\r\n\t\t\t\tlet formattedRollOutput = rollOutput\r\n\t\t\t\t\t.replace(explodingSuccess.normalizedSegment, explodingSuccess.originalSegment)\r\n\t\t\t\t\t.replace(/=\\s*-?\\d+(?:\\.\\d+)?$/, `= ${successesForRoll}`);\r\n\t\t\t\tformattedRollOutput = formatOutput(formattedRollOutput, false);\r\n\t\t\t\tresults.push(formattedRollOutput);\r\n\t\t\t} else {\r\n\t\t\t\tconst rollTotal = rollInstance.total;\r\n\t\t\t\tconst isSuccess = evaluate(\r\n\t\t\t\t\t`${rollTotal}${activeCompare.sign}${activeCompare.value}`\r\n\t\t\t\t);\r\n\r\n\t\t\t\tif (isSuccess) successCount++;\r\n\t\t\t\tresults.push(formatOutput(rollOutput, isSuccess));\r\n\t\t\t}\r\n\t\t} catch (error) {\r\n\t\t\tthrow new DiceTypeError(diceToRoll, \"roll\", error);\r\n\t\t}\r\n\t}\r\n\r\n\tif (explodingSuccess) {\r\n\t\tconst signSource = explodingSuccess?.originalDice ?? diceDisplay;\r\n\t\tconst explodingMatch = signSource.match(EXPLODING_SUCCESS_REGEX);\r\n\t\tif (explodingMatch) {\r\n\t\t\tconst [, doubledSignRaw, valueStr] = explodingMatch;\r\n\t\t\tlet doubledSign: string;\r\n\t\t\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\r\n\t\t\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\r\n\t\t\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\r\n\r\n\t\t\tconst signMap: Record<string, Compare[\"sign\"]> = {\r\n\t\t\t\t\">>\": \">\",\r\n\t\t\t\t\"<<\": \"<\",\r\n\t\t\t\t\">=\": \">=\",\r\n\t\t\t\t\"<=\": \"<=\",\r\n\t\t\t\t\"==\": \"=\",\r\n\t\t\t\t\"!==\": \"!=\",\r\n\t\t\t\t\"!!==\": \"=\",\r\n\t\t\t};\r\n\t\t\tconst mappedSign = signMap[doubledSign];\r\n\t\t\tconst mappedValue = Number.parseFloat(valueStr);\r\n\r\n\t\t\tif (mappedSign && !Number.isNaN(mappedValue)) {\r\n\t\t\t\tconst resultsString = replaceUnwantedText(results.join(\"; \"));\r\n\t\t\t\tconst flatValues = resultsString\r\n\t\t\t\t\t.split(\";\")\r\n\t\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment));\r\n\r\n\t\t\t\tif (mappedSign === \"!=\") {\r\n\t\t\t\t\tconst equalsCount = flatValues.filter((val) => val === mappedValue).length;\r\n\t\t\t\t\tsuccessCount = flatValues.length - equalsCount;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tsuccessCount = flatValues.filter((val) =>\r\n\t\t\t\t\t\tmatchComparison(mappedSign, val, mappedValue)\r\n\t\t\t\t\t).length;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif (compare && trivialComparisonDetected) compare.trivial = true;\r\n\r\n\tconst finalDice = isCurlyBulk\r\n\t\t? `{${diceToRoll}${curlyCompare?.sign}${curlyCompare?.value}}`\r\n\t\t: diceToRoll;\r\n\r\n\tconst resultOutput = replaceUnwantedText(results.join(\"; \"));\r\n\tconst finalTotal = explodingSuccess\r\n\t\t? resultOutput\r\n\t\t\t\t.split(\";\")\r\n\t\t\t\t.flatMap((segment) => extractValuesFromOutput(segment))\r\n\t\t\t\t.filter((val) =>\r\n\t\t\t\t\tmatchComparison(explodingSuccess.sign, val, explodingSuccess.value)\r\n\t\t\t\t).length\r\n\t\t: successCount;\r\n\r\n\tconst modificator = getModifier(diceDisplay);\r\n\r\n\treturn {\r\n\t\tdice: explodingSuccess ? diceDisplay : finalDice,\r\n\t\tresult: resultOutput,\r\n\t\tcomment: comments,\r\n\t\tcompare: isCurlyBulk ? undefined : compare,\r\n\t\tmodifier: modificator,\r\n\t\ttotal: finalTotal,\r\n\t\ttrivial: trivialComparisonDetected ? true : undefined,\r\n\t};\r\n}\r\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport type { ComparedValue } from \"../interfaces\";\r\nimport { SIGN_REGEX, SIGN_REGEX_SPACE } from \"../interfaces/constant\";\r\nimport { roll } from \"../roll\";\r\nimport { isNumber } from \"../utils\";\r\n\r\n/**\r\n * Check if a comparison is trivial (always true or always false)\r\n * Uses the existing canComparisonSucceed logic and checks both success and failure conditions\r\n * @param maxValue Maximum possible value from the dice roll\r\n * @param minValue Minimum possible value from the dice roll\r\n * @param compare The comparison object\r\n * @returns true if the comparison is trivial (always true or always false)\r\n */\r\nexport function isTrivialComparison(\r\n\tmaxValue: number,\r\n\tminValue: number,\r\n\tcompare: ComparedValue\r\n): boolean {\r\n\t// Check if comparison can never succeed (always false)\r\n\tconst canSucceed = canComparisonSucceed(maxValue, compare, minValue);\r\n\r\n\t// Check if comparison can never fail (always true) by checking the inverse with minValue\r\n\tconst canFail = canComparisonFail(maxValue, compare, minValue);\r\n\r\n\t// Trivial if it can never succeed OR can never fail\r\n\treturn !canSucceed || !canFail;\r\n}\r\n\r\n/**\r\n * Check if a comparison can theoretically fail given roll bounds\r\n * @param maxRollValue Maximum possible roll value\r\n * @param compare The comparison object\r\n * @param minRollValue Minimum possible roll value (defaults to 1)\r\n * @returns true if the comparison can fail at least once\r\n */\r\nexport function canComparisonFail(\r\n\tmaxRollValue: number,\r\n\tcompare: ComparedValue,\r\n\tminRollValue = 1\r\n): boolean {\r\n\tswitch (compare.sign) {\r\n\t\tcase \">\":\r\n\t\t\treturn minRollValue <= compare.value; // failure if roll <= value\r\n\t\tcase \">=\":\r\n\t\t\treturn minRollValue < compare.value; // failure if roll < value\r\n\t\tcase \"<\":\r\n\t\t\treturn maxRollValue >= compare.value; // failure if roll >= value\r\n\t\tcase \"<=\":\r\n\t\t\treturn maxRollValue > compare.value; // failure if roll > value\r\n\t\tcase \"=\":\r\n\t\tcase \"==\":\r\n\t\t\treturn minRollValue !== compare.value || maxRollValue !== compare.value; // can differ\r\n\t\tcase \"!=\":\r\n\t\t\treturn minRollValue <= compare.value && compare.value <= maxRollValue; // equality possible\r\n\t\tdefault:\r\n\t\t\treturn true;\r\n\t}\r\n}\r\n\r\nexport function rollCompare(\r\n\tvalue: unknown,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean\r\n) {\r\n\tif (isNumber(value)) return { value: Number.parseInt(value as string, 10) };\r\n\t// Handle empty value or string - return 0 as default\r\n\tif (!value || (typeof value === \"string\" && value.trim() === \"\")) {\r\n\t\treturn { value: 0, diceResult: value as string };\r\n\t}\r\n\tconst rollComp = roll(value as string, engine, pity);\r\n\tif (!rollComp?.total) {\r\n\t\t//not a dice throw\r\n\t\ttry {\r\n\t\t\treturn { value: evaluate(value as string), diceResult: value as string };\r\n\t\t} catch (error) {\r\n\t\t\t// If evaluate fails, return 0\r\n\t\t\treturn { value: 0, diceResult: value as string };\r\n\t\t}\r\n\t}\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\nexport function getCompare(\r\n\tdice: string,\r\n\tcompareRegex: RegExpMatchArray,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean\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 (\r\n\t\tdice.match(/((\\{.*,(.*)+\\}|([><=!]+\\d+f))([><=]|!=)+\\d+\\}?)|\\{(.*)(([><=]|!=)+).*\\}/)\r\n\t)\r\n\t\treturn { dice, compare: undefined };\r\n\tdice = dice.replace(SIGN_REGEX_SPACE, \"\");\r\n\tlet compare: ComparedValue;\r\n\t// compareRegex comes from SIGN_REGEX_SPACE: /([><=]|!=)+(\\S+)/\r\n\t// index 1 = the comparison sign (e.g., \">\", \">=\", \"!=\"); index 2 = the compared value/expression\r\n\tconst calc = compareRegex[2];\r\n\tconst sign = calc.match(/[+-/*^]/)?.[0];\r\n\tconst compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];\r\n\r\n\tif (sign) {\r\n\t\tconst toCalc = calc.replace(SIGN_REGEX, \"\").replace(/\\s/g, \"\").replace(/;(.*)/, \"\");\r\n\t\tconst rCompare = rollCompare(toCalc, engine, pity);\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, pity);\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\r\n\treturn { dice, compare };\r\n}\r\n\r\n/**\r\n * Check if a comparison can theoretically succeed given a maximum roll value\r\n * @example\r\n * canComparisonSucceed(10, { sign: \">=\", value: 15 }) => false (impossible to roll >= 15 with 1d10)\r\n * canComparisonSucceed(20, { sign: \">=\", value: 15 }) => true (possible to roll >= 15 with 1d20)\r\n */\r\nexport function canComparisonSucceed(\r\n\tmaxRollValue: number,\r\n\tcompare: ComparedValue,\r\n\tminRollValue?: number\r\n): boolean {\r\n\tswitch (compare.sign) {\r\n\t\tcase \">\":\r\n\t\t\treturn maxRollValue > compare.value;\r\n\t\tcase \">=\":\r\n\t\t\treturn maxRollValue >= compare.value;\r\n\t\tcase \"<\":\r\n\t\t\treturn compare.value > (minRollValue ?? 1); // Au moins minRollValue possible\r\n\t\tcase \"<=\":\r\n\t\t\treturn compare.value >= (minRollValue ?? 1); // Au moins minRollValue possible\r\n\t\tcase \"=\":\r\n\t\tcase \"==\":\r\n\t\t\treturn maxRollValue >= compare.value && compare.value >= (minRollValue ?? 1);\r\n\t\tcase \"!=\":\r\n\t\t\treturn maxRollValue !== compare.value || (minRollValue ?? 1) !== compare.value;\r\n\t\tdefault:\r\n\t\t\treturn true;\r\n\t}\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport \"uniformize\";\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport {\r\n\ttype CustomCritical,\r\n\tDiceTypeError,\r\n\tdiceTypeRandomParse,\r\n\tFormulaError,\r\n\tSIGN_REGEX_SPACE,\r\n\ttype StatisticalTemplate,\r\n} 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\r\n\t\t\t\t// Check for dice notation patterns like \"1dstat1\" or \"dstat1\"\r\n\t\t\t\tconst diceMatch = /^(\\d*)d(.+)$/i.exec(tokenStd);\r\n\t\t\t\tif (diceMatch) {\r\n\t\t\t\t\tconst diceCount = diceMatch[1] || \"\";\r\n\t\t\t\t\tconst afterD = diceMatch[2];\r\n\t\t\t\t\tlet foundStatAfterD = false;\r\n\t\t\t\t\tfor (const key of statKeys) {\r\n\t\t\t\t\t\tconst keyStd = key.standardize();\r\n\t\t\t\t\t\tif (afterD === keyStd) {\r\n\t\t\t\t\t\t\tresult += `${diceCount}d${stats[key].toString()}`;\r\n\t\t\t\t\t\t\tfoundStatAfterD = true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (foundStatAfterD) {\r\n\t\t\t\t\t\tlastIndex = tokenRegex.lastIndex;\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\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 (tokenStd === keyStd) {\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(/\\$\\B/g, 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/**\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\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","import type { DiceRoll } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Compare } from \"../interfaces\";\r\nimport { matchComparison } from \"./signs\";\r\n\r\nexport type ExplodingSuccess = {\r\n\tdice: string;\r\n\toriginalDice: string;\r\n\tsign: Compare[\"sign\"];\r\n\tvalue: number;\r\n\tnormalizedSegment: string;\r\n\toriginalSegment: string;\r\n};\r\n\r\nexport const EXPLODING_SUCCESS_REGEX =\r\n\t/(!(?:>>=|<<=|!==|!!==|>>|<<|==|!=))(-?\\d+(?:\\.\\d+)?)/;\r\n\r\nexport function normalizeExplodingSuccess(dice: string): ExplodingSuccess | undefined {\r\n\tconst match = dice.match(EXPLODING_SUCCESS_REGEX);\r\n\tif (!match) return undefined;\r\n\r\n\tconst [, doubledSignRaw, valueStr] = match;\r\n\tlet doubledSign: string;\r\n\tif (doubledSignRaw === \"!!==\") doubledSign = \"==\";\r\n\telse if (doubledSignRaw === \"!==\") doubledSign = \"!==\";\r\n\telse doubledSign = doubledSignRaw.replace(/^!/, \"\");\r\n\tconst signMap: Record<string, Compare[\"sign\"]> = {\r\n\t\t\">>\": \">\",\r\n\t\t\"<<\": \"<\",\r\n\t\t\">>=\": \">=\",\r\n\t\t\"<<=\": \"<=\",\r\n\t\t\"==\": \"=\",\r\n\t\t\"!==\": \"!=\",\r\n\t\t\"!!==\": \"=\",\r\n\t};\r\n\r\n\tconst normalizedSign = signMap[doubledSign];\r\n\tif (!normalizedSign) return undefined;\r\n\tlet parsedValue = Number.parseFloat(valueStr);\r\n\tif (Number.isNaN(parsedValue)) {\r\n\t\ttry {\r\n\t\t\tparsedValue = Number.parseFloat(evaluate(valueStr) as unknown as string);\r\n\t\t} catch (_error) {\r\n\t\t\tparsedValue = 0;\r\n\t\t}\r\n\t}\r\n\r\n\t// Remove comparison for the actual explode mechanic so it uses default explode\r\n\tconst normalizedSegment = \"!\";\r\n\tconst replacedDice = dice.replace(match[0], normalizedSegment);\r\n\r\n\treturn {\r\n\t\tdice: replacedDice,\r\n\t\toriginalDice: dice,\r\n\t\tsign: normalizedSign,\r\n\t\tvalue: parsedValue,\r\n\t\tnormalizedSegment,\r\n\t\toriginalSegment: match[0],\r\n\t};\r\n}\r\n\r\nexport function countExplodingSuccesses(\r\n\tdiceRoll: DiceRoll | DiceRoll[],\r\n\tsign: Compare[\"sign\"],\r\n\tvalue: number\r\n): number {\r\n\tconst rollsArray = Array.isArray(diceRoll) ? diceRoll : [diceRoll];\r\n\tconst flatValues: number[] = [];\r\n\r\n\tfor (const dr of rollsArray) {\r\n\t\tconst groups = (dr as DiceRoll).rolls ?? [];\r\n\t\tfor (const group of groups as unknown as Array<{\r\n\t\t\trolls?: Array<{ value?: number }>;\r\n\t\t}>) {\r\n\t\t\tconst innerRolls = group.rolls ?? [];\r\n\t\t\tfor (const roll of innerRolls) {\r\n\t\t\t\tif (typeof roll.value === \"number\") flatValues.push(roll.value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn flatValues.reduce(\r\n\t\t(acc, current) => acc + (matchComparison(sign, current, value) ? 1 : 0),\r\n\t\t0\r\n\t);\r\n}\r\n","import { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport type { Compare, Resultat } from \"../interfaces\";\r\nimport { replaceInFormula, roll } from \"../roll\";\r\nimport { getCompare, isTrivialComparison } from \"./compare\";\r\nimport { replaceText } from \"./replace\";\r\n\r\nexport function matchComparison(sign: Compare[\"sign\"], val: number, value: number) {\r\n\tswitch (sign) {\r\n\t\tcase \">\":\r\n\t\t\treturn val > value;\r\n\t\tcase \">=\":\r\n\t\t\treturn val >= value;\r\n\t\tcase \"<\":\r\n\t\t\treturn val < value;\r\n\t\tcase \"<=\":\r\n\t\t\treturn val <= value;\r\n\t\tcase \"=\":\r\n\t\tcase \"==\":\r\n\t\t\treturn val === value;\r\n\t\tcase \"!=\":\r\n\t\t\treturn val !== value;\r\n\t\tdefault:\r\n\t\t\treturn false;\r\n\t}\r\n}\r\n\r\nexport function 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\nexport function 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\tpity?: boolean,\r\n\trollBounds?: { min: number; max: number }\r\n): { dice: string; results: string; compare?: Compare; trivial: boolean } {\r\n\tlet results = \"\";\r\n\tlet trivial = false;\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, pity);\r\n\t}\r\n\tif (typeof res === \"boolean\") {\r\n\t\tconst detectedTrivial =\r\n\t\t\trollBounds && compareResult.compare\r\n\t\t\t\t? isTrivialComparison(rollBounds.max, rollBounds.min, compareResult.compare)\r\n\t\t\t\t: false;\r\n\t\tif (detectedTrivial && compareResult.compare) compareResult.compare.trivial = true;\r\n\t\tif (detectedTrivial) trivial = true;\r\n\t\tresults = replaceInFormula(element, diceResult, compareResult, res, engine, pity);\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\tif (diceResult.compare.trivial) trivial = true;\r\n\t\t}\r\n\t}\r\n\treturn { dice: compareResult.dice, results, compare: compareResult.compare, trivial };\r\n}\r\n","import { COMMENT_REGEX, SYMBOL_DICE } from \"../interfaces/constant\";\r\n\r\nexport function replaceUnwantedText(dice: string) {\r\n\treturn dice.replaceAll(/[{}]/g, \"\").replaceAll(/s[ad]/gi, \"\");\r\n}\r\n\r\nexport function 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\nexport function 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\nexport function formatComment(dice: string) {\r\n\tconst commentsRegex = /\\[(?<comments>.*?)\\]/;\r\n\tconst commentsMatch = commentsRegex.exec(dice);\r\n\tconst comments = commentsMatch?.groups?.comments\r\n\t\t? `${commentsMatch.groups.comments}`\r\n\t\t: \"\";\r\n\r\n\t// Search for optional comments (# or // style) only AFTER removing bracket comments\r\n\t// to avoid conflicts with parentheses inside bracket comments\r\n\tconst diceWithoutBrackets = dice.replace(commentsRegex, \"\");\r\n\tconst optionalCommentsRegex = /\\s+(#|\\/\\/)(?<comment>.*)/;\r\n\tconst optionalComments = optionalCommentsRegex.exec(diceWithoutBrackets);\r\n\tconst optional = optionalComments?.groups?.comment\r\n\t\t? `${optionalComments.groups.comment.trim()}`\r\n\t\t: \"\";\r\n\r\n\t//fusion of both comments with a space if both exists\r\n\t//result expected = \"__comment1 comment2__ — \"\r\n\t//or \"__comment1__ — \" or \"__comment2__ — \"\r\n\tlet finalComment = \"\";\r\n\tif (comments && optional) finalComment = `__${comments} ${optional}__ — `;\r\n\telse if (comments) finalComment = `__${comments}__ — `;\r\n\telse if (optional) finalComment = `__${optional}__ — `;\r\n\treturn finalComment;\r\n}\r\n","import { DiceRoller, NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport type { Engine } from \"random-js\";\r\nimport type { Modifier, Sign, SortOrder } from \"../interfaces\";\r\nimport { DETECT_CRITICAL } from \"../interfaces/constant\";\r\nimport { replaceFormulaInDice, standardizeDice } from \"../utils\";\r\nimport { calculator } from \"./calculator\";\r\nimport { type ExplodingSuccess, normalizeExplodingSuccess } from \"./exploding\";\r\n\r\nexport function 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\nexport function extractValuesFromOutput(output: string): number[] {\r\n\tconst values: number[] = [];\r\n\tconst regex = /\\[([^\\]]+)\\]/g;\r\n\tlet match: RegExpExecArray | null;\r\n\t// biome-ignore lint/suspicious/noAssignInExpressions: best method to extract all matches\r\n\twhile ((match = regex.exec(output)) !== null) {\r\n\t\tconst segmentValues = match[1]\r\n\t\t\t.split(\",\")\r\n\t\t\t.map((v) => Number.parseInt(v.replace(/[!*]/g, \"\").trim(), 10))\r\n\t\t\t.filter((v) => !Number.isNaN(v));\r\n\t\tvalues.push(...segmentValues);\r\n\t}\r\n\treturn values;\r\n}\r\n\r\nexport function getRollBounds(\r\n\tdice: string,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): { min: number; max: number } | undefined {\r\n\ttry {\r\n\t\tconst roller = new DiceRoller();\r\n\t\tNumberGenerator.generator.engine = engine;\r\n\t\tconst rollResult = roller.roll(dice);\r\n\t\tconst instance = Array.isArray(rollResult) ? rollResult[0] : rollResult;\r\n\t\tconst { minTotal, maxTotal } = instance;\r\n\t\treturn { min: minTotal, max: maxTotal };\r\n\t} catch (error) {\r\n\t\t// Ignore bounds computation errors; trivial detection will simply be skipped\r\n\t}\r\n\treturn undefined;\r\n}\r\n\r\nexport function setSortOrder(toRoll: string, sort?: SortOrder): string {\r\n\t//First check if the diceToRoll contains already a sort order\r\n\tconst sortRegex = /(sa|sd|s)/i;\r\n\tif (sort && !toRoll.match(sortRegex)) {\r\n\t\t//we should insert the sort order at the end of the dice string and before the possible modifier or comparison\r\n\t\tconst modifierComparisonRegex = /([+\\-*/%^]\\d+|([><=!]+\\d+f)|([><=]|!=)+\\d+)$/;\r\n\t\tconst match = toRoll.match(modifierComparisonRegex);\r\n\t\tif (match) {\r\n\t\t\t//Insert before the modifier or comparison\r\n\t\t\tconst index = match.index!;\r\n\t\t\ttoRoll = `${toRoll.slice(0, index)}${sort}${toRoll.slice(index)}`;\r\n\t\t} else {\r\n\t\t\t//Append at the end\r\n\t\t\ttoRoll += sort;\r\n\t\t}\r\n\t}\r\n\treturn toRoll;\r\n}\r\n\r\ninterface PreparedDice {\r\n\tdice: string;\r\n\tdiceDisplay: string;\r\n\texplodingSuccess?: ExplodingSuccess;\r\n\tisSharedRoll: boolean;\r\n\tisSharedCurly: boolean;\r\n\tisCurlyBulk: boolean;\r\n\tbulkContent: string;\r\n\tisSimpleCurly: boolean;\r\n}\r\n\r\n/**\r\n * Prépare la chaîne de dés pour le traitement\r\n */\r\nexport function prepareDice(diceInput: string): PreparedDice {\r\n\tlet dice = standardizeDice(replaceFormulaInDice(diceInput))\r\n\t\t.replace(/^\\+/, \"\")\r\n\t\t.replaceAll(\"=>\", \">=\")\r\n\t\t.replaceAll(\"=<\", \"<=\")\r\n\t\t.trimStart();\r\n\r\n\tdice = dice.replaceAll(DETECT_CRITICAL, \"\").trimEnd();\r\n\r\n\tconst explodingSuccess = normalizeExplodingSuccess(dice);\r\n\tif (explodingSuccess) dice = explodingSuccess.dice;\r\n\r\n\tlet diceDisplay: string;\r\n\tif (dice.includes(\";\")) {\r\n\t\tconst mainDice = dice.split(\";\")[0];\r\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? mainDice;\r\n\t} else {\r\n\t\tdiceDisplay = explodingSuccess?.originalDice ?? dice;\r\n\t}\r\n\r\n\tconst curlyBulkMatch = dice.match(/^\\{(\\d+#.*)\\}$/);\r\n\tconst isCurlyBulk = !!curlyBulkMatch;\r\n\tconst bulkContent = isCurlyBulk ? curlyBulkMatch![1] : \"\";\r\n\r\n\tconst isSharedRoll = dice.includes(\";\");\r\n\tlet isSharedCurly = false;\r\n\r\n\tif (isSharedRoll && dice.match(/^\\{.*;\\s*.*\\}$/)) {\r\n\t\tdice = dice.slice(1, -1);\r\n\t\tisSharedCurly = true;\r\n\t\tdiceDisplay = diceDisplay.slice(1);\r\n\t}\r\n\r\n\t// Handle simple curly braces like {1d20+5} or {1d20+5>10}\r\n\t// But NOT dice pool notation like {2d6>4} where the comparison is inside the braces WITHOUT modifiers\r\n\tlet isSimpleCurly = false;\r\n\tif (!isCurlyBulk && !isSharedRoll && dice.match(/^\\{.*\\}$/)) {\r\n\t\t// Check if this is a dice pool (comparison inside the braces WITHOUT modifiers)\r\n\t\tconst innerContent = dice.slice(1, -1); // Remove outer braces\r\n\t\tconst hasModifiers = innerContent.match(/[+\\-*/%^]/);\r\n\t\tconst hasComparison = innerContent.match(/(([><=!]+\\d+f)|([><=]|!=)+\\d+)/);\r\n\r\n\t\t// Only remove braces if it's not a dice pool\r\n\t\t// Dice pool: has comparison inside, NO modifiers (like {2d6>4})\r\n\t\t// Simple curly: has modifiers before comparison (like {1d20+5>10}) or just plain dice (like {1d20+5})\r\n\t\tif (!(hasComparison && !hasModifiers)) {\r\n\t\t\tdice = innerContent;\r\n\t\t\tisSimpleCurly = true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\tdice,\r\n\t\tdiceDisplay,\r\n\t\texplodingSuccess,\r\n\t\tisSharedRoll,\r\n\t\tisSharedCurly,\r\n\t\tisCurlyBulk,\r\n\t\tbulkContent,\r\n\t\tisSimpleCurly,\r\n\t};\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport type { Sign } from \"../interfaces\";\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","import type { DiceRoll, DiceRoller } from \"@dice-roller/rpg-dice-roller\";\r\nimport { evaluate } from \"mathjs\";\r\nimport type { Engine } from \"random-js\";\r\nimport { DiceTypeError } from \"../errors\";\r\nimport type { Compare, Resultat } from \"../interfaces\";\r\nimport { roll } from \"../roll\";\r\nimport { canComparisonSucceed } from \"./compare\";\r\n\r\n/**\r\n * Gère le système de pity (relance en cas d'échec)\r\n */\r\nexport function handlePitySystem(\r\n\tdice: string,\r\n\tcompare: Compare,\r\n\tdiceRoll: DiceRoll | DiceRoll[],\r\n\troller: DiceRoller,\r\n\tengine: Engine | null\r\n): { rerollCount: number; result?: Resultat } {\r\n\tconst currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;\r\n\tconst maxPossible = currentRoll ? currentRoll.maxTotal : null;\r\n\tconst isComparisonPossible =\r\n\t\tmaxPossible === null || canComparisonSucceed(maxPossible, compare);\r\n\r\n\tif (!isComparisonPossible) {\r\n\t\treturn { rerollCount: 0 };\r\n\t}\r\n\r\n\tlet isFail = evaluate(`${roller.total}${compare.sign}${compare.value}`);\r\n\tif (isFail) {\r\n\t\treturn { rerollCount: 0 };\r\n\t}\r\n\r\n\tconst maxReroll = 100;\r\n\tlet rerollCount = 0;\r\n\tlet res: Resultat | undefined;\r\n\r\n\twhile (!isFail && rerollCount < maxReroll) {\r\n\t\ttry {\r\n\t\t\tres = roll(dice, engine, false);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new DiceTypeError(dice, \"roll\", error);\r\n\t\t}\r\n\t\trerollCount++;\r\n\t\tif (res && res.total !== undefined) {\r\n\t\t\tisFail = evaluate(`${res.total}${compare.sign}${compare.value}`);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { rerollCount, result: res };\r\n}\r\n","import { evaluate } from \"mathjs\";\r\nimport { type Engine, Random } from \"random-js\";\r\nimport \"uniformize\";\r\n\r\nimport { NumberGenerator } from \"@dice-roller/rpg-dice-roller\";\r\nimport {\r\n\tcreateCriticalCustom,\r\n\tDETECT_CRITICAL,\r\n\tDiceTypeError,\r\n\tEmptyObjectError,\r\n\tescapeRegex,\r\n\tFormulaError,\r\n\tNoStatisticsError,\r\n\treplaceExpByRandom,\r\n\treplaceFormulaInDice,\r\n\troll,\r\n\ttype StatisticalTemplate,\r\n\tTooManyDice,\r\n\ttemplateSchema,\r\n} from \".\";\r\nimport { isNumber, randomInt } from \"./utils\";\r\n\r\n/**\r\n * Verify if the provided dice work with random value\r\n * @param testDice {string}\r\n * @param allStats {Record<string,number>}\r\n * @param engine\r\n * @param pity\r\n */\r\nexport function evalStatsDice(\r\n\ttestDice: string,\r\n\tallStats?: Record<string, number>,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto,\r\n\tpity?: boolean\r\n) {\r\n\tlet dice = testDice.trimEnd();\r\n\tif (allStats && Object.keys(allStats).length > 0) {\r\n\t\tconst names = Object.keys(allStats);\r\n\t\tfor (const name of names) {\r\n\t\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\t\tif (dice.standardize().match(regex)) {\r\n\t\t\t\tconst statValue = allStats[name];\r\n\t\t\t\tdice = dice.standardize().replace(regex, statValue.toString()).trimEnd();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\ttry {\r\n\t\tif (!roll(replaceFormulaInDice(replaceExpByRandom(dice)), engine, pity))\r\n\t\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", \"no roll result\");\r\n\t\treturn testDice;\r\n\t} catch (error) {\r\n\t\tthrow new DiceTypeError(dice, \"evalStatsDice\", error);\r\n\t}\r\n}\r\n\r\n/**\r\n * Generate a random dice and remove the formula (+ evaluate it)\r\n * Used for diceDamage only\r\n * @param value {string}\r\n * @param template {StatisticalTemplate}\r\n * @param engine\r\n * @returns\r\n */\r\nexport function diceRandomParse(\r\n\tvalue: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return replaceFormulaInDice(value.standardize());\r\n\tvalue = value.standardize();\r\n\tconst statNames = Object.keys(template.statistics);\r\n\tlet newDice = value;\r\n\tfor (const name of statNames) {\r\n\t\tconst regex = new RegExp(escapeRegex(name.standardize()), \"gi\");\r\n\t\tif (value.match(regex)) {\r\n\t\t\tlet max: undefined | number;\r\n\t\t\tlet min: undefined | number;\r\n\t\t\tconst foundStat = template.statistics?.[name];\r\n\t\t\tif (foundStat) {\r\n\t\t\t\tmax = foundStat.max;\r\n\t\t\t\tmin = foundStat.min;\r\n\t\t\t}\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tnewDice = value.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t}\r\n\treturn replaceFormulaInDice(newDice);\r\n}\r\n\r\n/**\r\n * Same as damageDice but for DiceType\r\n * @param dice {string}\r\n * @param template {StatisticalTemplate}\r\n * @param engine\r\n */\r\nexport function diceTypeRandomParse(\r\n\tdice: string,\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tdice = replaceExpByRandom(dice);\r\n\tif (!template.statistics) return dice;\r\n\tconst firstStatNotcombinaison = Object.keys(template.statistics).find(\r\n\t\t(stat) => !template.statistics?.[stat].combinaison\r\n\t);\r\n\tif (!firstStatNotcombinaison) return dice;\r\n\tconst stats = template.statistics[firstStatNotcombinaison];\r\n\tconst { min, max } = stats;\r\n\tconst total = template.total || 100;\r\n\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\treturn replaceFormulaInDice(dice.replaceAll(\"$\", randomStatValue.toString()));\r\n}\r\n\r\n/**\r\n * Random the combinaison and evaluate it to check if everything is valid\r\n * @param combinaison {Record<string,string>}\r\n * @param stats {Record<string,number|number>}\r\n */\r\nexport function evalCombinaison(\r\n\tcombinaison: Record<string, string>,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tconst newStats: Record<string, number> = {};\r\n\tfor (const [stat, combin] of Object.entries(combinaison)) {\r\n\t\t//replace the stats in formula\r\n\t\tlet formula = combin.standardize();\r\n\t\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\t\tformula = formula.replace(regex, value.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tnewStats[stat] = evaluate(formula);\r\n\t\t} catch (error) {\r\n\t\t\tthrow new FormulaError(stat, \"evalCombinaison\", error);\r\n\t\t}\r\n\t}\r\n\treturn newStats;\r\n}\r\n\r\n/**\r\n * Evaluate one selected combinaison\r\n * @param combinaison {string}\r\n * @param stats {[name: string]: string|number}\r\n */\r\nexport function evalOneCombinaison(\r\n\tcombinaison: string,\r\n\tstats: Record<string, number | string>\r\n) {\r\n\tlet formula = combinaison.standardize();\r\n\tfor (const [statName, value] of Object.entries(stats)) {\r\n\t\tconst regex = new RegExp(statName.standardize(), \"gi\");\r\n\t\tformula = formula.replace(regex, value.toString());\r\n\t}\r\n\ttry {\r\n\t\treturn evaluate(formula);\r\n\t} catch (error) {\r\n\t\tthrow new FormulaError(combinaison, \"evalOneCombinaison\", error);\r\n\t}\r\n}\r\n\r\nfunction convertNumber(number: string | number | undefined) {\r\n\tif (number === undefined || number === null) return undefined;\r\n\tif (\r\n\t\tnumber.toString().length === 0 ||\r\n\t\tNumber.isNaN(Number.parseInt(number.toString(), 10))\r\n\t)\r\n\t\treturn undefined;\r\n\tif (isNumber(number)) return Number.parseInt(number.toString(), 10);\r\n\treturn undefined;\r\n}\r\n\r\n/**\r\n * Parse the provided JSON and verify each field to check if everything could work when rolling\r\n * @param {unknown} template\r\n * @param {boolean} verify - If true, will roll the dices to check if everything is valid\r\n * @param engine\r\n * @returns {StatisticalTemplate}\r\n */\r\nexport function verifyTemplateValue(\r\n\ttemplate: unknown,\r\n\tverify = true,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n): StatisticalTemplate {\r\n\tconst parsedTemplate = templateSchema.parse(template);\r\n\tconst { success, failure } = parsedTemplate.critical ?? {};\r\n\tconst criticicalVal = {\r\n\t\tsuccess: convertNumber(success),\r\n\t\tfailure: convertNumber(failure),\r\n\t};\r\n\tconst statistiqueTemplate: StatisticalTemplate = {\r\n\t\tdiceType: parsedTemplate.diceType,\r\n\t\tstatistics: parsedTemplate.statistics,\r\n\t\tcritical: criticicalVal,\r\n\t\ttotal: parsedTemplate.total,\r\n\t\tcharName: parsedTemplate.charName,\r\n\t\tdamage: parsedTemplate.damage,\r\n\t\tcustomCritical: parsedTemplate.customCritical,\r\n\t\tforceDistrib: parsedTemplate.forceDistrib,\r\n\t};\r\n\tif (!verify) return statistiqueTemplate;\r\n\tif (statistiqueTemplate.diceType) {\r\n\t\tif (statistiqueTemplate.diceType.match(DETECT_CRITICAL)) {\r\n\t\t\tthrow new DiceTypeError(\r\n\t\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\t\t\"critical_dice_type\",\r\n\t\t\t\t\"contains critical detection: should be in custom critical instead\"\r\n\t\t\t);\r\n\t\t}\r\n\t\tconst cleanedDice = diceTypeRandomParse(\r\n\t\t\tstatistiqueTemplate.diceType,\r\n\t\t\tstatistiqueTemplate,\r\n\t\t\tengine\r\n\t\t);\r\n\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\tif (!rolled) throw new DiceTypeError(cleanedDice, \"no_roll_result\", \"no roll result\");\r\n\t}\r\n\tif (statistiqueTemplate.customCritical) {\r\n\t\tif (!statistiqueTemplate.diceType) {\r\n\t\t\tthrow new DiceTypeError(\"no_dice_type\", \"no_dice_type\", \"no dice type\");\r\n\t\t}\r\n\t\tconst customCritical = statistiqueTemplate.customCritical;\r\n\t\tfor (const [, custom] of Object.entries(customCritical)) {\r\n\t\t\tconst cleanedDice = createCriticalCustom(\r\n\t\t\t\tstatistiqueTemplate.diceType!,\r\n\t\t\t\tcustom,\r\n\t\t\t\tstatistiqueTemplate,\r\n\t\t\t\tengine\r\n\t\t\t);\r\n\t\t\tconst rolled = roll(cleanedDice, engine);\r\n\t\t\tif (!rolled)\r\n\t\t\t\tthrow new DiceTypeError(cleanedDice, \"verifyTemplateValue\", \"no roll result\");\r\n\t\t}\r\n\t}\r\n\ttestDiceRegistered(statistiqueTemplate, engine);\r\n\ttestStatCombinaison(statistiqueTemplate, engine);\r\n\treturn statistiqueTemplate;\r\n}\r\n\r\n/**\r\n * Test each damage roll from the template.damage\r\n * @param {StatisticalTemplate} template\r\n * @param engine\r\n */\r\nexport function testDiceRegistered(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.damage) return;\r\n\tif (Object.keys(template.damage).length === 0) throw new EmptyObjectError();\r\n\tif (Object.keys(template.damage).length > 25) throw new TooManyDice();\r\n\tfor (const [name, dice] of Object.entries(template.damage)) {\r\n\t\tif (!dice) continue;\r\n\t\tconst diceReplaced = replaceExpByRandom(dice);\r\n\t\tconst randomDiceParsed = diceRandomParse(diceReplaced, template, engine);\r\n\t\ttry {\r\n\t\t\tconst rolled = roll(randomDiceParsed, engine);\r\n\t\t\tif (!rolled) throw new DiceTypeError(name, \"no_roll_result\", dice);\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(error);\r\n\t\t\tthrow new DiceTypeError(name, \"testDiceRegistered\", error);\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Test all combinaison with generated random value\r\n * @param {StatisticalTemplate} template\r\n * @param engine\r\n */\r\nexport function testStatCombinaison(\r\n\ttemplate: StatisticalTemplate,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tif (!template.statistics) return;\r\n\tconst onlycombinaisonStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(\r\n\t\t\t([_, value]) => value.combinaison !== undefined\r\n\t\t)\r\n\t);\r\n\tconst allOtherStats = Object.fromEntries(\r\n\t\tObject.entries(template.statistics).filter(([_, value]) => !value.combinaison)\r\n\t);\r\n\tif (Object.keys(onlycombinaisonStats).length === 0) return;\r\n\tconst allStats = Object.keys(template.statistics).filter(\r\n\t\t(stat) => !template.statistics![stat].combinaison\r\n\t);\r\n\tif (allStats.length === 0) throw new NoStatisticsError();\r\n\tconst error = [];\r\n\tfor (const [stat, value] of Object.entries(onlycombinaisonStats)) {\r\n\t\tlet formula = value.combinaison as string;\r\n\t\tfor (const [other, data] of Object.entries(allOtherStats)) {\r\n\t\t\tconst { max, min } = data;\r\n\t\t\tconst total = template.total || 100;\r\n\t\t\tconst randomStatValue = generateRandomStat(total, max, min, engine);\r\n\t\t\tconst regex = new RegExp(other, \"gi\");\r\n\t\t\tformula = formula.replace(regex, randomStatValue.toString());\r\n\t\t}\r\n\t\ttry {\r\n\t\t\tevaluate(formula);\r\n\t\t} catch (e) {\r\n\t\t\terror.push(stat);\r\n\t\t}\r\n\t}\r\n\tif (error.length > 0) throw new FormulaError(error.join(\", \"), \"testStatCombinaison\");\r\n\treturn;\r\n}\r\n\r\n/**\r\n * Generate a random stat based on the template and the statistical min and max\r\n * @param {number|undefined} total\r\n * @param {number | undefined} max\r\n * @param {number | undefined} min\r\n * @param engine\r\n * @returns\r\n */\r\nexport function generateRandomStat(\r\n\ttotal: number | undefined = 100,\r\n\tmax?: number,\r\n\tmin?: number,\r\n\tengine: Engine | null = NumberGenerator.engines.nodeCrypto\r\n) {\r\n\tlet randomStatValue = total + 1;\r\n\tconst random = new Random(engine || NumberGenerator.engines.nodeCrypto);\r\n\twhile (randomStatValue >= total || randomStatValue === 0) {\r\n\t\tif (max && min) randomStatValue = randomInt(min, max, engine, random);\r\n\t\telse if (max) randomStatValue = randomInt(1, max, engine, random);\r\n\t\telse if (min) randomStatValue = randomInt(min, total, engine, random);\r\n\t\telse randomStatValue = randomInt(1, total, engine, random);\r\n\t}\r\n\treturn randomStatValue;\r\n}\r\n"],"mappings":"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","names":["SortOrder","DiceRoller","NumberGenerator","evaluate","DiceRoller","NumberGenerator","evaluate","NumberGenerator","evaluate","NumberGenerator","NumberGenerator","NumberGenerator","evaluate","evaluate","NumberGenerator","evaluate","NumberGenerator","evaluate","diceResult","evaluate","roll","NumberGenerator","evaluate","NumberGenerator","DiceRoller","NumberGenerator","evaluate","evaluate","evaluate","NumberGenerator","DiceRoller","evaluate","evaluateRoll","evaluate","Random","NumberGenerator","NumberGenerator","evaluate","cleanedDice","Random"]}
|