Skip to content

Commit

Permalink
Merge pull request #14 from homanp/feat/pokerstads-calculation
Browse files Browse the repository at this point in the history
feat: pokerstads calculation
  • Loading branch information
homanp authored Nov 19, 2024
2 parents db671c5 + 35fbdeb commit 9e9143a
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 26 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "open-hand-tracker",
"version": "1.0.8",
"version": "1.0.9",
"description": "A package for creating and managing poker hand histories",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
188 changes: 180 additions & 8 deletions src/__tests__/OpenHandHistory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ describe("OpenHandHistory", () => {
describe("winning calculations", () => {
beforeEach(() => {
ohh = new OpenHandHistory({
smallBlindAmount: 5,
bigBlindAmount: 10,
smallBlindAmount: 1,
bigBlindAmount: 2,
dealerSeat: 1,
});
ohh.addPlayer({ name: "Player 1", id: 1, starting_stack: 1000, seat: 1 });
Expand All @@ -165,40 +165,212 @@ describe("OpenHandHistory", () => {
action_number: 1,
player_id: 2,
action: "Post SB" as const,
amount: 5,
amount: 1,
});
ohh.addActionToRound(1, {
action_number: 2,
player_id: 3,
action: "Post BB" as const,
amount: 2,
});
ohh.addActionToRound(1, {
action_number: 3,
player_id: 1,
action: "Raise" as const,
amount: 6,
});
ohh.addActionToRound(1, {
action_number: 4,
player_id: 2,
action: "Fold" as const,
});
ohh.addActionToRound(1, {
action_number: 5,
player_id: 3,
action: "Fold" as const,
});
const win_amount = ohh.calculateWinningAmount(1);
ohh.addPot({
number: 1,
amount: 9,
player_wins: [{ player_id: 1, win_amount }],
});

const json = ohh.toJSON();
expect(json.ohh.pots[0].player_wins[0].win_amount).toBe(5); // 50 (pot) - 20 (raise)
});

test("calculates winning amount correctly for winner on flop", () => {
const preflopRound = { id: 1, street: "Preflop" as const, actions: [] };
ohh.addRound(preflopRound);
ohh.addActionToRound(1, {
action_number: 1,
player_id: 1,
action: "Post SB" as const,
amount: 1,
});
ohh.addActionToRound(1, {
action_number: 2,
player_id: 2,
action: "Post BB" as const,
amount: 2,
});
ohh.addActionToRound(1, {
action_number: 3,
player_id: 3,
action: "Call" as const,
amount: 2,
});
ohh.addActionToRound(1, {
action_number: 4,
player_id: 1,
action: "Call" as const,
amount: 1,
});
ohh.addActionToRound(1, {
action_number: 5,
player_id: 2,
action: "Check" as const,
});

const flopRound = { id: 2, street: "Flop" as const, actions: [] };
ohh.addRound(flopRound);
ohh.addActionToRound(2, {
action_number: 6,
player_id: 1,
action: "Bet" as const,
amount: 4,
});
ohh.addActionToRound(2, {
action_number: 7,
player_id: 2,
action: "Fold" as const,
});
ohh.addActionToRound(2, {
action_number: 8,
player_id: 3,
action: "Fold" as const,
});

const win_amount = ohh.calculateWinningAmount(1);
ohh.addPot({
number: 1,
amount: 10,
player_wins: [{ player_id: 1, win_amount }],
});

const json = ohh.toJSON();
expect(json.ohh.pots[0].player_wins[0].win_amount).toBe(6); // 10 (pot) - 4 (player 1's total contribution)
});

test("calculates winning amount correctly for winner on river in a complex hand", () => {
const preflopRound = { id: 1, street: "Preflop" as const, actions: [] };
ohh.addRound(preflopRound);
ohh.addActionToRound(1, {
action_number: 1,
player_id: 2,
action: "Post SB" as const,
amount: 1,
});
ohh.addActionToRound(1, {
action_number: 2,
player_id: 3,
action: "Post BB" as const,
amount: 2,
});
ohh.addActionToRound(1, {
action_number: 3,
player_id: 1,
action: "Raise" as const,
amount: 20,
amount: 6,
});
ohh.addActionToRound(1, {
action_number: 4,
player_id: 2,
action: "Call" as const,
amount: 15,
amount: 5,
});
ohh.addActionToRound(1, {
action_number: 5,
player_id: 3,
action: "Call" as const,
amount: 4,
});

const flopRound = { id: 2, street: "Flop" as const, actions: [] };
ohh.addRound(flopRound);
ohh.addActionToRound(2, {
action_number: 6,
player_id: 2,
action: "Check" as const,
});
ohh.addActionToRound(2, {
action_number: 7,
player_id: 3,
action: "Bet" as const,
amount: 8,
});
ohh.addActionToRound(2, {
action_number: 8,
player_id: 1,
action: "Call" as const,
amount: 8,
});
ohh.addActionToRound(2, {
action_number: 9,
player_id: 2,
action: "Fold" as const,
});
const win_amount = ohh.calculateWinningAmount(1, 50);

const turnRound = { id: 3, street: "Turn" as const, actions: [] };
ohh.addRound(turnRound);
ohh.addActionToRound(3, {
action_number: 10,
player_id: 3,
action: "Check" as const,
});
ohh.addActionToRound(3, {
action_number: 11,
player_id: 1,
action: "Bet" as const,
amount: 16,
});
ohh.addActionToRound(3, {
action_number: 12,
player_id: 3,
action: "Call" as const,
amount: 16,
});

const riverRound = { id: 4, street: "River" as const, actions: [] };
ohh.addRound(riverRound);
ohh.addActionToRound(4, {
action_number: 13,
player_id: 3,
action: "Check" as const,
});
ohh.addActionToRound(4, {
action_number: 14,
player_id: 1,
action: "Bet" as const,
amount: 30,
});
ohh.addActionToRound(4, {
action_number: 15,
player_id: 3,
action: "Call" as const,
amount: 30,
});

const win_amount = ohh.calculateWinningAmount(1);
ohh.addPot({
number: 1,
amount: 50,
amount: 126,
player_wins: [{ player_id: 1, win_amount }],
});

const json = ohh.toJSON();
expect(json.ohh.pots[0].player_wins[0].win_amount).toBe(30); // 50 (pot) - 20 (raise)
expect(json.ohh.pots[0].player_wins[0].win_amount).toBe(126); // 126 (pot) - 60 (player 1's total contribution)
});
});
});
39 changes: 22 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,36 +77,41 @@ export class OpenHandHistory {
writeFileSync(filename, stringRepresentation);
}

calculateWinningAmount(playerId: number, potAmount: number): number {
let totalContribution = 0;
calculateWinningAmount(playerId: number): number {
let totalCommitted = 0;
let playerContribution = 0;
let highestOtherBet = 0;
let otherPlayersContribution = 0;

// Calculate the total contribution of the player
// Calculate total committed and track contributions
for (const round of this.ohh.rounds) {
for (const action of round.actions) {
if (
action.player_id === playerId &&
["Bet", "Raise", "Call", "Post SB", "Post BB"].includes(action.action)
) {
totalContribution += action.amount || 0; // Add the action amount if present
const amount = action.amount || 0;
totalCommitted += amount;
if (action.player_id === playerId) {
playerContribution += amount;
} else {
otherPlayersContribution += amount;
highestOtherBet = Math.max(highestOtherBet, amount);
}
}
}
}

// Get the player's starting stack
const player = this.ohh.players.find((p) => p.id === playerId);
if (!player) {
throw new Error(`Player with ID ${playerId} not found`);
// If the player's bet is fully called, return the entire pot
if (otherPlayersContribution >= playerContribution) {
return totalCommitted;
}

const startingStack = player.starting_stack;
// Otherwise, calculate the winning amount as before
const matchedPlayerBet = Math.min(playerContribution, highestOtherBet);
const winningAmount =
totalCommitted - playerContribution + matchedPlayerBet;

// Calculate the final stack after winning the pot
const finalStack = startingStack - totalContribution + potAmount;

// Calculate the PokerTracker Win Amount (net change in stack)
const winAmount = finalStack - startingStack;

return winAmount;
return winningAmount;
}
}

Expand Down

0 comments on commit 9e9143a

Please sign in to comment.