import { settleSelection, calculatePayout, calculateParlayPayout, isQuarterHandicapOrTotal, ScoreInput, } from './settlement-calculator'; describe('SettlementCalculator', () => { const score: ScoreInput = { htHome: 1, htAway: 0, ftHome: 2, ftAway: 1 }; describe('FT_1X2', () => { it('S001: home win', () => { expect( settleSelection({ marketType: 'FT_1X2', selectionCode: 'HOME', score }), ).toBe('WIN'); expect( settleSelection({ marketType: 'FT_1X2', selectionCode: 'DRAW', score }), ).toBe('LOSE'); }); it('S002: draw', () => { const draw = { htHome: 0, htAway: 0, ftHome: 1, ftAway: 1 }; expect( settleSelection({ marketType: 'FT_1X2', selectionCode: 'DRAW', score: draw }), ).toBe('WIN'); }); }); describe('HT_1X2', () => { it('S003: half time result', () => { expect( settleSelection({ marketType: 'HT_1X2', selectionCode: 'HOME', score }), ).toBe('WIN'); }); }); describe('FT_ODD_EVEN', () => { it('S004: 0-0 is even', () => { const s = { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 }; expect( settleSelection({ marketType: 'FT_ODD_EVEN', selectionCode: 'EVEN', score: s }), ).toBe('WIN'); }); }); describe('Correct Score', () => { it('S005: exact score 2-1', () => { expect( settleSelection({ marketType: 'FT_CORRECT_SCORE', selectionCode: 'SCORE_2_1', score, }), ).toBe('WIN'); }); it('S006: other home win', () => { const s = { htHome: 2, htAway: 0, ftHome: 5, ftAway: 0 }; expect( settleSelection({ marketType: 'FT_CORRECT_SCORE', selectionCode: 'OTHER_HOME', score: s, templateScores: ['SCORE_1_0', 'SCORE_2_0'], }), ).toBe('WIN'); }); it('S008: second half correct score', () => { expect( settleSelection({ marketType: 'SH_CORRECT_SCORE', selectionCode: 'SCORE_1_1', score, }), ).toBe('WIN'); }); }); describe('Handicap', () => { it('S009: full win', () => { const r = settleSelection({ marketType: 'FT_HANDICAP', selectionCode: 'HOME', handicapLine: -1, score: { htHome: 0, htAway: 0, ftHome: 2, ftAway: 0 }, }); expect(r).toBe('WIN'); expect(calculatePayout(100, 1.85, r).toNumber()).toBe(185); }); it('S010: push', () => { const r = settleSelection({ marketType: 'FT_HANDICAP', selectionCode: 'HOME', handicapLine: -1, score: { htHome: 0, htAway: 0, ftHome: 1, ftAway: 0 }, }); expect(r).toBe('PUSH'); expect(calculatePayout(100, 1.85, r).toNumber()).toBe(100); }); it('S011: half win -0.25', () => { const r = settleSelection({ marketType: 'FT_HANDICAP', selectionCode: 'HOME', handicapLine: -0.25, score: { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 }, }); expect(r).toBe('HALF_LOSE'); }); it('0-0: home -0.5 loses', () => { const s = { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 }; expect( settleSelection({ marketType: 'FT_HANDICAP', selectionCode: 'HOME', handicapLine: -0.5, score: s, }), ).toBe('LOSE'); }); }); describe('Over/Under', () => { it('0-0: under 2.5 wins, over 2.5 loses', () => { const s = { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 }; const under = settleSelection({ marketType: 'FT_OVER_UNDER', selectionCode: 'UNDER', totalLine: 2.5, score: s, }); const over = settleSelection({ marketType: 'FT_OVER_UNDER', selectionCode: 'OVER', totalLine: 2.5, score: s, }); expect(under).toBe('WIN'); expect(over).toBe('LOSE'); expect(calculatePayout(100, 1.95, under).toNumber()).toBe(195); }); it('S013: over 2.5 wins with 3 goals', () => { const s = { htHome: 1, htAway: 1, ftHome: 2, ftAway: 1 }; expect( settleSelection({ marketType: 'FT_OVER_UNDER', selectionCode: 'OVER', totalLine: 2.5, score: s, }), ).toBe('WIN'); }); it('S014: push on integer line', () => { const s = { htHome: 1, htAway: 0, ftHome: 1, ftAway: 1 }; expect( settleSelection({ marketType: 'FT_OVER_UNDER', selectionCode: 'OVER', totalLine: 2, score: s, }), ).toBe('PUSH'); }); }); describe('Additional score-derived markets', () => { it('settles home and away team total goals', () => { const s = { htHome: 1, htAway: 0, ftHome: 2, ftAway: 1 }; expect( settleSelection({ marketType: 'FT_TEAM_TOTAL_HOME', selectionCode: 'OVER', totalLine: 1.5, score: s, }), ).toBe('WIN'); expect( settleSelection({ marketType: 'FT_TEAM_TOTAL_AWAY', selectionCode: 'UNDER', totalLine: 1.5, score: s, }), ).toBe('WIN'); }); it('settles half time / full time combinations', () => { expect( settleSelection({ marketType: 'HT_FT', selectionCode: 'HOME_HOME', score, }), ).toBe('WIN'); expect( settleSelection({ marketType: 'HT_FT', selectionCode: 'DRAW_HOME', score, }), ).toBe('LOSE'); }); it('settles total goals ranges', () => { expect( settleSelection({ marketType: 'FT_TOTAL_GOALS', selectionCode: 'TG_2_3', score, }), ).toBe('WIN'); expect( settleSelection({ marketType: 'FT_TOTAL_GOALS', selectionCode: 'TG_7_PLUS', score, }), ).toBe('LOSE'); }); it('settles corners handicap and totals from match stats', () => { const s = { htHome: 0, htAway: 0, ftHome: 1, ftAway: 1 }; const stats = { homeCorners: 7, awayCorners: 4 }; expect( settleSelection({ marketType: 'FT_CORNERS_HANDICAP', selectionCode: 'HOME', handicapLine: -2.5, score: s, stats, }), ).toBe('WIN'); expect( settleSelection({ marketType: 'FT_CORNERS_OVER_UNDER', selectionCode: 'OVER', totalLine: 10.5, score: s, stats, }), ).toBe('WIN'); }); it('settles cards total from match stats', () => { expect( settleSelection({ marketType: 'FT_CARDS_OVER_UNDER', selectionCode: 'UNDER', totalLine: 5.5, score, stats: { homeCards: 2, awayCards: 3 }, }), ).toBe('WIN'); }); }); describe('Parlay', () => { it('S016: all win', () => { const result = calculateParlayPayout(100, [ { odds: 1.8, result: 'WIN' }, { odds: 2.0, result: 'WIN' }, ]); expect(result.betResult).toBe('WON'); expect(result.payout.toNumber()).toBe(360); }); it('S017: one lose', () => { const result = calculateParlayPayout(100, [ { odds: 1.8, result: 'WIN' }, { odds: 2.0, result: 'LOSE' }, ]); expect(result.betResult).toBe('LOST'); expect(result.payout.toNumber()).toBe(0); }); it('S018: one push', () => { const result = calculateParlayPayout(100, [ { odds: 1.8, result: 'WIN' }, { odds: 2.0, result: 'PUSH' }, { odds: 1.9, result: 'WIN' }, ]); expect(result.betResult).toBe('WON'); expect(result.payout.toNumber()).toBe(342); }); it('S019: all push', () => { const result = calculateParlayPayout(100, [ { odds: 1.8, result: 'PUSH' }, { odds: 2.0, result: 'VOID' }, ]); expect(result.betResult).toBe('PUSH'); expect(result.payout.toNumber()).toBe(100); }); }); describe('OUTRIGHT_WINNER', () => { it('wins when selection matches winner team code', () => { expect( settleSelection({ marketType: 'OUTRIGHT_WINNER', selectionCode: 'BRA', score: { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 }, winnerTeamCode: 'BRA', }), ).toBe('WIN'); expect( settleSelection({ marketType: 'OUTRIGHT_WINNER', selectionCode: 'ARG', score: { htHome: 0, htAway: 0, ftHome: 0, ftAway: 0 }, winnerTeamCode: 'BRA', }), ).toBe('LOSE'); }); }); describe('Quarter line detection', () => { it('detects quarter lines', () => { expect(isQuarterHandicapOrTotal(-0.25)).toBe(true); expect(isQuarterHandicapOrTotal(2.5)).toBe(false); expect(isQuarterHandicapOrTotal(-1)).toBe(false); }); }); });