🚑️ Wait for client connect

This commit is contained in:
2022-03-22 22:52:20 +03:00
parent 6c1d62b389
commit c14bfcc1e1

View File

@@ -21,200 +21,203 @@ const names = require('./names.json');
const client = new MongoClient(process.env.URI, { useUnifiedTopology: true }); const client = new MongoClient(process.env.URI, { useUnifiedTopology: true });
app.use(session({ (async () => {
secret: process.env.SECRET, await client.connect();
resave: false, const cardsCollection = client.db(process.env.DB_NAME).collection('cards');
saveUninitialized: true, const answersCollection = client.db(process.env.DB_NAME).collection('answers');
store: MongoStore.create({
client,
dbName: process.env.DB_NAME,
}),
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24,
},
}));
client.connect(); app.use(session({
const cardsCollection = client.db(process.env.DB_NAME).collection('cards'); secret: process.env.SECRET,
const answersCollection = client.db(process.env.DB_NAME).collection('answers'); resave: false,
saveUninitialized: true,
store: MongoStore.create({
client,
dbName: process.env.DB_NAME,
}),
cookie: {
secure: false,
maxAge: 1000 * 60 * 60 * 24,
},
}));
// Выравнивание вероятности // Выравнивание вероятности
const dropProb = {}; // Объект хранящий вероятности с которой карта каждого участника отбрасывается // Объект хранящий вероятности с которой карта каждого участника отбрасывается
cardsCollection.aggregate([ const dropProb = {};
{ cardsCollection.aggregate([
$group: { {
_id: '$name', $group: {
count: { _id: '$name',
$sum: 1, count: {
$sum: 1,
},
}, },
}, },
}, ]).toArray().then((memeCount) => {
]).toArray().then((memeCount) => { cardsCollection.countDocuments().then((totalCount) => {
cardsCollection.countDocuments().then((totalCount) => { let quotaTimes;
let quotaTimes;
const quota = totalCount / memeCount.length; // Квота мемов на человека const quota = totalCount / memeCount.length; // Квота мемов на человека
console.log(`${totalCount} мемов всего. Квота: ${quota}`); console.log(`${totalCount} мемов всего. Квота: ${quota}`);
function activeUsers() { function activeUsers() {
let count = 0; let count = 0;
memeCount.forEach((person) => { memeCount.forEach((person) => {
if (person.count > quota / 10) { count += 1; } if (person.count > quota / 10) { count += 1; }
}); });
return count; return count;
}
memeCount.forEach((person) => {
// Во сколько раз превышена квота:
// (колич. астивных человек в конфе * колич. мемов данного человека / мемов всего)
quotaTimes = activeUsers() * (person.count / totalCount);
if (quotaTimes > 1) {
dropProb[person._id] = 1 - (1 / quotaTimes);
} else {
dropProb[person._id] = 0;
} }
console.log(`${person._id} [${person.count}]: ${dropProb[person._id]}`);
memeCount.forEach((person) => {
// Во сколько раз превышена квота:
// (колич. астивных человек в конфе * колич. мемов данного человека / мемов всего)
quotaTimes = activeUsers() * (person.count / totalCount);
if (quotaTimes > 1) {
dropProb[person._id] = 1 - (1 / quotaTimes);
} else {
dropProb[person._id] = 0;
}
console.log(`${person._id} [${person.count}]: ${dropProb[person._id]}`);
});
}); });
}); });
});
app.post('/api/auth', async (req, res) => { app.post('/api/auth', async (req, res) => {
if (req.session.loggedIn) { if (req.session.loggedIn) {
res.status(200).send('Logged in'); res.status(200).send('Logged in');
} else { } else {
try { try {
const { pass } = req.body; const { pass } = req.body;
if (pass && pass.toLowerCase() === process.env.PASSWORD) { if (pass && pass.toLowerCase() === process.env.PASSWORD) {
req.session.loggedIn = true; req.session.loggedIn = true;
res.status(200).send('Logged in'); res.status(200).send('Logged in');
} else { } else {
res.status(401).send('Wrong password'); res.status(401).send('Wrong password');
}
} catch (e) {
console.log(`Error: ${e}`);
res.status(500).send();
} }
}
});
app.get('/api/card', async (req, res) => {
async function drawCard() {
let card;
// Тянем карты и отбрасываем их в соответствии с их вероятностью отбрасывания
do {
/* eslint-disable no-await-in-loop */
card = await cardsCollection.aggregate([
{
$sample: { size: 1 },
}, {
$unset: ['name', 'link', 'date'],
},
]).toArray();
/* eslint-enable no-await-in-loop */
[card] = card;
} while (Math.random() < dropProb[card.name]);
return card;
}
if (req.session.loggedIn) {
res.status(200).send(await drawCard());
} else {
res.status(403).send();
}
});
app.get('/api/meme', async (req, res) => {
const amount = Number(req.query.amount) || 1;
try {
let cards = await cardsCollection.aggregate([{ $sample: { size: amount } }]).toArray();
// Удаляем конфиденциальную информацию
cards = cards.map((card) => card.image);
res.status(200).send(cards);
} catch (e) { } catch (e) {
console.log(`Error: ${e}`); console.log(`Error: ${e}`);
res.status(500).send(); res.status(500).send();
} }
} });
});
app.get('/api/card', async (req, res) => { app.post('/api/answer', async (req, res) => {
async function drawCard() { if (req.session.loggedIn) {
let card; if (req.body.data.id && req.body.data.name) {
// Тянем карты и отбрасываем их в соответствии с их вероятностью отбрасывания const card = await cardsCollection.findOne({ _id: ObjectId(req.body.data.id) });
do { if (card) {
/* eslint-disable no-await-in-loop */ const correct = card.name === req.body.data.name;
card = await cardsCollection.aggregate([ if (correct) {
{ req.session.right += 1;
$sample: { size: 1 }, } else {
}, { req.session.wrong += 1;
$unset: ['name', 'link', 'date'], }
}, answersCollection.insertOne({
]).toArray(); correct,
/* eslint-enable no-await-in-loop */ selected: req.body.data.name,
[card] = card; });
} while (Math.random() < dropProb[card.name]); res.status(200).send({
return card; correct,
} card,
});
if (req.session.loggedIn) {
res.status(200).send(await drawCard());
} else {
res.status(403).send();
}
});
app.get('/api/meme', async (req, res) => {
const amount = Number(req.query.amount) || 1;
try {
let cards = await cardsCollection.aggregate([{ $sample: { size: amount } }]).toArray();
// Удаляем конфиденциальную информацию
cards = cards.map((card) => card.image);
res.status(200).send(cards);
} catch (e) {
console.log(`Error: ${e}`);
res.status(500).send();
}
});
app.post('/api/answer', async (req, res) => {
if (req.session.loggedIn) {
if (req.body.data.id && req.body.data.name) {
const card = await cardsCollection.findOne({ _id: ObjectId(req.body.data.id) });
if (card) {
const correct = card.name === req.body.data.name;
if (correct) {
req.session.right += 1;
} else { } else {
req.session.wrong += 1; res.status(500).send();
} }
answersCollection.insertOne({
correct,
selected: req.body.data.name,
});
res.status(200).send({
correct,
card,
});
} else { } else {
res.status(500).send(); res.status(400).send();
} }
} else { } else {
res.status(400).send(); res.status(403).send();
} }
} else { });
res.status(403).send();
}
});
app.get('/api/score', (req, res) => { app.get('/api/score', (req, res) => {
if (req.session.loggedIn) { if (req.session.loggedIn) {
req.session.right = req.session.right || 0; req.session.right = req.session.right || 0;
req.session.wrong = req.session.wrong || 0; req.session.wrong = req.session.wrong || 0;
const scoreObj = { const scoreObj = {
right: req.session.right, right: req.session.right,
wrong: req.session.wrong, wrong: req.session.wrong,
}; };
res.status(200).send(scoreObj); res.status(200).send(scoreObj);
} else { } else {
res.status(403).send(); res.status(403).send();
} }
}); });
app.get('/api/stats', async (req, res) => { app.get('/api/stats', async (req, res) => {
if (req.session.loggedIn) { if (req.session.loggedIn) {
answersCollection.aggregate([ answersCollection.aggregate([
{ {
$group: { $group: {
_id: '$selected', _id: '$selected',
correct: { correct: {
$sum: { $sum: {
$cond: [ $cond: [
'$correct', 1, 0, '$correct', 1, 0,
], ],
},
}, },
}, wrong: {
wrong: { $sum: {
$sum: { $cond: [
$cond: [ '$correct', 0, 1,
'$correct', 0, 1, ],
], },
}, },
}, },
}, },
}, ]).toArray().then((stats) => res.status(200).send(stats));
]).toArray().then((stats) => res.status(200).send(stats)); } else {
} else { res.status(403).send();
res.status(403).send(); }
} });
});
app.get('/api/options', async (req, res) => { app.get('/api/options', async (req, res) => {
if (req.session.loggedIn) { if (req.session.loggedIn) {
res.status(200).send(names); res.status(200).send(names);
} else { } else {
res.status(403).send(); res.status(403).send();
} }
}); });
app.listen(process.env.PORT, () => console.log(`Server started on ${process.env.PORT}`)); app.listen(process.env.PORT, () => console.log(`Server started on ${process.env.PORT}`));
})();