mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-03-11 06:05:16 +08:00
init leaderboards branch
This commit is contained in:
parent
2160285e1e
commit
54c68e68bc
6 changed files with 242 additions and 9 deletions
38
backend/api/controllers/leaderboards.js
Normal file
38
backend/api/controllers/leaderboards.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
const LeaderboardsDAO = require("../../dao/leaderboards");
|
||||
|
||||
class LeaderboardsController {
|
||||
static async get(req, res, next) {
|
||||
try {
|
||||
const { language, mode, mode2 } = req.query;
|
||||
if (!language || !mode || !mode2) {
|
||||
return res.status(400).json({
|
||||
message: "Missing parameters",
|
||||
});
|
||||
}
|
||||
let retval = await LeaderboardsDAO.get(mode, mode2, language);
|
||||
retval.forEach((item) => {
|
||||
delete item.uid;
|
||||
});
|
||||
return res.status(200).json(retval);
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
}
|
||||
|
||||
static async update(req, res, next) {
|
||||
try {
|
||||
const { language, mode, mode2 } = req.body;
|
||||
if (!language || !mode || !mode2) {
|
||||
return res.status(400).json({
|
||||
message: "Missing parameters",
|
||||
});
|
||||
}
|
||||
let retval = await LeaderboardsDAO.update(mode, mode2, language);
|
||||
return res.status(200).json(retval);
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LeaderboardsController;
|
22
backend/api/routes/leaderboards.js
Normal file
22
backend/api/routes/leaderboards.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const { authenticateRequest } = require("../../middlewares/auth");
|
||||
const LeaderboardsController = require("../controllers/leaderboards");
|
||||
const RateLimit = require("../../middlewares/rate-limit");
|
||||
|
||||
const { Router } = require("express");
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get(
|
||||
"/",
|
||||
RateLimit.limit1persec,
|
||||
authenticateRequest,
|
||||
LeaderboardsController.get
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/debug_update",
|
||||
RateLimit.limit1persec,
|
||||
LeaderboardsController.update
|
||||
);
|
||||
|
||||
module.exports = router;
|
84
backend/dao/leaderboards.js
Normal file
84
backend/dao/leaderboards.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
const MonkeyError = require("../handlers/error");
|
||||
const { mongoDB } = require("../init/mongodb");
|
||||
const { ObjectID } = require("mongodb");
|
||||
|
||||
class LeaderboardsDAO {
|
||||
static async get(mode, mode2, language) {
|
||||
const preset = await mongoDB()
|
||||
.collection(`leaderboards.${language}.${mode}.${mode2}`)
|
||||
.find()
|
||||
.toArray();
|
||||
return preset;
|
||||
}
|
||||
|
||||
static async getRank(mode, mode2, language, uid) {
|
||||
const res = await mongoDB()
|
||||
.collection(`leaderboards.${language}.${mode}.${mode2}`)
|
||||
.findOne({ uid });
|
||||
return res.rank;
|
||||
}
|
||||
|
||||
static async update(mode, mode2, language, uid = undefined) {
|
||||
let str = `lbPersonalBests.${mode}.${mode2}.${language}`;
|
||||
let lb = await mongoDB()
|
||||
.collection("users")
|
||||
.aggregate([
|
||||
{
|
||||
$match: {
|
||||
[str]: {
|
||||
$exists: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
[str + ".uid"]: "$uid",
|
||||
[str + ".name"]: "$name",
|
||||
},
|
||||
},
|
||||
{
|
||||
$replaceRoot: {
|
||||
newRoot: "$" + str,
|
||||
},
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
wpm: -1,
|
||||
acc: -1,
|
||||
timestamp: -1,
|
||||
},
|
||||
},
|
||||
])
|
||||
.toArray();
|
||||
|
||||
let rerval = undefined;
|
||||
lb.forEach((lbEntry, index) => {
|
||||
lbEntry.rank = index + 1;
|
||||
if (uid && lbEntry.uid === uid) {
|
||||
rerval = index + 1;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await mongoDB()
|
||||
.collection(`leaderboards.${language}.${mode}.${mode2}`)
|
||||
.drop();
|
||||
} catch (e) {}
|
||||
await mongoDB()
|
||||
.collection(`leaderboards.${language}.${mode}.${mode2}`)
|
||||
.insertMany(lb);
|
||||
|
||||
if (rerval) {
|
||||
return {
|
||||
message: "Successfully updated leaderboard",
|
||||
rank: retval,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
message: "Successfully updated leaderboard",
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LeaderboardsDAO;
|
|
@ -191,6 +191,11 @@ class UsersDAO {
|
|||
await mongoDB()
|
||||
.collection("users")
|
||||
.updateOne({ uid }, { $set: { personalBests: pb.obj } });
|
||||
if (pb.lbPb) {
|
||||
await mongoDB()
|
||||
.collection("users")
|
||||
.updateOne({ uid }, { $set: { lbPersonalBests: pb.lbPb } });
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -96,20 +96,50 @@ module.exports = {
|
|||
});
|
||||
}
|
||||
|
||||
let topIndex = 0;
|
||||
let topWpm = 0;
|
||||
obj[mode][mode2].forEach((pb, index) => {
|
||||
delete pb.best;
|
||||
if (pb.wpm > topWpm) {
|
||||
topIndex = index;
|
||||
topWpm = pb.wpm;
|
||||
let lbPb;
|
||||
if (isPb && mode === "time" && (mode2 == "15" || mode2 == "60")) {
|
||||
lbPb = {
|
||||
time: {
|
||||
15: {},
|
||||
60: {},
|
||||
},
|
||||
};
|
||||
let bestForEveryLanguage = {};
|
||||
if (obj?.time?.[15]) {
|
||||
obj.time[15].forEach((pb) => {
|
||||
if (!bestForEveryLanguage[pb.language]) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
} else {
|
||||
if (bestForEveryLanguage[pb.language].wpm < pb.wpm) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(bestForEveryLanguage).forEach((key) => {
|
||||
lbPb.time[15][key] = bestForEveryLanguage[key];
|
||||
});
|
||||
bestForEveryLanguage = {};
|
||||
}
|
||||
});
|
||||
obj[mode][mode2][topIndex].best = true;
|
||||
if (obj?.time?.[60]) {
|
||||
obj.time[60].forEach((pb) => {
|
||||
if (!bestForEveryLanguage[pb.language]) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
} else {
|
||||
if (bestForEveryLanguage[pb.language].wpm < pb.wpm) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(bestForEveryLanguage).forEach((key) => {
|
||||
lbPb.time[60][key] = bestForEveryLanguage[key];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isPb,
|
||||
obj,
|
||||
lbPb,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -32,6 +32,8 @@ const quoteRatings = require("./api/routes/quote-ratings");
|
|||
app.use("/quote-ratings", quoteRatings);
|
||||
const psaRouter = require("./api/routes/psa");
|
||||
app.use("/psa", psaRouter);
|
||||
const leaderboardsRouter = require("./api/routes/leaderboards");
|
||||
app.use("/leaderboards", leaderboardsRouter);
|
||||
|
||||
app.use(function (e, req, res, next) {
|
||||
let uid = undefined;
|
||||
|
@ -70,4 +72,56 @@ app.listen(PORT, async () => {
|
|||
credential: admin.credential.cert(serviceAccount),
|
||||
});
|
||||
console.log("Database Connected");
|
||||
|
||||
// refactor();
|
||||
});
|
||||
|
||||
async function refactor() {
|
||||
let users = await mongoDB().collection("users").find({}).toArray();
|
||||
|
||||
for (let user of users) {
|
||||
let obj = user.personalBests;
|
||||
|
||||
lbPb = {
|
||||
time: {
|
||||
15: {},
|
||||
60: {},
|
||||
},
|
||||
};
|
||||
let bestForEveryLanguage = {};
|
||||
if (obj?.time?.[15]) {
|
||||
obj.time[15].forEach((pb) => {
|
||||
if (!bestForEveryLanguage[pb.language]) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
} else {
|
||||
if (bestForEveryLanguage[pb.language].wpm < pb.wpm) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(bestForEveryLanguage).forEach((key) => {
|
||||
lbPb.time[15][key] = bestForEveryLanguage[key];
|
||||
});
|
||||
bestForEveryLanguage = {};
|
||||
}
|
||||
if (obj?.time?.[60]) {
|
||||
obj.time[60].forEach((pb) => {
|
||||
if (!bestForEveryLanguage[pb.language]) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
} else {
|
||||
if (bestForEveryLanguage[pb.language].wpm < pb.wpm) {
|
||||
bestForEveryLanguage[pb.language] = pb;
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(bestForEveryLanguage).forEach((key) => {
|
||||
lbPb.time[60][key] = bestForEveryLanguage[key];
|
||||
});
|
||||
}
|
||||
|
||||
await mongoDB()
|
||||
.collection("users")
|
||||
.updateOne({ _id: user._id }, { $set: { lbPersonalBests: lbPb } });
|
||||
console.log(`updated ${user.name}`);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue