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