fix: Correct PnL calculation by using betAmount in net profit computation
Some checks failed
Deploy to Production / test (push) Failing after 34s

- 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
This commit is contained in:
syntaxbullet
2026-04-06 14:50:40 +02:00
parent f09cbe6939
commit 06c3891045
4 changed files with 13 additions and 8 deletions

View File

@@ -95,10 +95,9 @@ export class GameServer {
const gameName = gameRegistry.get(room.gameSlug)?.name ?? "Game";
const payoutDetails: Record<string, { net: number }> = {};
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,

View File

@@ -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,
};
}

View File

@@ -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<BlackjackState, BlackjackAction> = {
maxPlayers: 6,
manualStart: true,
createInitialState(players: string[], _options?: Record<string, unknown>): BlackjackState {
createInitialState(players: string[], options?: Record<string, unknown>): BlackjackState {
const betAmount = typeof options?.betAmount === 'number' ? options.betAmount : 0;
const seats: Record<string, PlayerSeat> = {};
for (const pid of players) {
seats[pid] = {
@@ -380,6 +381,7 @@ export const blackjackPlugin: GamePlugin<BlackjackState, BlackjackAction> = {
activePlayerIndex: -1,
phase: "betting",
roundNumber: 1,
betAmount,
};
},

View File

@@ -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 ──