## Guard + measurement for the scale-aware power bar in `bestPower`. ## ## Before the fix `bestPower` required an ABSOLUTE virtual hit rate >= MinHitRate ## (0.40). On the shipped path-metric scale a gun's per-bin rates sit around ## 3-40%, so once every bin had data no bin cleared the bar and bestPower ## silently collapsed to bin 0 (power 1.0). The fix compares each bin's rate to ## PowerBarFrac * (the same gun's best bin rate) — dimensionless, so it ## discriminates at any scale. ## ## Run: nim c -r common_libs/tests/test_power_selection.nim import std/[strformat, math, random, tables, os] import gun_harness/gun_interface import gun_harness/virtual_bullets import gun_harness/offline_range import range_guns const fixturesDir = currentSourcePath().parentDir.parentDir.parentDir / "tools" / "fixtures" var failures = 0 proc check(name: string, ok: bool) = if ok: echo "PASS: ", name else: echo "FAIL: ", name; inc failures proc recordHit(fw: var FitnessWindow, hit: bool) = fw.hits[fw.head] = hit fw.head = (fw.head + 1) mod WindowSize inc fw.count proc seedFromReport(t: var VirtualTracker, targetId, gunId: int, r: GunReport) = if targetId notin t.fitness: t.fitness[targetId] = newSeq[GunFitness](t.numGuns) var fw = addr t.fitness[targetId][gunId].bins for b in 0.. 0: anyObs = true if not anyObs: return 0 for b in countdown(len(PowerBins) - 1, 0): if fit.bins[b].hitRate() >= MinHitRate or fit.bins[b].count == 0: return b 0 proc main() = # A real closed-loop fixture where every gun's rates sit below the old 40% # absolute bar — the regime the bug lives in. Fall back to a synthetic fixture # if the committed capture is missing. let realPath = fixturesDir / "drussgt_vs_crazy.jsonl" let fx = if fileExists(realPath): loadFixture(realPath) else: synthesizeByName("energy-threshold-turner") echo "fixture: ", fx.meta.adversary, " (source=", fx.meta.source, ")" let reports = replayFixture(fx, buildAllGunDrivers(seed = 1), metric = bmPath) var t = initTracker(reports.len) let tid = fx.enemyId for gi, r in reports: seedFromReport(t, tid, gi, r) echo "per-gun per-bin virtual hit rate (measured) and selected bin (old | new):" var changed = 0 var anyOldFellToZero = false for gi, r in reports: let fit = t.fitnessFor(tid) var rates = "" for b in 0.. 0: anyOldFellToZero = true echo fmt" {r.name:<11}{rates} old=bin{ob} new=bin{nb}" echo "" echo fmt"selections changed by the fix: {changed}/{reports.len}" check "the scale-aware bar changes at least one gun's power selection", changed > 0 check "at least one gun the old absolute 0.40 bar sent to power 1.0 now uses a heavier bullet", anyOldFellToZero # Relative bar still picks the best bin when it is the lowest power (no # pathological power-3 bias). block: var t2 = initTracker(1) # bin0 30%, bin1 25%, bin2 12%, bin3 5% -> bar=15%, only bins 0 and 1 clear # it; the HIGHEST acceptable is bin 1, not bin 0 and not bin 3. seedFromReport(t2, 7, 0, GunReport(name: "x", bins: [ BinStat(shots: 100, hits: 30), BinStat(shots: 100, hits: 25), BinStat(shots: 100, hits: 12), BinStat(shots: 100, hits: 5)])) let (b, p) = t2.bestPower(0, 7) echo fmt" synthetic [30,25,12,5]% -> bin {b} (power {p})" check "relative bar picks the highest bin clearing 50% of the best (bin 1)", b == 1 if failures > 0: echo "\n", failures, " check(s) FAILED" quit(1) echo "\nAll power-selection checks passed." when isMainModule: main()