This commit is contained in:
2025-09-11 15:41:48 +02:00
parent e7b964078c
commit 86c2cd0d70
6 changed files with 799 additions and 99 deletions

View File

@@ -1,8 +1,5 @@
import { Router } from "express";
import dotenv from 'dotenv';
dotenv.config();
const db = await import('./db.js'); // dynamic import because otherwise dotenv will not work correctly
import { pool } from './db.js';
const router = Router();
@@ -10,73 +7,112 @@ router.get("/healthcheck", (req, res) => {
res.json({ status: "ok" })
});
router.post("/scores", async (req, res) => {
console.log(req.body)
const { name, game, score } = req.body;
if (!name || !game || !Number.isFinite(score) || !Number.isInteger(score) || score < 0) {
return res.status(400).json({ error: "Missing or invalid parameters" });
}
const conn = await db.pool.getConnection();
try {
await conn.beginTransaction();
const [userRows] = await conn.query(
`INSERT INTO users (name) VALUES (?)`,
[name]
);
const userId = userRows.insertId;
const [gameRows] = await conn.query(
`INSERT INTO games (name) VALUES (?) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)`,
[game]
);
const gameId = gameRows.insertId;
await conn.query(
`
INSERT INTO scores (user_id, game_id, score)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE score = GREATEST(score, VALUES(score))
`,
[userId, gameId, score]
);
await conn.commit();
res.json({ success: true });
} catch (err) {
await conn.rollback();
console.error(err);
res.status(500).json({ error: "Database error" });
} finally {
conn.release();
}
router.get("/users", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM users`);
res.json(rows);
});
router.get("/leaderboard/:game", async (req, res) => {
const gameName = req.params.game;
router.get("/users/:id", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM users WHERE id = ?`, [req.params.id]);
res.json(rows[0] || null);
});
try {
const [rows] = await db.pool.query(
`
SELECT u.name AS user, s.score, s.created_at
FROM scores s
JOIN users u ON s.user_id = u.id
JOIN games g ON s.game_id = g.id
WHERE g.name = ?
ORDER BY s.score DESC, s.created_at ASC
LIMIT 10
`,
[gameName]
);
router.post("/users", async (req, res) => {
const { username } = req.body;
const [result] = await pool.query(`INSERT INTO users (username) VALUES (?)`, [username]);
res.status(201).json({ id: result.insertId, username });
});
res.json({ leaderboard: rows });
} catch (err) {
console.error(err);
res.status(500).json({ error: "Database error" });
}
router.put("/users/:id", async (req, res) => {
const { username } = req.body;
await pool.query(`UPDATE users SET username = ? WHERE id = ?`, [username, req.params.id]);
res.json({ id: req.params.id, username });
});
router.delete("/users/:id", async (req, res) => {
await pool.query(`DELETE FROM users WHERE id = ?`, [req.params.id]);
res.status(204).send();
});
router.get("/users/:id/settings", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM user_settings WHERE user = ?`, [req.params.id]);
res.json(rows[0] || null);
});
router.put("/users/:id/settings", async (req, res) => {
const { input_method } = req.body;
await pool.query(`
INSERT INTO user_settings (user, input_method)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE input_method = ?
`, [req.params.id, input_method, input_method]);
res.json({ user: req.params.id, input_method });
});
router.get("/games", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM games`);
res.json(rows);
});
router.get("/games/:id", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM games WHERE id = ?`, [req.params.id]);
res.json(rows[0] || null);
});
router.post("/games", async (req, res) => {
const [result] = await pool.query(`INSERT INTO games (created_at) VALUES (NOW())`);
res.status(201).json({ id: result.insertId, created_at: new Date() });
});
router.put("/games/:id", async (req, res) => {
const { winner } = req.body;
await pool.query(`UPDATE games SET winner = ? WHERE id = ?`, [winner, req.params.id]);
res.json({ id: req.params.id, winner });
});
router.delete("/games/:id", async (req, res) => {
await pool.query(`DELETE FROM games WHERE id = ?`, [req.params.id]);
res.status(204).send();
});
router.get("/games/:id/players", async (req, res) => {
const [rows] = await pool.query(`
SELECT u.id, u.username
FROM game_players gp
JOIN users u ON gp.user = u.id
WHERE gp.game = ?
`, [req.params.id]);
res.json(rows);
});
router.post("/games/:id/players", async (req, res) => {
const { user } = req.body;
await pool.query(`INSERT IGNORE INTO game_players (game, user) VALUES (?, ?)`, [req.params.id, user]);
res.status(201).json({ game: req.params.id, user });
});
router.delete("/games/:id/players/:user", async (req, res) => {
await pool.query(`DELETE FROM game_players WHERE game = ? AND user = ?`, [req.params.id, req.params.user]);
res.status(204).send();
});
router.get("/games/:id/turns", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM turns WHERE game = ? ORDER BY round_number`, [req.params.id]);
res.json(rows);
});
router.post("/games/:id/turns", async (req, res) => {
const { user, round_number, start_points, first_throw, second_throw, third_throw, end_points } = req.body;
const [result] = await pool.query(`
INSERT INTO turns (game, user, round_number, start_points, first_throw, second_throw, third_throw, end_points)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`, [req.params.id, user, round_number, start_points, first_throw, second_throw, third_throw, end_points]);
res.status(201).json({ id: result.insertId });
});
router.get("/turns/:id", async (req, res) => {
const [rows] = await pool.query(`SELECT * FROM turns WHERE id = ?`, [req.params.id]);
res.json(rows[0] || null);
});
export default router;