Pay somebody out and keep the chair, the cash and the record straight #108

Closed
jheaps wants to merge 1 commits from feat/casino-holdem-cash-out into feat/casino-holdem-clock
Owner

The most ordinary thing that happens at a home game after midnight — somebody counts up and goes home — and the tool had nothing for it. Freeing the chair meant wiping the seat by hand, and the bank check then declared their whole stack missing: "someone has paid for chips they haven't been given", for the rest of the night. Measured on a balanced table, cashing a player out with $350 in front of them left the check $350 short. Wiping their buy-in as well silenced it, at the price of losing their entire night from the standings and from the file the dealer hands over.

Cashing out is two facts, and both have to survive the empty chair: the box took their cash, and the box handed their chips back. Both are kept now, so the chair opens and the money still adds up.

What it looks like

  • Cash out… in the seat menu says what to count — "Count out $350 — 3×$100, 2×$25. They bought in for $200, so they leave up $150." — because that's the sentence a dealer says while their hands are moving.
  • The bank check gains a Paid out line and reads "balanced … once the $350 paid out to players who have left is counted", alongside the discards and the house's cut.
  • The standings keep them with a stripe and "· paid out", so nobody counts money out to them twice at 2am. The export marks them the same way.
  • It refuses to pay anybody with money still in the middle — "Ben has $1 in the pot. Finish the hand first." Taking chips out of a live pot, or handing the same chips over twice, are both worse than waiting.
  • The chair gets a fresh id: the person who had it has gone, and the next player to sit down is not them.

Two things this turned up

My first draft worked out what a seat was holding by itself, read Number(null) as a perfectly good zero, and offered to pay a player with no stack set nothing at all. It asks Betting.stackOf now, which owns that rule — including "a seat that was never given a stack is holding the table's starting one".

The second was mine and the audit caught it. Marking the departed row with opacity: 0.72 took its In and Won cells to 3.83:1, under AA, on the very list a dealer settles from — exactly the kind of fade the contrast check learned to measure two rounds ago. It's a stripe instead.

Validated

  • Walked through in the browser: long-press → Cash out… → confirm → seat empty, cashedOut recorded, bank showing Paid out $350 and balanced, standings row striped and labelled, toast offering Undo — and Undo puts Ann back with her $350 and her buy-in, still balanced.
  • The refusal checked mid-hand: nothing moved, seat untouched.
  • 156 audits across 13 viewports, mouse and thumb, with two players already cashed out plus a rake and a discard on the books: one failure (the fade above), fixed, then clean.
  • 19 new tests, suite at 513, 0 failures. The departed buy-in was dropped from the check and the pot guard disabled on purpose to confirm the tests catch both.
The most ordinary thing that happens at a home game after midnight — somebody counts up and goes home — and the tool had nothing for it. Freeing the chair meant wiping the seat by hand, and the bank check then declared their whole stack **missing**: *"someone has paid for chips they haven't been given"*, for the rest of the night. Measured on a balanced table, cashing a player out with $350 in front of them left the check **$350 short**. Wiping their buy-in as well silenced it, at the price of losing their entire night from the standings and from the file the dealer hands over. Cashing out is two facts, and both have to survive the empty chair: **the box took their cash, and the box handed their chips back**. Both are kept now, so the chair opens and the money still adds up. ### What it looks like - **Cash out…** in the seat menu says what to count — *"Count out $350 — 3×$100, 2×$25. They bought in for $200, so they leave up $150."* — because that's the sentence a dealer says while their hands are moving. - The bank check gains a **Paid out** line and reads *"balanced … once the $350 paid out to players who have left is counted"*, alongside the discards and the house's cut. - The standings keep them with a stripe and *"· paid out"*, so nobody counts money out to them twice at 2am. The export marks them the same way. - It **refuses to pay anybody with money still in the middle** — *"Ben has $1 in the pot. Finish the hand first."* Taking chips out of a live pot, or handing the same chips over twice, are both worse than waiting. - The chair gets a fresh id: the person who had it has gone, and the next player to sit down is not them. ### Two things this turned up **My first draft worked out what a seat was holding by itself**, read `Number(null)` as a perfectly good zero, and offered to pay a player with no stack set **nothing at all**. It asks `Betting.stackOf` now, which owns that rule — including "a seat that was never given a stack is holding the table's starting one". **The second was mine and the audit caught it.** Marking the departed row with `opacity: 0.72` took its In and Won cells to **3.83:1**, under AA, on the very list a dealer settles from — exactly the kind of fade the contrast check learned to measure two rounds ago. It's a stripe instead. ### Validated - Walked through in the browser: long-press → **Cash out…** → confirm → seat empty, `cashedOut` recorded, bank showing **Paid out $350** and balanced, standings row striped and labelled, toast offering Undo — and **Undo puts Ann back** with her $350 and her buy-in, still balanced. - The refusal checked mid-hand: nothing moved, seat untouched. - 156 audits across 13 viewports, mouse and thumb, with two players already cashed out plus a rake and a discard on the books: one failure (the fade above), fixed, then clean. - 19 new tests, suite at **513, 0 failures**. The departed buy-in was dropped from the check and the pot guard disabled on purpose to confirm the tests catch both.
jheaps added 1 commit 2026-09-02 08:09:18 -06:00
The most ordinary thing that happens at a home game after midnight — somebody
counts up and goes home — and the tool had nothing for it. Freeing the chair
meant wiping the seat by hand, and the bank check then declared their whole stack
missing: "someone has paid for chips they haven't been given", for the rest of
the night. Measured on a balanced table, cashing a player out with $350 in front
of them left the check $350 short. Wiping their buy-in as well silenced it, at
the price of losing their entire night from the standings and from the file the
dealer hands over at the end.

Cashing out is two facts, and both have to survive the empty chair: the box took
their cash, and the box handed their chips back. Both are kept now, so the chair
opens and the money still adds up.

Cash out… is in the seat menu. It says what to count — "$350 — 3×$100, 2×$25" —
what they bought in for, and whether they leave up or down, because that is the
sentence the dealer says while their hands are moving. The bank check gains a
Paid out line and reads "balanced ... once the $350 paid out to players who have
left is counted", alongside the discards and the house's cut. The standings keep
them with a stripe and the words "· paid out", so nobody counts money out to them
twice at 2am, and the export marks them the same way.

It refuses to pay anybody with money still in the middle: taking chips out of a
pot other people can win, or handing the same chips over twice, are both worse
than waiting for the hand to finish. The chair gets a fresh id, because the
person who had it has gone and the next player to sit down is not them.

Two things this turned up. The first draft worked out what a seat was holding by
itself, read `Number(null)` as a perfectly good zero, and offered to pay a player
with no stack set nothing at all — it asks Betting now, which owns that rule.
The second was mine and the audit caught it: marking the departed row with
opacity took the In and Won cells to 3.83:1, under AA, on the very list a dealer
settles from. It is a stripe instead.

19 new tests, with the departed buy-in dropped from the check and the pot guard
disabled on purpose to confirm they fail. Walked through in the browser: menu,
confirm, payout, bank, standings, undo, and the refusal.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
jheaps closed this pull request 2026-09-02 09:58:07 -06:00

Pull request closed

Please reopen this pull request to perform a merge.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jheaps/JoshHeaps.Net#108