diff options
| author | Pinapelz <yukais@pinapelz.com> | 2025-07-05 21:42:22 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2025-07-05 21:42:22 -0700 |
| commit | 400d772cc391d979747510776fa8acfb5a1d00cb (patch) | |
| tree | 55e1d4bd5bdbd65418e4d6f5822bd3c1c1fc1e32 /backend/src | |
| parent | 943014fd38a3d784542f78cd4625d1ef2e220980 (diff) | |
implement generic score viewer and import deduplication
Diffstat (limited to 'backend/src')
| -rw-r--r-- | backend/src/config/constants.ts | 1 | ||||
| -rw-r--r-- | backend/src/index.ts | 1 | ||||
| -rw-r--r-- | backend/src/routes/score.ts | 95 |
3 files changed, 85 insertions, 12 deletions
diff --git a/backend/src/config/constants.ts b/backend/src/config/constants.ts new file mode 100644 index 0000000..45d559e --- /dev/null +++ b/backend/src/config/constants.ts @@ -0,0 +1 @@ +export const PAGE_SIZE = 25; diff --git a/backend/src/index.ts b/backend/src/index.ts index 4a63c41..ec38ee6 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -54,6 +54,7 @@ app.get('/api/session', userRoutes.handleGetCurrentSession); app.get('/api/supportedGames', gameRoutes.handleGetSupportedGames); app.post('/api/uploadScore', requireAuth, scoreRoutes.handleScoreUpload); +app.get('/api/scores', scoreRoutes.handleGetScores); app.listen(port, () => { console.log(`Server listening on port ${port}`); diff --git a/backend/src/routes/score.ts b/backend/src/routes/score.ts index 9e9c597..4bbedb4 100644 --- a/backend/src/routes/score.ts +++ b/backend/src/routes/score.ts @@ -1,6 +1,6 @@ import express from 'express'; import { prisma } from '../config/db'; -import { timeStamp } from 'node:console'; +import { PAGE_SIZE } from '../config/constants'; export const handleScoreUpload = async (req: express.Request, res: express.Response) => { try { @@ -28,21 +28,46 @@ export const handleScoreUpload = async (req: express.Request, res: express.Respo const internalGameName = game.internalName; const scoresArray = Array.isArray(scores) ? scores : [scores]; - // Create score records - const createdScores = await prisma.score.createMany({ - data: scoresArray.map(scoreData => ({ - gameInternalName: internalGameName, - userId: userId, - timestamp: scoreData.timestamp, - data: scoreData - })) - }); + const scoresToCreate = []; + let skippedCount = 0; + + for (const scoreData of scoresArray) { + // Check if exact same score data already exists + const existingScore = await prisma.score.findFirst({ + where: { + gameInternalName: internalGameName, + userId: userId, + data: { + equals: scoreData + } + } + }); + + if (existingScore) { + skippedCount++; + } else { + scoresToCreate.push({ + gameInternalName: internalGameName, + userId: userId, + timestamp: scoreData.timestamp, + data: scoreData + }); + } + } + + const createdScores = scoresToCreate.length > 0 + ? await prisma.score.createMany({ + data: scoresToCreate + }) + : { count: 0 }; res.status(200).json({ - message: 'Score upload received successfully', + message: 'Score upload processed successfully', game: meta.game, service: meta.service, - scoreCount: createdScores.count + scoreCount: createdScores.count, + skippedCount: skippedCount, + totalProcessed: scoresArray.length }); } catch (error) { @@ -50,3 +75,49 @@ export const handleScoreUpload = async (req: express.Request, res: express.Respo res.status(500).json({ error: 'Internal server error. Unable to process score upload' }); } } + +export const handleGetScores = async (req: express.Request, res: express.Response) => { + try { + const { userId, internalGameName, pageNum } = req.query; + if (!userId || !internalGameName || !pageNum) { + return res.status(400).json({ error: 'Missing required parameters' }); + } + const pageNumber = parseInt(pageNum as string); + const gameInternalName = internalGameName as string; + const userIdNumber = parseInt(userId as string); + + const num_pages = Math.ceil(await prisma.score.count({ + where: { + gameInternalName: gameInternalName, + userId: userIdNumber + } + }) / PAGE_SIZE); + + const scores = await prisma.score.findMany({ + where: { + gameInternalName: gameInternalName, + userId: userIdNumber + }, + orderBy: { + timestamp: 'desc' + }, + skip: (pageNumber - 1) * PAGE_SIZE, + take: PAGE_SIZE + }); + + const safeScores = scores.map(score => ({ + ...score, + timestamp: typeof score.timestamp === 'bigint' + ? Number(score.timestamp) + : score.timestamp + })); + + res.status(200).json({ + scores: safeScores, + num_pages + }); + } catch (error) { + console.error('Failed to fetch scores:', error); + res.status(500).json({ error: 'Internal server error. Unable to process score upload' }); + } +}; |
