@alexjamesmalcolm/poker-odds-machine
Version:
Poker odds machine (calculator)
254 lines • 8.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deck = exports.CardGroup = exports.Card = exports.makeStatsTieHandStatsIfItIsNotAlready = exports.isStatsWithTieHandStats = exports.makeStatsHandStatsIfItIsNotAlready = exports.isStatsWithHandStats = exports.isStatsWithBothHandAndTieHandStats = exports.isInputAnExternalInputWithNumberOfPlayers = exports.isInputAnExternalInputWithHands = exports.isInputAnEternalInputWithEverythingProvided = exports.HandRanks = exports.Ranks = exports.Suits = void 0;
const util_1 = require("./util");
var Suits;
(function (Suits) {
Suits[Suits["club"] = 1] = "club";
Suits[Suits["diamond"] = 2] = "diamond";
Suits[Suits["heart"] = 3] = "heart";
Suits[Suits["spade"] = 4] = "spade";
})(Suits = exports.Suits || (exports.Suits = {}));
var Ranks;
(function (Ranks) {
Ranks[Ranks["two"] = 2] = "two";
Ranks[Ranks["three"] = 3] = "three";
Ranks[Ranks["four"] = 4] = "four";
Ranks[Ranks["five"] = 5] = "five";
Ranks[Ranks["six"] = 6] = "six";
Ranks[Ranks["seven"] = 7] = "seven";
Ranks[Ranks["eight"] = 8] = "eight";
Ranks[Ranks["nine"] = 9] = "nine";
Ranks[Ranks["ten"] = 10] = "ten";
Ranks[Ranks["jack"] = 11] = "jack";
Ranks[Ranks["queen"] = 12] = "queen";
Ranks[Ranks["king"] = 13] = "king";
Ranks[Ranks["ace"] = 14] = "ace";
})(Ranks = exports.Ranks || (exports.Ranks = {}));
var HandRanks;
(function (HandRanks) {
HandRanks[HandRanks["highCard"] = 1] = "highCard";
HandRanks[HandRanks["pair"] = 2] = "pair";
HandRanks[HandRanks["twoPair"] = 3] = "twoPair";
HandRanks[HandRanks["trips"] = 4] = "trips";
HandRanks[HandRanks["straight"] = 5] = "straight";
HandRanks[HandRanks["flush"] = 6] = "flush";
HandRanks[HandRanks["fullHouse"] = 7] = "fullHouse";
HandRanks[HandRanks["quads"] = 8] = "quads";
HandRanks[HandRanks["straightFlush"] = 9] = "straightFlush";
})(HandRanks = exports.HandRanks || (exports.HandRanks = {}));
exports.isInputAnEternalInputWithEverythingProvided = (input) => exports.isInputAnExternalInputWithHands(input) &&
exports.isInputAnExternalInputWithNumberOfPlayers(input);
exports.isInputAnExternalInputWithHands = (input) => 'hands' in input;
exports.isInputAnExternalInputWithNumberOfPlayers = (input) => {
return 'numPlayers' in input;
};
exports.isStatsWithBothHandAndTieHandStats = (stats) => exports.isStatsWithHandStats(stats) && exports.isStatsWithTieHandStats(stats);
exports.isStatsWithHandStats = (stats) => 'handStats' in stats;
exports.makeStatsHandStatsIfItIsNotAlready = (stats) => {
if (exports.isStatsWithHandStats(stats))
return stats;
stats.handStats = {};
return stats;
};
exports.isStatsWithTieHandStats = (stats) => 'tieHandStats' in stats;
exports.makeStatsTieHandStatsIfItIsNotAlready = (stats) => {
if (exports.isStatsWithTieHandStats(stats))
return stats;
stats.tieHandStats = {};
return stats;
};
class Suit {
static fromString(s) {
switch (s) {
case 'c':
return Suits.club;
case 'd':
return Suits.diamond;
case 'h':
return Suits.heart;
case 's':
return Suits.spade;
default:
throw new Error(`Invalid card suit string: ${s}`);
}
}
static toString(suit) {
if (!(suit in Suits))
throw new Error(`Invalid suit value: ${suit}`);
return Suits[suit][0];
}
static toLongName(suit, plural) {
if (!(suit in Suits))
throw new Error(`Invalid suit value: ${suit}`);
let longName = Suits[suit];
if (plural)
longName += 's';
return longName;
}
}
class Rank {
static fromString(s) {
switch (s) {
case 'T':
return Ranks.ten;
case 'J':
return Ranks.jack;
case 'Q':
return Ranks.queen;
case 'K':
return Ranks.king;
case 'A':
return Ranks.ace;
default:
const n = Number(s);
if (isNaN(n) || n < Ranks.two || n > Ranks.nine)
throw new Error(`Invalid card rank string: ${s}`);
return n;
}
}
static toString(r) {
switch (r) {
case Ranks.ten:
return 'T';
case Ranks.jack:
return 'J';
case Ranks.queen:
return 'Q';
case Ranks.king:
return 'K';
case Ranks.ace:
return 'A';
default:
if (isNaN(r) || r < Ranks.two || r > Ranks.ace)
throw new Error(`Invalid card rank value: ${r}`);
return r.toString();
}
}
static toLongName(rank) {
if (!(rank in Ranks))
throw new Error(`Invalid rank value: ${rank}`);
return Ranks[rank];
}
}
class Card {
constructor(s) {
Card.validateCardString(s);
this._rank = Rank.fromString(s[0]);
this._suit = Suit.fromString(s[1]);
}
get rank() {
return this._rank;
}
get suit() {
return this._suit;
}
static validateCardString(s) {
if (s.length !== 2)
throw new Error(`Card string must have a length of 2. Invalid: ${s}`);
if (!['T', 'J', 'Q', 'K', 'A'].includes(s[0]) &&
(+s[0] < 2 || +s[0] > 9))
throw new Error(`Card string must begin with 2-9, T, J, Q, K, or A. Invalid: ${s}`);
if (!['c', 'd', 'h', 's'].includes(s[1]))
throw new Error(`Card string must end with c, d, h, or s. Invalid: ${s}`);
}
equals(card) {
// todo: implement range card == standard card
return this._rank === card.rank && this._suit === card.suit;
}
toString() {
return Rank.toString(this._rank) + Suit.toString(this._suit);
}
toLongName() {
return `${Rank.toLongName(this._rank)} of ${Suit.toLongName(this._suit, true)}`;
}
}
exports.Card = Card;
class CardGroup {
constructor(cards) {
this._cards = [];
if (!cards)
return;
// todo: why are these conditions necessary to call function?
if (Array.isArray(cards))
this.addCards(cards);
else if (typeof cards === 'string')
this.addCards(cards);
else
this.addCards(cards);
}
get cards() {
return this._cards;
}
static validateCardGroupString(s) {
for (const e of s.split(',')) {
Card.validateCardString(e);
}
}
toString() {
return this._cards.map((c) => c.toString()).join(',');
}
addCardGroup(cardGroup) {
this._cards.push(...cardGroup.cards);
}
addCards(cards) {
if (typeof cards === 'string')
this.addCardsString(cards);
else if (Array.isArray(cards))
this._cards.push(...cards);
else
this._cards.push(cards);
}
sortDesc() {
this._cards.sort((a, b) => b.suit - a.suit);
this._cards.sort((a, b) => b.rank - a.rank);
}
countBy(type) {
const map = {};
for (const card of this._cards) {
const prop = type === 'rank' ? card.rank : card.suit;
if (!(prop in map))
map[prop] = 1;
else
map[prop]++;
}
return map;
}
addCardsString(s) {
for (const e of s.split(',')) {
const card = new Card(e);
this.addCards(card);
}
}
}
exports.CardGroup = CardGroup;
class Deck extends CardGroup {
constructor(numDecks) {
const deckString = '2c,2d,2h,2s,3c,3d,3h,3s,4c,4d,4h,4s,5c,5d,5h,5s,6c,6d,6h,6s,7c,7d,7h,7s,8c,8d,8h,8s,9c,9d,9h,9s,Tc,Td,Th,Ts,Jc,Jd,Jh,Js,Qc,Qd,Qh,Qs,Kc,Kd,Kh,Ks,Ac,Ad,Ah,As';
const decksString = Array(numDecks).fill(deckString);
super(decksString.join(','));
}
pop() {
const card = this._cards.pop();
if (card === undefined)
throw new Error('Deck is empty. There are either too many players, or the boardSize is too large');
return card;
}
removeCard(cardToRemove) {
let found = false;
for (let i = 0; i < this._cards.length; i++) {
if (this._cards[i].equals(cardToRemove)) {
this._cards.splice(i, 1);
found = true;
}
}
if (!found)
throw new Error(`CardGroup does not contain card string: ${cardToRemove.toString()}`);
return cardToRemove;
}
shuffle() {
util_1.shuffle(this._cards);
}
}
exports.Deck = Deck;
//# sourceMappingURL=types.js.map