'use strict'; /** * The letter a user sees. * * What these protect: that no input manufactures an A, that a band which cannot * be distinguished from the base rate SAYS so, and that nothing ever renders * blank. */ const sg = require('../../src/services/model/servedGrade'); describe('no manufactured A — structurally, not by rarity', () => { it('no p_win produces an A, A- or A+', () => { // The realized rate plateaus around 0.65-0.68 above p_win 0.70, so no band // of this forecast has earned a top letter. This is the ceiling made real. for (let p = 0; p <= 1.0001; p += 0.01) { const g = sg.gradeFor({ p_win: p }); expect(sg.UNISSUABLE).not.toContain(g.letter); } expect(sg.BANDS.some((b) => sg.UNISSUABLE.includes(b.letter))).toBe(false); }); it('even a 0.99 forecast tops out at the strongest honest band', () => { const g = sg.gradeFor({ p_win: 0.99 }); expect(g.letter).toBe('B+'); expect(g.band_realized_rate).toBeLessThan(0.70); expect(g.meaning).toMatch(/strongest read/); }); }); describe('a band that cannot separate SAYS so', () => { it('mid bands are flagged as not distinguishable from base rate', () => { for (const p of [0.50, 0.58, 0.66]) { const g = sg.gradeFor({ p_win: p }); expect(g.separates_from_base_rate).toBe(false); // The copy must not imply a separation the band does not have. expect(g.meaning).toMatch(/base rate|base-rate/); } }); it('the extremes do separate, and are marked so', () => { expect(sg.gradeFor({ p_win: 0.85 }).separates_from_base_rate).toBe(true); expect(sg.gradeFor({ p_win: 0.20 }).separates_from_base_rate).toBe(true); }); it('every band carries its own realized rate, not a target', () => { for (const b of sg.BANDS) { expect(b.realized).toBeGreaterThan(0); expect(b.realized).toBeLessThan(0.70); // the honest ceiling } }); }); describe('never blank', () => { it('a refusal renders a real state with a reason', () => { const g = sg.gradeFor({ refused: true, refusal_reason: 'insufficient_data' }); expect(g.letter).toBeNull(); expect(g.state).toBe('refused'); expect(g.label).toBe('NO READ'); expect(g.meaning).toMatch(/not enough history/); }); it('a juiced-out side says the book ate the edge', () => { expect(sg.gradeFor({ refused: true, refusal_reason: 'juiced_no_edge' }).meaning).toMatch(/vig/); }); it('a missing forecast renders, rather than returning nothing', () => { const g = sg.gradeFor({ p_win: null }); expect(g.state).toBe('no_forecast'); expect(g.label).toBe('NO READ'); }); it('an empty prop still renders', () => { expect(sg.gradeFor({}).label).toBe('NO READ'); expect(sg.gradeFor().label).toBe('NO READ'); }); }); describe('the basis is stated, never implied', () => { it('names when matchup factors moved the forecast', () => { const g = sg.gradeFor({ p_win: 0.72, factor_adjustment: { applied: [{ factor: 'platoon_severity' }] } }); expect(g.basis).toBe('forecast_plus_matchup_factors'); expect(g.factors_applied).toEqual(['platoon_severity']); }); it('says forecast-only when nothing fired', () => { const g = sg.gradeFor({ p_win: 0.72 }); expect(g.basis).toBe('forecast_only'); expect(g.factors_applied).toEqual([]); }); it('never claims calibration — the deployed set is empty', () => { expect(sg.gradeFor({ p_win: 0.72 }).calibrated).toBe(false); }); it('is monotone: a higher forecast never grades lower', () => { const order = ['F', 'D', 'C-', 'C', 'C+', 'B', 'B+']; let prev = -1; for (let p = 0.02; p <= 0.98; p += 0.02) { const i = order.indexOf(sg.gradeFor({ p_win: p }).letter); expect(i).toBeGreaterThanOrEqual(prev); prev = i; } }); });