Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gameplay: raise #51

Merged
merged 20 commits into from
May 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"start": "tsc && node dist/index.js",
"build": "tsc",
"test": "jest src/tests --coverage --config package.json ",
"test": "jest src/tests/ --coverage --config package.json --runInBand",
"lint": "eslint --ext '.js,.ts,.tsx' src/",
"pretty": "yarn prettier --write .",
"pretty-check": "yarn prettier --check src/",
Expand Down
11 changes: 7 additions & 4 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import createGame from './routes/createGame'
import modifyGame from './routes/modifyGame'
import leaveGame from './routes/leaveGame'
import startGame from './routes/startGame'
import fold from './routes/gameplay/fold'
import check from './routes/gameplay/check'
import actionFold from './routes/gameplay/fold'
import actionRaise from './routes/gameplay/raise'
import actionCheck from './routes/gameplay/check'
import { rateLimiter } from './utils/rateLimiter'

export const app = express()
Expand Down Expand Up @@ -41,8 +42,10 @@ app.use(leaveGame)

app.use(startGame)

app.use(fold)
app.use(actionFold)

app.use(check)
app.use(actionRaise)

app.use(actionCheck)

app.use(errorHandling)
18 changes: 15 additions & 3 deletions src/routes/gameplay/fold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { PlayerState } from '../../utils/types'
const router: Router = express.Router()

router.get(
'/fold',
'/actionFold',
rateLimiter,
celebrate({
[Segments.QUERY]: Joi.object().keys({
Expand Down Expand Up @@ -47,9 +47,22 @@ router.get(
if (!(await isPlayersTurn(playerToken, gameId, client))) {
return res.sendStatus(402)
}

await setPlayerState(playerToken, client, PlayerState.Folded)
const newPlayer = await setNewCurrentPlayer(playerToken, gameId, client)
if (newPlayer === '') {
const message = {
data: {
player: sha256(newPlayer).toString(),
type: PlayerState.Won,
actionPayload: '',
},
token: '',
}

await sendFirebaseMessageToEveryone(message, gameId, client)
return res.sendStatus(201)
}

await changeGameRoundIfNeeded(gameId, newPlayer, client)

const message = {
Expand All @@ -62,7 +75,6 @@ router.get(
}

await sendFirebaseMessageToEveryone(message, gameId, client)

res.sendStatus(200)
})
.catch((err) => {
Expand Down
93 changes: 93 additions & 0 deletions src/routes/gameplay/raise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { getClient } from '../../utils/databaseConnection'
import { celebrate, Joi, Segments } from 'celebrate'
import {
sendFirebaseMessageToEveryone,
verifyFCMToken,
} from '../../utils/firebase'
import express, { type Router } from 'express'
import { rateLimiter } from '../../utils/rateLimiter'
import {
isPlayerInGame,
isPlayersTurn,
setPlayerState,
setNewCurrentPlayer,
changeGameRoundIfNeeded,
playerHasEnoughMoney,
isRaising,
playerRaised,
} from '../../utils/commonRequest'
import sha256 from 'crypto-js/sha256'
import { PlayerState } from '../../utils/types'

const router: Router = express.Router()

router.get(
'/actionRaise',
rateLimiter,
celebrate({
[Segments.QUERY]: Joi.object().keys({
playerToken: Joi.string().required().min(1).max(250).label('playerToken'),
gameId: Joi.number().required().min(0).max(999999).label('gameId'),
amount: Joi.number().required().min(1).label('amount'),
}),
}),
async (req, res) => {
const playerToken = req.query.playerToken as string
const gameId = req.query.gameId as string
const amount = req.query.amount as string
if (!(await verifyFCMToken(playerToken))) {
return res.sendStatus(401)
}

const client = getClient()

client
.connect()
.then(async () => {
if (!(await isPlayerInGame(playerToken, gameId, client))) {
return res.sendStatus(400)
}

if (!(await isPlayersTurn(playerToken, gameId, client))) {
return res.sendStatus(402)
}

if (
!(await playerHasEnoughMoney(gameId, playerToken, amount, client))
) {
return res.sendStatus(403)
}

if (!(await isRaising(gameId, amount, client))) {
return res.sendStatus(404)
}

const newPlayer = await setNewCurrentPlayer(playerToken, gameId, client)

await playerRaised(gameId, playerToken, amount, client)
await setPlayerState(playerToken, client, PlayerState.Raised)
await changeGameRoundIfNeeded(gameId, newPlayer, client)

const message = {
data: {
player: sha256(playerToken).toString(),
type: PlayerState.Raised,
Kwasow marked this conversation as resolved.
Show resolved Hide resolved
actionPayload: amount.toString(),
},
token: '',
}

await sendFirebaseMessageToEveryone(message, gameId, client)
res.sendStatus(200)
})
.catch((err) => {
console.log(err.stack)
return res.sendStatus(500)
})
.finally(async () => {
await client.end()
})
}
)

export default router
14 changes: 11 additions & 3 deletions src/routes/startGame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,17 +177,25 @@ async function updateGameState(
smallBlind: string,
playerSize: number
) {
const smallBlindValue = await getSmallBlindValue(gameId, client)
const query = `UPDATE Games SET current_player=$1, small_blind_who=$2,
game_round=$3, current_table_value=$4,
card1=$5, card2=$6, card3=$7, card4=$8, card5=$9 WHERE game_id=$10`

const values = [firstPlayerToken, smallBlind, 1, 0, ...gameInfo.cards, gameId]
const values = [
firstPlayerToken,
smallBlind,
1,
+smallBlindValue * 3,
...gameInfo.cards,
gameId,
]
await client.query(query, values)
await prepareBlinds(
client,
smallBlind,
await getBigBlind(gameId, playerSize, client),
await getSmallBlindValue(gameId, client)
smallBlindValue
)
}

Expand Down Expand Up @@ -216,7 +224,7 @@ async function notifyPlayers(
const message = {
data: {
type: 'startGame',
startedGameInfo: JSON.stringify(gameInfo),
players: JSON.stringify(gameInfo.players),
card1: '',
card2: '',
},
Expand Down
103 changes: 103 additions & 0 deletions src/tests/actionRaise.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { app } from '../app'
import request from 'supertest'
import { getClient } from '../utils/databaseConnection'
import type { NewGameInfo } from '../utils/types'
import { getGameIdAndStatus, getPlayersInGame } from '../utils/commonRequest'

test('Raise, wrong args', (done) => {
const wrongToken = 'TESTRAISE_INCORRECT'
const wrongGameId = 'WRONG_ID'
request(app)
.get(`/actionRaise?playerToken=${wrongToken}`)
.expect(400)
.end(done)

request(app)
.get(`/actionRaise?playerToken=${wrongToken}&gameId=${wrongGameId}`)
.expect(400)
.end(done)
})

test('Raise, correct arguments 1', async () => {
const gameMasterToken = 'RAISETEST'
const gameMasterNick = 'RAISENICK'
const playerToken = 'RAISETEST2'
const playerNick = 'RAISENICK2'
const player2Token = 'RAISETEST3'
const player2Nick = 'RAISENICK3'

const client = getClient()
await client.connect()
const res = await request(app)
.get(
`/createGame?creatorToken=${gameMasterToken}&nickname=${gameMasterNick}`
)
.expect(200)

const key = (res.body as NewGameInfo).gameId
await request(app)
.get(
`/joinGame?playerToken=${playerToken}&nickname=${playerNick}&gameId=${key}`
)
.expect(200)

await request(app)
.get(
`/joinGame?playerToken=${player2Token}&nickname=${player2Nick}&gameId=${key}`
)
.expect(200)

await request(app)
.get(`/startGame?creatorToken=${gameMasterToken}`)
.expect(200)

const gameId =
(await getGameIdAndStatus(gameMasterToken, client)).gameId ?? ''
const players = await getPlayersInGame(gameId, client)

await request(app)
.get(
`/actionRaise?playerToken=${players[1].token}&gameId=${gameId}&amount=5`
)
.expect(402)

await request(app)
.get(
`/actionRaise?playerToken=${players[0].token}&gameId=${gameId}&amount=300`
)
.expect(200)
await request(app)
.get(`/actionFold?playerToken=${players[1].token}&gameId=${gameId}`)
.expect(200)
const getRound = 'SELECT game_round FROM Games WHERE game_id=$1'

expect(
await (
await client.query(getRound, [gameId])
).rows[0].game_round
).toEqual('1') // Player 2 can still act

await request(app)
.get(
`/actionRaise?playerToken=${players[2].token}&gameId=${gameId}&amount=2`
)
.expect(404)

await request(app)
.get(
`/actionRaise?playerToken=${players[2].token}&gameId=${gameId}&amount=2000000000`
)
.expect(403)

await request(app)
.get(
`/actionRaise?playerToken=${players[2].token}&gameId=${gameId}&amount=400`
)
.expect(200)

await request(app)
.get(`/actionFold?playerToken=${players[0].token}&gameId=${gameId}`)
.expect(201)

await client.end()
}, 60000)
19 changes: 10 additions & 9 deletions src/tests/fold.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import { getPlayersInGame } from '../utils/commonRequest'
test('Fold, wrong args', (done) => {
const wrongToken = 'TESTFOLD_INCORRECT'
const wrongGameId = 'WRONG_ID'
request(app).get(`/fold?playerToken=${wrongToken}`).expect(400).end(done)
request(app)
.get(`/actionFold?playerToken=${wrongToken}`)
.expect(400)
.end(done)

request(app)
.get(`/fold?playerToken=${wrongToken}&gameId=${wrongGameId}`)
.get(`/actionFold?playerToken=${wrongToken}&gameId=${wrongGameId}`)
.expect(400)
.end(done)
})
Expand Down Expand Up @@ -50,24 +53,22 @@ test('Fold, correct arguments, wrong turn', async () => {

const gameId = key.toString()
const players = await getPlayersInGame(gameId, client)

await request(app)
.get(`/fold?playerToken=${players[1].token}&gameId=${gameId}`)
.get(`/actionFold?playerToken=${players[1].token}&gameId=${gameId}`)
.expect(402)

await request(app)
.get(`/fold?playerToken=${players[0].token}&gameId=${gameId}`)
.get(`/actionFold?playerToken=${players[0].token}&gameId=${gameId}`)
.expect(200)
await request(app)
.get(`/fold?playerToken=${players[1].token}&gameId=${gameId}`)
.expect(200)
.get(`/actionFold?playerToken=${players[1].token}&gameId=${gameId}`)
.expect(201)
const getRound = 'SELECT game_round FROM Games WHERE game_id=$1'

expect(
await (
await client.query(getRound, [gameId])
).rows[0].game_round
).toEqual('2')
).toEqual('1') // because last guy has won - no new rounds then.

await client.end()
}, 20000)
Loading