const DB=require('better-sqlite3'); const {Router}=require('express'); const db=new DB('db.sqlite'); const api=new Router(); const leaderboardSelect='SELECT username, score, length, time, speed FROM leaderboards'; const getLeaderboardsBy={ score: db.prepare(`${leaderboardSelect} WHERE mode=? ORDER BY score DESC LIMIT ? OFFSET ?`), timeA: db.prepare(`${leaderboardSelect} WHERE mode=? ORDER BY time ASC LIMIT ? OFFSET ?`), timeD: db.prepare(`${leaderboardSelect} WHERE mode=? ORDER BY time DESC LIMIT ? OFFSET ?`) }; const addLeaderboard=db.prepare(` INSERT INTO leaderboards(mode, username, score, length, time, speed) VALUES(@mode, @username, @score, @length, @time, @speed) `); const levelList=require('./assets/levelList.json'); const validMode=mode => { try { const [category, name]=mode.split('/'); return levelList[category].levels.map(l => ''+l).includes(name); } catch(e) { return false; } }; api.get('/leaderboards/:category/:id', (req, res) => { const sort=req.query.sort || 'score'; if(!['score', 'timeA', 'timeD'].includes(sort)) return res.status(400).json({ ok: false, err: 'Invalid sort' }); const results=+req.query.results || 20; if((typeof results)!='number' || results<1 || results >100) return res.status(400).json({ ok: false, err: 'Invalid result count' }); const page=+req.query.page || 1; if((typeof page)!='number' || page<1) return res.status(400).json({ ok: false, err: 'Invalid page' }); const data=getLeaderboardsBy[sort] .all(req.params.category+'/'+req.params.id, results, (page-1)*results); return res.status(200).json({ ok: true, data }); }); api.post('/leaderboards/:category/:id', (req, res) => { const mode=req.params.category+'/'+req.params.id; if((typeof mode)!='string' || !validMode(mode)) return res.status(400).json({ ok: false, err: 'Invalid mode' }); const username=req.body.username; if((typeof username)!='string' || username.length>100) return res.status(400).json({ ok: false, err: 'Invalid username' }); const score=req.body.score; if((typeof score)!='number' || score%1 || score<0) return res.status(400).json({ ok: false, err: 'Invalid score' }); const length=req.body.length; if((typeof length)!='number' || length%1 || length<1) return res.status(400).json({ ok: false, err: 'Invalid length' }); const time=req.body.time; if((typeof time)!='number' || time%1 || time<0) return res.status(400).json({ ok: false, err: 'Invalid time' }); const speed=req.body.speed; if((typeof speed)!='number' || speed%1 || speed<0) return res.status(400).json({ ok: false, err: 'Invalid speed' }); try { addLeaderboard.run({ mode, username, score, length, time, speed }); res.json({ ok: true }); } catch(e) { res.status(500).json({ ok: false, err: 'Failed to add score' }); } }); return module.exports=exports=api;