Skip to content

Instantly share code, notes, and snippets.

@JohnnyBizzel
Last active March 28, 2018 00:08
Show Gist options
  • Save JohnnyBizzel/0e1ccdfc3f6d534194884c2748fbe8ad to your computer and use it in GitHub Desktop.
Save JohnnyBizzel/0e1ccdfc3f6d534194884c2748fbe8ad to your computer and use it in GitHub Desktop.
Charlie's fixed poker comparer
const Result = { "win": 1, "loss": 2, "tie": 3 };
/*
High pair:
AH 8S AS KC JH
KS 8D 4D 9S 4S
Same hand:
KD 4S KC 3H 8S (marked as loss)
*/
function PokerHand(hand) {
const cards = hand.trim().split(' ').map(card => {
const c = card.split('');
let rank = cardRank(c[0]);
return { rank , suit: c[1] };
});
// JB: Ranks changed to numbers (as a string the later compare will not work correctly)
function cardRank(rank) {
switch (rank) {
case "A":
return 14;
case "K":
return 13;
case "Q":
return 12;
case "J":
return 11;
case "T":
return 10;
default:
return Number(rank);
}
}
// check pairs
let matches = [];
// loop through each card output object of pairings
cards.forEach(card => {
if (!matches.find(c => c.rank === card.rank)) {
const amount = cards.filter(c => card.rank === c.rank).length;
if (amount > 1) {
matches.push({ rank: card.rank, amount })
}
}
});
// filter different types of pairing
const isPair = matches.filter(m => m.amount === 2).length === 1;
const isTrip = matches.filter(m => m.amount === 3).length === 1;
const isQuad = matches.filter(m => m.amount === 4).length === 1;
const isTwoPair = matches.filter(m => m.amount === 2).length === 2;
const isFullHouse = isPair && isTrip;
// check flush
const suit = cards[0].suit;
const isFlush = cards.filter(card => suit === card.suit).length === 5;
let isWheel = false;
// check straight
function isStraight(cards) {
cards = cards.map(c => Number(c.rank));
// JB: added check for wheel condition checking if 2 exists
if (cards.includes(14) && cards.includes(2)) {
isWheel = true;
cards.push(1);
}
let result = [];
let sorted = cards
.sort((a, b) => a - b)
.filter((item, pos, self) => self.indexOf(item) === pos)
for (let i = 0; i < sorted.length; i++) {
result[i] = sorted[i] === sorted[i - 1] + 1 ? result[i - 1] + 1 : 1;
}
return Math.max.apply({}, result) >= 5;
}
const straight = isStraight(cards);
let cardScore = cards
.map(c => Number(c.rank))
.reduce((a, b) => a + b);
cardScore = cardScore - (isWheel && straight ? 14 : 0);
function handScore() {
switch(true) {
case (straight && isFlush && cardScore === 60):
return 9;
case (straight && isFlush):
return 8;
case (isQuad):
return 7;
case (isFullHouse):
return 6;
case (isFlush):
return 5;
case (straight):
return 4;
case (isTrip):
return 3;
case (isTwoPair):
return 2;
case (isPair):
return 1;
default:
return 0;
}
}
const handRating = handScore();
let kickers = null;
if (handRating === 7 || handRating < 4) {
const a = matches[0] ? matches[0].rank : 0;
const b = matches[1] ? matches[1].rank : 0;
kickers = cards
.map(c => c.rank)
.filter(c => c !== a && c !== b)
.sort((a, b) => b - a);
}
const multipleParings = isFullHouse || isTwoPair ? matches.sort((a, b) => b.amount - a.amount) : false;
const flush = isFlush ? cards.map(c => Number(c.rank)).sort((a,b) => b - a) : false;
// JB: added saving the rank of the pair card
let pairValue = 0;
if (matches.length > 0) pairValue = matches[0].rank;
this.score = { card: cardScore, hand: handRating, kickers, multipleParings, flush, pairRank : pairValue };
}
PokerHand.prototype.compareWith = function(hand) {
let p = this.score;
let o = hand.score;
function kickersCheck(player, opponent, index) {
while (index < player.length) {
// JB: index++ moved to after the test as I think it was ignoring the 1st card
if (player[index] !== opponent[index]) {
return player[index] > opponent[index] ? Result.win : Result.loss;
}
index++;
}
return Result.tie;
}
function multipleParingsCheck(pMultiples, oMultiples, p, o) {
for (let i = 0; i < 2; i++) {
if (pMultiples[i].rank !== oMultiples[i].rank) {
return Number(pMultiples[i].rank) > Number(oMultiples[i].rank) ? Result.win : Result.loss;
}
}
const isPair = pMultiples.reduce((a, b) => a.amount + b.amount) === 4;
if (isPair && p.kickers[0] !== o.kickers[0]) {
return Number(p.kickers[0]) > Number(o.kickers[0]) ? Result.win : Result.loss;
} else {
return Result.tie;
}
}
if (p.hand === o.hand && p.flush) {
return kickersCheck(p.flush, o.flush, 0);
} else if (p.hand === o.hand && p.hand > 1) {
if (p.multipleParings) {
return multipleParingsCheck(p.multipleParings, o.multipleParings, p, o);
}
if (p.card === o.card) {
return p.kickers !== null ? kickersCheck(p.kickers, o.kickers, 0) : Result.tie;
}
// JB: added check for highest straight
else {
return p.card > o.card ? Result.win : Result.loss;
}
// JB: added a check for highest value of a pair
} else if (p.hand === 1 && o.hand === 1) {
return (p.pairRank > o.pairRank) ? Result.win :
(p.pairRank < o.pairRank) ? Result.loss :
kickersCheck(p.kickers, o.kickers, 0);
} else if (p.hand !== o.hand) {
return p.hand > o.hand ? Result.win : Result.loss;
} else {
// JB: This test is incorrect. Need to check each card in turn
// return p.card > o.card ? Result.win : Result.loss;
for (let i = 0; i < 5; i++) {
if (p.kickers[i] > o.kickers[i]) {
return Result.win;
} else if (p.kickers[i] < o.kickers[i]) {
return Result.loss;
}
}
return Result.tie;
}
}
// let p = new PokerHand("TH TH TH TH AC");
// let o = new PokerHand("TH TH TH TH 2C");
//
// console.log(p.compareWith(o));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment