Show the banker the amount to count out, not just whether the player is up
The standings had a column headed "Cash out" and it did not hold an amount to pay.
It held the difference against the player's buy-in. Measured on a table where Ann
bought in for $200 and sits behind $340:
PLAYER NET CASH OUT
Ann $0 +$140
She is handed $340. The column called "Cash out" says $140, under a heading that
invites reading it as the payout, at the exact moment somebody is counting money onto
the table. The number a banker's hands actually follow — what the player is holding —
was computed all along and written to the CSV, and never shown on screen.
Three columns now, and they say what they are: Player, Chips, Up/down. Chips is a
plain amount and never signed, because it is a quantity of money to hand over. Up/down
keeps the sign and the colour, because it is a result. The two differ by exactly the
buy-in, which is asserted rather than assumed.
Chips counts what is out in the middle for the hand in progress as still theirs, for
the same reason the up/down figure does: the panel is read mid-hand constantly and a
stack that drops by the size of a bet looks like money going missing.
Net — won less paid in, from the hand log — comes off the screen to make room. It is
the weakest of the three: it only moves when a pot is resolved through the wizard, so
at a table where the dealer settles pots by hand it reads $0 all night beside two
columns that don't, and up/down already answers "how are they doing". It stays in the
CSV export, which loses nothing.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015bnp7xKUPFFSpwkYNFaPgb
This commit is contained in:
@@ -110,8 +110,9 @@
|
||||
<span>Player</span>
|
||||
<span class="standingsInHead">In</span>
|
||||
<span class="standingsWonHead">Won</span>
|
||||
<span>Net</span>
|
||||
<span title="Chips in front of them, less the cash they handed over">Cash out</span>
|
||||
<span class="standingsNetHead">Net</span>
|
||||
<span class="standingsChipsHead" title="What they are holding — the cash to count out if they leave now">Chips</span>
|
||||
<span title="Those chips, less the cash they handed over">Up/down</span>
|
||||
</div>
|
||||
<div id="standingsList"></div>
|
||||
</div>
|
||||
@@ -270,6 +271,7 @@
|
||||
<span class="standingsIn"></span>
|
||||
<span class="standingsWon"></span>
|
||||
<span class="standingsNet"></span>
|
||||
<span class="standingsChips"></span>
|
||||
<span class="standingsCashOut"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1816,31 +1816,44 @@ button,
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* The per-hand columns are detail: how the night's swings happened. They're the
|
||||
first thing to go when there isn't room, because Net and Cash out are what the
|
||||
banker is actually reading. */
|
||||
/* The per-hand columns are detail: how the night's swings happened. They're the first
|
||||
to go when there isn't room, and Net goes with them — it only moves when a pot is
|
||||
resolved through the wizard, so on a table where the dealer settles pots by hand it
|
||||
reads $0 all night beside two columns that don't.
|
||||
|
||||
What survives at every width is the pair the banker actually works from: what the
|
||||
player is holding, and whether that leaves them up or down. */
|
||||
.standingsIn,
|
||||
.standingsWon,
|
||||
.standingsNet,
|
||||
.standingsInHead,
|
||||
.standingsWonHead {
|
||||
.standingsWonHead,
|
||||
.standingsNetHead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@container (min-width: 30rem) {
|
||||
.standingsRow {
|
||||
grid-template-columns: minmax(5rem, 1fr) auto auto auto auto;
|
||||
grid-template-columns: minmax(5rem, 1fr) auto auto auto auto auto;
|
||||
}
|
||||
|
||||
.standingsIn,
|
||||
.standingsWon,
|
||||
.standingsNet,
|
||||
.standingsInHead,
|
||||
.standingsWonHead {
|
||||
.standingsWonHead,
|
||||
.standingsNetHead {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* The settle-up column is the one a banker reads while counting out cash, so it
|
||||
carries the weight the per-hand columns don't. */
|
||||
/* The chips column is the one a banker's hands follow while counting money onto the
|
||||
table, so it carries the weight. Up/down is read once, at the end. */
|
||||
.standingsChips {
|
||||
font-weight: 600;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
.standingsCashOut {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@@ -818,9 +818,15 @@ const Render = {
|
||||
netEl.classList.toggle("netUp", row.net > 0);
|
||||
netEl.classList.toggle("netDown", row.net < 0);
|
||||
|
||||
// What they'd actually be handed if the night ended now: chips in front of
|
||||
// them less the cash they gave the banker. This was computed and written to
|
||||
// the CSV all along, but never shown to the person doing the paying out.
|
||||
// The cash to count out, which is a plain amount and never signed — this
|
||||
// is the one the banker's hands follow. It sat only in the CSV: on screen
|
||||
// the column headed "Cash out" held the difference against their buy-in
|
||||
// instead, so a player up $140 on a $340 stack read as "$140" at the exact
|
||||
// moment somebody was counting money onto the table.
|
||||
node.querySelector(".standingsChips").textContent = Money.format(row.chipsInFront);
|
||||
|
||||
// And whether that leaves them up or down, which is the question the rest
|
||||
// of the table asks and the one the old column was actually answering.
|
||||
const cashEl = node.querySelector(".standingsCashOut");
|
||||
cashEl.textContent = Money.formatSigned(row.cashPosition);
|
||||
cashEl.classList.toggle("netUp", row.cashPosition > 0);
|
||||
|
||||
@@ -683,6 +683,14 @@ const HoldemState = {
|
||||
net: Money.round(t.won - t.in),
|
||||
boughtIn,
|
||||
chipsNow,
|
||||
// Everything still theirs: the stack in front of them plus whatever
|
||||
// is out in the middle for the hand in progress. This is the number
|
||||
// a banker counts out when somebody leaves, and it was the one
|
||||
// figure the standings never showed — the column called "Cash out"
|
||||
// held the difference against their buy-in, so a player up $140 on
|
||||
// a $340 stack read as "$140" at the exact moment cash changed
|
||||
// hands.
|
||||
chipsInFront: Money.round(chipsNow + inFrontOfThem),
|
||||
cashPosition: Money.round(chipsNow + inFrontOfThem - boughtIn),
|
||||
notes,
|
||||
};
|
||||
|
||||
@@ -167,3 +167,58 @@ describe("does the cash box cover the chips on the table", () => {
|
||||
assert.equal(HoldemState.bankReconciliation(state).balanced, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("the number the banker counts out", () => {
|
||||
// The standings had two signed columns and neither was an amount to pay. A player
|
||||
// up $140 on a $340 stack read "$140" under a heading saying "Cash out", at the
|
||||
// exact moment somebody was counting money onto the table.
|
||||
test("chips in front is what they are holding, not what they are up", () => {
|
||||
const state = makeTable({ seatCount: 6, seated: [0, 1], stack: 340 });
|
||||
state.seats[0].name = "Ann";
|
||||
state.seats[0].buyIns = 200;
|
||||
state.seats[1].buyIns = 200;
|
||||
state.seats[1].stack = 60;
|
||||
|
||||
const rows = HoldemState.sessionStandings(state);
|
||||
const ann = rows.find(r => r.name === "Ann");
|
||||
assert.equal(ann.chipsInFront, 340, "the cash to count out");
|
||||
assert.equal(ann.cashPosition, 140, "and separately, that they are up $140");
|
||||
});
|
||||
|
||||
test("a player who is down still has chips to be handed", () => {
|
||||
const state = makeTable({ seatCount: 6, seated: [0, 1], stack: 60 });
|
||||
state.seats[0].name = "Cal";
|
||||
state.seats.forEach(p => { p.buyIns = 200; });
|
||||
|
||||
const cal = HoldemState.sessionStandings(state).find(r => r.name === "Cal");
|
||||
assert.equal(cal.chipsInFront, 60, "they leave with $60 of chips");
|
||||
assert.equal(cal.cashPosition, -140, "having lost $140 of the $200 they brought");
|
||||
});
|
||||
|
||||
test("chips still out in the middle are counted as theirs", () => {
|
||||
// Cashing out mid-hand isn't a thing, but the panel is read mid-hand constantly
|
||||
// and a stack that drops by the size of a bet looks like money going missing.
|
||||
const state = makeTable({ seatCount: 6, seated: [0, 1], stack: 200 });
|
||||
state.seats[0].name = "Dee";
|
||||
state.seats.forEach(p => { p.buyIns = 200; });
|
||||
Betting.beginHand(state);
|
||||
Betting.raiseTo(state, 0, 50);
|
||||
|
||||
const dee = HoldemState.sessionStandings(state).find(r => r.name === "Dee");
|
||||
assert.equal(dee.chipsInFront, 200, "stack plus what's in the middle for them");
|
||||
assert.equal(dee.cashPosition, 0, "so they are still level");
|
||||
});
|
||||
|
||||
test("chips and up/down always differ by exactly the buy-in", () => {
|
||||
const state = makeTable({ seatCount: 9, seated: [0, 1, 2, 3], stack: 100 });
|
||||
[340, 150, 60, 250].forEach((chips, i) => {
|
||||
state.seats[i].stack = chips;
|
||||
state.seats[i].buyIns = 200 + i * 50;
|
||||
});
|
||||
|
||||
HoldemState.sessionStandings(state).forEach(row => {
|
||||
assert.equal(Money.round(row.chipsInFront - row.boughtIn), row.cashPosition,
|
||||
`${row.name}'s two columns should tell one story`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user