initial commit
This commit is contained in:
340
backend/routes/sessions.js
Normal file
340
backend/routes/sessions.js
Normal file
@@ -0,0 +1,340 @@
|
||||
const express = require('express');
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const db = require('../database');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Get all sessions
|
||||
router.get('/', (req, res) => {
|
||||
try {
|
||||
const sessions = db.prepare(`
|
||||
SELECT
|
||||
s.*,
|
||||
COUNT(sg.id) as games_played
|
||||
FROM sessions s
|
||||
LEFT JOIN session_games sg ON s.id = sg.session_id
|
||||
GROUP BY s.id
|
||||
ORDER BY s.created_at DESC
|
||||
`).all();
|
||||
|
||||
res.json(sessions);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get active session
|
||||
router.get('/active', (req, res) => {
|
||||
try {
|
||||
const session = db.prepare(`
|
||||
SELECT
|
||||
s.*,
|
||||
COUNT(sg.id) as games_played
|
||||
FROM sessions s
|
||||
LEFT JOIN session_games sg ON s.id = sg.session_id
|
||||
WHERE s.is_active = 1
|
||||
GROUP BY s.id
|
||||
LIMIT 1
|
||||
`).get();
|
||||
|
||||
if (!session) {
|
||||
return res.status(404).json({ error: 'No active session found' });
|
||||
}
|
||||
|
||||
res.json(session);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get single session by ID
|
||||
router.get('/:id', (req, res) => {
|
||||
try {
|
||||
const session = db.prepare(`
|
||||
SELECT
|
||||
s.*,
|
||||
COUNT(sg.id) as games_played
|
||||
FROM sessions s
|
||||
LEFT JOIN session_games sg ON s.id = sg.session_id
|
||||
WHERE s.id = ?
|
||||
GROUP BY s.id
|
||||
`).get(req.params.id);
|
||||
|
||||
if (!session) {
|
||||
return res.status(404).json({ error: 'Session not found' });
|
||||
}
|
||||
|
||||
res.json(session);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Create new session (admin only)
|
||||
router.post('/', authenticateToken, (req, res) => {
|
||||
try {
|
||||
const { notes } = req.body;
|
||||
|
||||
// Check if there's already an active session
|
||||
const activeSession = db.prepare('SELECT id FROM sessions WHERE is_active = 1').get();
|
||||
|
||||
if (activeSession) {
|
||||
return res.status(400).json({
|
||||
error: 'An active session already exists. Please close it before creating a new one.',
|
||||
activeSessionId: activeSession.id
|
||||
});
|
||||
}
|
||||
|
||||
const stmt = db.prepare(`
|
||||
INSERT INTO sessions (notes, is_active)
|
||||
VALUES (?, 1)
|
||||
`);
|
||||
|
||||
const result = stmt.run(notes || null);
|
||||
const newSession = db.prepare('SELECT * FROM sessions WHERE id = ?').get(result.lastInsertRowid);
|
||||
|
||||
res.status(201).json(newSession);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Close/finalize session (admin only)
|
||||
router.post('/:id/close', authenticateToken, (req, res) => {
|
||||
try {
|
||||
const { notes } = req.body;
|
||||
|
||||
const session = db.prepare('SELECT * FROM sessions WHERE id = ?').get(req.params.id);
|
||||
|
||||
if (!session) {
|
||||
return res.status(404).json({ error: 'Session not found' });
|
||||
}
|
||||
|
||||
if (session.is_active === 0) {
|
||||
return res.status(400).json({ error: 'Session is already closed' });
|
||||
}
|
||||
|
||||
const stmt = db.prepare(`
|
||||
UPDATE sessions
|
||||
SET is_active = 0, closed_at = CURRENT_TIMESTAMP, notes = COALESCE(?, notes)
|
||||
WHERE id = ?
|
||||
`);
|
||||
|
||||
stmt.run(notes || null, req.params.id);
|
||||
|
||||
const closedSession = db.prepare('SELECT * FROM sessions WHERE id = ?').get(req.params.id);
|
||||
res.json(closedSession);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Get games played in a session
|
||||
router.get('/:id/games', (req, res) => {
|
||||
try {
|
||||
const games = db.prepare(`
|
||||
SELECT
|
||||
sg.*,
|
||||
g.pack_name,
|
||||
g.title,
|
||||
g.game_type,
|
||||
g.min_players,
|
||||
g.max_players,
|
||||
g.popularity_score
|
||||
FROM session_games sg
|
||||
JOIN games g ON sg.game_id = g.id
|
||||
WHERE sg.session_id = ?
|
||||
ORDER BY sg.played_at ASC
|
||||
`).all(req.params.id);
|
||||
|
||||
res.json(games);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Add game to session (admin only)
|
||||
router.post('/:id/games', authenticateToken, (req, res) => {
|
||||
try {
|
||||
const { game_id, manually_added } = req.body;
|
||||
|
||||
if (!game_id) {
|
||||
return res.status(400).json({ error: 'game_id is required' });
|
||||
}
|
||||
|
||||
// Verify session exists and is active
|
||||
const session = db.prepare('SELECT * FROM sessions WHERE id = ?').get(req.params.id);
|
||||
|
||||
if (!session) {
|
||||
return res.status(404).json({ error: 'Session not found' });
|
||||
}
|
||||
|
||||
if (session.is_active === 0) {
|
||||
return res.status(400).json({ error: 'Cannot add games to a closed session' });
|
||||
}
|
||||
|
||||
// Verify game exists
|
||||
const game = db.prepare('SELECT * FROM games WHERE id = ?').get(game_id);
|
||||
|
||||
if (!game) {
|
||||
return res.status(404).json({ error: 'Game not found' });
|
||||
}
|
||||
|
||||
// Add game to session
|
||||
const stmt = db.prepare(`
|
||||
INSERT INTO session_games (session_id, game_id, manually_added)
|
||||
VALUES (?, ?, ?)
|
||||
`);
|
||||
|
||||
const result = stmt.run(req.params.id, game_id, manually_added ? 1 : 0);
|
||||
|
||||
// Increment play count for the game
|
||||
db.prepare('UPDATE games SET play_count = play_count + 1 WHERE id = ?').run(game_id);
|
||||
|
||||
const sessionGame = db.prepare(`
|
||||
SELECT
|
||||
sg.*,
|
||||
g.pack_name,
|
||||
g.title,
|
||||
g.game_type
|
||||
FROM session_games sg
|
||||
JOIN games g ON sg.game_id = g.id
|
||||
WHERE sg.id = ?
|
||||
`).get(result.lastInsertRowid);
|
||||
|
||||
res.status(201).json(sessionGame);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Import chat log and process popularity (admin only)
|
||||
router.post('/:id/chat-import', authenticateToken, (req, res) => {
|
||||
try {
|
||||
const { chatData } = req.body;
|
||||
|
||||
if (!chatData || !Array.isArray(chatData)) {
|
||||
return res.status(400).json({ error: 'chatData must be an array' });
|
||||
}
|
||||
|
||||
const session = db.prepare('SELECT * FROM sessions WHERE id = ?').get(req.params.id);
|
||||
|
||||
if (!session) {
|
||||
return res.status(404).json({ error: 'Session not found' });
|
||||
}
|
||||
|
||||
// Get all games played in this session with timestamps
|
||||
const sessionGames = db.prepare(`
|
||||
SELECT sg.game_id, sg.played_at, g.title
|
||||
FROM session_games sg
|
||||
JOIN games g ON sg.game_id = g.id
|
||||
WHERE sg.session_id = ?
|
||||
ORDER BY sg.played_at ASC
|
||||
`).all(req.params.id);
|
||||
|
||||
if (sessionGames.length === 0) {
|
||||
return res.status(400).json({ error: 'No games played in this session to match votes against' });
|
||||
}
|
||||
|
||||
let votesProcessed = 0;
|
||||
const votesByGame = {};
|
||||
|
||||
const insertChatLog = db.prepare(`
|
||||
INSERT INTO chat_logs (session_id, chatter_name, message, timestamp, parsed_vote)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
const updatePopularity = db.prepare(`
|
||||
UPDATE games SET popularity_score = popularity_score + ? WHERE id = ?
|
||||
`);
|
||||
|
||||
const processVotes = db.transaction((messages) => {
|
||||
for (const msg of messages) {
|
||||
const { username, message, timestamp } = msg;
|
||||
|
||||
if (!username || !message || !timestamp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for vote patterns
|
||||
let vote = null;
|
||||
if (message.includes('thisgame++')) {
|
||||
vote = 'thisgame++';
|
||||
} else if (message.includes('thisgame--')) {
|
||||
vote = 'thisgame--';
|
||||
}
|
||||
|
||||
// Insert into chat logs
|
||||
insertChatLog.run(
|
||||
req.params.id,
|
||||
username,
|
||||
message,
|
||||
timestamp,
|
||||
vote
|
||||
);
|
||||
|
||||
if (vote) {
|
||||
// Find which game was being played at this timestamp
|
||||
const messageTime = new Date(timestamp).getTime();
|
||||
let matchedGame = null;
|
||||
|
||||
for (let i = 0; i < sessionGames.length; i++) {
|
||||
const currentGame = sessionGames[i];
|
||||
const nextGame = sessionGames[i + 1];
|
||||
|
||||
const currentGameTime = new Date(currentGame.played_at).getTime();
|
||||
|
||||
if (nextGame) {
|
||||
const nextGameTime = new Date(nextGame.played_at).getTime();
|
||||
if (messageTime >= currentGameTime && messageTime < nextGameTime) {
|
||||
matchedGame = currentGame;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Last game in session
|
||||
if (messageTime >= currentGameTime) {
|
||||
matchedGame = currentGame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedGame) {
|
||||
const points = vote === 'thisgame++' ? 1 : -1;
|
||||
updatePopularity.run(points, matchedGame.game_id);
|
||||
|
||||
if (!votesByGame[matchedGame.game_id]) {
|
||||
votesByGame[matchedGame.game_id] = {
|
||||
title: matchedGame.title,
|
||||
upvotes: 0,
|
||||
downvotes: 0
|
||||
};
|
||||
}
|
||||
|
||||
if (points > 0) {
|
||||
votesByGame[matchedGame.game_id].upvotes++;
|
||||
} else {
|
||||
votesByGame[matchedGame.game_id].downvotes++;
|
||||
}
|
||||
|
||||
votesProcessed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
processVotes(chatData);
|
||||
|
||||
res.json({
|
||||
message: 'Chat log imported and processed successfully',
|
||||
messagesImported: chatData.length,
|
||||
votesProcessed,
|
||||
votesByGame
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user