110 lines
4.0 KiB
TypeScript
110 lines
4.0 KiB
TypeScript
import { usePrisma } from "../../../../utils/prisma";
|
|
|
|
const WIN_LINES = [
|
|
[0, 1, 2], [3, 4, 5], [6, 7, 8],
|
|
[0, 3, 6], [1, 4, 7], [2, 5, 8],
|
|
[0, 4, 8], [2, 4, 6],
|
|
];
|
|
|
|
function checkWinner(board: string): "X" | "O" | null {
|
|
for (const [a, b, c] of WIN_LINES) {
|
|
if (board[a!] !== "-" && board[a!] === board[b!] && board[a!] === board[c!]) {
|
|
return board[a!] as "X" | "O";
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await requireUser(event);
|
|
const id = getRouterParam(event, "id");
|
|
if (!id) throw createError({ statusCode: 400, message: "id fehlt" });
|
|
|
|
const body = await readBody(event) as { cellIndex: number };
|
|
const { cellIndex } = body;
|
|
|
|
if (typeof cellIndex !== "number" || cellIndex < 0 || cellIndex > 8) {
|
|
throw createError({ statusCode: 400, message: "Ungültiger Zug" });
|
|
}
|
|
|
|
const db = usePrisma();
|
|
const challenge = await db.gameChallenge.findUnique({ where: { id } });
|
|
|
|
if (!challenge) throw createError({ statusCode: 404, message: "Challenge nicht gefunden" });
|
|
if (challenge.status !== "ACTIVE") throw createError({ statusCode: 409, message: "Spiel nicht aktiv" });
|
|
|
|
const isChallenger = user.id === challenge.challengerId;
|
|
const isOpponent = user.id === challenge.opponentId;
|
|
|
|
if (!isChallenger && !isOpponent) throw createError({ statusCode: 403, message: "Nicht autorisiert" });
|
|
|
|
const myMark = isChallenger ? "X" : "O";
|
|
if (challenge.currentTurn !== myMark) throw createError({ statusCode: 409, message: "Nicht dein Zug" });
|
|
if (challenge.board[cellIndex] !== "-") throw createError({ statusCode: 409, message: "Feld bereits belegt" });
|
|
|
|
const cells = challenge.board.split("");
|
|
cells[cellIndex] = myMark;
|
|
const newBoard = cells.join("");
|
|
|
|
const winner = checkWinner(newBoard);
|
|
const isDraw = !winner && !newBoard.includes("-");
|
|
|
|
const updated = await db.gameChallenge.update({
|
|
where: { id },
|
|
data: {
|
|
board: newBoard,
|
|
currentTurn: myMark === "X" ? "O" : "X",
|
|
...(winner && { winner, status: "FINISHED" }),
|
|
...(isDraw && { winner: "draw", status: "FINISHED" }),
|
|
},
|
|
});
|
|
|
|
// Ranking update wenn Spiel beendet
|
|
if ((winner || isDraw) && challenge.opponentId && challenge.opponentName) {
|
|
const challengerId = challenge.challengerId;
|
|
const opponentId = challenge.opponentId;
|
|
const challengerName = challenge.challengerName;
|
|
const opponentName = challenge.opponentName;
|
|
|
|
if (isDraw) {
|
|
await Promise.all([
|
|
db.gameScore.upsert({
|
|
where: { userId: challengerId },
|
|
update: { draws: { increment: 1 }, points: { increment: 1 }, playerName: challengerName },
|
|
create: { userId: challengerId, playerName: challengerName, draws: 1, points: 1 },
|
|
}),
|
|
db.gameScore.upsert({
|
|
where: { userId: opponentId },
|
|
update: { draws: { increment: 1 }, points: { increment: 1 }, playerName: opponentName },
|
|
create: { userId: opponentId, playerName: opponentName, draws: 1, points: 1 },
|
|
}),
|
|
]);
|
|
} else {
|
|
const winnerId = winner === "X" ? challengerId : opponentId;
|
|
const loserId = winner === "X" ? opponentId : challengerId;
|
|
const winnerName = winner === "X" ? challengerName : opponentName;
|
|
const loserName = winner === "X" ? opponentName : challengerName;
|
|
|
|
await Promise.all([
|
|
db.gameScore.upsert({
|
|
where: { userId: winnerId },
|
|
update: { wins: { increment: 1 }, points: { increment: 3 }, playerName: winnerName },
|
|
create: { userId: winnerId, playerName: winnerName, wins: 1, points: 3 },
|
|
}),
|
|
db.gameScore.upsert({
|
|
where: { userId: loserId },
|
|
update: { losses: { increment: 1 }, playerName: loserName },
|
|
create: { userId: loserId, playerName: loserName, losses: 1 },
|
|
}),
|
|
]);
|
|
}
|
|
}
|
|
|
|
// Delete community post when game ends
|
|
if ((winner || isDraw) && challenge.postId) {
|
|
await db.communityPost.delete({ where: { id: challenge.postId } }).catch(() => {});
|
|
}
|
|
|
|
return updated;
|
|
});
|