@aoi-js/aka 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import { IRanklist } from '../client.js';
2
+ import { IRanklistSyncOptions, RanklistCalculator } from './base.js';
3
+ export declare class AcmCalculator extends RanklistCalculator {
4
+ topstars: number;
5
+ warnings: string;
6
+ startTime: number;
7
+ loadConfig(dict: Record<string, string>): Promise<IRanklistSyncOptions>;
8
+ private _renderParticipantItemColumn;
9
+ private _renderPenaltyColumn;
10
+ calculate(contestId: string, taskId: string, key: string): Promise<IRanklist>;
11
+ }
@@ -0,0 +1,178 @@
1
+ import { RanklistCalculator } from './base.js';
2
+ export class AcmCalculator extends RanklistCalculator {
3
+ topstars = 0;
4
+ warnings = '';
5
+ startTime = 0;
6
+ async loadConfig(dict) {
7
+ const topstars = +dict.topstars;
8
+ if (!Number.isInteger(topstars) || topstars < 0 || topstars > 20) {
9
+ this.warnings += 'topstars must be an integer between 0 and 20\n';
10
+ }
11
+ else {
12
+ this.topstars = topstars;
13
+ }
14
+ const startTime = Date.parse(dict.startTime);
15
+ if (Number.isNaN(startTime)) {
16
+ this.warnings += 'startTime is not a valid timestamp\n';
17
+ }
18
+ else {
19
+ this.startTime = startTime;
20
+ }
21
+ return {
22
+ shouldSyncParticipants: true,
23
+ shouldSyncSolutions: true
24
+ };
25
+ }
26
+ _renderParticipantItemColumn(score, solutionCount, lastSubmission) {
27
+ let html = '<div align=center>';
28
+ if (score) {
29
+ html += `<font color=green>+`;
30
+ if (solutionCount > 1) {
31
+ html += `${solutionCount - 1}`;
32
+ }
33
+ html += `</font><br><code>`;
34
+ const delay = Math.floor(Math.max(0, lastSubmission - this.startTime) / 1000 / 60);
35
+ const hours = Math.floor(delay / 60);
36
+ const minutes = delay % 60;
37
+ if (hours) {
38
+ html += `${hours}h`;
39
+ }
40
+ html += `${minutes}m</code>`;
41
+ }
42
+ else if (solutionCount) {
43
+ html += `<font color=red>-${solutionCount}</font>`;
44
+ }
45
+ else {
46
+ html += `<font color=gray>-</font>`;
47
+ }
48
+ html += '</div>';
49
+ return { content: html };
50
+ }
51
+ _renderPenaltyColumn(penalty) {
52
+ const format = () => {
53
+ let str = (penalty % 1000) + 'ms';
54
+ if (!(penalty = Math.floor(penalty / 1000)))
55
+ return str;
56
+ str = (penalty % 60) + 's' + str;
57
+ if (!(penalty = Math.floor(penalty / 60)))
58
+ return str;
59
+ str = (penalty % 60) + 'm' + str;
60
+ if (!(penalty = Math.floor(penalty / 60)))
61
+ return str;
62
+ return penalty + 'h' + str;
63
+ };
64
+ return { content: `\`${format()}\`` };
65
+ }
66
+ async calculate(contestId, taskId, key) {
67
+ const problems = await this.client.problems(contestId, taskId);
68
+ problems.sort((a, b) => a.settings.slug.localeCompare(b.settings.slug));
69
+ const problemIdList = problems.map((p) => p._id);
70
+ const problemScoreList = problems.map((p) => p.settings.score);
71
+ const participants = await this.db.participants.find({ contestId }).toArray();
72
+ let participantRecords = participants
73
+ .map(({ userId, tags, results }) => ({
74
+ userId,
75
+ tags,
76
+ scores: problemIdList
77
+ .map((pid) => results[pid]?.lastSolution.score ?? 0)
78
+ // In ACM, you will get score only if you get full points XD
79
+ .map((score, i) => ((score === 100 ? 100 : 0) * problemScoreList[i]) / 100),
80
+ lastSubmitTimestamps: problemIdList.map(() => 0),
81
+ solutionCounts: problemIdList.map(() => 0),
82
+ penalty: 0,
83
+ rank: 0
84
+ }))
85
+ .map((record) => ({
86
+ ...record,
87
+ totalScore: record.scores.reduce((a, b) => a + b, 0)
88
+ }));
89
+ // Iterate over all solutons to calculate submit timestamps
90
+ const info = new Map();
91
+ const cursor = this.db.solutions.find({ contestId });
92
+ for await (const { userId, problemId, submittedAt } of cursor) {
93
+ const [userTimestamps, userSolutionCounts] = info.get(userId) ??
94
+ info.set(userId, [Object.create(null), Object.create(null)]).get(userId);
95
+ userTimestamps[problemId] = Math.max(userTimestamps[problemId] ?? 0, submittedAt);
96
+ userSolutionCounts[problemId] = (userSolutionCounts[problemId] ?? 0) + 1;
97
+ }
98
+ for (const record of participantRecords) {
99
+ const pair = info.get(record.userId);
100
+ if (!pair)
101
+ continue;
102
+ const [timestamps, solutionCounts] = pair;
103
+ for (let i = 0; i < problemIdList.length; ++i) {
104
+ const problemId = problemIdList[i];
105
+ record.lastSubmitTimestamps[i] = timestamps[problemId] ?? 0;
106
+ record.solutionCounts[i] = solutionCounts[problemId] ?? 0;
107
+ if (record.scores[i]) {
108
+ record.penalty += Math.max(0, timestamps[problemId] - this.startTime);
109
+ }
110
+ }
111
+ }
112
+ participantRecords = participantRecords
113
+ .sort((a, b) => b.totalScore === a.totalScore ? a.penalty - b.penalty : b.totalScore - a.totalScore)
114
+ .map((record, index) => ({
115
+ ...record,
116
+ rank: index + 1
117
+ }));
118
+ // Since we calculate penalty in milliseconds, we do not need to consider same rank
119
+ let topstar;
120
+ if (this.topstars) {
121
+ const topstarUserIdList = participantRecords
122
+ .slice(0, this.topstars)
123
+ .filter((record) => record.totalScore > 0)
124
+ .map((p) => p.userId);
125
+ topstar = {
126
+ list: await Promise.all(topstarUserIdList.map(async (userId) => {
127
+ const solutions = await this.db.solutions
128
+ .find({ contestId, userId })
129
+ .sort({ completedAt: 1 })
130
+ .toArray();
131
+ const currentScores = Object.create(null);
132
+ const mutations = [];
133
+ for (const { problemId, score, submittedAt } of solutions) {
134
+ currentScores[problemId] = score;
135
+ mutations.push({
136
+ score: problemIdList
137
+ .map((pid, i) => ((currentScores[pid] ?? 0) * problemScoreList[i]) / 100)
138
+ .reduce((a, b) => a + b, 0),
139
+ ts: submittedAt
140
+ });
141
+ }
142
+ return { userId, mutations };
143
+ }))
144
+ };
145
+ }
146
+ if (this.warnings) {
147
+ this.logger.warn({ contestId, taskId, key }, this.warnings);
148
+ }
149
+ return {
150
+ topstar,
151
+ participant: {
152
+ list: participantRecords.map(({ userId, rank, tags, scores, totalScore, solutionCounts, lastSubmitTimestamps, penalty }) => ({
153
+ userId,
154
+ rank,
155
+ tags,
156
+ columns: [
157
+ ...scores.map((score, i) => this._renderParticipantItemColumn(score, solutionCounts[i], lastSubmitTimestamps[i])),
158
+ { content: `${totalScore}` },
159
+ this._renderPenaltyColumn(penalty)
160
+ ]
161
+ })),
162
+ columns: [
163
+ ...problems.map(({ title, settings: { slug } }) => ({
164
+ name: slug,
165
+ description: title
166
+ })),
167
+ { name: 'Total', description: 'Total Score' },
168
+ { name: 'Penalty', description: 'Penalty Time' }
169
+ ]
170
+ },
171
+ metadata: {
172
+ generatedAt: Date.now(),
173
+ description: 'ACM ranklist generated'
174
+ }
175
+ };
176
+ }
177
+ }
178
+ //# sourceMappingURL=acm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acm.js","sourceRoot":"","sources":["../../src/calc/acm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { Logger } from 'pino';
2
+ import { AkaClient, IRanklist } from '../client.js';
3
+ import { AkaDb } from '../db.js';
4
+ export interface IRanklistSyncOptions {
5
+ shouldSyncSolutions?: boolean;
6
+ shouldSyncParticipants?: boolean;
7
+ }
8
+ export declare abstract class RanklistCalculator {
9
+ protected db: AkaDb;
10
+ protected client: AkaClient;
11
+ protected logger: Logger;
12
+ constructor(db: AkaDb, client: AkaClient, logger: Logger);
13
+ abstract loadConfig(dict: Record<string, string>): Promise<IRanklistSyncOptions>;
14
+ abstract calculate(contestId: string, taskId: string, key: string): Promise<IRanklist>;
15
+ }
@@ -0,0 +1,11 @@
1
+ export class RanklistCalculator {
2
+ db;
3
+ client;
4
+ logger;
5
+ constructor(db, client, logger) {
6
+ this.db = db;
7
+ this.client = client;
8
+ this.logger = logger;
9
+ }
10
+ }
11
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/calc/base.ts"],"names":[],"mappings":"AASA,MAAM,OAAgB,kBAAkB;IAE1B;IACA;IACA;IAHZ,YACY,EAAS,EACT,MAAiB,EACjB,MAAc;QAFd,OAAE,GAAF,EAAE,CAAO;QACT,WAAM,GAAN,MAAM,CAAW;QACjB,WAAM,GAAN,MAAM,CAAQ;IACvB,CAAC;CAIL"}
@@ -0,0 +1,8 @@
1
+ import { IRanklist } from '../client.js';
2
+ import { IRanklistSyncOptions, RanklistCalculator } from './base.js';
3
+ export declare class BasicCalculator extends RanklistCalculator {
4
+ topstars: number;
5
+ warnings: string;
6
+ loadConfig(dict: Record<string, string>): Promise<IRanklistSyncOptions>;
7
+ calculate(contestId: string, taskId: string, key: string): Promise<IRanklist>;
8
+ }
@@ -0,0 +1,103 @@
1
+ import { RanklistCalculator } from './base.js';
2
+ export class BasicCalculator extends RanklistCalculator {
3
+ topstars = 0;
4
+ warnings = '';
5
+ async loadConfig(dict) {
6
+ const topstars = +dict.topstars;
7
+ if (!Number.isInteger(topstars) || topstars < 0 || topstars > 20) {
8
+ this.warnings += 'topstars must be an integer between 0 and 20\n';
9
+ }
10
+ else {
11
+ this.topstars = topstars;
12
+ }
13
+ return {
14
+ shouldSyncParticipants: true,
15
+ shouldSyncSolutions: !!this.topstars
16
+ };
17
+ }
18
+ async calculate(contestId, taskId, key) {
19
+ const problems = await this.client.problems(contestId, taskId);
20
+ problems.sort((a, b) => a.settings.slug.localeCompare(b.settings.slug));
21
+ const problemIdList = problems.map((p) => p._id);
22
+ const problemScoreList = problems.map((p) => p.settings.score);
23
+ const participants = await this.db.participants.find({ contestId }).toArray();
24
+ const participantRecords = participants
25
+ .map(({ userId, tags, results }) => ({
26
+ userId,
27
+ tags,
28
+ scores: problemIdList
29
+ .map((pid) => results[pid]?.lastSolution.score ?? 0)
30
+ .map((score, i) => (score * problemScoreList[i]) / 100)
31
+ }))
32
+ .map((record) => ({
33
+ ...record,
34
+ totalScore: record.scores.reduce((a, b) => a + b, 0)
35
+ }))
36
+ .sort((a, b) => b.totalScore - a.totalScore)
37
+ .map((record, index) => ({
38
+ ...record,
39
+ rank: index + 1
40
+ }));
41
+ participantRecords.forEach((record, index, arr) => {
42
+ if (index > 0 && record.totalScore === arr[index - 1].totalScore) {
43
+ record.rank = arr[index - 1].rank;
44
+ }
45
+ });
46
+ let topstar;
47
+ if (this.topstars) {
48
+ const topstarUserIdList = participantRecords
49
+ .slice(0, this.topstars)
50
+ .filter((record) => record.totalScore > 0)
51
+ .map((p) => p.userId);
52
+ topstar = {
53
+ list: await Promise.all(topstarUserIdList.map(async (userId) => {
54
+ const solutions = await this.db.solutions
55
+ .find({ contestId, userId })
56
+ .sort({ completedAt: 1 })
57
+ .toArray();
58
+ const currentScores = Object.create(null);
59
+ const mutations = [];
60
+ for (const { problemId, score, submittedAt } of solutions) {
61
+ currentScores[problemId] = score;
62
+ mutations.push({
63
+ score: problemIdList
64
+ .map((pid, i) => ((currentScores[pid] ?? 0) * problemScoreList[i]) / 100)
65
+ .reduce((a, b) => a + b, 0),
66
+ ts: submittedAt
67
+ });
68
+ }
69
+ return { userId, mutations };
70
+ }))
71
+ };
72
+ }
73
+ if (this.warnings) {
74
+ this.logger.warn({ contestId, taskId, key }, this.warnings);
75
+ }
76
+ return {
77
+ topstar,
78
+ participant: {
79
+ list: participantRecords.map(({ userId, rank, tags, scores, totalScore }) => ({
80
+ userId,
81
+ rank,
82
+ tags,
83
+ columns: [
84
+ ...scores.map((score) => ({ content: `${score}` })),
85
+ { content: `${totalScore}` }
86
+ ]
87
+ })),
88
+ columns: [
89
+ ...problems.map(({ title, settings: { slug } }) => ({
90
+ name: slug,
91
+ description: title
92
+ })),
93
+ { name: 'Total', description: 'Total Score' }
94
+ ]
95
+ },
96
+ metadata: {
97
+ generatedAt: Date.now(),
98
+ description: 'Basic ranklist generated'
99
+ }
100
+ };
101
+ }
102
+ }
103
+ //# sourceMappingURL=basic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basic.js","sourceRoot":"","sources":["../../src/calc/basic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { Logger } from 'pino';
2
+ import { AkaClient } from '../client.js';
3
+ import { AkaDb } from '../db.js';
4
+ import { RanklistCalculator } from './base.js';
5
+ import { BasicCalculator } from './basic.js';
6
+ import { PlusCalculator } from './plus.js';
7
+ import { AcmCalculator } from './acm.js';
8
+ export declare const calculators: {
9
+ basic: typeof BasicCalculator;
10
+ plus: typeof PlusCalculator;
11
+ acm: typeof AcmCalculator;
12
+ };
13
+ export declare function getCalculator(db: AkaDb, client: AkaClient, logger: Logger, dict: Record<string, string>): RanklistCalculator | null;
@@ -0,0 +1,15 @@
1
+ import { BasicCalculator } from './basic.js';
2
+ import { PlusCalculator } from './plus.js';
3
+ import { AcmCalculator } from './acm.js';
4
+ export const calculators = {
5
+ basic: BasicCalculator,
6
+ plus: PlusCalculator,
7
+ acm: AcmCalculator
8
+ };
9
+ export function getCalculator(db, client, logger, dict) {
10
+ const type = dict.type ?? 'basic';
11
+ if (!Object.hasOwn(calculators, type))
12
+ return null;
13
+ return new calculators[type](db, client, logger);
14
+ }
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/calc/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE,eAAe;IACtB,IAAI,EAAE,cAAc;IACpB,GAAG,EAAE,aAAa;CACnB,CAAA;AAED,MAAM,UAAU,aAAa,CAC3B,EAAS,EACT,MAAiB,EACjB,MAAc,EACd,IAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAA;IACjC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;IAClD,OAAO,IAAI,WAAW,CAAC,IAAgC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9E,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { IRanklist } from '../client.js';
2
+ import { IRanklistSyncOptions, RanklistCalculator } from './base.js';
3
+ declare const reduceMethods: readonly ["override", "max", "min"];
4
+ type ReduceMethod = (typeof reduceMethods)[number];
5
+ declare const totalReduceMethods: readonly ["sum", "max", "min"];
6
+ type TotalReduceMethod = (typeof totalReduceMethods)[number];
7
+ export declare class PlusCalculator extends RanklistCalculator {
8
+ topstars: number;
9
+ warnings: string;
10
+ participantTagWhitelist?: string[];
11
+ participantTagBlacklist?: string[];
12
+ problemTagWhitelist?: string[];
13
+ problemTagBlacklist?: string[];
14
+ problemSlugFilter?: RegExp;
15
+ problemTitleFilter?: RegExp;
16
+ scoreReduceMethod: ReduceMethod;
17
+ totalReduceMethod: TotalReduceMethod;
18
+ private _reduceScore;
19
+ private _reduceTotal;
20
+ showOriginalScore: boolean;
21
+ showProblemScore: boolean;
22
+ showLastSubmission: boolean;
23
+ sameRankForSameScore: boolean;
24
+ loadConfig(dict: Record<string, string>): Promise<IRanklistSyncOptions>;
25
+ private _loadRenderConfig;
26
+ private _loadTotalReduceConfig;
27
+ private _loadScoreReduceConfig;
28
+ private _loadFilterConfig;
29
+ private _getProblems;
30
+ private _getParticipants;
31
+ private _renderParticipantItemColumn;
32
+ private _formatDate;
33
+ private _renderDate;
34
+ calculate(contestId: string, taskId: string, key: string): Promise<IRanklist>;
35
+ private _calculateTopstars;
36
+ private _calculateScores;
37
+ private _calculateLastSubmission;
38
+ }
39
+ export {};
@@ -0,0 +1,329 @@
1
+ import { RanklistCalculator } from './base.js';
2
+ const reduceMethods = ['override', 'max', 'min'];
3
+ const totalReduceMethods = ['sum', 'max', 'min'];
4
+ export class PlusCalculator extends RanklistCalculator {
5
+ topstars = 0;
6
+ warnings = '';
7
+ participantTagWhitelist;
8
+ participantTagBlacklist;
9
+ problemTagWhitelist;
10
+ problemTagBlacklist;
11
+ problemSlugFilter;
12
+ problemTitleFilter;
13
+ scoreReduceMethod = 'override';
14
+ totalReduceMethod = 'sum';
15
+ _reduceScore = (a, b) => b;
16
+ _reduceTotal = (a, b) => a + b;
17
+ showOriginalScore = false;
18
+ showProblemScore = false;
19
+ showLastSubmission = false;
20
+ sameRankForSameScore = false;
21
+ async loadConfig(dict) {
22
+ const topstars = +dict.topstars;
23
+ if (!Number.isInteger(topstars) || topstars < 0 || topstars > 20) {
24
+ this.warnings += 'topstars must be an integer between 0 and 20\n';
25
+ }
26
+ else {
27
+ this.topstars = topstars;
28
+ }
29
+ this._loadFilterConfig(dict);
30
+ this._loadScoreReduceConfig(dict);
31
+ this._loadTotalReduceConfig(dict);
32
+ this._loadRenderConfig(dict);
33
+ return {
34
+ shouldSyncParticipants: true,
35
+ shouldSyncSolutions: true
36
+ };
37
+ }
38
+ _loadRenderConfig(dict) {
39
+ if (dict.showOriginalScore) {
40
+ this.showOriginalScore = !!+dict.showOriginalScore;
41
+ }
42
+ if (dict.showProblemScore) {
43
+ this.showProblemScore = !!+dict.showProblemScore;
44
+ }
45
+ if (dict.showLastSubmission) {
46
+ this.showLastSubmission = !!+dict.showLastSubmission;
47
+ }
48
+ if (dict.sameRankForSameScore) {
49
+ this.sameRankForSameScore = !!+dict.sameRankForSameScore;
50
+ }
51
+ }
52
+ _loadTotalReduceConfig(dict) {
53
+ if (dict.totalReduceMethod) {
54
+ if (totalReduceMethods.includes(dict.totalReduceMethod)) {
55
+ this.totalReduceMethod = dict.totalReduceMethod;
56
+ switch (this.totalReduceMethod) {
57
+ case 'sum':
58
+ this._reduceTotal = (a, b) => a + b;
59
+ break;
60
+ case 'max':
61
+ this._reduceTotal = Math.max;
62
+ break;
63
+ case 'min':
64
+ this._reduceTotal = Math.min;
65
+ break;
66
+ }
67
+ }
68
+ else {
69
+ this.warnings += `totalReduceMethod must be one of ${totalReduceMethods.join(', ')}\n`;
70
+ }
71
+ }
72
+ }
73
+ _loadScoreReduceConfig(dict) {
74
+ if (dict.scoreReduceMethod) {
75
+ if (reduceMethods.includes(dict.scoreReduceMethod)) {
76
+ this.scoreReduceMethod = dict.scoreReduceMethod;
77
+ switch (this.scoreReduceMethod) {
78
+ case 'override':
79
+ this._reduceScore = (a, b) => b;
80
+ break;
81
+ case 'max':
82
+ this._reduceScore = Math.max;
83
+ break;
84
+ case 'min':
85
+ this._reduceScore = Math.min;
86
+ break;
87
+ }
88
+ }
89
+ else {
90
+ this.warnings += `scoreReduceMethod must be one of ${reduceMethods.join(', ')}\n`;
91
+ }
92
+ }
93
+ }
94
+ _loadFilterConfig(dict) {
95
+ if (dict.participantTagWhitelist) {
96
+ this.participantTagWhitelist = dict.participantTagWhitelist.split(',');
97
+ }
98
+ if (dict.participantTagBlacklist) {
99
+ this.participantTagBlacklist = dict.participantTagBlacklist.split(',');
100
+ }
101
+ if (dict.problemTagWhitelist) {
102
+ this.problemTagWhitelist = dict.problemTagWhitelist.split(',');
103
+ }
104
+ if (dict.problemTagBlacklist) {
105
+ this.problemTagBlacklist = dict.problemTagBlacklist.split(',');
106
+ }
107
+ if (dict.problemSlugFilter) {
108
+ this.problemSlugFilter = new RegExp(dict.problemSlugFilter);
109
+ }
110
+ if (dict.problemTitleFilter) {
111
+ this.problemTitleFilter = new RegExp(dict.problemTitleFilter);
112
+ }
113
+ }
114
+ async _getProblems(contestId, taskId) {
115
+ let problems = await this.client.problems(contestId, taskId);
116
+ const { problemTagWhitelist, problemTagBlacklist, problemSlugFilter, problemTitleFilter } = this;
117
+ if (problemTagWhitelist) {
118
+ problems = problems.filter((p) => p.tags.some((t) => problemTagWhitelist.includes(t)));
119
+ }
120
+ if (problemTagBlacklist) {
121
+ problems = problems.filter((p) => !p.tags.some((t) => problemTagBlacklist.includes(t)));
122
+ }
123
+ if (problemSlugFilter) {
124
+ problems = problems.filter((p) => problemSlugFilter.test(p.settings.slug));
125
+ }
126
+ if (problemTitleFilter) {
127
+ problems = problems.filter((p) => problemTitleFilter.test(p.title));
128
+ }
129
+ return problems;
130
+ }
131
+ async _getParticipants(contestId) {
132
+ let participants = await this.db.participants.find({ contestId }).toArray();
133
+ const { participantTagWhitelist, participantTagBlacklist } = this;
134
+ if (participantTagWhitelist) {
135
+ participants = participants.filter((p) => p.tags && p.tags.some((t) => participantTagWhitelist.includes(t)));
136
+ }
137
+ if (participantTagBlacklist) {
138
+ participants = participants.filter((p) => !p.tags || !p.tags.some((t) => participantTagBlacklist.includes(t)));
139
+ }
140
+ return participants;
141
+ }
142
+ _renderParticipantItemColumn(score, problemScore) {
143
+ if (this.showProblemScore)
144
+ return { content: `\`${score}/${problemScore}\`` };
145
+ return { content: `${score}` };
146
+ }
147
+ _formatDate(ts) {
148
+ const date = new Date(ts);
149
+ const iso = new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString();
150
+ return iso.replace(/-/g, '').replace('T', ' ').slice(0, -1);
151
+ }
152
+ _renderDate(ts) {
153
+ return `\`${this._formatDate(ts)}\``;
154
+ }
155
+ async calculate(contestId, taskId, key) {
156
+ const logger = this.logger.child({ contestId, taskId, key });
157
+ logger.info('Start to calculate ranklist');
158
+ const problems = await this._getProblems(contestId, taskId);
159
+ problems.sort((a, b) => a.settings.slug.localeCompare(b.settings.slug));
160
+ const problemIdList = problems.map((p) => p._id);
161
+ const problemScoreList = problems.map((p) => p.settings.score);
162
+ const participants = await this._getParticipants(contestId);
163
+ const participantsWithScores = participants.map(({ userId, tags, results }) => ({
164
+ userId,
165
+ tags,
166
+ scores: problemIdList.map((pid) => results[pid]?.lastSolution.score ?? 0),
167
+ lastSubmission: 0
168
+ }));
169
+ logger.info(`Loaded ${problems.length} problems and ${participants.length} participants`);
170
+ if (this.topstars || !this.sameRankForSameScore || this.showLastSubmission) {
171
+ // Calculate lastSubmission
172
+ await this._calculateLastSubmission(logger, contestId, problemIdList, participantsWithScores);
173
+ }
174
+ if (this.scoreReduceMethod !== 'override') {
175
+ // We need to manually calculate the scores
176
+ await this._calculateScores(logger, contestId, problemIdList, participantsWithScores);
177
+ }
178
+ if (!this.showOriginalScore) {
179
+ for (const participant of participantsWithScores) {
180
+ participant.scores = participant.scores.map((score, i) => (score * problemScoreList[i]) / 100);
181
+ }
182
+ }
183
+ const participantRecords = participantsWithScores
184
+ .map((record) => ({
185
+ ...record,
186
+ totalScore: (this.showOriginalScore
187
+ ? record.scores.map((score, i) => (score * problemScoreList[i]) / 100)
188
+ : record.scores).reduce((a, b) => this._reduceTotal(a, b), 0)
189
+ }))
190
+ .sort((a, b) =>
191
+ // First sort by totalScore DESC, then by updatedAt ASC
192
+ b.totalScore === a.totalScore
193
+ ? a.lastSubmission - b.lastSubmission
194
+ : b.totalScore - a.totalScore)
195
+ .map((record, index) => ({
196
+ ...record,
197
+ rank: index + 1
198
+ }));
199
+ if (this.sameRankForSameScore) {
200
+ participantRecords.forEach((record, index, arr) => {
201
+ if (index > 0 && record.totalScore === arr[index - 1].totalScore) {
202
+ record.rank = arr[index - 1].rank;
203
+ }
204
+ });
205
+ }
206
+ let topstar;
207
+ if (this.topstars) {
208
+ topstar = await this._calculateTopstars(logger, participantRecords, contestId, problemIdList, problemScoreList);
209
+ }
210
+ const now = performance.now();
211
+ logger.info(`Start to generate ranklist object`);
212
+ let description = 'Ranklist generated with type `plus`\n';
213
+ if (this.warnings) {
214
+ this.logger.warn({ contestId, taskId, key }, `Generated with warnings:\n${this.warnings}`);
215
+ description += `Warnings:\n\`\`\`\n${this.warnings}\`\`\``;
216
+ }
217
+ const problemTotalScore = problemScoreList.reduce((a, b) => this._reduceTotal(a, b), 0);
218
+ const ranklist = {
219
+ topstar,
220
+ participant: {
221
+ list: participantRecords.map(({ userId, rank, tags, scores, totalScore, lastSubmission }) => ({
222
+ userId,
223
+ rank,
224
+ tags,
225
+ columns: [
226
+ ...scores.map((score, i) => this._renderParticipantItemColumn(score, this.showOriginalScore ? 100 : problemScoreList[i])),
227
+ this._renderParticipantItemColumn(totalScore, problemTotalScore),
228
+ ...(this.showLastSubmission ? [{ content: this._renderDate(lastSubmission) }] : [])
229
+ ]
230
+ })),
231
+ columns: [
232
+ ...problems.map(({ title, settings: { slug } }) => ({
233
+ name: slug,
234
+ description: title
235
+ })),
236
+ { name: 'Total', description: 'Total Score' },
237
+ ...(this.showLastSubmission
238
+ ? [{ name: 'Last Submit', description: 'Last Submission Time' }]
239
+ : [])
240
+ ]
241
+ },
242
+ metadata: {
243
+ generatedAt: Date.now(),
244
+ description
245
+ }
246
+ };
247
+ logger.info(`Generated ranklist object in ${performance.now() - now}ms`);
248
+ return ranklist;
249
+ }
250
+ async _calculateTopstars(logger, participantRecords, contestId, problemIdList, problemScoreList) {
251
+ const now = Date.now();
252
+ logger.info('Calculating topstars');
253
+ const topstarUserIdList = participantRecords
254
+ .slice(0, this.topstars)
255
+ .filter((record) => record.totalScore > 0)
256
+ .map((p) => p.userId);
257
+ const topstar = {
258
+ list: await Promise.all(topstarUserIdList.map(async (userId) => {
259
+ const solutions = await this.db.solutions
260
+ .find({ contestId, userId, problemId: { $in: problemIdList } })
261
+ .sort({ completedAt: 1 })
262
+ .toArray();
263
+ const currentScores = Object.create(null);
264
+ const mutations = [];
265
+ for (const { problemId, score, submittedAt } of solutions) {
266
+ if (Object.hasOwn(currentScores, problemId)) {
267
+ currentScores[problemId] = this._reduceScore(currentScores[problemId], score);
268
+ }
269
+ else {
270
+ currentScores[problemId] = score;
271
+ }
272
+ mutations.push({
273
+ score: problemIdList
274
+ .map((pid, i) => ((currentScores[pid] ?? 0) * problemScoreList[i]) / 100)
275
+ .reduce((a, b) => this._reduceTotal(a, b), 0),
276
+ ts: submittedAt
277
+ });
278
+ }
279
+ return { userId, mutations };
280
+ }))
281
+ };
282
+ logger.info(`Calculated topstars in ${Date.now() - now}ms`);
283
+ return topstar;
284
+ }
285
+ async _calculateScores(logger, contestId, problemIdList, participantsWithScores) {
286
+ logger.info('Calculating scores');
287
+ const start = performance.now();
288
+ const scores = new Map();
289
+ const cursor = this.db.solutions.find({ contestId, problemId: { $in: problemIdList } });
290
+ for await (const solution of cursor) {
291
+ const { userId, problemId, score } = solution;
292
+ if (!scores.has(userId)) {
293
+ scores.set(userId, Object.create(null));
294
+ }
295
+ const userScores = scores.get(userId);
296
+ if (Object.hasOwn(userScores, problemId)) {
297
+ userScores[problemId] = this._reduceScore(userScores[problemId], score);
298
+ }
299
+ else {
300
+ userScores[problemId] = score;
301
+ }
302
+ }
303
+ for (const participant of participantsWithScores) {
304
+ const userScores = scores.get(participant.userId) ?? Object.create(null);
305
+ participant.scores = problemIdList.map((pid) => userScores[pid] ?? 0);
306
+ }
307
+ logger.info(`Calculated scores in ${performance.now() - start}ms`);
308
+ }
309
+ async _calculateLastSubmission(logger, contestId, problemIdList, participantsWithScores) {
310
+ logger.info('Calculating lastSubmission');
311
+ const start = performance.now();
312
+ const lastSubmissions = new Map();
313
+ const cursor = this.db.solutions.find({ contestId, problemId: { $in: problemIdList } });
314
+ for await (const solution of cursor) {
315
+ const { userId, submittedAt } = solution;
316
+ if (lastSubmissions.has(userId)) {
317
+ lastSubmissions.set(userId, Math.max(lastSubmissions.get(userId), submittedAt));
318
+ }
319
+ else {
320
+ lastSubmissions.set(userId, submittedAt);
321
+ }
322
+ }
323
+ for (const participant of participantsWithScores) {
324
+ participant.lastSubmission = lastSubmissions.get(participant.userId) ?? 0;
325
+ }
326
+ logger.info(`Calculated lastSubmission in ${performance.now() - start}ms`);
327
+ }
328
+ }
329
+ //# sourceMappingURL=plus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plus.js","sourceRoot":"","sources":["../../src/calc/plus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { type KyInstance } from 'ky';
2
+ export interface IAkaClientConfig {
3
+ server: string;
4
+ runnerId: string;
5
+ runnerKey: string;
6
+ }
7
+ export interface IParticipant {
8
+ _id: string;
9
+ userId: string;
10
+ contestId: string;
11
+ tags?: string[];
12
+ results: Record<string, {
13
+ solutionCount: number;
14
+ lastSolutionId: string;
15
+ lastSolution: {
16
+ score: number;
17
+ status: string;
18
+ completedAt: number;
19
+ };
20
+ }>;
21
+ updatedAt: number;
22
+ }
23
+ export interface ISolution {
24
+ _id: string;
25
+ problemId: string;
26
+ userId: string;
27
+ label: string;
28
+ problemDataHash: string;
29
+ state: number;
30
+ solutionDataHash: string;
31
+ score: number;
32
+ metrics: Record<string, number>;
33
+ status: string;
34
+ message: string;
35
+ createdAt: number;
36
+ submittedAt: number;
37
+ completedAt: number;
38
+ }
39
+ export interface IRanklistTopstarItemMutation {
40
+ score: number;
41
+ ts: number;
42
+ }
43
+ export interface IRanklistTopstarItem {
44
+ userId: string;
45
+ mutations: IRanklistTopstarItemMutation[];
46
+ }
47
+ export interface IRanklistTopstar {
48
+ list: IRanklistTopstarItem[];
49
+ }
50
+ export interface IRanklistParticipantColumn {
51
+ name: string;
52
+ description: string;
53
+ }
54
+ export interface IRanklistParticipantItemColumn {
55
+ content: string;
56
+ }
57
+ export interface IRanklistParticipantItem {
58
+ rank: number;
59
+ userId: string;
60
+ tags?: string[];
61
+ columns: IRanklistParticipantItemColumn[];
62
+ }
63
+ export interface IRanklistParticipant {
64
+ columns: IRanklistParticipantColumn[];
65
+ list: IRanklistParticipantItem[];
66
+ }
67
+ export interface IRanklistMetadata {
68
+ generatedAt: number;
69
+ description: string;
70
+ }
71
+ export interface IRanklist {
72
+ topstar?: IRanklistTopstar;
73
+ participant: IRanklistParticipant;
74
+ metadata: IRanklistMetadata;
75
+ }
76
+ export declare class AkaClient {
77
+ private config;
78
+ http: KyInstance;
79
+ constructor(config: IAkaClientConfig);
80
+ poll(): Promise<{
81
+ taskId: string;
82
+ contestId: string;
83
+ ranklists: Array<{
84
+ key: string;
85
+ name: string;
86
+ settings: {
87
+ showAfter?: number;
88
+ showBefore?: number;
89
+ config?: string;
90
+ };
91
+ }>;
92
+ ranklistUpdatedAt: number;
93
+ }>;
94
+ complete(contestId: string, taskId: string, payload: {
95
+ ranklistUpdatedAt: number;
96
+ }): Promise<void>;
97
+ problems(contestId: string, taskId: string): Promise<{
98
+ _id: string;
99
+ title: string;
100
+ tags: string[];
101
+ settings: {
102
+ score: number;
103
+ slug: string;
104
+ solutionCountLimit: number;
105
+ showAfter?: number;
106
+ };
107
+ }[]>;
108
+ participants(contestId: string, taskId: string, since: number, lastId: string): Promise<IParticipant[]>;
109
+ solutions(contestId: string, taskId: string, since: number, lastId: string): Promise<ISolution[]>;
110
+ uploadUrls(contestId: string, taskId: string): Promise<{
111
+ key: string;
112
+ url: string;
113
+ }[]>;
114
+ uploadRanklist(url: string, ranklist: IRanklist): Promise<import("ky").KyResponse>;
115
+ }
package/lib/client.js ADDED
@@ -0,0 +1,57 @@
1
+ import ky from 'ky';
2
+ import metadata from '../package.json' assert { type: 'json' };
3
+ export class AkaClient {
4
+ config;
5
+ http;
6
+ constructor(config) {
7
+ this.config = config;
8
+ this.http = ky.create({
9
+ prefixUrl: config.server,
10
+ headers: {
11
+ 'X-AOI-Runner-Id': config.runnerId,
12
+ 'X-AOI-Runner-Key': config.runnerKey,
13
+ 'User-Agent': `Aka/${metadata.version}`
14
+ }
15
+ });
16
+ }
17
+ async poll() {
18
+ return this.http.post('api/runner/ranklist/poll').json();
19
+ }
20
+ async complete(contestId, taskId, payload) {
21
+ return this.http
22
+ .post(`api/runner/ranklist/task/${contestId}/${taskId}/complete`, { json: payload })
23
+ .json();
24
+ }
25
+ async problems(contestId, taskId) {
26
+ return this.http.get(`api/runner/ranklist/task/${contestId}/${taskId}/problems`).json();
27
+ }
28
+ async participants(contestId, taskId, since, lastId) {
29
+ return this.http
30
+ .get(`api/runner/ranklist/task/${contestId}/${taskId}/participants`, {
31
+ searchParams: {
32
+ since,
33
+ lastId
34
+ }
35
+ })
36
+ .json();
37
+ }
38
+ async solutions(contestId, taskId, since, lastId) {
39
+ return this.http
40
+ .get(`api/runner/ranklist/task/${contestId}/${taskId}/solutions`, {
41
+ searchParams: {
42
+ since,
43
+ lastId
44
+ }
45
+ })
46
+ .json();
47
+ }
48
+ async uploadUrls(contestId, taskId) {
49
+ return this.http.get(`api/runner/ranklist/task/${contestId}/${taskId}/uploadUrls`).json();
50
+ }
51
+ async uploadRanklist(url, ranklist) {
52
+ return ky.put(url, {
53
+ json: ranklist
54
+ });
55
+ }
56
+ }
57
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,MAAM,IAAI,CAAA;AACxC,OAAO,QAAQ,MAAM,iBAAiB,CAAC,SAAS,IAAI,EAAE,MAAM,EAAE,CAAA;AA2F9D,MAAM,OAAO,SAAS;IAEA;IADpB,IAAI,CAAY;IAChB,YAAoB,MAAwB;QAAxB,WAAM,GAAN,MAAM,CAAkB;QAC1C,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC;YACpB,SAAS,EAAE,MAAM,CAAC,MAAM;YACxB,OAAO,EAAE;gBACP,iBAAiB,EAAE,MAAM,CAAC,QAAQ;gBAClC,kBAAkB,EAAE,MAAM,CAAC,SAAS;gBACpC,YAAY,EAAE,OAAO,QAAQ,CAAC,OAAO,EAAE;aACxC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,IAAI,EAalD,CAAA;IACN,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,MAAc,EAAE,OAAsC;QACtF,OAAO,IAAI,CAAC,IAAI;aACb,IAAI,CAAC,4BAA4B,SAAS,IAAI,MAAM,WAAW,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;aACnF,IAAI,EAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,MAAc;QAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,4BAA4B,SAAS,IAAI,MAAM,WAAW,CAAC,CAAC,IAAI,EAYlF,CAAA;IACL,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,MAAc,EAAE,KAAa,EAAE,MAAc;QACjF,OAAO,IAAI,CAAC,IAAI;aACb,GAAG,CAAC,4BAA4B,SAAS,IAAI,MAAM,eAAe,EAAE;YACnE,YAAY,EAAE;gBACZ,KAAK;gBACL,MAAM;aACP;SACF,CAAC;aACD,IAAI,EAAkB,CAAA;IAC3B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,SAAiB,EAAE,MAAc,EAAE,KAAa,EAAE,MAAc;QAC9E,OAAO,IAAI,CAAC,IAAI;aACb,GAAG,CAAC,4BAA4B,SAAS,IAAI,MAAM,YAAY,EAAE;YAChE,YAAY,EAAE;gBACZ,KAAK;gBACL,MAAM;aACP;SACF,CAAC;aACD,IAAI,EAAe,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB,EAAE,MAAc;QAChD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,4BAA4B,SAAS,IAAI,MAAM,aAAa,CAAC,CAAC,IAAI,EAKpF,CAAA;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAW,EAAE,QAAmB;QACnD,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE;YACjB,IAAI,EAAE,QAAQ;SACf,CAAC,CAAA;IACJ,CAAC;CACF"}
package/lib/db.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { MongoClient } from 'mongodb';
2
+ import { IParticipant, ISolution } from './client.js';
3
+ export interface IAkaDbConfig {
4
+ mongoUrl: string;
5
+ }
6
+ export declare class AkaDb {
7
+ private config;
8
+ mongo: MongoClient;
9
+ db: import("mongodb").Db;
10
+ participants: import("mongodb").Collection<IParticipant & {
11
+ contestId: string;
12
+ }>;
13
+ solutions: import("mongodb").Collection<ISolution & {
14
+ contestId: string;
15
+ }>;
16
+ constructor(config: IAkaDbConfig);
17
+ }
package/lib/db.js ADDED
@@ -0,0 +1,16 @@
1
+ import { MongoClient } from 'mongodb';
2
+ export class AkaDb {
3
+ config;
4
+ mongo;
5
+ db;
6
+ participants;
7
+ solutions;
8
+ constructor(config) {
9
+ this.config = config;
10
+ this.mongo = new MongoClient(config.mongoUrl);
11
+ this.db = this.mongo.db('aka');
12
+ this.participants = this.db.collection('participants');
13
+ this.solutions = this.db.collection('solutions');
14
+ }
15
+ }
16
+ //# sourceMappingURL=db.js.map
package/lib/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAOrC,MAAM,OAAO,KAAK;IAMI;IALpB,KAAK,CAAA;IACL,EAAE,CAAA;IACF,YAAY,CAAA;IACZ,SAAS,CAAA;IAET,YAAoB,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;QACtC,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC7C,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAA;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAuC,cAAc,CAAC,CAAA;QAC5F,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,UAAU,CAAoC,WAAW,CAAC,CAAA;IACrF,CAAC;CACF"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { AkaClient, IAkaClientConfig } from './client.js';
2
+ import { AkaDb, IAkaDbConfig } from './db.js';
3
+ export interface IAkaConfig {
4
+ client: IAkaClientConfig;
5
+ db: IAkaDbConfig;
6
+ }
7
+ export declare class Aka {
8
+ private config;
9
+ client: AkaClient;
10
+ db: AkaDb;
11
+ logger: import("pino").Logger<never>;
12
+ constructor(config: IAkaConfig);
13
+ syncSolutions(contestId: string, taskId: string, limit: number): Promise<number>;
14
+ syncParticipants(contestId: string, taskId: string, limit: number): Promise<number>;
15
+ poll(): Promise<boolean>;
16
+ start(): Promise<void>;
17
+ }
package/lib/index.js ADDED
@@ -0,0 +1,123 @@
1
+ import dotenv from 'dotenv';
2
+ import { AkaClient } from './client.js';
3
+ import { getCalculator } from './calc/index.js';
4
+ import { AkaDb } from './db.js';
5
+ import { pino } from 'pino';
6
+ import { wait } from './utils.js';
7
+ export class Aka {
8
+ config;
9
+ client;
10
+ db;
11
+ logger;
12
+ constructor(config) {
13
+ this.config = config;
14
+ this.client = new AkaClient(config.client);
15
+ this.db = new AkaDb(config.db);
16
+ this.logger = pino();
17
+ }
18
+ async syncSolutions(contestId, taskId, limit) {
19
+ this.logger.info({ contestId, taskId }, `Start to sync solutions with limit=${limit}`);
20
+ const last = await this.db.solutions.findOne({ contestId }, { sort: { completedAt: -1, _id: -1 } });
21
+ let since = 0, lastId = '00000000-0000-0000-0000-000000000000';
22
+ if (last) {
23
+ since = last.completedAt;
24
+ lastId = last._id;
25
+ }
26
+ for (;;) {
27
+ this.logger.info({ contestId, taskId }, `Sync solutions from since=${since} lastId=${lastId}`);
28
+ const solutions = await this.client.solutions(contestId, taskId, since, lastId);
29
+ for (const solution of solutions) {
30
+ await this.db.solutions.updateOne({ _id: solution._id }, { $set: { ...solution, contestId } }, { upsert: true });
31
+ }
32
+ if (!solutions.length) {
33
+ this.logger.info({ contestId, taskId }, `No more solutions`);
34
+ break;
35
+ }
36
+ since = solutions[solutions.length - 1].completedAt;
37
+ lastId = solutions[solutions.length - 1]._id;
38
+ if (since >= limit) {
39
+ this.logger.info({ contestId, taskId }, `Reach limit=${limit}`);
40
+ break;
41
+ }
42
+ }
43
+ return Math.max(since, limit);
44
+ }
45
+ async syncParticipants(contestId, taskId, limit) {
46
+ this.logger.info({ contestId, taskId }, `Start to sync participants with limit=${limit}`);
47
+ const last = await this.db.participants.findOne({ contestId }, { sort: { updatedAt: -1, _id: -1 } });
48
+ let since = 0, lastId = '00000000-0000-0000-0000-000000000000';
49
+ if (last) {
50
+ since = last.updatedAt;
51
+ lastId = last._id;
52
+ }
53
+ for (;;) {
54
+ this.logger.info({ contestId, taskId }, `Sync participants from since=${since} lastId=${lastId}`);
55
+ const participants = await this.client.participants(contestId, taskId, since, lastId);
56
+ for (const participant of participants) {
57
+ await this.db.participants.updateOne({ _id: participant._id }, { $set: { ...participant, contestId } }, { upsert: true });
58
+ }
59
+ if (!participants.length) {
60
+ this.logger.info({ contestId, taskId }, `No more participants`);
61
+ break;
62
+ }
63
+ since = participants[participants.length - 1].updatedAt;
64
+ lastId = participants[participants.length - 1]._id;
65
+ if (since >= limit) {
66
+ this.logger.info({ contestId, taskId }, `Reach limit=${limit}`);
67
+ break;
68
+ }
69
+ }
70
+ return Math.max(since, limit);
71
+ }
72
+ async poll() {
73
+ const { contestId, taskId, ranklistUpdatedAt, ranklists } = await this.client.poll();
74
+ if (!contestId)
75
+ return false;
76
+ this.logger.info({ contestId, taskId }, `Poll ${ranklists.length} ranklists at ${ranklistUpdatedAt}`);
77
+ let limit = ranklistUpdatedAt;
78
+ const configDicts = ranklists.map((r) => dotenv.parse(r.settings.config ?? ''));
79
+ const calculators = configDicts.map((dict) => getCalculator(this.db, this.client, this.logger, dict));
80
+ const syncOptions = await Promise.all(calculators.map(async (calc, i) => calc && (await calc.loadConfig(configDicts[i])))).then((list) => list.filter((opt) => !!opt));
81
+ const shouldSyncParticipants = syncOptions.some((opt) => opt.shouldSyncParticipants);
82
+ const shouldSyncSolutions = syncOptions.some((opt) => opt.shouldSyncSolutions);
83
+ if (shouldSyncParticipants) {
84
+ limit = await this.syncParticipants(contestId, taskId, limit);
85
+ }
86
+ if (shouldSyncSolutions) {
87
+ limit = await this.syncSolutions(contestId, taskId, limit);
88
+ }
89
+ this.logger.info({ contestId, taskId }, `Sync done, calculate ${ranklists.length} ranklists`);
90
+ const urls = await this.client.uploadUrls(contestId, taskId);
91
+ const urlDict = Object.fromEntries(urls.map(({ key, url }) => [key, url]));
92
+ await Promise.all(ranklists.map(async (ranklist, index) => {
93
+ const calculator = calculators[index];
94
+ const url = urlDict[ranklist.key];
95
+ if (!calculator || !url) {
96
+ this.logger.warn({ contestId, taskId, key: ranklist.key }, `No calculator or url`);
97
+ return;
98
+ }
99
+ const now = performance.now();
100
+ const result = await calculator.calculate(contestId, taskId, ranklist.key);
101
+ this.logger.info({ contestId, taskId, key: ranklist.key }, `Ranklist ${ranklist.key} calculated in ${performance.now() - now}ms`);
102
+ await this.client.uploadRanklist(url, result);
103
+ }));
104
+ await this.client.complete(contestId, taskId, { ranklistUpdatedAt: limit });
105
+ return true;
106
+ }
107
+ async start() {
108
+ this.logger.info(`Start to poll`);
109
+ for (;;) {
110
+ try {
111
+ const success = await this.poll();
112
+ if (!success) {
113
+ await wait(1000);
114
+ }
115
+ }
116
+ catch (err) {
117
+ this.logger.error(err);
118
+ await wait(1000);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/utils.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function wait(ms: number): Promise<unknown>;
package/lib/utils.js ADDED
@@ -0,0 +1,4 @@
1
+ export function wait(ms) {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ }
4
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,IAAI,CAAC,EAAU;IAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC1D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aoi-js/aka",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "packageManager": "yarn@4.0.2",
5
5
  "publishConfig": {
6
6
  "access": "public"