{"version":3,"file":"numeric.test.d.ts","sourceRoot":"","sources":["../../../src/core/web-research/numeric.test.ts"],"names":[],"mappings":"","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport {\n\tpercentDifference,\n\tvalidateCycleAverage,\n\tvalidateFlatBonus,\n\tvalidateTargetMultiplierPlusProc,\n\tvalidateUpgradeLevels,\n} from \"./numeric.js\";\n\ndescribe(\"numeric validation\", () => {\n\tit(\"treats a flat +15 as additive, not percent\", () => {\n\t\tconst result = validateFlatBonus(\"1\", \"NPC bonus\", 175, 15, false);\n\t\texpect(result.outcome).toBe(\"verified\");\n\t\texpect(result.computed).toBe(190);\n\t});\n\n\tit(\"rejects interpreting a flat +15 as +15%\", () => {\n\t\t// A flat +15 cannot be treated as a percentage bonus without a source\n\t\t// explicitly saying percent. The verifier therefore computes base + delta.\n\t\tconst result = validateFlatBonus(\"2\", \"NPC bonus\", 175, 15, false);\n\t\texpect(result.outcome).toBe(\"verified\");\n\t\texpect(result.computed).toBe(190); // 175 + 15, not 175 × 1.15\n\t\t// Guard: without a percent source, the +15 must remain additive.\n\t\texpect(result.assumed).toContain(\"175 + 15\");\n\t\t// Only an explicit percent source may produce 175 × 1.15 = 201.25.\n\t\tconst percentOnly = validateFlatBonus(\"2\", \"percent misuse\", 175, 15, true);\n\t\texpect(percentOnly.computed).toBeCloseTo(201.25);\n\t});\n\n\tit(\"applies a target multiplier to base then adds the flat proc\", () => {\n\t\tconst result = validateTargetMultiplierPlusProc(\"3\", \"target multiplier plus proc\", 210, 3.5, 200, false);\n\t\texpect(result.outcome).toBe(\"verified\");\n\t\t// 210 × 3.5 + 200 = 935\n\t\texpect(result.computed).toBe(935);\n\t});\n\n\tit(\"only multiplies the proc when the source says so\", () => {\n\t\t// When source applies multiplier to proc: (210 + 200) × 3.5 = 1435\n\t\tconst result = validateTargetMultiplierPlusProc(\"4\", \"multiplier applies to proc\", 210, 3.5, 200, true);\n\t\texpect(result.computed).toBe(1435);\n\t\t// Default (no evidence) keeps the additive proc outside the multiplier.\n\t\tconst defaultResult = validateTargetMultiplierPlusProc(\"5\", \"default\", 210, 3.5, 200, false);\n\t\texpect(defaultResult.computed).toBe(935);\n\t});\n\n\tit(\"labels a per-cycle average not as DPS without sourced cadence\", () => {\n\t\tconst result = validateCycleAverage(\"6\", \"cycle average\", [210, 210, 210, 210, 410]);\n\t\texpect(result.computed).toBe(250);\n\t\t// Explicitly not labeled DPS without attacks-per-second.\n\t\texpect(result.assumed).toContain(\"not labeled DPS\");\n\t});\n\n\tit(\"computes DPS only when attacks-per-second is sourced\", () => {\n\t\tconst result = validateCycleAverage(\"7\", \"cycle DPS\", [210, 210, 210, 210, 410], 2);\n\t\texpect(result.computed).toBe(500);\n\t\texpect(result.assumed).toContain(\"DPS\");\n\t});\n\n\tit(\"computes percentage difference correctly\", () => {\n\t\texpect(percentDifference(200, 250)).toBeCloseTo(25);\n\t\texpect(percentDifference(250, 200)).toBeCloseTo(-20);\n\t});\n\n\tit(\"applies upgrade levels with a cap\", () => {\n\t\tconst result = validateUpgradeLevels(\"8\", \"upgrades\", 100, 5, 5, 20);\n\t\t// 5 × 5% = 25% but capped at 20% => 120\n\t\texpect(result.computed).toBe(120);\n\t});\n});\n"]}