-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstandings.ts
93 lines (90 loc) · 3.46 KB
/
standings.ts
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
import { TextChannel } from 'discord.js';
import { db } from './db';
import { markdownTable } from 'markdown-table';
import { DateTime } from 'luxon';
export function addPoint(channel: TextChannel, name: string, question: Question) {
let query = db.query('INSERT INTO points (id,createdAt,channelID,userName,category) VALUES ($id,$createdAt,$channelID,$userName,$category)');
query.run({
$id: null,
$createdAt: DateTime.now().toSQL({ includeOffset: false }), // doing this to user the server's timezone
$channelID: channel.id,
$userName: name,
$category: question.category,
});
}
export function getStandings(channel: TextChannel, type = 'all') {
let message: string[] = [];
const possibleTypes = ['day', 'week', 'lifetime'];
if (type == 'all') type = possibleTypes.join(' ');
const requestedTypes = type.split(/(,|\s+)/).filter((t) => possibleTypes.includes(t));
for (const requestedType of requestedTypes) {
switch (requestedType) {
case 'day': {
let hoursQuery = db.query(`select strftime('%H',createdAt) as Hour
from points
WHERE channelID = $channelID AND createdAt > datetime('now', 'start of day')
group by Hour`);
let hours = hoursQuery.all({ $channelID: channel.id }) as { Hour: string }[];
let hoursSelects = hours.map((h) => `sum(case when strftime('%H',createdAt)='${h.Hour}' then 1 else null end) as '${h.Hour}'`).join(',\n');
let query = db.query(`SELECT userName
, ${hoursSelects}
, count(id) as Total
FROM points
WHERE channelID = $channelID AND createdAt > datetime('now', 'start of day')
GROUP BY userName
ORDER BY Total DESC
`);
let results = query.all({ $channelID: channel.id }) as { userName: string; Points: number }[];
if (results.length > 0) {
message.push(resultsToTable(results, 'DAY'));
}
break;
}
case 'week': {
const startOfWeek = DateTime.now().startOf('week');
let daysQuery = db.query(`select strftime('%d',createdAt) as Day
from points
WHERE channelID = $channelID AND createdAt > '${startOfWeek.toSQLDate()}'
group by Day
order by createdAt asc
`);
let days = daysQuery.all({ $channelID: channel.id }) as { Day: string }[];
let daysSelects = days.map((d) => `sum(case when strftime('%d',createdAt)='${d.Day}' then 1 else null end) as '${d.Day}'`).join(',\n');
let sql = `SELECT userName
,${daysSelects}
,count(id) as Total
FROM points
WHERE channelID = $channelID AND createdAt > '${startOfWeek.toSQLDate()}'
GROUP BY userName
ORDER BY Total DESC
`;
let query = db.query(sql);
let results = query.all({ $channelID: channel.id }) as { userName: string; Points: number }[];
if (results.length > 0) {
message.push(resultsToTable(results, 'WEEK'));
}
break;
}
case 'lifetime': {
let query = db.query(`SELECT userName,count(id) as Points
FROM points
WHERE channelID = $channelID
GROUP BY userName
ORDER BY Points DESC
`);
let results = query.all({ $channelID: channel.id }) as { userName: string; Points: number }[];
if (results.length > 0) {
message.push(resultsToTable(results, 'LIFETIME'));
}
break;
}
}
message.push('');
}
return message.join('\n').trim();
}
function resultsToTable(data: Record<string, string | number>[], title = '') {
const table = [Object.keys(data[0]), ...data.map((r) => Object.values(r) as string[])];
if (title) table[0][0] = title;
return markdownTable(table);
}