From cd9e1e72425c55b64504107365ea05ebdb4538d1 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Mon, 6 Apr 2026 14:42:18 +0200 Subject: [PATCH] fix: Correct PnL calculation to show net profit instead of gross payout - GameServer.ts: Calculate netProfit = grossPayout - betAmount and send as 'net' instead of sending gross payout labeled as net - BlackjackGame.tsx: Fix PnL calculations to use net profit correctly - Hand win/blackjack now shows net profit (payout minus bet) - Lose correctly shows negative bet amount - Round result banner displays roundNet (net profit) with appropriate colors - Remove dead code (myPnl variable that was calculated but never used) - Update color coding: green for profit, red for loss, blue for zero balance --- api/src/games/GameServer.ts | 7 +++--- panel/src/games/blackjack/BlackjackGame.tsx | 24 ++++++--------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/api/src/games/GameServer.ts b/api/src/games/GameServer.ts index 1689b09..b6ff568 100644 --- a/api/src/games/GameServer.ts +++ b/api/src/games/GameServer.ts @@ -97,15 +97,16 @@ export class GameServer { for (const [playerId, multiplier] of Object.entries(roundPayouts)) { if (multiplier <= 0) continue; - const amount = Math.floor(betAmount * multiplier); + const grossPayout = Math.floor(betAmount * multiplier); + const netProfit = grossPayout - betAmount; // Calculate net profit (gross payout minus original bet) try { await economyService.modifyUserBalance( playerId, - BigInt(amount), + BigInt(grossPayout), TransactionType.GAME_WIN, `${gameName} round payout (room ${roomId.slice(0, 8)})`, ); - payoutDetails[playerId] = { net: amount }; + payoutDetails[playerId] = { net: netProfit }; } catch (err) { logger.error("web", `Round payout failed for ${playerId} in room ${roomId}: ${err}`); } diff --git a/panel/src/games/blackjack/BlackjackGame.tsx b/panel/src/games/blackjack/BlackjackGame.tsx index 6f88f8a..a71d3a7 100644 --- a/panel/src/games/blackjack/BlackjackGame.tsx +++ b/panel/src/games/blackjack/BlackjackGame.tsx @@ -211,13 +211,13 @@ function Seat({ seat, playerName, isMe, isActivePlayer, activeHandIdx, betAmount const hasHands = seat.hands.length > 0; const compact = seat.hands.length > 2; - // Calculate current round PnL for the display + // Calculate current round PnL for the display (only needed before results are shown) const currentRoundPnl = seat.hands.reduce((sum, h) => { if (!h.result) return sum; // Not yet resolved const handWin = h.bet * betAmount; - if (h.result === "win" || h.result === "blackjack") return sum + handWin; - if (h.result === "push") return sum; // Push returns bet - return sum - handWin; // Lose + if (h.result === "win" || h.result === "blackjack") return sum + (handWin - betAmount); // Net profit + if (h.result === "push") return sum; // Push returns bet, so net is 0 + return sum - betAmount; // Lose loses the bet amount }, 0); const totalPnl = seat.cumulativePnl + currentRoundPnl; @@ -364,11 +364,11 @@ function RoundResultBanner({ roundNumber, roundResult, myPlayerId, betAmount, my
Round {roundNumber}
- {myPayout && betAmount > 0 && ( + {betAmount > 0 && ( betAmount ? "text-emerald-400" : myPayout.net === betAmount ? "text-blue-400" : "text-white/60" + roundNet > 0 ? "text-emerald-400" : roundNet < 0 ? "text-red-400" : "text-blue-300" }`}> - Round: {myPayout.net > 0 ? "+" : ""}{myPayout.net} AU + Round: {roundNet > 0 ? "+" : ""}{roundNet} AU )}
@@ -398,16 +398,6 @@ export function BlackjackGame({ state, myPlayerId, isSpectator, onAction, player }, [players]); const mySeat = view.seats[myPlayerId]; - const myBetPlaced = mySeat?.hasBet ?? false; - - // Calculate current balance (if betting) or just track profit/loss - const balance = betAmount > 0 && mySeat?.hands.length === 0 - ? 0 // Not yet bet for this round - : mySeat?.hands.reduce((sum, h) => sum + (h.result === "win" || h.result === "blackjack" - ? h.bet * betAmount - : h.result === "push" ? h.bet * betAmount - : 0), 0) - (myBetPlaced ? mySeat.hands.reduce((sum, h) => sum + h.bet * betAmount, 0) : 0); - const myPnl = (mySeat?.cumulativePnl ?? 0) + balance; // Determine who can sit (spectators during betting phase) const canSitDown = isSpectator && isBetting && view.turnOrder.length < 6;