more QOL improvements
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 29s

This commit is contained in:
2026-02-28 01:37:32 -05:00
parent b9981d0e70
commit 4f9e92bda7
18 changed files with 426 additions and 32 deletions

View File

@@ -180,21 +180,75 @@ const Hunts = {
return new Date(hunt.expiry_date) < new Date();
},
getLeaderboard(huntId) {
return db.prepare(`
getLeaderboard(huntId, limit = null, offset = 0) {
let sql = `
SELECT u.id, u.username, SUM(s.points_awarded) as total_points, COUNT(s.id) as scans
FROM scans s
JOIN users u ON s.user_id = u.id
JOIN packages p ON s.package_id = p.id
WHERE p.hunt_id = ? AND s.points_awarded > 0
GROUP BY u.id
ORDER BY total_points DESC
`).all(huntId);
ORDER BY total_points DESC`;
if (limit) {
sql += ` LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`;
}
return db.prepare(sql).all(huntId);
},
getLeaderboardCount(huntId) {
return db.prepare(`
SELECT COUNT(DISTINCT s.user_id) as count
FROM scans s
JOIN packages p ON s.package_id = p.id
WHERE p.hunt_id = ? AND s.points_awarded > 0
`).get(huntId).count;
},
shortNameExists(shortName) {
const row = db.prepare('SELECT id FROM hunts WHERE short_name = ? COLLATE NOCASE').get(shortName);
return !!row;
},
update(id, name, description, expiryDate) {
db.prepare('UPDATE hunts SET name = ?, description = ?, expiry_date = ? WHERE id = ?')
.run(name, description, expiryDate || null, id);
},
delete(id) {
const doDelete = db.transaction(() => {
// Delete scans for all packages in this hunt
db.prepare('DELETE FROM scans WHERE package_id IN (SELECT id FROM packages WHERE hunt_id = ?)').run(id);
// Delete packages
db.prepare('DELETE FROM packages WHERE hunt_id = ?').run(id);
// Delete hunt
db.prepare('DELETE FROM hunts WHERE id = ?').run(id);
});
doDelete();
},
getStats(huntId) {
const totalScans = db.prepare('SELECT COUNT(*) as count FROM scans s JOIN packages p ON s.package_id = p.id WHERE p.hunt_id = ? AND s.points_awarded > 0').get(huntId).count;
const uniquePlayers = db.prepare('SELECT COUNT(DISTINCT s.user_id) as count FROM scans s JOIN packages p ON s.package_id = p.id WHERE p.hunt_id = ? AND s.points_awarded > 0').get(huntId).count;
const discoveredCount = db.prepare('SELECT COUNT(*) as count FROM packages WHERE hunt_id = ? AND scan_count > 0').get(huntId).count;
const totalPackages = db.prepare('SELECT package_count FROM hunts WHERE id = ?').get(huntId).package_count;
const totalPoints = db.prepare('SELECT COALESCE(SUM(s.points_awarded), 0) as total FROM scans s JOIN packages p ON s.package_id = p.id WHERE p.hunt_id = ?').get(huntId).total;
const topFinders = db.prepare(`
SELECT u.username, SUM(s.points_awarded) as points, COUNT(s.id) as finds
FROM scans s
JOIN users u ON s.user_id = u.id
JOIN packages p ON s.package_id = p.id
WHERE p.hunt_id = ? AND s.points_awarded > 0
GROUP BY u.id ORDER BY points DESC LIMIT 5
`).all(huntId);
const recentScans = db.prepare(`
SELECT s.scanned_at, s.points_awarded, u.username, p.card_number
FROM scans s
JOIN users u ON s.user_id = u.id
JOIN packages p ON s.package_id = p.id
WHERE p.hunt_id = ? AND s.points_awarded > 0
ORDER BY s.scanned_at DESC LIMIT 10
`).all(huntId);
return { totalScans, uniquePlayers, discoveredCount, totalPackages, totalPoints, topFinders, recentScans, discoveryRate: totalPackages > 0 ? Math.round((discoveredCount / totalPackages) * 100) : 0 };
}
};
@@ -320,15 +374,22 @@ const Scans = {
return doScan();
},
getGlobalLeaderboard() {
return db.prepare(`
getGlobalLeaderboard(limit = null, offset = 0) {
let sql = `
SELECT u.id, u.username, SUM(s.points_awarded) as total_points, COUNT(s.id) as scans
FROM scans s
JOIN users u ON s.user_id = u.id
WHERE s.points_awarded > 0
GROUP BY u.id
ORDER BY total_points DESC
`).all();
ORDER BY total_points DESC`;
if (limit) {
sql += ` LIMIT ${parseInt(limit)} OFFSET ${parseInt(offset)}`;
}
return db.prepare(sql).all();
},
getGlobalLeaderboardCount() {
return db.prepare('SELECT COUNT(DISTINCT user_id) as count FROM scans WHERE points_awarded > 0').get().count;
},
getRecentActivity(limit = 5) {