-
Notifications
You must be signed in to change notification settings - Fork 1
/
user-stats.js
100 lines (88 loc) · 3.18 KB
/
user-stats.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import 'dotenv/config';
import { MongoClient } from 'mongodb';
const uri = `mongodb+srv://${process.env.MONGODB_USERNAME || 'geoffreywu42'}:${process.env.MONGODB_PASSWORD || 'password'}@qbreader.0i7oej9.mongodb.net/?retryWrites=true&w=majority`;
const client = new MongoClient(uri);
client.connect().then(async () => {
console.log('connected to mongodb');
await printMostActiveUsers(10, 'tossup');
await printMostActiveUsers(10, 'bonus');
// await printUserStats('');
// console.log(array.map(user => user.count));
// console.log(array.map((user) => user.count).reduce((a, b) => a + b));
client.close();
});
const accountInfo = client.db('account-info');
const tossupData = accountInfo.collection('tossup-data');
const bonusData = accountInfo.collection('bonus-data');
const users = accountInfo.collection('users');
/**
*
* @param {Number} limit - the max number of users to return
* @param {"tossup" | "bonus"} type - whether to use tossup or bonus data
* @returns {Promise<Array<{
* username: String,
* _id: String,
* count: Number
* }>>} an array of objects
*/
async function getMostActiveUsers(limit, type = 'tossup') {
const aggregation = [
{ $group: {
_id: '$user_id',
count: { '$sum': 1 },
} },
{ $sort: {
count: -1,
} },
{ $lookup: {
from: 'users',
localField: '_id',
foreignField: '_id',
as: 'user',
} },
{ $project: {
username: { $arrayElemAt: [ '$user.username', 0 ] },
_id: 1,
count: 1,
} },
{ $limit: limit },
];
switch (type) {
case 'tossup':
return await tossupData.aggregate(aggregation).toArray();
case 'bonus':
return await bonusData.aggregate(aggregation).toArray();
}
}
/**
* Nicely prints the most active users.
* @param {Number} limit - the max number of users to print
* @param {"tossup" | "bonus"} type - whether to use tossup or bonus data
* @returns {Promise<void>}
*/
async function printMostActiveUsers(limit = 10, type = 'tossup') {
const result = await getMostActiveUsers(limit, type);
result.forEach((user, index) => {
console.log(`${(index + 1).toString().padStart(2)}. ${user.username} (${user.count})`);
});
}
async function printUserStats(username) {
const { _id: user_id } = await users.findOne({ username: username });
const tossupCount = await tossupData.countDocuments({ user_id: user_id });
const bonusCount = await bonusData.countDocuments({ user_id: user_id });
const aggregation = (count) => [
{ $group: {
_id: '$user_id',
count: { '$sum': 1 },
} },
{ $match: {
count: { $gte: count },
} },
{ $count: 'position' },
];
const { position: tossupPosition } = (await tossupData.aggregate(aggregation(tossupCount)).toArray())[0];
const { position: bonusPosition } = (await bonusData.aggregate(aggregation(bonusCount)).toArray())[0];
console.log(`User: ${username} (${user_id})`);
console.log(`Tossups: ${tossupCount} (#${tossupPosition})`);
console.log(`Bonuses: ${bonusCount} (#${bonusPosition})`);
}