UNPKG

poker-helper

Version:
977 lines (881 loc) 32.5 kB
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.isBusy = exports.isActive = undefined;var _defineProperty2 = require('babel-runtime/helpers/defineProperty');var _defineProperty3 = _interopRequireDefault(_defineProperty2);var _extends3 = require('babel-runtime/helpers/extends');var _extends4 = _interopRequireDefault(_extends3);var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);var _createClass2 = require('babel-runtime/helpers/createClass');var _createClass3 = _interopRequireDefault(_createClass2);var _assign = require('babel-runtime/core-js/object/assign');var _assign2 = _interopRequireDefault(_assign);var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2); var _abPokersolver = require('ab-pokersolver');var _abPokersolver2 = _interopRequireDefault(_abPokersolver); var _receiptCache = require('./receiptCache');var _receiptCache2 = _interopRequireDefault(_receiptCache); var _receipt = require('./receipt');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} var EMPTY = '0x0000000000000000000000000000000000000000'; /* eslint-disable class-methods-use-this */ var VALUES = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A']; var SUITS = ['c', 'd', 'h', 's']; var getPlayers = function getPlayers(helper, state, rawLineup) {var withSitouts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var lineup = withSitouts ? rawLineup : rawLineup.map(function (_ref) {var sitout = _ref.sitout,seat = (0, _objectWithoutProperties3.default)(_ref, ['sitout']);return seat;}); var players = lineup.reduce(function (list, seat, pos) { if (seat.last) { var last = helper.rc.get(seat.last); var active = state === 'showdown' && last.type === _receipt.Type.SHOW || state !== 'showdown' && (helper.isActivePlayer(lineup, pos) || seat.sitout === 'allin'); return [].concat((0, _toConsumableArray3.default)(list), [{ pos: pos, active: active, amount: last.amount.toNumber() }]); } return list; }, []); var activePlayers = players.filter(function (p) {return p.active;}); if (activePlayers.length === 0 && withSitouts) { return getPlayers(helper, state, rawLineup, false); } return players; }; /** * findLatest find a receipt type used latest in an activeLineup * * @param lineup of type activeLineup * @returns {{ pos: number, last: receipt }} */ var findLatest = function findLatest(activeLineup) {var minType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;var rc = arguments[2]; if (!activeLineup.sorted) { throw new Error('active lineup expected.'); } var lineup = activeLineup.lineup; var latest = {}; for (var i = 0; i < lineup.length; i += 1) { var lastRec = lineup[i].last ? rc.get(lineup[i].last) : null; if (lastRec && lastRec.type >= minType && lastRec.type <= _receipt.Type.CHECK_RIVER) { minType = lastRec.type; // eslint-disable-line no-param-reassign latest = (0, _assign2.default)({}, { pos: i, oldPos: lineup[i].pos, last: lineup[i].last }); } } return latest; }; /** * isActive check if a seat in active * * @param lineup * @param state * @param receiptCache * @returns bool */ var isActive = exports.isActive = function isActive(seat, state, rc) { if (typeof seat === 'undefined' || seat === null) { throw new Error('seat undefined'); } // if we are at showdown and player is all in he is active if (seat.sitout === 'allin' && state === 'showdown') { return true; } // check seat state if (seat.sitout || !seat.address || seat.address === EMPTY) { return false; } // get last receipt var receipt = seat.last && rc.get(seat.last); if (!receipt || !receipt.type || !receipt.amount) { if (state === 'waiting' || state === 'dealing') {// in waiting or dealing a player might not have a receipt yet return true; } throw new Error('receipt undefined'); } else { // check receipt type for receipts we don't want return !( receipt.type === _receipt.Type.FOLD || receipt.type === _receipt.Type.SHOW || receipt.type === _receipt.Type.SIT_OUT && state !== 'waiting' && state !== 'dealing'); } }; /** * isBusy check if a seat is busy * * @param lineup * @param state * @param receiptCache * @returns bool */ var isBusy = exports.isBusy = function isBusy(seat) { if (typeof seat === 'undefined' || seat === null) { throw new Error('seat undefined'); } // check seat state if (!seat.address || seat.address === EMPTY) { return false; } return true; }; /** * nextActive returns next active players * * @param lineup * @param palyerPos as index in lineup * @param state * @param receiptCache * @returns index in lineup */ var nextActive = function nextActive(lineup, playerPos, state, rc) { var newPos = playerPos % lineup.length; for (var i = newPos; i < lineup.length + newPos; i += 1) { var pos = i % lineup.length; if (isActive(lineup[pos], state, rc)) { return pos; } } throw new Error('no active player in lineup'); }; /** * wasInvolved * * @param * @returns */ var wasInvolved = function wasInvolved(seat, state) { if (!seat) { throw new Error('invalid lineup'); } if (!seat.address) { throw new Error('invalid seat'); } // check seat state if (seat.address === EMPTY || seat.sitout && seat.sitout !== 'allin') { return false; } if (state === 'waiting' || state === 'dealing' || seat.last) { return true; } return false; }; var lineupFilters = { active: isActive, busy: isBusy, involved: wasInvolved }; /** * countPlayers counts the players in lineup * * @param lineup * @param type * @returns number of active players */ var countPlayers = function countPlayers(lineup, type, state, rc) {return ( lineup. filter(function (seat) {return lineupFilters[type](seat, state, rc);}). length);}; /** * findNextPlayer * * @param * @returns */ var findNextPlayer = function findNextPlayer(lineup, startPos, type, state, rc) { var shiftPos = function shiftPos(pos) {return (startPos + pos) % lineup.length;}; var filter = lineupFilters[type]; if (!filter || lineup.length < 2) { throw new Error('wrong state.'); } return shiftPos( lineup. findIndex(function (seat, pos) {return filter( lineup[shiftPos(pos)], state, rc);})); }; /** * findBbPos * * @param * @returns */ var findBbPos = function findBbPos(lineup, dealer, state, type, rc) { if (dealer === undefined || !lineup) { throw new Error('invalid params.'); } if (dealer < 0 || dealer >= lineup.length || lineup.length < 2) { throw new Error('invalid more params.'); } var lineupType = type === 'tournament' ? 'busy' : 'involved'; var next = findNextPlayer(lineup, dealer + 1, lineupType, state, rc); if (next === dealer) { throw new Error('only one player found.'); } var activePlayerCount = countPlayers(lineup, lineupType, state, rc); if (activePlayerCount === 2) { return next; } var nextNext = findNextPlayer(lineup, next + 1, lineupType, state, rc); if (nextNext === next) { throw new Error('only one player found.'); } return nextNext; }; /** * activeLineup returns normalized lineup with active players * * @param lineup * @param dealer position as index to lineup * @param state * @returns activeLineup array */ var activeLineup = function activeLineup(lineup, dealer, state, rc) { var activePlayers = []; try { var startPos = void 0; if (state === 'preflop') { // BB is last to act try { var bbPos = findBbPos(lineup, dealer, state, rc); startPos = nextActive(lineup, bbPos + 1, state, rc); } catch (err) { // not able to find bb in lineup, not enough players? } } if (state !== 'preflop' || typeof startPos === 'undefined') { // BU is last to act startPos = nextActive(lineup, dealer + 1, state, rc); } for (var i = startPos; i < lineup.length + startPos; i += 1) { var pos = i % lineup.length; if (isActive(lineup[pos], state, rc)) { var player = (0, _assign2.default)({}, lineup[pos], { pos: pos }); activePlayers.push(player); } } } catch (err) { if (err.message === 'no active player in lineup') { return []; } throw err; } return activePlayers; }; /** * evenLineup * * @param * @returns */ var evenLineup = function evenLineup(lineup, rc) { var prev = void 0; for (var i = 0; i < lineup.length; i += 1) { var amount = lineup[i].last ? rc.get(lineup[i].last).amount.toNumber() : 0; if (prev !== undefined && prev !== amount) { return false; } prev = amount; } return true; }; /** * countNoReceipts counts the players in lineup without receipt * * @param lineup * @param type * @returns number of active players */ var countNoReceipts = function countNoReceipts(lineup, rc) {return ( lineup.filter(function (seat) {return isActive(seat, 'waiting', rc) && !seat.last;}).length);}; /** * checks if a certain type of receipt exists * * @param lineup * @param rc * @returns bool */ var checkForReceipt = function checkForReceipt(lineup, type, rc) {return lineup.some(function (seat) { var receipt = seat.last ? rc.get(seat.last) : null; return receipt && receipt.type === type; });}; /** * countReceipt counts receipts of type in lineup * * @param lineup * @param type - as lower case * @param rc * @returns bool */ var countReceipts = function countReceipts(lineup, type, rc) { if (!lineup) { throw new Error('invalid lineup'); } return lineup.filter(function (seat) {return seat.last && rc.get(seat.last).type === type;}).length; }; /** * maxAllIn gets the amount betted by the latest all-in * * @param lineup * @returns amount of last all-in */ var maxAllIn = function maxAllIn(lineup, rc) {return lineup.reduce(function (maxBet, seat) { if (seat.sitout && seat.sitout === 'allin') { var amount = seat.last ? rc.get(seat.last).amount.toNumber() : 0; if (amount > maxBet) { return amount; } } return maxBet; }, 0);};var PokerHelper = function () { function PokerHelper(receiptCache) {(0, _classCallCheck3.default)(this, PokerHelper); this.rc = receiptCache || new _receiptCache2.default(); } // ########## SEAT STATE HELPERS ########## /** * isActivePlayer * * @param * @returns */(0, _createClass3.default)(PokerHelper, [{ key: 'isActivePlayer', value: function isActivePlayer( lineup, pos, state) { if (typeof pos === 'undefined' || !lineup) { throw new Error('lineup undefined'); } if (pos < 0 || pos >= lineup.length || lineup.length < 2) { throw new Error('bad param pos: ' + pos); } // TODO: pass correct hand state return isActive(lineup[pos], state, this.rc); } /** * inLineup * * @param * @returns */ }, { key: 'inLineup', value: function inLineup( signer, lineup) { return lineup.findIndex(function (seat) {return seat.address === signer;}); } /** * getMyMaxBet * * @param * @returns */ }, { key: 'getMyMaxBet', value: function getMyMaxBet( lineup, address) { if (!lineup || !address) { throw new Error('invalid params.'); } var myPos = this.getMyPos(lineup, address); if (myPos < 0) { throw new Error('address ' + address + ' not in lineup.'); } var receipt = lineup[myPos].last ? this.rc.get(lineup[myPos].last) : undefined; return receipt ? receipt.amount.toNumber() : 0; } /** * getMyPos * * @param * @returns */ }, { key: 'getMyPos', value: function getMyPos( lineup, address) { for (var i = 0; i < lineup.length; i += 1) { if (lineup[i].address === address) { return i; } } throw new Error('pos of ' + address + ' not found.'); } // ########## LINEUP STATE HELPERS ########## /** * findMinRaiseAmount * * @param * @returns */ }, { key: 'findMinRaiseAmount', value: function findMinRaiseAmount( lineup, dealer, lastRoundMaxBet, state) { if (!lineup || dealer === undefined) { throw new Error('invalid params.'); } var lastRoundMaxBetInt = parseInt(lastRoundMaxBet, 10); // TODO: pass correct state var max = this.getMaxBet(lineup, state); if (max.amount === lastRoundMaxBetInt) { throw new Error('can not find minRaiseAmount.'); } // finding second highest bet var secondMax = lastRoundMaxBetInt; for (var i = max.pos + 1; i < lineup.length + max.pos; i += 1) { var pos = i % lineup.length; var last = lineup[pos].last ? this.rc.get(lineup[pos].last).amount.toNumber() : 0; if (last > secondMax && last < max.amount) { secondMax = last; } } return max.amount - secondMax; } /** * getMaxBet * * @param * @returns */ }, { key: 'getMaxBet', value: function getMaxBet( lineup, state) {var _this = this; var startPos = state === 'preflop' && lineup.length > 2 ? 2 : 0; var seats = [].concat((0, _toConsumableArray3.default)( lineup.slice(startPos, lineup.length)), (0, _toConsumableArray3.default)( lineup.slice(0, startPos))); var result = seats.reduce(function (memo, seat, i) { if (!seat.last) { return memo; } var last = _this.rc.get(seat.last); var amount = last.type !== _receipt.Type.SIT_OUT ? last.amount.toNumber() : 0; // if we are in dealing the last 0 bet is the max bet if (amount >= memo.amount || amount === 0 && state === 'dealing') { return { amount: amount, pos: (i + startPos) % lineup.length }; } return memo; }, { pos: -1, amount: 0 }); if (result.pos === -1) { throw new Error('could not find max bet.'); } return result; } /** * calculatePotsize * * @param * @returns */ }, { key: 'calculatePotsize', value: function calculatePotsize( lineup) {var _this2 = this; return lineup.reduce(function (potSize, seat) { var receipt = seat.last ? _this2.rc.get(seat.last) : undefined; return potSize + (receipt ? receipt.amount.toNumber() : 0); }, 0); } /** * isTurn * * @param * @returns */ }, { key: 'isTurn', value: function isTurn( lineup, dealer, state, bbAmount, addr) { var pos = this.getMyPos(lineup, addr); return this.getWhosTurn(lineup, dealer, state, bbAmount) === pos; } /** * getWhosTurn * * @param * @returns */ }, { key: 'getWhosTurn', value: function getWhosTurn( lineup, dealer, state, bbAmount) { if (this.isHandComplete(lineup, dealer, state)) { throw new Error('no ones turn if hand complete.'); } var activePlayers = activeLineup(lineup, dealer, state, this.rc); var maxBet = void 0; if (state !== 'waiting') { maxBet = this.getMaxBet(activePlayers, state); if (!evenLineup(activePlayers, this.rc)) { // if betting amounts are not even return next player of to the maxBettor var next = activePlayers[(maxBet.pos + 1) % activePlayers.length]; var last = this.rc.get(next.last); if (last && last.amount.toNumber() === maxBet.amount) { next.pos = nextActive(lineup, next.pos + 1, state, this.rc); } return next.pos; } } var stateChecksMap = { preflop: _receipt.Type.CHECK_PRE, flop: _receipt.Type.CHECK_FLOP, turn: _receipt.Type.CHECK_TURN, river: _receipt.Type.CHECK_RIVER }; var checkType = stateChecksMap[state] || 0; var checker = findLatest({ sorted: true, lineup: activePlayers }, checkType, this.rc); if (checker.last) { return activePlayers[(checker.pos + 1) % activePlayers.length].pos; } if (state === 'preflop') { if (!bbAmount) throw new Error('BB amount cannot be undefined'); if (!maxBet) { maxBet = this.getMaxBet(activePlayers, state); } var maxAllInAmount = maxAllIn(lineup, this.rc); var maxAmount = maxAllInAmount > maxBet.amount ? maxAllInAmount : maxBet.amount; if (maxAmount === parseInt(bbAmount, 10)) { return this.getBbPos(lineup, dealer, state); } } if (activePlayers.length === 2 && state === 'waiting') { return activePlayers[1].pos; } return activePlayers[0].pos; } /** * nextPlayer * * @param * @returns */ }, { key: 'nextPlayer', value: function nextPlayer( lineup, startPos, type, state) { return findNextPlayer(lineup, startPos, type, state, this.rc); } /** * getSbPos * * @param * @returns */ }, { key: 'getSbPos', value: function getSbPos( lineup, dealer, state) {var type = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'cashgame'; var lineupType = type === 'tournament' ? 'busy' : 'involved'; if (typeof dealer === 'undefined' || !lineup) { throw new Error('dealer or lineup undefined'); } if (dealer < 0 || dealer >= lineup.length || lineup.length < 2) { throw new Error('lineup not valid.'); } var next = this.nextPlayer(lineup, dealer + 1, lineupType, state); var activePlayerCount = countPlayers(lineup, lineupType, state, this.rc); if (activePlayerCount < 2) { throw new Error('can not find SB if involved player count < 2'); } if (activePlayerCount === 2) { return dealer; } return next; } /** * getBbPos * * @param * @returns */ }, { key: 'getBbPos', value: function getBbPos( lineup, dealer, state) {var type = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'cashgame'; return findBbPos(lineup, dealer, state, type, this.rc); } // ########### COUNTS ############### /** * countActivePlayers counts the active players in lineup * used in oracle * * @param lineup * @returns number of active players */ }, { key: 'countActivePlayers', value: function countActivePlayers( lineup, state) {var _this3 = this; return lineup.filter(function (_, pos) {return _this3.isActivePlayer(lineup, pos, state);}).length; } /** * countAllIn counts the number of players that are allin * for countAllIns * * @param lineup * @returns number of all-in players */ }, { key: 'countAllIn', value: function countAllIn( lineup) { if (!lineup) { throw new Error('invalid lineup'); } return lineup.filter(function (seat) {return seat.sitout && seat.sitout === 'allin';}).length; } // ########### HAND STATE RELATED ############ /** * isBettingDone checks if a round of betting has completed. * * @param lineup * @param dealer * @param state * @param max * @param bbAmount * @returns boolean */ }, { key: 'isBettingDone', value: function isBettingDone( lineup, dealer, state, bbAmount) { if (this.isHandComplete(lineup, dealer, state)) { return true; } var activePlayers = activeLineup(lineup, dealer, state, this.rc); var maxBet = void 0; if (state === 'waiting' || state === 'preflop') { try { maxBet = this.getMaxBet(activePlayers, state); } catch (err) { if (state === 'waiting') { return false; } // try with all players, in case everyone all-in maxBet = this.getMaxBet(lineup, state); } } if (state === 'waiting') { return maxBet.amount > 0; } if (state === 'dealing') { var noRecCount = countNoReceipts(lineup, this.rc); if (noRecCount === 0) { return true; } } var allInPlayerCount = this.countAllIn(lineup); if (allInPlayerCount > 0 && activePlayers.length === 1) { // see if last active player matched latest all-in var maxAllInAmount = maxAllIn(lineup, this.rc); if (!maxBet) { maxBet = this.getMaxBet(activePlayers, state); } return maxAllInAmount <= maxBet.amount; } var allEven = evenLineup(activePlayers, this.rc); if (!allEven) { return false; } var checker = findLatest({ sorted: true, lineup: activePlayers }, _receipt.Type.CHECK_PRE, this.rc); if (checker.last) { // prefop betting done if check found if (state === 'preflop') { return true; } // on other streets wait until all active players have checked var checkType = state === 'preflop' ? // eslint-disable-line _receipt.Type.CHECK_PRE : state === 'flop' ? // eslint-disable-line _receipt.Type.CHECK_FLOP : state === 'turn' ? _receipt.Type.CHECK_TURN : _receipt.Type.CHECK_RIVER; var checkCount = countReceipts(lineup, checkType, this.rc); if (checkCount === activePlayers.length) { return true; } return false; } if (state === 'preflop') { if (!bbAmount) throw new Error('BB amount cannot be undefined'); var bbPos = this.getBbPos(lineup, dealer, state); var bbRec = this.rc.get(lineup[bbPos].last); if (isActive(lineup[bbPos], state, this.rc) && bbRec.type !== _receipt.Type.CHECK_PRE && maxBet.amount === parseInt(bbAmount, 10)) { return false; } } if (allInPlayerCount > 0 && activePlayers.length === 0) { return true; } if (allEven) { return true; } throw Error('could not determine betting state'); } /** * isHandComplete checks if the hand is complete. * the complete state is met when the second to last player folded or timed out, * or once everyone has shown in showdown. * replaces: checkForNextHand * * @param lineup * @param dealer * @param state * @returns boolean */ }, { key: 'isHandComplete', value: function isHandComplete( lineup, dealer, state) { var activePlayers = activeLineup(lineup, dealer, state, this.rc); var allInPlayerCount = this.countAllIn(lineup); if (state === 'showdown') { if (checkForReceipt(lineup, _receipt.Type.SHOW, this.rc)) { return activePlayers.length === 0 && allInPlayerCount === 0; } return activePlayers.length <= 1 && allInPlayerCount === 0; } return ( activePlayers.length <= 1 && allInPlayerCount === 0 || activePlayers.length === 0 && allInPlayerCount === 1); } /** * renderHand * * @param * @returns */ }, { key: 'renderHand', value: function renderHand( handId, lineupParam, dealer, sb, state, changed, deck, preMaxBet, flopMaxBet, turnMaxBet, riverMaxBet, distribution, netting) { var lineup = lineupParam.slice(); if (state === 'showdown') { for (var i = 0; i < lineup.length; i += 1) { if (lineup[i].last) { var last = this.rc.get(lineup[i].last); if (last.type === _receipt.Type.SHOW) { lineup[i].cards = []; lineup[i].cards.push(deck[i * 2]); lineup[i].cards.push(deck[i * 2 + 1]); } } } } var rv = { handId: handId, lineup: lineup, dealer: dealer, state: state, changed: changed, sb: sb, cards: [] }; if (state === 'flop') { rv.preMaxBet = preMaxBet; rv.cards.push(deck[20]); rv.cards.push(deck[21]); rv.cards.push(deck[22]); } if (state === 'turn') { rv.preMaxBet = preMaxBet; rv.flopMaxBet = flopMaxBet; rv.cards.push(deck[20]); rv.cards.push(deck[21]); rv.cards.push(deck[22]); rv.cards.push(deck[23]); } if (state === 'river') { rv.preMaxBet = preMaxBet; rv.flopMaxBet = flopMaxBet; rv.turnMaxBet = turnMaxBet; rv.cards.push(deck[20]); rv.cards.push(deck[21]); rv.cards.push(deck[22]); rv.cards.push(deck[23]); rv.cards.push(deck[24]); } if (state === 'showdown') { rv.preMaxBet = preMaxBet; rv.flopMaxBet = flopMaxBet; rv.turnMaxBet = turnMaxBet; rv.riverMaxBet = riverMaxBet; rv.cards.push(deck[20]); rv.cards.push(deck[21]); rv.cards.push(deck[22]); rv.cards.push(deck[23]); rv.cards.push(deck[24]); } if (distribution) { rv.distribution = distribution; } if (netting) { rv.netting = netting; } return rv; } /** * user PokerSolver do determine winner. * * @param lineup * @param dealer * @param board * @returns winners array */ }, { key: 'getWinners', value: function getWinners( lineup, dealer, board) { if (!lineup) { throw new Error('invalid params'); } var boardCards = board.map(function (c) {return VALUES[c % 13] + SUITS[Math.floor([c / 13])];}); var winners = []; var players = []; _abPokersolver2.default.Hand.winners(lineup.filter(function (obj) {return obj.cards;}).map(function (player) { var pHand = []; var card1 = VALUES[player.cards[0] % 13] + SUITS[Math.floor([player.cards[0] / 13])]; var card2 = VALUES[player.cards[1] % 13] + SUITS[Math.floor([player.cards[1] / 13])]; pHand.push.apply(pHand, (0, _toConsumableArray3.default)(boardCards).concat([card1, card2])); var handObj = _abPokersolver2.default.Hand.solve(pHand); players.push((0, _assign2.default)(player, { hand: handObj })); return handObj; })).forEach(function (wHand) { players.forEach(function (player) { if (player.hand === wHand) { var winner = { addr: player.address, hand: player.hand.descr }; winners.push(winner); } }); }); return winners; } /** * calcDistribution evaluates a hand and creates a distribution * * @param lineup * @param state * @param boardCards * @param rakePerMil * @param rakeAddr * @returns signed distribution */ }, { key: 'calcDistribution', value: function calcDistribution( lineup, state, boardCards, rakePerMil, rakeAddr) { if (!state || !lineup) { throw new Error('invalid params'); } // create pots var players = getPlayers(this, state, lineup); var pots = players.filter(function (p) {return p.active;}).reduce(function (list, player) { if (!(list.indexOf(player.amount) !== -1)) { return [].concat((0, _toConsumableArray3.default)(list), [player.amount]); } return list; }, []).sort(function (a, b) {return a - b;}); if (pots.reduce(function (a, b) {return a + b;}, 0) === 0) { // zero pots, can't be distributed // return money to players return players.reduce(function (result, player) {return (0, _extends4.default)({}, result, (0, _defineProperty3.default)({}, lineup[player.pos].address, player.amount));}, (0, _defineProperty3.default)({}, rakeAddr, 0)); } var evals = pots.map(function (pot) {return { limit: pot, size: 0, chal: [], winners: [] };}); // distribute players on evals // while all players amounts is not distributed while (players.filter(function (p) {return p.amount > 0;}).length > 0) { for (var i = 0; i < evals.length; i += 1) { for (var j = 0; j < players.length; j += 1) { if (players[j].amount > 0) { var limit = i > 0 ? evals[i].limit - evals[i - 1].limit : evals[i].limit; var contribution = Math.min(limit, players[j].amount); evals[i].size += contribution; players[j].amount -= contribution; if (players[j].active) { evals[i].chal.push(players[j].pos); } } } } } // solve hands for (var _i = 0; _i < evals.length; _i += 1) { if (evals[_i].chal.length > 1) { var hands = []; for (var _j = 0; _j < evals[_i].chal.length; _j += 1) { var h = []; // hole cards var card = lineup[evals[_i].chal[_j]].cards[0]; h.push(VALUES[card % 13] + SUITS[Math.floor(card / 13)]); card = lineup[evals[_i].chal[_j]].cards[1]; h.push(VALUES[card % 13] + SUITS[Math.floor(card / 13)]); // board cards h.push(VALUES[boardCards[0] % 13] + SUITS[Math.floor(boardCards[0] / 13)]); h.push(VALUES[boardCards[1] % 13] + SUITS[Math.floor(boardCards[1] / 13)]); h.push(VALUES[boardCards[2] % 13] + SUITS[Math.floor(boardCards[2] / 13)]); h.push(VALUES[boardCards[3] % 13] + SUITS[Math.floor(boardCards[3] / 13)]); h.push(VALUES[boardCards[4] % 13] + SUITS[Math.floor(boardCards[4] / 13)]); hands.push(_abPokersolver2.default.Hand.solve(h)); } var wnrs = _abPokersolver2.default.Hand.winners(hands); for (var _j2 = 0; _j2 < wnrs.length; _j2 += 1) { var pos = evals[_i].chal[hands.indexOf(wnrs[_j2])]; evals[_i].winners.push(pos); } } else { evals[_i].winners.push(evals[_i].chal[0]); } } // sum up pots by players and calc rake var winners = {}; for (var _i2 = 0; _i2 < evals.length; _i2 += 1) { var total = evals[_i2].size; for (var _j3 = 0; _j3 < evals[_i2].winners.length; _j3 += 1) { var addr = lineup[evals[_i2].winners[_j3]].address; if (!winners[addr]) { winners[addr] = 0; } var share = Math.floor((evals[_i2].size - evals[_i2].size / 1000 * rakePerMil) / evals[_i2].winners.length); total -= share; winners[addr] += share; } if (!winners[rakeAddr]) { winners[rakeAddr] = 0; } winners[rakeAddr] += total; } return winners; } }]);return PokerHelper;}();exports.default = PokerHelper;