/** * Ship Build — Scheme Classifier Enhancement Tests * Validates backward compatibility + new Synergy integration. */ const { SCHEME_TYPES, MIN_POSSESSIONS, CACHE_TTL, getCacheKey, classifyFromDistribution, extractPnRPossessions, classifyScheme, } = require('../../src/services/schemeClassifier'); describe('Scheme Classifier — Ship Enhancement', () => { // --- Backward Compatibility --- describe('Backward Compatibility', () => { test('SCHEME_TYPES still contains all 5 classifications', () => { expect(SCHEME_TYPES).toEqual(['DROP', 'SWITCH', 'HEDGE', 'MIXED', 'UNKNOWN']); }); test('MIN_POSSESSIONS still 8', () => { expect(MIN_POSSESSIONS).toBe(8); }); test('CACHE_TTL still 6 hours', () => { expect(CACHE_TTL).toBe(21600); }); test('cache key format unchanged', () => { expect(getCacheKey('BOS', '2026-04-13')).toBe('scheme:BOS:2026-04-13'); }); test('regex classification still works for DROP', () => { const possessions = Array.from({ length: 10 }, () => ({ description: 'drop coverage on ball screen' })); const result = classifyScheme(possessions); expect(result.scheme).toBe('DROP'); }); test('regex classification still returns UNKNOWN below threshold', () => { const possessions = Array.from({ length: 5 }, () => ({ description: 'drop coverage' })); const result = classifyScheme(possessions); expect(result.scheme).toBe('UNKNOWN'); }); test('extractPnRPossessions still finds PnR plays', () => { const plays = [ { description: 'pick and roll ball handler' }, { description: 'transition fastbreak' }, ]; expect(extractPnRPossessions(plays)).toHaveLength(1); }); }); // --- Synergy Distribution Classification --- describe('Synergy Distribution Classification', () => { test('classifyFromDistribution returns UNKNOWN for empty distribution', () => { expect(classifyFromDistribution({})).toBe('UNKNOWN'); expect(classifyFromDistribution(null)).toBe('UNKNOWN'); }); test('classifyFromDistribution returns DROP for high PPP PnR', () => { const dist = { 'PRBallHandler': { frequency_pct: 0.15, ppp: 1.0, to_pct: 0.05 }, 'PRRollman': { frequency_pct: 0.10, ppp: 0.90 }, 'Isolation': { frequency_pct: 0.08 }, }; expect(classifyFromDistribution(dist)).toBe('DROP'); }); test('classifyFromDistribution returns HEDGE for low PPP high TO PnR', () => { const dist = { 'PRBallHandler': { frequency_pct: 0.15, ppp: 0.75, to_pct: 0.18 }, 'PRRollman': { frequency_pct: 0.08, ppp: 0.70 }, 'Isolation': { frequency_pct: 0.05 }, }; expect(classifyFromDistribution(dist)).toBe('HEDGE'); }); test('classifyFromDistribution returns SWITCH for high isolation frequency', () => { const dist = { 'PRBallHandler': { frequency_pct: 0.10, ppp: 0.85, to_pct: 0.10 }, 'PRRollman': { frequency_pct: 0.05 }, 'Isolation': { frequency_pct: 0.18 }, }; expect(classifyFromDistribution(dist)).toBe('SWITCH'); }); test('classifyFromDistribution returns UNKNOWN when too little PnR data', () => { const dist = { 'PRBallHandler': { frequency_pct: 0.02, ppp: 0.90 }, 'PRRollman': { frequency_pct: 0.01 }, 'Isolation': { frequency_pct: 0.10 }, }; expect(classifyFromDistribution(dist)).toBe('UNKNOWN'); }); test('classifyFromDistribution returns MIXED for mid-range values', () => { const dist = { 'PRBallHandler': { frequency_pct: 0.12, ppp: 0.88, to_pct: 0.12 }, 'PRRollman': { frequency_pct: 0.08 }, 'Isolation': { frequency_pct: 0.10 }, }; expect(classifyFromDistribution(dist)).toBe('MIXED'); }); }); // --- Export validation --- describe('Module Exports', () => { test('exports fetchSynergyScheme (new)', () => { expect(typeof require('../../src/services/schemeClassifier').fetchSynergyScheme).toBe('function'); }); test('exports classifyFromDistribution (new)', () => { expect(typeof require('../../src/services/schemeClassifier').classifyFromDistribution).toBe('function'); }); test('exports all original functions', () => { const mod = require('../../src/services/schemeClassifier'); expect(typeof mod.getCacheKey).toBe('function'); expect(typeof mod.fetchPlayByPlay).toBe('function'); expect(typeof mod.extractPnRPossessions).toBe('function'); expect(typeof mod.classifyScheme).toBe('function'); expect(typeof mod.getSchemeClassification).toBe('function'); expect(typeof mod.logSchemeToExtended).toBe('function'); }); }); });