// ブラインド計算(サーバ・ブラウザ共用) (function (root, factory) { if (typeof module === 'object' && module.exports) module.exports = factory(); else root.Blinds = factory(); })(typeof self !== 'undefined' ? self : this, function () { 'use strict'; // 1, 2, 3, 4, 5, 6, 10, 15, 20, 25, 30, 40, 50, 60, 75, 100, 150, ... const MANTISSAS = [1, 1.5, 2, 2.5, 3, 4, 5, 6, 7.5]; const LADDER = []; for (let e = 0; e <= 9; e++) { for (const m of MANTISSAS) { const v = Math.round(m * Math.pow(10, e) * 100) / 100; if (Number.isInteger(v)) LADDER.push(v); } } function nearestNice(x) { if (!(x >= 1)) return 1; let best = LADDER[0]; for (const v of LADDER) if (Math.abs(v - x) < Math.abs(best - x)) best = v; return best; } // 開始スタックに合うブラインド(BB = スタックの約1/100) function defaultBlinds(stack) { const sb = nearestNice(stack / 200); return { sb, bb: sb * 2 }; } // 1レベルごとに約1.5倍 function nextSmallBlind(sb) { const target = sb * 1.4; for (const v of LADDER) if (v >= target && v > sb) return v; return Math.ceil(sb * 1.5); } // level は 1 始まり function blindsAt(sb0, bb0, level) { const ratio = bb0 / sb0; let sb = sb0; let bb = bb0; for (let i = 2; i <= level; i++) { sb = nextSmallBlind(sb); bb = Math.round(sb * ratio); } return { sb, bb }; } function schedule(sb0, bb0, levels) { const out = []; for (let i = 1; i <= levels; i++) out.push(Object.assign({ level: i }, blindsAt(sb0, bb0, i))); return out; } return { defaultBlinds, blindsAt, schedule }; });