'use strict'; /** * The champion's forecast window, and what depends on it. * * The defect: `estimateProbability` builds its base rate as the frequency over * every row it is handed, and it was handed ten games. So the "season rate" was * a ten-game rate, and 0.4 of the forecast was the last five OF THOSE TEN. * Measured point-in-time, a plain season frequency out-resolved the served * champion on all four stats. */ const est = require('../../src/services/intelligence/probabilityEstimator'); const snapshotService = require('../../src/services/snapshotService'); /** n games where the player cleared the line at the given rate, most-recent-first. */ const logs = (n, rate, statType = 'hits') => Array.from({ length: n }, (_, i) => ({ date: `2026-06-${String((i % 28) + 1).padStart(2, '0')}`, [statType]: (i % Math.round(1 / rate)) === 0 ? 2 : 0, })); describe('the forecast is no longer dominated by five games', () => { it('a long cold streak inside a good season does not swing the forecast wildly', () => { // Ten recent zeros on top of a strong season. At the old 0.40 weight this // pulled the number a long way off a better one. const season = logs(80, 0.6); const cold = Array.from({ length: 5 }, (_, i) => ({ date: `2026-07-0${i + 1}`, hits: 0 })); const withCold = [...cold, ...season]; const out = est.estimateProbability({ gameLogs: withCold, line: 0.5, statType: 'hits', features: {} }); const seasonOnly = est.estimateProbability({ gameLogs: season, line: 0.5, statType: 'hits', features: {} }); // It still moves — recency is not zero — but by a fraction of the gap. expect(out.p_over).toBeLessThan(seasonOnly.p_over); expect(seasonOnly.p_over - out.p_over).toBeLessThan(0.25); }); it('more history produces a steadier forecast than ten games', () => { const ten = logs(10, 0.6); const many = logs(80, 0.6); const a = est.estimateProbability({ gameLogs: ten, line: 0.5, statType: 'hits', features: {} }); const b = est.estimateProbability({ gameLogs: many, line: 0.5, statType: 'hits', features: {} }); expect(Number.isFinite(a.p_over)).toBe(true); expect(Number.isFinite(b.p_over)).toBe(true); }); }); describe('calibration is off while its maps are stale', () => { it('serves nothing calibrated — the maps were fit on the retired forecast', () => { expect(snapshotService.CALIBRATION_DEPLOYED).toEqual([]); expect(snapshotService.CALIBRATION_BASIS).toEqual({}); }); it('the deploy list is still frozen, so nothing can re-enable it at runtime', () => { expect(Object.isFrozen(snapshotService.CALIBRATION_DEPLOYED)).toBe(true); }); });