monkeytype/backend/handlers/leaderboard.js
2021-06-07 14:29:51 +01:00

227 lines
6.8 KiB
JavaScript

function addToLeaderboard(lb, result, username) {
//insertedAt is index of array inserted position, 1 is added after
retData = { insertedAt: -1 };
//check for duplicate user
for (i = 0; i < lb.board.length; i++) {
if (lb.board[i].name == username) {
if (lb.board[i].wpm <= result.wpm) {
//delete old entry if speed is faster this time
lb.board.splice(i, 1);
retData.foundAt = i + 1;
retData.newBest = true;
} else {
//don't add new entry if slower than last time
return lb, { insertedAt: -1, foundAt: i + 1 };
}
}
}
//when is newBest not true?
retData.newBest = true;
if (!retData.foundAt) retData.foundAt = -1;
//determine if the entry should be hidden
//add item to leaderboard
const lbitem = {
name: username,
wpm: result.wpm,
raw: result.rawWpm,
acc: result.acc,
consistency: result.consistency,
mode: result.mode,
mode2: result.mode2,
timestamp: Date.now(),
hidden: false,
};
if (lb.board.length == 0) {
console.log("adding to first position");
lb.board.push(lbitem);
retData.insertedAt = 0;
} else if (lbitem.wpm < lb.board.slice(-1)[0].wpm) {
console.log("adding to the end");
console.log(lb.board.slice(-1)[0].wpm);
lb.board.push(lbitem);
retData.insertedAt = lb.board.length - 1;
} else {
console.log("searching for addition spot");
for (i = 0; i < lb.board.length; i++) {
//start from top, if item wpm > lb item wpm, insert before it
if (lbitem.wpm >= lb.board[i].wpm) {
console.log("adding to daily lb position " + i);
lb.board.splice(i, 0, lbitem);
retData.insertedAt = i;
break;
}
}
if (lb.board.length > lb.size) {
lb.pop();
}
}
return lb, retData;
}
app.post("/attemptAddToLeaderboards", authenticateToken, (req, res) => {
const result = req.body.result;
let retData = {};
User.findOne({ uid: req.uid }, (err, user) => {
admin
.auth()
.getUser(req.uid)
.then((fbUser) => {
return fbUser.emailVerified;
})
.then((emailVerified) => {
if (user.emailVerified === false) {
if (emailVerified === true) {
user.emailVerified = true;
} else {
res.status(200).send({ needsToVerifyEmail: true });
return;
}
}
if (user.name === undefined) {
//cannot occur since name is required, why is this here?
res.status(200).send({ noName: true });
return;
}
if (user.banned) {
res.status(200).send({ banned: true });
return;
}
/*
if (user.verified === false) {
res.status(200).send({ needsToVerify: true });
return;
}*/
Leaderboard.find(
{
mode: result.mode,
mode2: result.mode2,
},
(err, lbs) => {
//for all leaderboards queried, determine if it qualifies, and add if it does
lbs.forEach((lb) => {
if (
lb.board.length == 0 ||
lb.board.length < lb.size ||
result.wpm > lb.board.slice(-1)[0].wpm
) {
lb, (lbPosData = addToLeaderboard(lb, result, user.name)); //should uid be added instead of name? //or together
console.log(user.lbMemory[lb.mode + lb.mode2][lb.type]);
//lbPosData.foundAt = user.lbMemory[lb.mode+lb.mode2][lb.type];
retData[lb.type] = lbPosData;
lb.save();
user.lbMemory[lb.mode + lb.mode2][lb.type] =
retData[lb.type].insertedAt;
//check if made global top 10 and send to discord if it did
if (lb.type == "global") {
let usr =
user.discordId != undefined ? user.discordId : user.name;
if (
retData.global !== null &&
retData.global.insertedAt >= 0 &&
retData.global.insertedAt <= 9 &&
retData.global.newBest
) {
let lbstring = `${result.mode} ${result.mode2} global`;
console.log(
`sending command to the bot to announce lb update ${usr} ${
retData.global.insertedAt + 1
} ${lbstring} ${result.wpm}`
);
announceLbUpdate(
usr,
retData.global.insertedAt + 1,
lbstring,
result.wpm,
result.rawWpm,
result.acc,
result.consistency
);
}
}
}
});
}
).then((e) => {
retData.status = 2;
user.save();
res.json(retData);
});
});
});
res.status(200);
});
app.get("/getLeaderboard/:type/:mode/:mode2", (req, res) => {
Leaderboard.findOne(
{ mode: req.params.mode, mode2: req.params.mode2, type: req.params.type },
(err, lb) => {
res.send(lb);
}
);
});
// Initialize database leaderboards if no leaderboards exist and start clearDailyLeaderboards
Leaderboard.findOne((err, lb) => {
if (lb === null) {
let lb = {
size: 999,
board: [],
mode: "time",
mode2: 15,
type: "global",
};
Leaderboard.create(lb);
lb.mode2 = 60;
Leaderboard.create(lb);
lb.type = "daily";
lb.size = 100;
Leaderboard.create(lb);
lb.mode2 = 15;
Leaderboard.create(lb);
}
}).then(() => {
clearDailyLeaderboards();
});
// Daily leaderboard clear function
function clearDailyLeaderboards() {
var nextClear = new Date();
nextClear.setHours(24, 0, 0, 0); //next occurrence of 12am
let currentTime = new Date();
Leaderboard.find({ type: "daily" }, (err, lbs) => {
lbs.forEach((lb) => {
lb.resetTime = nextClear;
lb.save();
});
});
setTimeout(() => {
Leaderboard.find({ type: "daily" }, (err, lbs) => {
lbs.forEach((lb) => {
User.findOne({ name: lb.board[0].name }, (err, user) => {
if (user) {
if (user.dailyLbWins === undefined) {
user.dailyLbWins = {
[lb.mode + lb.mode2]: 1,
};
} else if (user.dailyLbWins[lb.mode + lb.mode2] === undefined) {
user.dailyLbWins[lb.mode + lb.mode2] = 1;
} else {
user.dailyLbWins[lb.mode + lb.mode2]++;
}
user.save();
}
}).then(() => {
announceDailyLbResult(lb);
lb.board = [];
lb.save();
});
});
});
clearDailyLeaderboards();
}, nextClear.getTime() - currentTime.getTime());
}