aboutsummaryrefslogtreecommitdiffstats
path: root/backend
diff options
context:
space:
mode:
authorPinapelz <yukais@pinapelz.com>2025-07-05 21:42:22 -0700
committerPinapelz <yukais@pinapelz.com>2025-07-05 21:42:22 -0700
commit400d772cc391d979747510776fa8acfb5a1d00cb (patch)
tree55e1d4bd5bdbd65418e4d6f5822bd3c1c1fc1e32 /backend
parent943014fd38a3d784542f78cd4625d1ef2e220980 (diff)
implement generic score viewer and import deduplication
Diffstat (limited to 'backend')
-rw-r--r--backend/src/config/constants.ts1
-rw-r--r--backend/src/index.ts1
-rw-r--r--backend/src/routes/score.ts95
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' });
+ }
+};
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage