From 99977bc8e6712e749138428461d25653e2605971 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Mon, 19 Jan 2026 13:10:07 -0700 Subject: [PATCH] Fix comeback bonus --- constants.ts | 4 +++- hooks/useGame.ts | 3 +++ scripts/setup-prod.sh | 10 ++++++++++ tests/constants.test.ts | 30 ++++++++++++++++++++++++++++-- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/constants.ts b/constants.ts index 476eff1..14546f1 100644 --- a/constants.ts +++ b/constants.ts @@ -46,6 +46,7 @@ interface PointsCalculationParams { playerRank: number; isFirstCorrect: boolean; config: GameConfig; + currentQuestionIndex?: number; } export const calculatePointsWithBreakdown = (params: PointsCalculationParams): PointsBreakdown => { @@ -78,7 +79,8 @@ export const calculatePointsWithBreakdown = (params: PointsCalculationParams): P breakdown.streakBonus = pointsAfterStreak - breakdown.basePoints; } - if (config.comebackBonusEnabled && playerRank > 3) { + const isFirstQuestion = params.currentQuestionIndex === 0 || params.currentQuestionIndex === undefined; + if (config.comebackBonusEnabled && playerRank > 3 && !isFirstQuestion) { breakdown.comebackBonus = config.comebackBonusPoints; } diff --git a/hooks/useGame.ts b/hooks/useGame.ts index 1da08ed..eef9865 100644 --- a/hooks/useGame.ts +++ b/hooks/useGame.ts @@ -915,6 +915,7 @@ export const useGame = () => { playerRank, isFirstCorrect, config: gameConfigRef.current, + currentQuestionIndex: currentQuestionIndexRef.current, }); const newScore = Math.max(0, currentPlayer.score + breakdown.total); @@ -1055,6 +1056,7 @@ export const useGame = () => { playerRank, isFirstCorrect: false, config: gameConfigRef.current, + currentQuestionIndex: currentQuestionIndexRef.current, }); const newScore = Math.max(0, p.score + breakdown.total); @@ -1436,6 +1438,7 @@ export const useGame = () => { playerRank, isFirstCorrect, config: gameConfigRef.current, + currentQuestionIndex: currentQuestionIndexRef.current, }); setLastPointsEarned(breakdown.total); diff --git a/scripts/setup-prod.sh b/scripts/setup-prod.sh index 4cbf817..463ca96 100755 --- a/scripts/setup-prod.sh +++ b/scripts/setup-prod.sh @@ -246,6 +246,7 @@ if [ -n "$TURN_IP" ]; then # Coturn TURN Server Configuration # Generated by setup-prod.sh on $(date) +listening-ip=0.0.0.0 listening-port=3478 tls-listening-port=5349 external-ip=${TURN_IP} @@ -342,9 +343,18 @@ echo -e " ${AUTH_DOMAIN} → ${BLUE}${NC}" echo "" if [ -n "$TURN_IP" ]; then echo " 2. Open firewall ports for TURN server:" +echo "" +echo " For Ubuntu/ufw:" echo -e " ${YELLOW}sudo ufw allow 3478/tcp && sudo ufw allow 3478/udp${NC}" echo -e " ${YELLOW}sudo ufw allow 5349/tcp && sudo ufw allow 49152:65535/udp${NC}" echo "" +echo " For Oracle Cloud (firewalld):" +echo -e " ${YELLOW}sudo firewall-cmd --permanent --add-port=3478/tcp${NC}" +echo -e " ${YELLOW}sudo firewall-cmd --permanent --add-port=3478/udp${NC}" +echo -e " ${YELLOW}sudo firewall-cmd --permanent --add-port=5349/tcp${NC}" +echo -e " ${YELLOW}sudo firewall-cmd --permanent --add-port=49152-65535/udp${NC}" +echo -e " ${YELLOW}sudo firewall-cmd --reload${NC}" +echo "" echo " 3. Start the TURN server:" echo -e " ${YELLOW}docker compose -f docker-compose.turn.yml up -d${NC}" echo "" diff --git a/tests/constants.test.ts b/tests/constants.test.ts index 30e483c..66331e7 100644 --- a/tests/constants.test.ts +++ b/tests/constants.test.ts @@ -231,6 +231,7 @@ describe('calculatePointsWithBreakdown', () => { const result = calculatePointsWithBreakdown({ ...baseParams, playerRank: 5, + currentQuestionIndex: 1, config: { ...DEFAULT_GAME_CONFIG, comebackBonusEnabled: false }, }); @@ -242,6 +243,7 @@ describe('calculatePointsWithBreakdown', () => { const result = calculatePointsWithBreakdown({ ...baseParams, playerRank: rank, + currentQuestionIndex: 1, config: { ...DEFAULT_GAME_CONFIG, comebackBonusEnabled: true, comebackBonusPoints: 100 }, }); @@ -253,6 +255,7 @@ describe('calculatePointsWithBreakdown', () => { const result = calculatePointsWithBreakdown({ ...baseParams, playerRank: 4, + currentQuestionIndex: 1, config: { ...DEFAULT_GAME_CONFIG, comebackBonusEnabled: true, comebackBonusPoints: 100 }, }); @@ -264,11 +267,33 @@ describe('calculatePointsWithBreakdown', () => { const result = calculatePointsWithBreakdown({ ...baseParams, playerRank: 10, + currentQuestionIndex: 2, config: { ...DEFAULT_GAME_CONFIG, comebackBonusEnabled: true, comebackBonusPoints: 150 }, }); expect(result.comebackBonus).toBe(150); }); + + it('applies no comeback bonus on first question (index 0)', () => { + const result = calculatePointsWithBreakdown({ + ...baseParams, + playerRank: 5, + currentQuestionIndex: 0, + config: { ...DEFAULT_GAME_CONFIG, comebackBonusEnabled: true, comebackBonusPoints: 100 }, + }); + + expect(result.comebackBonus).toBe(0); + }); + + it('applies no comeback bonus when currentQuestionIndex is undefined', () => { + const result = calculatePointsWithBreakdown({ + ...baseParams, + playerRank: 5, + config: { ...DEFAULT_GAME_CONFIG, comebackBonusEnabled: true, comebackBonusPoints: 100 }, + }); + + expect(result.comebackBonus).toBe(0); + }); }); describe('first correct bonus', () => { @@ -319,9 +344,10 @@ describe('calculatePointsWithBreakdown', () => { const result = calculatePointsWithBreakdown({ ...baseParams, - streak: 4, // Above threshold - playerRank: 5, // Qualifies for comeback + streak: 4, + playerRank: 5, isFirstCorrect: true, + currentQuestionIndex: 2, config, });