@haihire/baccarat-score-board-road
v1.0.0
Published
Baccarat scoreboard roadmap generator — Big Road plus the three Chinese-style derived roads (Big Eye, Small, Cockroach), with next-hand prediction. Zero dependencies, fully typed.
Maintainers
Readme
@haihire/baccarat-score-board-road
A baccarat scoreboard roadmap generator. Feed it a shoe's result log and it builds the Big Road plus the three Chinese-style derived roads (Big Eye, Small, Cockroach), with optional next-hand prediction.
import { ScoreBoard } from "@haihire/baccarat-score-board-road";
const board = new ScoreBoard(log);
const { bigRoad, bigEyeRoad, smallRoad, cockroachRoad } = board.getAllRoads();
const next = board.predict(); // { player: {...}, banker: {...} }Why this package
- Fully typed — proper unions and interfaces (
Winner,Mark,BigRoadCell, …), notany. Real autocomplete and compile-time checks. - ESM + CommonJS — dual build with an
exportsmap, so it works in modern bundlers (tree-shakable) and legacy Node alike. - Zero runtime dependencies — nothing pulled into your bundle.
- One-line API — the
ScoreBoardfacade hides the Big-Road→derived-road wiring. No manualgubun/.old/col * 2bookkeeping (the low-level classes are still exported if you want them). - Built-in prediction — "ask the road" (問路) for both a hypothetical Player and Banker next hand.
- MIT licensed — free for commercial use.
- Battle-tested — the road algorithm runs in a live baccarat product, and the test suite verifies it against real production shoes (including the lossless-placement invariant: every Player/Banker/Tie result is preserved).
Install
npm install @haihire/baccarat-score-board-roadUsage (recommended: ScoreBoard)
import { ScoreBoard, RoundInput } from "@haihire/baccarat-score-board-road";
const log: RoundInput[] = [
{ sWinner: "Player", sPair: "", sPlayer_Score: 8, sBanker_Score: 5 },
{ sWinner: "Banker", sPair: "Banker_Pair", sPlayer_Score: 4, sBanker_Score: 7 },
// ...one entry per round of the shoe
];
const board = new ScoreBoard(log, {
col: 13, // Big Road width (derived roads use col * 2). Default 13
cut: true, // drop the oldest columns past `col`. Default true
color: false, // Tie starts a new column (score-color mode). Default false
trimLeadingTie: true, // drop leading ties. Default true
});
// Everything in one pass (Big Road is computed only once):
const { bigRoad, bigEyeRoad, smallRoad, cockroachRoad } = board.getAllRoads();
// Or individually:
const big = board.getBigRoad(); // { old, new, gubunIndex, over }
const bigEye = board.getBigEyeRoad(); // MarkCell[][]
// Render the Big Road:
for (let col = 0; col < bigRoad.new.length; col++) {
for (let row = 0; row < bigRoad.new[col].length; row++) {
const cell = bigRoad.new[col][row];
if (cell.Win) draw(cell.Win, cell.Pair, cell.WinScore, cell.TieCount);
}
}Prediction (next hand)
const next = board.predict();
// {
// player: { bigEye: "Player"|"Banker"|"", small: ..., cockroach: ... },
// banker: { bigEye: ..., small: ..., cockroach: ... },
// }predict() reproduces the "ask the road" technique: it appends a hypothetical
next round (once as a Player win, once as a Banker win), rebuilds the Big Road,
and reports the mark each derived road would draw.
Input format
Each element of the log is one round. Only sWinner, sPair, and the two
scores are read — extra fields (raw card data, etc.) are ignored, so DB records
can be passed straight in.
interface RoundInput {
sWinner: "Player" | "Banker" | "Tie"; // required
sPair?: "" | "Player_Pair" | "Banker_Pair" | "Player_Pair,Banker_Pair";
sPlayer_Score?: number | string; // used in color mode
sBanker_Score?: number | string;
}Output types
Big Road → BigRoadResult
interface BigRoadResult {
old: BigRoadCell[][]; // untrimmed 6×200 source grid (input for derived roads)
new: BigRoadCell[][]; // trimmed/padded render grid
gubunIndex: ColumnBreak[]; // column breaks ("dragon tail")
over: boolean; // whether any column was cut off
}
interface BigRoadCell {
TieCount: number;
Win: "Player" | "Banker" | "Tie" | "";
Pair?: 0 | 1 | 2 | 3; // 0 none, 1 player, 2 banker, 3 both
WinScore?: number;
}Derived roads → MarkCell[][]
interface MarkCell {
Mark: "Player" | "Banker" | ""; // Player = blue, Banker = red, "" = empty
}For the Chinese-style roads only the color is meaningful; it does not map directly to an actual P/B win.
Low-level API
If you need direct control, the road classes are exported. Note the wiring the facade normally handles for you:
import { BigRoad, BigEyeRoad, SmallRoad, CockroachRoad } from "@haihire/baccarat-score-board-road";
const Row = 6;
const g1 = new BigRoad({ array: log, row: Row, col: 13, cut: true, color: false }).getBigRoad();
const g2 = new BigEyeRoad({
gubun: g1.gubunIndex, // ★ the gubunIndex, under the key 'gubun'
row: Row,
col: 13 * 2, // ★ derived roads use col * 2
cut: true,
}).getBigEyeRoad(g1.old); // ★ pass g1.old (untrimmed), NOT g1.new
const g3 = new SmallRoad({ gubun: g1.gubunIndex, row: Row, col: 13 * 2, cut: true }).getSmallRoad(g1.old);
const g4 = new CockroachRoad({ gubun: g1.gubunIndex, row: Row, col: 13 * 2, cut: true }).getCockroachRoad(g1.old);Gotchas the facade removes for you:
- Derived roads consume
g1.old(untrimmed), notg1.new. - The constructor key is
gubun(its value isg1.gubunIndex). - Derived-road
colis conventionallycol * 2. colorchanges how the Big Road handles a Tie (new column vs. count).
For lower-level prediction, the derived roads accept (bigRoad, inGame, who) and
record the last mark on the exported Expects object.
Build / publish (maintainers)
npm install # install devDependencies (typescript, rimraf)
npm run build # src → dist/cjs (CommonJS) + dist/esm (ESM) + dist/types (.d.ts)
npm run typecheck # type-check only, no emit
npm publish # prepublishOnly runs build; publishes with --access publicBuild layout:
dist/cjs/— CommonJS (require), tagged viadist/cjs/package.jsondist/esm/— ES modules (import), tagged viadist/esm/package.jsondist/types/— shared TypeScript declarations
Tests
npm test # run the Vitest suite once
npm run test:watchCoverage includes placement rules, the ScoreBoard facade, and real shoes
exported from production (test/fixtures/shoes.json): a lossless-placement
invariant, a valid-mark invariant, and a regression snapshot.
License
MIT © haihire
