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

@@ -303,7 +303,7 @@ func (s *Server) table(user string) (tableView, error) {
if live.TableID == "" {
return s.dropUnreadable(user, v, fmt.Errorf("holdem row with no table"))
}
t, _, err := storage.LoadTable(live.TableID)
t, tableSeats, err := storage.LoadTable(live.TableID)
if errors.Is(err, storage.ErrNoSuchTable) {
// The table closed under them (reaped, or the last hand cashed them out).
// Their claim is stale; clear it so they can sit down again.
@@ -321,6 +321,15 @@ func (s *Server) table(user string) (tableView, error) {
return s.dropUnreadable(user, v, err)
}
hv := viewHoldem(g, seat)
// bought_in is a per-player figure — "you bought in for X" — but the engine's
// BoughtIn is the table's total across every human. The player's own stake is
// border accounting, which lives in storage; take it from their seat row.
for _, ts := range tableSeats {
if ts.Seat == seat {
hv.BoughtIn = ts.Staked
break
}
}
v.Holdem = &hv
default:
return s.dropUnreadable(user, v, fmt.Errorf("unknown game %q", live.Game))