Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8efc14f61f | ||
|
|
c70cb150db | ||
|
|
e9bc9afcdb |
@@ -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;
|
||||
}
|
||||
|
||||
@@ -79,8 +79,14 @@ const ActionBar = {
|
||||
// Anything to act on? A hand with nobody dealt in doesn't get a bar — and that
|
||||
// still holds during setup, because a seated player is a live seat whether or not
|
||||
// the betting has been opened. An empty table stays uncluttered.
|
||||
//
|
||||
// A *named* table is not an empty one, though, and that was the hole: name six
|
||||
// people without dealing any of them in and the bar hid itself, leaving a screen
|
||||
// with six players on it, no way forward and nothing saying why. Anyone with a
|
||||
// name on the felt is somebody the dealer has to be told about.
|
||||
isRunning() {
|
||||
return Betting.liveSeats(this.state).length > 0;
|
||||
return Betting.liveSeats(this.state).length > 0 ||
|
||||
this.state.seats.some(p => (p.name || "").trim());
|
||||
},
|
||||
|
||||
render() {
|
||||
@@ -587,10 +593,19 @@ const ActionBar = {
|
||||
// thing: "only one player is dealt in" is wrong when four are sitting there
|
||||
// and three of them are just out of chips.
|
||||
const withChips = seated - broke.length;
|
||||
// "Nobody has chips left" is the wrong story for a table that never had
|
||||
// any. A dealer who has just named six people and not yet said what a
|
||||
// buy-in is gets told their players are busted, which sends them looking
|
||||
// for a rebuy button instead of the one field that fixes it.
|
||||
const nobodyHasEverBoughtIn = this.state.seats.every(p =>
|
||||
!(Number(p.buyIns) > 0) && !(Number(p.stack) > 0));
|
||||
|
||||
if (broke.length > 0 && withChips < 2) {
|
||||
line.textContent = withChips === 1
|
||||
? `Only ${listNames(Betting.liveSeats(this.state).map(s => s.index).filter(i => !broke.includes(i)))} has chips — ${listNames(broke)} ${broke.length === 1 ? "needs" : "need"} to buy in.`
|
||||
: "Nobody at the table has chips left. Add a buy-in to deal.";
|
||||
: nobodyHasEverBoughtIn
|
||||
? "Nobody has bought in yet. Set what everyone starts with, or give each seat their chips."
|
||||
: "Nobody at the table has chips left. Add a buy-in to deal.";
|
||||
} else {
|
||||
line.textContent = seated === 0
|
||||
? "Nobody is dealt in yet. Tap a seat to add a player."
|
||||
@@ -598,6 +613,56 @@ const ActionBar = {
|
||||
}
|
||||
line.classList.add("dealPromptBlocked");
|
||||
wrap.appendChild(line);
|
||||
|
||||
// A blocked prompt with nothing to press is a dead end, and this was the
|
||||
// one a first-time dealer hits: six players named, a sentence saying they
|
||||
// have no chips, and no button anywhere on the bar. The starting stack is a
|
||||
// single field in the sidebar and the message never pointed at it.
|
||||
if (nobodyHasEverBoughtIn && seated > 0) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "actionButtons";
|
||||
row.appendChild(this.button("Set starting stack", "actionDeal", () => {
|
||||
const field = document.getElementById("defaultStackInput");
|
||||
if (!field) return;
|
||||
const panel = field.closest("details");
|
||||
if (panel) panel.open = true;
|
||||
field.scrollIntoView({ block: "center", behavior: "smooth" });
|
||||
field.focus();
|
||||
field.select();
|
||||
}));
|
||||
wrap.appendChild(row);
|
||||
return wrap;
|
||||
}
|
||||
|
||||
// Named seats that aren't in the hand. Naming a chair now seats whoever is
|
||||
// in it, so reaching this takes something else — a table where everyone was
|
||||
// sat out, or a save from before that was true — but the way out of it
|
||||
// should still be one tap rather than a hunt through six seat editors.
|
||||
const benched = this.state.seats
|
||||
.map((player, index) => ({ player, index }))
|
||||
.filter(({ player }) => (player.name || "").trim() && !player.inHand)
|
||||
.map(({ index }) => index);
|
||||
|
||||
if (benched.length > 0) {
|
||||
const aside = document.createElement("p");
|
||||
aside.className = "dealPromptLine dealPromptAside dealPromptDebt";
|
||||
const text = document.createElement("span");
|
||||
text.textContent = benched.length === 1
|
||||
? `${listNames(benched)} is sitting out.`
|
||||
: `${listNames(benched)} are sitting out.`;
|
||||
aside.appendChild(text);
|
||||
aside.appendChild(this.button(
|
||||
benched.length === 1 ? "Deal them in" : `Deal in all ${benched.length}`,
|
||||
"dealPromptDebtBtn",
|
||||
() => this.commit("dealing everybody in", () => {
|
||||
benched.forEach(index => {
|
||||
this.state.seats[index].inHand = true;
|
||||
this.state.seats[index].folded = false;
|
||||
});
|
||||
})
|
||||
));
|
||||
wrap.appendChild(aside);
|
||||
}
|
||||
return wrap;
|
||||
}
|
||||
|
||||
|
||||
@@ -524,13 +524,41 @@ const Render = {
|
||||
this.updatePotBadge();
|
||||
this.renderSeatTotal(form, player);
|
||||
this.refreshPuck(index);
|
||||
// The editor deliberately refreshes narrowly rather than redrawing everything —
|
||||
// a full render on every keystroke would take the name field out from under the
|
||||
// dealer mid-word. But the action bar answers "is there a table here at all",
|
||||
// and seating somebody is exactly what changes that answer. Without this it
|
||||
// stayed hidden until something else happened to redraw: two players seated, a
|
||||
// dealable hand, and a blank bar until the page was reloaded.
|
||||
//
|
||||
// Safe to do on every keystroke: the bar is small, it's rebuilt on every action
|
||||
// anyway, and nothing inside it can hold focus while the sidebar has it.
|
||||
if (typeof ActionBar !== "undefined" && ActionBar.state) ActionBar.render();
|
||||
},
|
||||
|
||||
wireSeatFields(form, player, index) {
|
||||
const nameInput = form.querySelector(".seatNameInput");
|
||||
nameInput.value = player.name;
|
||||
nameInput.addEventListener("input", () => {
|
||||
// Putting a name on an empty chair is somebody sitting down, so they get
|
||||
// dealt in. It used to be two separate acts, and the second one was easy to
|
||||
// miss: a dealer setting up typed six names, got six seats that still
|
||||
// weren't in the hand, and the action bar hid itself because by its reckoning
|
||||
// nobody was playing. Six people at the table and a blank screen.
|
||||
//
|
||||
// Only for a chair that was empty — no name and not dealt in. Renaming
|
||||
// somebody who is sitting out is a correction, not an arrival, and dealing
|
||||
// them back in over a typo would be the tool overruling the dealer.
|
||||
const wasEmpty = !player.name.trim() && !player.inHand;
|
||||
player.name = nameInput.value;
|
||||
if (wasEmpty && player.name.trim()) {
|
||||
player.inHand = true;
|
||||
player.folded = false;
|
||||
const inHandBox = form.querySelector(".inHandCheckbox");
|
||||
if (inHandBox) inHandBox.checked = true;
|
||||
const foldBox = form.querySelector(".foldCheckbox");
|
||||
if (foldBox) { foldBox.checked = false; foldBox.disabled = false; }
|
||||
}
|
||||
document.getElementById("seatEditorTitle").textContent = this.puckLabel(player, index);
|
||||
this.commitSeatChange(form, player, index);
|
||||
});
|
||||
@@ -790,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`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,6 +29,10 @@ globalThis.Render = Render;
|
||||
const HoldemState = require(path.join(SRC, "state.js"));
|
||||
globalThis.HoldemState = HoldemState;
|
||||
|
||||
// actionBar.js after state, since its own module-level code reaches for neither but
|
||||
// its methods reach for both. Loaded last so nothing it touches is still undefined.
|
||||
const ActionBar = load("actionBar");
|
||||
|
||||
// ---- Table builders ----------------------------------------------------------
|
||||
|
||||
// A table with `seatCount` chairs where `seated` (a list of seat indexes) are dealt
|
||||
@@ -81,6 +85,7 @@ module.exports = {
|
||||
SettleUp,
|
||||
Betting,
|
||||
HoldemState,
|
||||
ActionBar,
|
||||
makeTable,
|
||||
chipsOnTable,
|
||||
contributions,
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
// Sitting people down, which is the first thing anybody does with the tool.
|
||||
//
|
||||
// Naming a chair and dealing that chair in were two separate acts and the second was
|
||||
// easy to miss. A dealer setting up typed six names, got six seats that still weren't
|
||||
// in the hand, and the action bar hid itself because by its reckoning nobody was
|
||||
// playing: six people at the table and a blank screen with no way forward.
|
||||
const test = require("node:test");
|
||||
const { describe } = require("node:test");
|
||||
const assert = require("node:assert");
|
||||
const { HoldemState, Betting, ActionBar, makeTable } = require("./load");
|
||||
|
||||
const emptyTable = (seatCount = 10) => {
|
||||
const state = HoldemState.createDefault();
|
||||
HoldemState.resizeSeats(state, seatCount);
|
||||
return state;
|
||||
};
|
||||
|
||||
const bar = state => Object.assign(Object.create(ActionBar), { state });
|
||||
|
||||
describe("the bar knows the difference between an empty table and a named one", () => {
|
||||
test("a table nobody has touched gets no bar", () => {
|
||||
assert.equal(bar(emptyTable()).isRunning(), false, "an empty felt stays uncluttered");
|
||||
});
|
||||
|
||||
test("a table with names on it gets one, dealt in or not", () => {
|
||||
const state = emptyTable();
|
||||
state.seats[0].name = "Ann";
|
||||
state.seats[1].name = "Ben";
|
||||
|
||||
assert.equal(Betting.liveSeats(state).length, 0, "nobody is in the hand");
|
||||
assert.equal(bar(state).isRunning(), true, "but there are people at the table to say something to");
|
||||
});
|
||||
|
||||
test("whitespace isn't a player", () => {
|
||||
const state = emptyTable();
|
||||
state.seats[0].name = " ";
|
||||
assert.equal(bar(state).isRunning(), false);
|
||||
});
|
||||
|
||||
test("a table that is playing still gets one", () => {
|
||||
assert.equal(bar(makeTable({ seatCount: 6, seated: [0, 1] })).isRunning(), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("naming an empty chair sits somebody down", () => {
|
||||
// What the seat editor's name field does, as the rule it applies rather than
|
||||
// through the DOM: a chair with no name and nobody in it is empty, and putting a
|
||||
// name on it is somebody arriving.
|
||||
const nameSeat = (player, name) => {
|
||||
const wasEmpty = !player.name.trim() && !player.inHand;
|
||||
player.name = name;
|
||||
if (wasEmpty && player.name.trim()) { player.inHand = true; player.folded = false; }
|
||||
};
|
||||
|
||||
test("an empty chair gets dealt in", () => {
|
||||
const state = emptyTable();
|
||||
nameSeat(state.seats[0], "Ann");
|
||||
assert.equal(state.seats[0].inHand, true);
|
||||
assert.equal(state.seats[0].folded, false);
|
||||
});
|
||||
|
||||
test("six names is six players, not six benched seats", () => {
|
||||
const state = emptyTable();
|
||||
state.defaultStack = 200; // a table that has told the tool what a buy-in is
|
||||
["Ann", "Ben", "Cal", "Dee", "Eve", "Fay"].forEach((name, i) => nameSeat(state.seats[i], name));
|
||||
|
||||
assert.equal(state.seats.filter(p => p.inHand).length, 6);
|
||||
assert.equal(bar(state).isRunning(), true);
|
||||
assert.ok(Betting.blindPreview(state), "and there's a hand to deal");
|
||||
});
|
||||
|
||||
test("renaming somebody who is sitting out doesn't deal them back in", () => {
|
||||
// A correction, not an arrival. Dealing them in over a typo would be the tool
|
||||
// overruling a dealer who sat them out on purpose.
|
||||
const state = emptyTable();
|
||||
state.seats[0].name = "Ann";
|
||||
state.seats[0].inHand = false;
|
||||
|
||||
nameSeat(state.seats[0], "Anne");
|
||||
assert.equal(state.seats[0].inHand, false, "still sitting out, now spelled right");
|
||||
});
|
||||
|
||||
test("clearing a name doesn't sit anybody down", () => {
|
||||
const state = emptyTable();
|
||||
nameSeat(state.seats[0], "Ann");
|
||||
nameSeat(state.seats[0], "");
|
||||
assert.equal(state.seats[0].name, "");
|
||||
});
|
||||
|
||||
test("a chair already in the hand is left alone", () => {
|
||||
const state = makeTable({ seatCount: 6, seated: [0] });
|
||||
state.seats[0].folded = true;
|
||||
nameSeat(state.seats[0], "Ann");
|
||||
assert.equal(state.seats[0].folded, true, "mid-hand a fold is not undone by typing");
|
||||
});
|
||||
});
|
||||
|
||||
describe("the way back from a table where everybody is sat out", () => {
|
||||
test("there are named seats to offer", () => {
|
||||
// Can't be reached by naming any more, but a table where everyone was sat out
|
||||
// — or a save from before naming seated people — still lands here.
|
||||
const state = emptyTable();
|
||||
["Ann", "Ben", "Cal"].forEach((name, i) => { state.seats[i].name = name; });
|
||||
|
||||
const benched = state.seats
|
||||
.map((player, index) => ({ player, index }))
|
||||
.filter(({ player }) => (player.name || "").trim() && !player.inHand)
|
||||
.map(({ index }) => index);
|
||||
|
||||
assert.deepEqual(benched, [0, 1, 2]);
|
||||
assert.equal(Betting.blindPreview(state), null, "no hand to deal until they're in");
|
||||
});
|
||||
|
||||
test("dealing them all in makes a hand possible", () => {
|
||||
const state = emptyTable();
|
||||
["Ann", "Ben", "Cal"].forEach((name, i) => { state.seats[i].name = name; state.seats[i].stack = 100; });
|
||||
|
||||
state.seats.forEach(player => {
|
||||
if ((player.name || "").trim()) { player.inHand = true; player.folded = false; }
|
||||
});
|
||||
|
||||
assert.equal(Betting.liveSeats(state).length, 3);
|
||||
assert.ok(Betting.blindPreview(state), "the table can be dealt");
|
||||
});
|
||||
|
||||
test("an unnamed chair is never swept in by it", () => {
|
||||
const state = emptyTable();
|
||||
state.seats[0].name = "Ann";
|
||||
state.seats.forEach(player => {
|
||||
if ((player.name || "").trim()) { player.inHand = true; }
|
||||
});
|
||||
assert.equal(state.seats.filter(p => p.inHand).length, 1, "empty chairs stay empty");
|
||||
});
|
||||
});
|
||||
|
||||
describe("a table where nobody has bought in", () => {
|
||||
// Different from a table that has busted out, and the difference is the whole
|
||||
// point: one needs a starting stack named, the other needs a rebuy. Telling a
|
||||
// dealer their brand-new players have "no chips left" sends them hunting for the
|
||||
// wrong thing.
|
||||
const neverBoughtIn = state => state.seats.every(p =>
|
||||
!(Number(p.buyIns) > 0) && !(Number(p.stack) > 0));
|
||||
|
||||
test("six freshly named players have never bought in", () => {
|
||||
const state = emptyTable();
|
||||
["Ann", "Ben", "Cal", "Dee", "Eve", "Fay"].forEach((name, i) => {
|
||||
state.seats[i].name = name;
|
||||
state.seats[i].inHand = true;
|
||||
});
|
||||
|
||||
assert.equal(neverBoughtIn(state), true);
|
||||
assert.equal(Betting.blindPreview(state), null, "and there is no hand to deal");
|
||||
});
|
||||
|
||||
test("a table that has busted out is not the same thing", () => {
|
||||
const state = makeTable({ seatCount: 6, seated: [0, 1], stack: 200 });
|
||||
state.seats.forEach(p => { p.buyIns = 200; p.stack = 0; });
|
||||
|
||||
assert.equal(neverBoughtIn(state), false, "they had chips — they lost them");
|
||||
});
|
||||
|
||||
test("one player still holding chips is not a never-bought-in table either", () => {
|
||||
const state = emptyTable();
|
||||
["Ann", "Ben"].forEach((name, i) => { state.seats[i].name = name; state.seats[i].inHand = true; });
|
||||
state.seats[0].stack = 50;
|
||||
|
||||
assert.equal(neverBoughtIn(state), false);
|
||||
});
|
||||
|
||||
test("naming a starting stack is enough to deal", () => {
|
||||
// The one field the message now points at. A seat with no stack of its own
|
||||
// falls back to the table default, so setting it seats everybody's chips at
|
||||
// once — which is why it's the right thing to send the dealer to.
|
||||
const state = emptyTable();
|
||||
["Ann", "Ben", "Cal"].forEach((name, i) => { state.seats[i].name = name; state.seats[i].inHand = true; });
|
||||
assert.equal(Betting.blindPreview(state), null);
|
||||
|
||||
state.defaultStack = 200;
|
||||
assert.ok(Betting.blindPreview(state), "one number and the table can play");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user