diff --git a/server/src/controllers/auth.controller.ts b/server/src/controllers/auth.controller.ts index 9292464..a1cb64a 100644 --- a/server/src/controllers/auth.controller.ts +++ b/server/src/controllers/auth.controller.ts @@ -119,6 +119,10 @@ export const registerUser = async (req: Request, res: Response) => { throw new Error("Failed to create user"); } + const publicUser = { + id: newUser.id, + name: newUser.name + }; if (req.session.user?.id && typeof req.session.user.id === "string") { const game = activeGames.find( (g) => @@ -128,17 +132,17 @@ export const registerUser = async (req: Request, res: Response) => { ); if (game) { if (game.host?.id === req.session.user.id) { - game.host = newUser; + game.host = publicUser; } if (game.white && game.white?.id === req.session.user.id) { - game.white = newUser; + game.white = publicUser; } else if (game.black && game.black?.id === req.session.user.id) { - game.black = newUser; + game.black = publicUser; } else { const observer = game.observers?.find((o) => o.id === req.session.user.id); if (observer) { - observer.id = newUser.id; - observer.name = newUser.name; + observer.id = publicUser.id; + observer.name = publicUser.name; } } io.to(game.code as string).emit("receivedLatestGame", game); @@ -180,10 +184,9 @@ export const loginUser = async (req: Request, res: Response) => { return; } - const newUser = { + const publicUser = { id: users[0].id, - name: users[0].name, - email: users[0].email + name: users[0].name }; if (req.session.user?.id && typeof req.session.user.id === "string") { @@ -195,17 +198,17 @@ export const loginUser = async (req: Request, res: Response) => { ); if (game) { if (game.host?.id === req.session.user.id) { - game.host = newUser; + game.host = publicUser; } if (game.white && game.white?.id === req.session.user.id) { - game.white = newUser; + game.white = publicUser; } else if (game.black && game.black?.id === req.session.user.id) { - game.black = newUser; + game.black = publicUser; } else { const observer = game.observers?.find((o) => o.id === req.session.user.id); if (observer) { - observer.id = newUser.id; - observer.name = newUser.name; + observer.id = publicUser.id; + observer.name = publicUser.name; } } io.to(game.code as string).emit("receivedLatestGame", game); @@ -214,7 +217,11 @@ export const loginUser = async (req: Request, res: Response) => { req.session.user = { id: users[0].id, - name: users[0].name + name: users[0].name, + email: users[0].email, + wins: users[0].wins, + losses: users[0].losses, + draws: users[0].draws }; req.session.save(() => { res.status(200).json(req.session.user); @@ -263,6 +270,35 @@ export const updateUser = async (req: Request, res: Response) => { throw new Error("Failed to update user"); } + const publicUser = { + id: updatedUser.id, + name: updatedUser.name + }; + + const game = activeGames.find( + (g) => + g.white?.id === req.session.user.id || + g.black?.id === req.session.user.id || + g.observers?.find((o) => o.id === req.session.user.id) + ); + if (game) { + if (game.host?.id === req.session.user.id) { + game.host = publicUser; + } + if (game.white && game.white?.id === req.session.user.id) { + game.white = publicUser; + } else if (game.black && game.black?.id === req.session.user.id) { + game.black = publicUser; + } else { + const observer = game.observers?.find((o) => o.id === req.session.user.id); + if (observer) { + observer.id = publicUser.id; + observer.name = publicUser.name; + } + } + io.to(game.code as string).emit("receivedLatestGame", game); + } + req.session.user = updatedUser; req.session.save(() => { res.status(200).json(req.session.user); diff --git a/server/src/db/index.ts b/server/src/db/index.ts index baacae6..61b8cd4 100644 --- a/server/src/db/index.ts +++ b/server/src/db/index.ts @@ -8,6 +8,9 @@ export const INIT_TABLES = /* sql */ ` name VARCHAR(128) UNIQUE NOT NULL, email VARCHAR(128), password TEXT, + wins INTEGER DEFAULT 0, + losses INTEGER DEFAULT 0, + draws INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS "game" ( diff --git a/server/src/db/models/game.model.ts b/server/src/db/models/game.model.ts index fe12521..527f115 100644 --- a/server/src/db/models/game.model.ts +++ b/server/src/db/models/game.model.ts @@ -5,7 +5,7 @@ export const activeGames: Array = []; // todo: join user and game relationship -export const create = async (game: Game) => { +export const save = async (game: Game) => { try { const white: User = {}; const black: User = {}; @@ -31,6 +31,28 @@ export const create = async (game: Game) => { black.name || null ] ); + if (black.id || white.id) { + // draws + if (game.winner === "draw") { + if (white.id) { + await db.query(`UPDATE "user" SET draws = draws + 1 WHERE id = $1`, [white.id]); + } + if (black.id) { + await db.query(`UPDATE "user" SET draws = draws + 1 WHERE id = $1`, [black.id]); + } + } else { + const winner = game.winner === "white" ? white : black; + const loser = game.winner === "white" ? black : white; + if (winner.id) { + await db.query(`UPDATE "user" SET wins = wins + 1 WHERE id = $1`, [winner.id]); + } + if (loser.id) { + await db.query(`UPDATE "user" SET losses = losses + 1 WHERE id = $1`, [ + loser.id + ]); + } + } + } return { id: res.rows[0].id, winner: res.rows[0].winner, @@ -135,7 +157,7 @@ export const remove = async (id: number) => { }; const GameModel = { - create, + save, findById, findByUserId, update, diff --git a/server/src/db/models/user.model.ts b/server/src/db/models/user.model.ts index 92ef948..5d29f1b 100644 --- a/server/src/db/models/user.model.ts +++ b/server/src/db/models/user.model.ts @@ -8,7 +8,7 @@ export const create = async (user: User, password: string) => { try { const res = await db.query( - `INSERT INTO "user"(name, email, password) VALUES($1, $2, $3) RETURNING id, name, email`, + `INSERT INTO "user"(name, email, password) VALUES($1, $2, $3) RETURNING id, name, email, wins, losses, draws`, [user.name, user.email || null, password] ); return res.rows[0] as User; @@ -23,7 +23,10 @@ export const findById = async (id: number) => { return null; } try { - const res = await db.query(`SELECT id, name, email FROM "user" WHERE id=$1`, [id]); + const res = await db.query( + `SELECT id, name, email, wins, losses, draws FROM "user" WHERE id=$1`, + [id] + ); if (res.rowCount) { return res.rows[0] as User; } else return null; @@ -37,9 +40,10 @@ export const findByNameEmail = async (user: User, includePassword = false, limit // if user is not specified, get all users if (!user) { try { - const res = await db.query(`SELECT id, name, email FROM "user" LIMIT $1`, [ - limit ?? 10 - ]); + const res = await db.query( + `SELECT id, name, email, wins, losses, draws FROM "user" LIMIT $1`, + [limit ?? 10] + ); return res.rows as Array; } catch (err: unknown) { console.log(err); @@ -49,7 +53,7 @@ export const findByNameEmail = async (user: User, includePassword = false, limit try { const res = await db.query( - `SELECT id, name, email${ + `SELECT id, name, email, wins, losses, draws${ includePassword ? `, password` : "" } FROM "user" WHERE name=$1 OR email=$2 LIMIT $3`, [user.name, user.email, limit ?? 1] @@ -67,11 +71,11 @@ export const update = async (id: number, updatedUser: User & { password?: string } try { - let query = `UPDATE "user" SET name=$1, email=$2 WHERE id=$3 RETURNING id, name, email`; + let query = `UPDATE "user" SET name=$1, email=$2 WHERE id=$3 RETURNING id, name, email, wins, losses, draws`; let values = [updatedUser.name, updatedUser.email, id]; if (updatedUser.password) { - query = `UPDATE "user" SET name=$1, email=$2, password=$3 WHERE id=$4 RETURNING id, name, email`; + query = `UPDATE "user" SET name=$1, email=$2, password=$3 WHERE id=$4 RETURNING id, name, email, wins, losses, draws`; values = [updatedUser.name, updatedUser.email, updatedUser.password, id]; } const res = await db.query(query, values); diff --git a/server/src/socket/game.socket.ts b/server/src/socket/game.socket.ts index f15fff6..6545869 100644 --- a/server/src/socket/game.socket.ts +++ b/server/src/socket/game.socket.ts @@ -138,7 +138,7 @@ export async function claimAbandoned(this: Socket, type: "win" | "draw") { game.winner = "black"; } - const { id } = (await GameModel.create(game)) as Game; + const { id } = (await GameModel.save(game)) as Game; game.id = id; const gameOver = { @@ -202,7 +202,7 @@ export async function sendMove(this: Socket, m: { from: string; to: string; prom } game.endReason = reason; - const { id } = (await GameModel.create(game)) as Game; // save game to db + const { id } = (await GameModel.save(game)) as Game; // save game to db game.id = id; io.to(game.code as string).emit("gameOver", { reason, winnerName, winnerSide, id }); } diff --git a/types/index.d.ts b/types/index.d.ts index e4bca64..94a583b 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -16,6 +16,9 @@ export interface User { id?: number | string; // string for guest IDs name?: string | null; email?: string; + wins?: number; + losses?: number; + draws?: number; // mainly for players, not spectators connected?: boolean;