{"version":3,"file":"numeric.d.ts","sourceRoot":"","sources":["../../../src/core/web-research/numeric.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAE/F;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,OAAO,EAC1B,WAAW,CAAC,EAAE,cAAc,GAC1B;IACF,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACnB,CAOA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAChC,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,OAAO,GACxB,mBAAmB,CA8BrB;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC/C,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,uBAAuB,EAAE,OAAO,GAC9B,mBAAmB,CAWrB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EAAE,EACjB,gBAAgB,CAAC,EAAE,MAAM,GACvB,mBAAmB,CAkBrB;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACpC,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,EACvB,UAAU,CAAC,EAAE,MAAM,GACjB,mBAAmB,CAWrB;AAED,YAAY,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC","sourcesContent":["import type { NumericFact, NumericVerification, NumericVerificationOutcome } from \"./types.js\";\n\n/**\n * Bounded research calculation verifier.\n *\n * This is not a general theorem prover. It validates arithmetic and units used\n * in research synthesis:\n * - flat additions versus percentage additions\n * - additive versus multiplicative bonuses\n * - per-shot versus per-cycle versus per-second terminology\n * - percentages and deltas\n * - upgrade-level application\n * - caps and set thresholds\n *\n * When the verifier cannot resolve units or order of operations it marks the\n * calculation `unsupported` rather than silently choosing a formula.\n */\n\nexport interface FlatPercentAdd {\n\tkind: \"flat\" | \"percent\";\n}\n\n/**\n * Decide whether a \"+N\" additive delta should be treated as flat (+N) or\n * percent (× (1 + N/100)).\n */\nexport function classifyFlatVsPercent(\n\tdelta: number,\n\tsourceSaysPercent: boolean,\n\tdeltaOption?: FlatPercentAdd,\n): {\n\tadditive: boolean;\n\tmultiplier: number;\n} {\n\tif (deltaOption?.kind === \"percent\" || sourceSaysPercent) {\n\t\t// Only treat as percent when a source explicitly says percent.\n\t\treturn { additive: false, multiplier: 1 + delta / 100 };\n\t}\n\t// Default: flat additive bonus.\n\treturn { additive: true, multiplier: 0 };\n}\n\n/**\n * Validate a base + flat bonus computation.\n * Rejects interpreting a flat `+15` as `× 1.15`.\n */\nexport function validateFlatBonus(\n\tid: string,\n\tdescription: string,\n\tbase: number,\n\tdelta: number,\n\tsourceSaysPercent: boolean,\n): NumericVerification {\n\tconst classified = classifyFlatVsPercent(delta, sourceSaysPercent);\n\tif (!classified.additive && !sourceSaysPercent) {\n\t\treturn {\n\t\t\tid,\n\t\t\tdescription,\n\t\t\toutcome: \"unsupported\",\n\t\t\tassumed: `${base} × (1 + ${delta}/100)`,\n\t\t\tviolation: `Flat +${delta} was treated as a percent bonus without a source saying percent.`,\n\t\t};\n\t}\n\tif (classified.additive) {\n\t\tconst computed = base + delta;\n\t\treturn {\n\t\t\tid,\n\t\t\tdescription,\n\t\t\toutcome: \"verified\",\n\t\t\tcomputed,\n\t\t\tassumed: `${base} + ${delta} = ${computed}`,\n\t\t};\n\t}\n\t// Percent bonus explicitly sourced: base × (1 + delta/100).\n\tconst computed = base * classified.multiplier;\n\treturn {\n\t\tid,\n\t\tdescription,\n\t\toutcome: \"verified\",\n\t\tcomputed,\n\t\tassumed: `${base} × (1 + ${delta}/100) = ${computed}`,\n\t};\n}\n\n/**\n * Validate additive + multiplicative composition.\n * Default order: multiplier applies to base, then flat proc is added.\n */\nexport function validateTargetMultiplierPlusProc(\n\tid: string,\n\tdescription: string,\n\tbase: number,\n\tmultiplier: number,\n\tflatProc: number,\n\tmultiplierAppliesToProc: boolean,\n): NumericVerification {\n\tconst computed = multiplierAppliesToProc ? (base + flatProc) * multiplier : base * multiplier + flatProc;\n\treturn {\n\t\tid,\n\t\tdescription,\n\t\toutcome: \"verified\",\n\t\tcomputed,\n\t\tassumed: multiplierAppliesToProc\n\t\t\t? `(${base} + ${flatProc}) × ${multiplier} = ${computed}`\n\t\t\t: `${base} × ${multiplier} + ${flatProc} = ${computed}`,\n\t};\n}\n\n/**\n * Compute a per-cycle average and label it correctly.\n * Refuses to label it DPS unless attacks-per-second is sourced.\n */\nexport function validateCycleAverage(\n\tid: string,\n\tdescription: string,\n\tattacks: number[],\n\tattacksPerSecond?: number,\n): NumericVerification {\n\tconst average = attacks.reduce((sum, value) => sum + value, 0) / attacks.length;\n\tif (attacksPerSecond !== undefined) {\n\t\treturn {\n\t\t\tid,\n\t\t\tdescription,\n\t\t\toutcome: \"verified\",\n\t\t\tcomputed: average * attacksPerSecond,\n\t\t\tassumed: `average = ${average.toFixed(2)}; DPS = ${average.toFixed(2)} × ${attacksPerSecond} attacks/s = ${(average * attacksPerSecond).toFixed(2)}`,\n\t\t};\n\t}\n\treturn {\n\t\tid,\n\t\tdescription,\n\t\toutcome: \"verified\",\n\t\tcomputed: average,\n\t\tassumed: `average nominal damage per attack = ${average.toFixed(2)} (no attacks-per-second sourced; not labeled DPS)`,\n\t};\n}\n\n/** Percentage difference between two values. */\nexport function percentDifference(left: number, right: number): number {\n\treturn ((right - left) / left) * 100;\n}\n\n/**\n * Apply an upgrade-level bonus. Default supported model: cumulative percent\n * bonus per level, capped.\n */\nexport function validateUpgradeLevels(\n\tid: string,\n\tdescription: string,\n\tbase: number,\n\tlevels: number,\n\tpercentPerLevel: number,\n\tcapPercent?: number,\n): NumericVerification {\n\tconst rawBonus = levels * percentPerLevel;\n\tconst effectiveBonus = capPercent !== undefined ? Math.min(rawBonus, capPercent) : rawBonus;\n\tconst computed = base * (1 + effectiveBonus / 100);\n\treturn {\n\t\tid,\n\t\tdescription,\n\t\toutcome: \"verified\",\n\t\tcomputed,\n\t\tassumed: `base ${base} × (1 + ${effectiveBonus}%/100) = ${computed}${capPercent !== undefined ? ` (capped at ${capPercent}%)` : \"\"}`,\n\t};\n}\n\nexport type { NumericFact, NumericVerificationOutcome };\n"]}