A seat's number was a grey digit in the top-left corner of the puck, and the top-left corner is also where the blind badge drops off the rim and where a long centred name reaches. Measured across 348 seats on 36 tables: 117 of them had it printed under something else. All 66 seats posting a blind had it covered outright — a 22px badge at z-index 4 over a 6px digit — and 51 more had it sitting on the first letter of the player's own name, the whole glyph in the worst case, on a 54px puck. There is nowhere on the felt to move it to. The button's chip has the other end of the top rim. Bets land on the rim between a seat and the pot, which is the bottom edge for the seats above centre and the top edge for the ones below. The middle of the puck is name, bet and stack, and all three are about this hand. The chair number is the only mark on a puck that isn't, so it is the one that gave way. Nothing is lost that a tap doesn't return. The seat editor's heading reads "Mike from work · Seat 2" now and the seat menu's first line leads with the chair; a seat nobody has named still calls itself "Seat 5"; and an open chair still wears its number large and centred, which is the one moment the number is the thing being looked for rather than a footnote on somebody else's name. The sweep had never mentioned any of this. The check that asks whether a puck covers itself up knew about two of the three things a puck wears, and only ever held them against writing — so the mark sitting on the names was invisible to it, and so was a badge painted straight over another mark. Both gaps are closed: put the number back and it reports five offenders on a Galaxy S8 ten-handed, naming Christopher, Alexandra, Jonah and the SB. 1148 tests, 418 audits clean.
130 lines
6.3 KiB
JavaScript
130 lines
6.3 KiB
JavaScript
// The one mark on a puck that isn't about this hand.
|
|
//
|
|
// A seat's chair number was a grey digit in the top-left corner, and the top-left corner
|
|
// is where the blind badge drops off the rim and where a long centred name reaches.
|
|
// Measured across 348 seats on 36 tables: 117 of them had the number printed under
|
|
// something else. All 66 seats posting a blind had it covered outright — the badge is
|
|
// 22px wide over a 6px digit, at z-index 4 — and 51 more had it sitting on the first
|
|
// letter of the player's own name, the whole glyph in the worst case, on a 54px puck.
|
|
//
|
|
// There is nowhere on the felt to move it to. The button's chip owns the right-hand end
|
|
// of the top rim. Bets land on the rim between a seat and the pot, which is the bottom
|
|
// edge for the seats above centre and the top edge for the ones below. The middle of the
|
|
// puck is three rows — name, bet, stack — and all three are about this hand. So the mark
|
|
// that isn't gave way, and the two sheets that are about one seat say which seat.
|
|
//
|
|
// The sweep had never mentioned any of it, because the check that asks whether a puck
|
|
// covers itself up only knew about two of the three things a puck wears, and only ever
|
|
// tested them against writing.
|
|
const test = require("node:test");
|
|
const { describe } = require("node:test");
|
|
const assert = require("node:assert");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { HoldemState, makeTable } = require("./load");
|
|
|
|
const ROOT = path.join(__dirname, "..", "..", "JoshHeaps.Net");
|
|
const CSS = fs.readFileSync(path.join(ROOT, "wwwroot", "css", "casino", "holdem.css"), "utf8");
|
|
const AUDIT = fs.readFileSync(path.join(__dirname, "uiAudit.js"), "utf8");
|
|
const src = name => fs.readFileSync(
|
|
path.join(ROOT, "wwwroot", "js", "casino", "holdem", `${name}.js`), "utf8");
|
|
|
|
const ruleFor = selector => {
|
|
const at = CSS.indexOf(`\n${selector} {`);
|
|
assert.ok(at >= 0, `there is no \`${selector}\` rule`);
|
|
return CSS.slice(at, CSS.indexOf("}", at));
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe("a chair with somebody in it", () => {
|
|
test("does not draw its number on the felt at all", () => {
|
|
assert.match(ruleFor(".seat:not(.seatEmpty) .seatChairNumber"), /display:\s*none/);
|
|
});
|
|
|
|
// Where the number is the thing being looked for rather than a footnote on somebody
|
|
// else's name — which chair is open — it is still large and centred and washed.
|
|
test("and an open one still wears its number, large and in the middle", () => {
|
|
const rule = ruleFor(".seatEmpty .seatChairNumber");
|
|
assert.match(rule, /top:\s*50%/);
|
|
assert.match(rule, /left:\s*50%/);
|
|
assert.match(rule, /background:/);
|
|
});
|
|
|
|
// Removing it from the felt is only defensible because the felt is not the only
|
|
// place it appears. A seat nobody has named says "Seat 5" as its name already.
|
|
test("a seat with no name typed in still says which seat it is", () => {
|
|
const state = makeTable({ seatCount: 6 });
|
|
state.seats[4].name = "";
|
|
assert.equal(HoldemState.displayName(state.seats[4], 4), "Seat 5");
|
|
});
|
|
});
|
|
|
|
describe("the two sheets that are about one seat", () => {
|
|
test("name the chair as well as the player", () => {
|
|
assert.equal(HoldemState.seatHeading({ name: "Alexandra" }, 2), "Alexandra · Seat 3");
|
|
});
|
|
|
|
test("and don't say it twice when the name is already the number", () => {
|
|
assert.equal(HoldemState.seatHeading({ name: "" }, 4), "Seat 5");
|
|
assert.equal(HoldemState.seatHeading({ name: " " }, 4), "Seat 5");
|
|
assert.equal(HoldemState.seatHeading({}, 0), "Seat 1");
|
|
assert.equal(HoldemState.seatHeading(null, 0), "Seat 1");
|
|
});
|
|
|
|
test("a typed name keeps its own spacing off the ends", () => {
|
|
assert.equal(HoldemState.seatHeading({ name: " Mike from work " }, 1), "Mike from work · Seat 2");
|
|
});
|
|
|
|
test("the seat editor's heading is the one that says it", () => {
|
|
const render = src("render");
|
|
const at = render.indexOf("renderSeatEditor() {");
|
|
assert.ok(at >= 0);
|
|
const body = render.slice(at, render.indexOf("\n },", at));
|
|
assert.match(body, /title\.textContent = HoldemState\.seatHeading\(player, index\)/);
|
|
});
|
|
|
|
// Not the heading here: this header is stuck to the top of the sheet that scrolls,
|
|
// and a name long enough to wrap would cost every action below it a line.
|
|
test("the seat menu says it on its first line instead, and says it first", () => {
|
|
const menu = src("seatMenu");
|
|
const at = menu.indexOf("const stack = Betting.stackOf(this.state, player);");
|
|
assert.ok(at >= 0);
|
|
const body = menu.slice(at, menu.indexOf("subtitle.textContent", at));
|
|
assert.match(body, /const bits = \[`Seat \$\{this\.seatIndex \+ 1\}`\]/);
|
|
});
|
|
});
|
|
|
|
describe("the sweep can see it now", () => {
|
|
const check = () => {
|
|
const at = AUDIT.indexOf(" seatLabelsClear() {");
|
|
assert.ok(at >= 0, "the check that asks whether a puck covers itself up is gone");
|
|
return AUDIT.slice(at, AUDIT.indexOf("\n },", at));
|
|
};
|
|
|
|
// The mark that was sitting on names was neither of the two this check knew about.
|
|
test("the chair number counts as something a puck wears", () => {
|
|
assert.match(check(), /const MARKS = "\.dealerChip, \.blindBadge, \.seatChairNumber"/);
|
|
});
|
|
|
|
// And a badge painted over the number is a puck covering itself up, which is the
|
|
// whole subject of this check, and was invisible to it.
|
|
test("and the marks are held against each other, not only against the writing", () => {
|
|
const body = check();
|
|
assert.match(body, /marks\.forEach\(\(a, i\) => marks\.slice\(i \+ 1\)/);
|
|
assert.match(body, /px across/);
|
|
});
|
|
|
|
test("a mark that isn't drawn isn't an offender", () => {
|
|
const body = check();
|
|
assert.match(body, /style\.display === "none"/);
|
|
assert.match(body, /parseFloat\(style\.opacity\) < 0\.05/);
|
|
// An empty badge slot has a box and no text; three of them sit on every puck.
|
|
assert.match(body, /if \(!\(mark\.textContent \|\| ""\)\.trim\(\)\) return null;/);
|
|
});
|
|
|
|
test("and the check says what it now covers", () => {
|
|
assert.match(AUDIT, /name: "nothing a seat wears covers its name or another mark"/);
|
|
});
|
|
});
|