From 06c3891045b3035cf0d2cc47a61049d31716b360 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Mon, 6 Apr 2026 14:50:40 +0200 Subject: [PATCH] fix: Correct PnL calculation by using betAmount in net profit computation - Add betAmount field to BlackjackState to track the base bet - Fix finishPlayerTurns: multiply hand.bet by state.betAmount for actual money bets - Fix GameServer: roundPayouts are already gross payouts (not multipliers) - Update cumulative PnL calculation to correctly subtract actual bet amount - Add betAmount support to riggedState test helper --- api/src/games/GameServer.ts | 7 +++---- shared/games/blackjack/blackjack.plugin.test.ts | 2 ++ shared/games/blackjack/blackjack.plugin.ts | 10 ++++++---- shared/games/blackjack/blackjack.types.ts | 2 ++ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/api/src/games/GameServer.ts b/api/src/games/GameServer.ts index b6ff568..92e12cd 100644 --- a/api/src/games/GameServer.ts +++ b/api/src/games/GameServer.ts @@ -95,10 +95,9 @@ export class GameServer { const gameName = gameRegistry.get(room.gameSlug)?.name ?? "Game"; const payoutDetails: Record = {}; - for (const [playerId, multiplier] of Object.entries(roundPayouts)) { - if (multiplier <= 0) continue; - const grossPayout = Math.floor(betAmount * multiplier); - const netProfit = grossPayout - betAmount; // Calculate net profit (gross payout minus original bet) + for (const [playerId, grossPayout] of Object.entries(roundPayouts)) { + // roundPayout is already the gross payout amount (not a multiplier) + const netProfit = Math.floor(grossPayout) - betAmount; // Calculate net profit (gross payout minus original bet) try { await economyService.modifyUserBalance( playerId, diff --git a/shared/games/blackjack/blackjack.plugin.test.ts b/shared/games/blackjack/blackjack.plugin.test.ts index 49da3c6..d44cfe1 100644 --- a/shared/games/blackjack/blackjack.plugin.test.ts +++ b/shared/games/blackjack/blackjack.plugin.test.ts @@ -34,6 +34,7 @@ function riggedState(overrides: { activePlayerIndex?: number; phase?: "betting" | "player_turns" | "resolved"; roundNumber?: number; + betAmount?: number; }): BlackjackState { return { deck: overrides.deck ?? [makeCard("5"), makeCard("6"), makeCard("7"), makeCard("8"), makeCard("9"), makeCard("10")], @@ -43,6 +44,7 @@ function riggedState(overrides: { activePlayerIndex: overrides.activePlayerIndex ?? 0, phase: overrides.phase ?? "player_turns", roundNumber: overrides.roundNumber ?? 1, + betAmount: overrides.betAmount ?? 0, }; } diff --git a/shared/games/blackjack/blackjack.plugin.ts b/shared/games/blackjack/blackjack.plugin.ts index 447c65a..1725aa3 100644 --- a/shared/games/blackjack/blackjack.plugin.ts +++ b/shared/games/blackjack/blackjack.plugin.ts @@ -196,10 +196,10 @@ function finishPlayerTurns(state: BlackjackState): BlackjackState { // Then calculate PnL based on resolved hands const roundPayout = calculateRoundPayouts({ [id]: { ...seat, hands: resolvedHands } }); - const roundPnl = roundPayout[id] ?? 0; + const roundPayoutMoney = roundPayout[id] ?? 0; // Subtract the total bet amount to get net profit/loss - const roundBetTotal = seat.hands.reduce((sum, h) => sum + h.bet, 0); - const roundNetPnl = roundPayout[id] ? roundPayout[id] - roundBetTotal : -roundBetTotal; + const roundBetTotal = seat.hands.reduce((sum, h) => sum + (h.bet * state.betAmount), 0); + const roundNetPnl = roundPayoutMoney ? roundPayoutMoney - roundBetTotal : -roundBetTotal; resolvedSeats[id] = { ...seat, @@ -361,7 +361,8 @@ export const blackjackPlugin: GamePlugin = { maxPlayers: 6, manualStart: true, - createInitialState(players: string[], _options?: Record): BlackjackState { + createInitialState(players: string[], options?: Record): BlackjackState { + const betAmount = typeof options?.betAmount === 'number' ? options.betAmount : 0; const seats: Record = {}; for (const pid of players) { seats[pid] = { @@ -380,6 +381,7 @@ export const blackjackPlugin: GamePlugin = { activePlayerIndex: -1, phase: "betting", roundNumber: 1, + betAmount, }; }, diff --git a/shared/games/blackjack/blackjack.types.ts b/shared/games/blackjack/blackjack.types.ts index 4066225..8850f10 100644 --- a/shared/games/blackjack/blackjack.types.ts +++ b/shared/games/blackjack/blackjack.types.ts @@ -41,6 +41,8 @@ export interface BlackjackState { activePlayerIndex: number; phase: "betting" | "player_turns" | "resolved"; roundNumber: number; + /** The base bet amount for this game (0 for free play). */ + betAmount: number; } // ── Actions ──