diff --git a/package.json b/package.json index 57aaf3a..47005d0 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "scripts": { "start": "tsc && node dist/index.js", "build": "tsc", + "test": "jest src/tests --coverage --config --runInBand package.json ", "test": "jest src/tests/ --coverage --config package.json --runInBand", "lint": "eslint --ext '.js,.ts,.tsx' src/", "pretty": "yarn prettier --write .", @@ -41,7 +42,8 @@ "firebase-admin": "^11.5.0", "jest": "^29.5.0", "joi": "^17.9.1", - "pg": "^8.10.0" + "pg": "^8.10.0", + "pokersolver": "^2.1.4" }, "jest": { "collectCoverage": true, diff --git a/src/tests/fold.test.ts b/src/tests/fold.test.ts index a94b0fc..2dfbac5 100644 --- a/src/tests/fold.test.ts +++ b/src/tests/fold.test.ts @@ -1,7 +1,7 @@ import { app } from '../app' import request from 'supertest' import { getClient } from '../utils/databaseConnection' -import type { NewGameInfo } from '../utils/types' +import { type NewGameInfo } from '../utils/types' import { getPlayersInGame } from '../utils/commonRequest' test('Fold, wrong args', (done) => { diff --git a/src/utils/commonRequest.ts b/src/utils/commonRequest.ts index 457ebce..0109018 100644 --- a/src/utils/commonRequest.ts +++ b/src/utils/commonRequest.ts @@ -1,5 +1,11 @@ import { type Client } from 'pg' -import { type FirebasePlayerInfo, PlayerState } from './types' +import { + type FirebasePlayerInfo, + PlayerState, + type FirebasePlayerInfoWIthCards, +} from './types' +import { Hand } from 'pokersolver' +import { convertCardName } from './randomise' export const STARTING_FUNDS_DEFAULT = 1000 export const SMALL_BLIND_DEFAULT = 100 @@ -196,6 +202,52 @@ export async function getSmallBlindValue( return (await client.query(query, [gameId])).rows[0].small_blind } + +export async function getRemainingPlayersCards( + gameId: string, + client: Client +): Promise { + const query = + 'SELECT token, nickname, card1, card2 FROM Players WHERE game_id=$1 and last_action <> $2' + const values = [gameId, PlayerState.Folded] + return (await client.query(query, values)).rows +} + +export async function getGameCards(gameId: string, client: Client) { + const query = + 'SELECT card1, card2, card3, card4, card5 FROM games WHERE game_id=$1' + const queryResult = await client.query(query, [gameId]) + const cards: string[] = [] + Object.entries(queryResult.rows[0]).forEach(([key, value]) => { + cards.push(convertCardName(value as string)) + }) + return cards +} + +export async function calculateWinner(gameId: string, client: Client) { + const playersWithCards = await getRemainingPlayersCards(gameId, client) + const gameCards = await getGameCards(gameId, client) + const playersHands: any[] = [] + + playersWithCards.forEach((player) => { + playersHands.push( + Hand.solve([ + convertCardName(player.card1), + convertCardName(player.card2), + ...gameCards, + ]) + ) + }) + + const solution: any[] = Hand.winners(playersHands) + const winners: any[] = [] + for (let i = 0; i < playersHands.length; i++) { + if (solution.includes(playersHands[i])) { + winners.push(playersWithCards[i].token) + } + } + return winners + export async function playerHasEnoughMoney( gameId: string, playerToken: string, diff --git a/src/utils/randomise.ts b/src/utils/randomise.ts index a52d68e..f073bba 100644 --- a/src/utils/randomise.ts +++ b/src/utils/randomise.ts @@ -67,3 +67,41 @@ export const fullCardDeck = [ '12T', '13T', ] + +export function convertCardName(cardName: string): string { + let newName = '' + if (cardName[0] === '1') { + switch (cardName[1]) { + case '0': + newName += 'T' + break + case '1': + newName += 'J' + break + case '2': + newName += 'Q' + break + case '3': + newName += 'K' + } + } else if (cardName[1] === '1') { + // Ace + newName += 'A' + } else { + newName += cardName[1] + } + switch (cardName[2]) { + case 'K': + newName += 'h' + break + case 'O': + newName += 'd' + break + case 'T': + newName += 'c' + break + case 'P': + newName += 's' + } + return newName +} diff --git a/yarn.lock b/yarn.lock index 18d8118..7db3dd0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4896,6 +4896,11 @@ pm2@^5.3.0: optionalDependencies: pm2-sysmonit "^1.2.8" +pokersolver@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pokersolver/-/pokersolver-2.1.4.tgz#58934f3dad1dc597c44e80474bc82e9626790ccc" + integrity sha512-vmgZS+K8H8r1RePQykFM5YyvlKo1v3xVec8FMBjg9N6mR2Tj/n/X415w+lG67FWbrk71D/CADmKFinDgaQlAsw== + postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"