162 lines
6.3 KiB
TypeScript
162 lines
6.3 KiB
TypeScript
import type { Game, User } from "@michess/types";
|
|
import { db } from "../index.js";
|
|
|
|
export const activeGames: Game[] = [];
|
|
|
|
export const save = async (game: Game) => {
|
|
try {
|
|
const white: User = { name: game.white?.name };
|
|
const black: User = { name: game.black?.name };
|
|
if (typeof game.white?.id !== "string") {
|
|
white.id = game.white?.id;
|
|
}
|
|
if (typeof game.black?.id !== "string") {
|
|
black.id = game.black?.id;
|
|
}
|
|
const res = await db.query(
|
|
`INSERT INTO "game"(winner, end_reason, pgn, white_id, white_name, black_id, black_name, started_at, vs_ai, ai_level) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *`,
|
|
[
|
|
game.winner || null,
|
|
game.endReason || null,
|
|
game.pgn,
|
|
white.id || null,
|
|
white.name || null,
|
|
black.id || null,
|
|
black.name || null,
|
|
new Date(game.startedAt as number),
|
|
game.vsAi || false,
|
|
game.aiLevel || 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,
|
|
endReason: res.rows[0].end_reason,
|
|
pgn: res.rows[0].pgn,
|
|
white: {
|
|
id: res.rows[0].white_id || undefined,
|
|
name: res.rows[0].white_name || undefined
|
|
},
|
|
black: {
|
|
id: res.rows[0].black_id || undefined,
|
|
name: res.rows[0].black_name || undefined
|
|
},
|
|
startedAt: res.rows[0].started_at.getTime(),
|
|
endedAt: res.rows[0].ended_at?.getTime() || undefined,
|
|
vsAi: res.rows[0].vs_ai || undefined,
|
|
aiLevel: res.rows[0].ai_level || undefined
|
|
} as Game;
|
|
} catch (err: unknown) {
|
|
console.log(err);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export const findById = async (id: number) => {
|
|
try {
|
|
const res = await db.query(
|
|
`SELECT game.id, game.winner, game.end_reason, game.pgn, game.vs_ai, game.ai_level, white_user.id AS white_id, COALESCE(white_user.name, game.white_name) AS white_name, black_user.id AS black_id, started_at, ended_at, COALESCE(black_user.name, game.black_name) AS black_name FROM game LEFT JOIN "user" white_user ON white_user.id = game.white_id LEFT JOIN "user" black_user ON black_user.id = game.black_id WHERE game.id=$1`,
|
|
[id]
|
|
);
|
|
if (res.rowCount) {
|
|
return {
|
|
id: res.rows[0].id,
|
|
winner: res.rows[0].winner,
|
|
endReason: res.rows[0].end_reason,
|
|
pgn: res.rows[0].pgn,
|
|
white: { id: res.rows[0].white_id || undefined, name: res.rows[0].white_name },
|
|
black: { id: res.rows[0].black_id || undefined, name: res.rows[0].black_name },
|
|
startedAt: res.rows[0].started_at.getTime(),
|
|
endedAt: res.rows[0].ended_at?.getTime() || undefined,
|
|
vsAi: res.rows[0].vs_ai || undefined,
|
|
aiLevel: res.rows[0].ai_level || undefined
|
|
} as Game;
|
|
} else return null;
|
|
} catch (err: unknown) {
|
|
console.log(err);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export const findByUserId = async (id: number, limit = 10) => {
|
|
if (id == 0) {
|
|
return null;
|
|
}
|
|
try {
|
|
// TODO: pagination
|
|
const res = await db.query(
|
|
`SELECT game.id, game.winner, game.end_reason, game.pgn, game.vs_ai, game.ai_level, white_user.id AS white_id, COALESCE(white_user.name, game.white_name) AS white_name, black_user.id AS black_id, started_at, ended_at, COALESCE(black_user.name, game.black_name) AS black_name FROM game LEFT JOIN "user" white_user ON white_user.id = game.white_id LEFT JOIN "user" black_user ON black_user.id = game.black_id WHERE white_user.id=$1 OR black_user.id=$1 ORDER BY id DESC LIMIT $2`,
|
|
[id, limit]
|
|
);
|
|
return res.rows.map((r) => {
|
|
return {
|
|
id: r.id,
|
|
winner: r.winner,
|
|
endReason: r.end_reason,
|
|
pgn: r.pgn,
|
|
white: { id: r.white_id || undefined, name: r.white_name },
|
|
black: { id: r.black_id || undefined, name: r.black_name },
|
|
startedAt: r.started_at.getTime(),
|
|
endedAt: r.ended_at?.getTime() || undefined,
|
|
vsAi: r.vs_ai || undefined,
|
|
aiLevel: r.ai_level || undefined
|
|
} as Game;
|
|
});
|
|
} catch (err: unknown) {
|
|
console.log(err);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export const remove = async (id: number) => {
|
|
try {
|
|
const res = await db.query(`DELETE FROM "game" WHERE id = $1 RETURNING *`, [id]);
|
|
return {
|
|
id: res.rows[0].id,
|
|
winner: res.rows[0].winner,
|
|
endReason: res.rows[0].end_reason,
|
|
pgn: res.rows[0].pgn,
|
|
white: { id: res.rows[0].white_id, name: res.rows[0].white_name },
|
|
black: { id: res.rows[0].black_id, name: res.rows[0].black_name },
|
|
startedAt: res.rows[0].started_at.getTime(),
|
|
endedAt: res.rows[0].ended_at?.getTime() || undefined,
|
|
vsAi: res.rows[0].vs_ai || undefined,
|
|
aiLevel: res.rows[0].ai_level || undefined
|
|
} as Game;
|
|
} catch (err: unknown) {
|
|
console.log(err);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const GameModel = {
|
|
save,
|
|
findById,
|
|
findByUserId,
|
|
remove
|
|
};
|
|
|
|
export default GameModel;
|