Almost working statistics and match saving

This commit is contained in:
Maciej Gomoła 2024-03-18 12:41:50 +01:00
parent eff3ed1914
commit dd963ec0a9
3 changed files with 67 additions and 5 deletions

View File

@ -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];

View File

@ -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}`);

View File

@ -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;