67 lines
2.2 KiB
JavaScript
67 lines
2.2 KiB
JavaScript
import { Router } from 'express';
|
|
import db from '../db/index.js';
|
|
import { requireAuth } from '../auth/middleware.js';
|
|
import { getGame } from '../games/registry.js';
|
|
|
|
const router = Router();
|
|
|
|
const RESULTS = new Set(['win', 'loss', 'draw']);
|
|
|
|
// POST /api/history/single-player
|
|
// Body: { slug, score, opponentScores: number[], result }
|
|
// Records a finished single-player vs-AI match for the signed-in user.
|
|
// AI opponents do not get match_players rows (user_id is a FK to users).
|
|
router.post('/single-player', requireAuth, (req, res) => {
|
|
const { slug, score, opponentScores, result } = req.body ?? {};
|
|
|
|
if (typeof slug !== 'string' || !slug) {
|
|
return res.status(400).json({ error: 'Missing slug.' });
|
|
}
|
|
const def = getGame(slug);
|
|
if (!def) {
|
|
return res.status(400).json({ error: 'Unknown game slug.' });
|
|
}
|
|
if (!Number.isFinite(score) || score < 0 || score > 100000) {
|
|
return res.status(400).json({ error: 'Invalid score.' });
|
|
}
|
|
if (!Array.isArray(opponentScores) || !opponentScores.every((n) => Number.isFinite(n))) {
|
|
return res.status(400).json({ error: 'Invalid opponentScores.' });
|
|
}
|
|
if (!RESULTS.has(result)) {
|
|
return res.status(400).json({ error: 'Invalid result.' });
|
|
}
|
|
|
|
const tx = db.transaction(() => {
|
|
db.prepare(
|
|
`INSERT INTO games (slug, name, category, max_players, supports_multiplayer)
|
|
VALUES (?, ?, ?, ?, 0)
|
|
ON CONFLICT(slug) DO NOTHING`,
|
|
).run(def.slug, def.name, def.category, def.maxPlayers);
|
|
|
|
const gameRow = db.prepare('SELECT id FROM games WHERE slug = ?').get(def.slug);
|
|
|
|
const matchRes = db.prepare(
|
|
`INSERT INTO matches (game_id, ended_at, status)
|
|
VALUES (?, datetime('now'), 'completed')`,
|
|
).run(gameRow.id);
|
|
const matchId = matchRes.lastInsertRowid;
|
|
|
|
db.prepare(
|
|
`INSERT INTO match_players (match_id, user_id, seat, result, score)
|
|
VALUES (?, ?, 0, ?, ?)`,
|
|
).run(matchId, req.user.id, result, Math.round(score));
|
|
|
|
return matchId;
|
|
});
|
|
|
|
try {
|
|
const matchId = tx();
|
|
res.json({ matchId });
|
|
} catch (err) {
|
|
console.error('[history/single-player]', err);
|
|
res.status(500).json({ error: 'Failed to record match.' });
|
|
}
|
|
});
|
|
|
|
export default router;
|