Track session standings so the dealer can settle up at the end of the night
The hand log answered "what happened in hand 12"; it couldn't answer "what does Alice owe". Each resolved pot now records a per-seat ledger (what that player put in, what they took down) alongside the payouts, and a Session Standings panel sums it into one row per player — paid in, won, net, sorted by who's up. The CSV export carries the same table, so one file covers both the hand-by-hand trail and the cash-out numbers. Keyed by seat id rather than name, so renaming or reseating a player doesn't split their totals. Hands recorded before this change have no ledger and are skipped rather than counted wrong. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
This commit is contained in:
@@ -88,6 +88,12 @@ const HoldemState = {
|
||||
return state;
|
||||
},
|
||||
|
||||
// What to call a seat in logs, payouts and standings when the dealer hasn't
|
||||
// typed a name in yet.
|
||||
displayName(player, seatIndex) {
|
||||
return player.name && player.name.trim() ? player.name.trim() : `Seat ${seatIndex + 1}`;
|
||||
},
|
||||
|
||||
// Contribution the table calculator will treat this player as having put in.
|
||||
computeContribution(player, chipLegend, basePotAmount) {
|
||||
if (!player.inHand) return 0;
|
||||
@@ -146,17 +152,32 @@ const HoldemState = {
|
||||
|
||||
// Appends a resolved-pot record to the running session log a dealer can point to
|
||||
// for chip-count disputes, then advances the hand counter. `payouts` is
|
||||
// [{ label, amount }, ...] — who got paid what out of this hand's pot(s).
|
||||
// [{ id, label, amount }, ...] — who got paid what out of this hand's pot(s).
|
||||
//
|
||||
// Must be called before startNextHand() clears the seats: the per-player `ledger`
|
||||
// it stores alongside the payouts is what session standings are summed from later,
|
||||
// and it needs this hand's contributions while they're still on the table.
|
||||
recordHand(state, payouts) {
|
||||
if (typeof state.handNumber !== "number") state.handNumber = 1;
|
||||
if (!Array.isArray(state.handHistory)) state.handHistory = [];
|
||||
|
||||
const pot = payouts.reduce((sum, p) => sum + p.amount, 0);
|
||||
const wonById = new Map(payouts.map(p => [p.id, p.amount]));
|
||||
const ledger = state.seats
|
||||
.map((player, index) => ({
|
||||
id: player.id,
|
||||
name: this.displayName(player, index),
|
||||
in: this.computeContribution(player, state.chipLegend, state.basePotAmount),
|
||||
won: wonById.get(player.id) || 0,
|
||||
}))
|
||||
.filter(row => row.in > 0 || row.won > 0);
|
||||
|
||||
state.handHistory.unshift({
|
||||
handNumber: state.handNumber,
|
||||
timestamp: Date.now(),
|
||||
pot,
|
||||
payouts,
|
||||
ledger,
|
||||
});
|
||||
if (state.handHistory.length > this.MAX_HISTORY_ENTRIES) {
|
||||
state.handHistory.length = this.MAX_HISTORY_ENTRIES;
|
||||
@@ -168,6 +189,34 @@ const HoldemState = {
|
||||
state.handHistory = [];
|
||||
state.handNumber = 1;
|
||||
},
|
||||
|
||||
// Running per-player totals for the whole session, so a dealer settling up at the
|
||||
// end of the night reads one number per person instead of adding up every hand.
|
||||
// Keyed by seat id, which survives renames and reseating; hands recorded before
|
||||
// the ledger existed simply don't contribute to the totals.
|
||||
sessionStandings(state) {
|
||||
const totals = new Map();
|
||||
|
||||
(state.handHistory || []).forEach(entry => {
|
||||
(entry.ledger || []).forEach(row => {
|
||||
// History is newest-first, so the first name seen for an id is the
|
||||
// most recent one the dealer typed.
|
||||
const running = totals.get(row.id) || { id: row.id, name: row.name, in: 0, won: 0 };
|
||||
running.in += row.in;
|
||||
running.won += row.won;
|
||||
totals.set(row.id, running);
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(totals.values())
|
||||
.map(t => ({
|
||||
...t,
|
||||
in: Math.round(t.in * 100) / 100,
|
||||
won: Math.round(t.won * 100) / 100,
|
||||
net: Math.round((t.won - t.in) * 100) / 100,
|
||||
}))
|
||||
.sort((a, b) => b.net - a.net);
|
||||
},
|
||||
};
|
||||
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
|
||||
Reference in New Issue
Block a user