diff --git a/index.js b/index.js index 62fbd65..143a7f0 100644 --- a/index.js +++ b/index.js @@ -49,7 +49,11 @@ const sessionMiddleware = session({ secret: uuidv4(), resave: true, saveUninitialized: true, - cookie: { secure: process.env.cookie_secure === "true" ? true : false } + rolling: true, + cookie: { + secure: process.env.cookie_secure === "true" ? true : false, + maxAge: 24 * 60 * 60 * 1000, + }, }); app.use(sessionMiddleware); @@ -230,10 +234,22 @@ io.on('connection', async (socket) => { ships: [], // zawiera np. {type: 2, posX: 3, posY: 4, rot: 2, hits: [false, false, true]} // pozycja na planszy czy strzał miał udział w zatopieniu statku? shots: [], // zawiera np. {posX: 3, posY: 5} + stats: { + shots: 0, + hits: 0, + placedShips: 0, + sunkShips: 0, + }, }, { ships: [], shots: [], + stats: { + shots: 0, + hits: 0, + placedShips: 0, + sunkShips: 0, + }, } ], nextPlayer: 0, @@ -310,7 +326,7 @@ io.on('connection', async (socket) => { let UTCTs = Math.floor((new Date()).getTime() / 1000 + 90); io.to(playerGame.id).emit('turn update', { turn: 0, phase: "preparation", timerToUTC: UTCTs }); - GInfo.timer(playerGame.id, 90, async () => { + GInfo.timer(playerGame.id, 10, async () => { const playerGame = await GInfo.getPlayerGameData(socket); for (let i = 0; i < playerGame.data.boards.length; i++) { const ships = playerGame.data.boards[i].ships; @@ -351,6 +367,7 @@ io.on('connection', async (socket) => { } else { await GInfo.placeShip(socket, { type: type, posX: posX, posY: posY, rot: rot, hits: Array.from(new Array(type+1), () => false) }); socket.emit("placed ship", { type: type, posX: posX, posY: posY, rot: rot }); + await GInfo.incrStat(socket, 'placedShips'); } } }); @@ -361,6 +378,7 @@ io.on('connection', async (socket) => { if (playerGame.data.state === 'preparation') { const deletedShip = await GInfo.removeShip(socket, posX, posY); socket.emit("removed ship", { posX: posX, posY: posY, type: deletedShip.type }); + await GInfo.incrStat(socket, 'placedShips', -1); } }); @@ -374,13 +392,18 @@ io.on('connection', async (socket) => { let hit = await GInfo.shootShip(socket, posX, posY); await redis.json.arrAppend(`game:${playerGame.id}`, `.boards[${enemyIdx}].shots`, { posX: posX, posY: posY }); + await GInfo.incrStat(socket, 'shots'); + if (!hit.status) { io.to(playerGame.id).emit("shot missed", enemyIdx, posX, posY); } else if (hit.status === 1) { io.to(playerGame.id).emit("shot hit", enemyIdx, posX, posY); + await GInfo.incrStat(socket, 'hits'); } else if (hit.status === 2) { io.to(playerGame.id).emit("shot hit", enemyIdx, posX, posY); + await GInfo.incrStat(socket, 'hits'); io.to(playerGame.id).emit("ship sunk", enemyIdx, hit.ship); + await GInfo.incrStat(socket, 'sunkShips'); if (hit.gameFinished) { const members = [...roomMemberIterator(playerGame.id)]; @@ -393,8 +416,11 @@ io.on('connection', async (socket) => { hostSocket.emit("game finished", !enemyIdx ? 1 : 0, guestNickname); guestSocket.emit("game finished", !enemyIdx ? 1 : 0, hostNickname); + const stats = await GInfo.getStats(socket); + auth.saveMatch(playerGame.id, "pvp", hostSocket.request.session.userId, guestSocket.request.session.userId, stats, !enemyIdx ? 1 : 0); + GInfo.resetTimer(playerGame.id); - endGame(playerGame.id); + endGame(playerGame.id, !enemyIdx ? 1 : 0); return; } } else if (hit.status === -1) { @@ -438,7 +464,11 @@ function resetUserGame(req) { }); } -function endGame(gameId) { +function endGame(gameId, winnerIdx = -1) { + const boards = redis.json.get(`game:${gameId}`, { keys: [".boards"] }); + const hostUid = redis.json.get(`game:${gameId}`, { keys: [".hostUserId"] }); + const guestUid = redis.json.get(`game:${gameId}`, { keys: [".hostUserId"] }); + let iterator = roomMemberIterator(gameId); if (iterator != null) { const members = [...iterator]; diff --git a/utils/auth.js b/utils/auth.js index e73f34f..223a715 100644 --- a/utils/auth.js +++ b/utils/auth.js @@ -129,6 +129,19 @@ export class MailAuth { }); } + saveMatch(matchId, type, hostId, guestId, stats, winnerIdx) { + return new Promise((resolve, reject) => { + const conn = mysql.createConnection(this.mysqlOptions); + conn.query(`INSERT INTO matches(match_id, match_type, host_id, guest_id) VALUES (${conn.escape(matchId)}, ${conn.escape(type)}, ${conn.escape(hostId)}, ${conn.escape(guestId)})`, async (error, response) => { + if (error) reject(error); + conn.query(`INSERT INTO statistics(match_id, user_id, shots, hits, placed_ships, sunk_ships, sunk_ships_by, won) VALUES (${conn.escape(matchId)}, ${conn.escape(hostId)}, ${conn.escape(stats[0].shots)}, ${conn.escape(stats[0].hits)}, ${conn.escape(stats[0].placedShips)}, ${conn.escape(stats[0].sunkShips)}, ${conn.escape(stats[0].sunkShipsBy)}, ${conn.escape(winnerIdx == 0)}), (${conn.escape(matchId)}, ${conn.escape(guestId)}, ${conn.escape(stats[1].shots)}, ${conn.escape(stats[1].hits)}, ${conn.escape(stats[1].placedShips)}, ${conn.escape(stats[1].sunkShips)}, ${conn.escape(stats[1].sunkShipsBy)}, ${conn.escape(winnerIdx == 1)})`).then((error) => { + if (error) reject(error); + resolve(); + }); + }); + }); + } + async finishVerification(uid, authCode) { authCode = authCode.replace(/\s+/g, ""); let redisRes = await this.redis.json.get(`code_auth:${authCode}`); diff --git a/utils/battleships.js b/utils/battleships.js index bbeb9c5..ef081e7 100644 --- a/utils/battleships.js +++ b/utils/battleships.js @@ -42,6 +42,25 @@ export class GameInfo { return game == null ? null : { id: socket.session.activeGame, data: game }; } + async getStats(socket) { + const boards = await this.redis.json.get(`game:${socket.session.activeGame}`, { path: ".boards" }); + let stats = []; + + console.log(boards); + boards.forEach(board => { + stats.push(board.stats); + }); + + return stats; + } + + async incrStat(socket, statKey, by = 1) { + const game = await this.redis.json.get(`game:${socket.session.activeGame}`); + const idx = socket.request.session.id === game.hostId ? 0 : 1; + + this.redis.json.numIncrBy(`game:${socket.session.activeGame}`, `.boards[${idx}].stats.${statKey}`, by); + } + async getPlayerShips(socket) { const game = await this.redis.json.get(`game:${socket.session.activeGame}`); const idx = socket.request.session.id === game.hostId ? 0 : 1; @@ -75,7 +94,7 @@ export class GameInfo { async placeShip(socket, shipData) { const gameId = socket.session.activeGame; const key = `game:${gameId}`; - const hostId = (await this.redis.json.get(key, {path: '.hostId'})); + const hostId = (await this.redis.json.get(key, { path: '.hostId' })); const playerIdx = socket.request.session.id === hostId ? 0 : 1; await this.redis.json.arrAppend(key, `.boards[${playerIdx}].ships`, shipData);