games: the buy-in and the rake each player sees are their own, not the table's

The two-browser pass found it: at a table two humans share, the felt quoted
each of them the pair's total. "Bought in for 200" to a player who put in 100,
and a session-rake line that climbed on a pot the other one won.

Both were table totals the view read straight off the engine — correct while a
table had one human, wrong the moment it had two. Fixed along the border it
already draws: bought_in is border accounting, so it comes from the viewer's own
game_seats.staked; session rake is a within-table event, so it rides a new
per-seat Seat.Paid beside the audit's table-total s.Paid.

And top-up never grew game_seats.staked, so the storage invariant drifted by
every top-up and the felt under-reported the buy-in — it does now.

Claude-Session: https://claude.ai/code/session_013M5nD7PgUboJXoDcYHzpuJ
This commit is contained in:
prosolis
2026-07-14 17:17:25 -07:00
parent 4ad96dcb5e
commit f8b07d8e6c
6 changed files with 87 additions and 3 deletions

View File

@@ -87,6 +87,36 @@ func TestHoldemJoinTakesAnOpenSeat(t *testing.T) {
}
}
// The felt tells each player "you bought in for X" — their own stake, not the
// table's. The engine's BoughtIn is the sum across every human (the audit wants
// that), so a two-human table would quote both of them the pair's total if the
// view read it straight. It reads each seat's own staked row from storage instead.
func TestBoughtInIsPerPlayerNotTheTableTotal(t *testing.T) {
s := newCasino(t)
fund(t, 5000) // reala
fundUser(t, bobPlayer, 5000)
call(t, s, s.handleHoldemSit, as(t, s, "reala", "POST", "/api/games/holdem/sit",
map[string]any{"tier": "low", "bots": 2, "buyin": 500}))
tableID, _ := storage.TableOf(testPlayer)
call(t, s, s.handleHoldemSit, as(t, s, "bob", "POST", "/api/games/holdem/sit",
map[string]any{"table": tableID, "buyin": 500}))
for _, who := range []string{testPlayer, bobPlayer} {
v, err := s.table(who)
if err != nil {
t.Fatal(err)
}
if v.Holdem == nil {
t.Fatalf("%s has no table", who)
}
if v.Holdem.BoughtIn != 500 {
t.Errorf("%s is shown bought-in %d, want their own 500 — not the table's 1000",
who, v.Holdem.BoughtIn)
}
}
}
// Leaving a shared table gives you your stack and hands your chair back to the
// house; the table stays open for the people still on it. Only the last human out
// closes the felt.