Files
blitzkit/scripts/buildRatingsLeaderboard.ts
T

144 lines
4.3 KiB
TypeScript
Raw Normal View History

import { Octokit } from '@octokit/rest';
import { rm, writeFile } from 'fs/promises';
import { argv, env } from 'process';
2023-07-16 17:51:01 +00:00
import {
RatingsInfo,
RatingsNeighbors,
RatingsPlayer,
} from '../src/commands/ratings';
import commitMultipleFiles from './commitMultipleFiles.js';
2023-07-14 01:52:05 +00:00
/*
* Central North American Time (UTC-5): use 0 5 * * *.
* Central European Time (UTC+1): use 0 23 * * *.
* Central Asia Standard Time (UTC+7): use 0 17 * * *.
*
2023-07-16 17:51:01 +00:00
* na/ratings/49/info.json: season info like rewards, start & end time, etc.
* na/ratings/49/latest.json: the absolute latest leaderboard recorded at UTC+0 midnight
* na/ratings/49/midnight.json: last midnight's leaderboard relative to the region
*/
2023-07-14 01:52:05 +00:00
export type BlitzkriegRatingsLeaderboard = { id: number; score: number }[];
const publish = argv.includes('--publish');
const latest = argv.includes('--latest');
2023-07-14 01:52:05 +00:00
const server = argv.find((arg) => arg.startsWith('--region='))?.split('=')[1];
if (!server) throw new Error('Region parameter not specified');
const NEIGHBORS = 1000;
const PLAYERS = await fetch(
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
)
2023-07-16 17:51:01 +00:00
.then((response) => response.json() as Promise<RatingsInfo>)
2023-09-07 01:13:03 +00:00
.then((data) => (data.detail === undefined ? data.count : undefined));
if (PLAYERS === undefined) {
throw new Error('No current ratings season running');
}
2023-07-15 01:21:59 +00:00
const players: Record<number, RatingsPlayer> = {};
const leaderboard: BlitzkriegRatingsLeaderboard = [];
let registered = 0;
2023-07-15 01:21:59 +00:00
async function branchFromPlayer(id: number) {
const { neighbors } = await fetch(
`https://${server}.wotblitz.com/en/api/rating-leaderboards/user/${id}/?neighbors=${NEIGHBORS}`,
2023-07-15 01:21:59 +00:00
).then((response) => response.json() as Promise<RatingsNeighbors>);
const firstPlayer = neighbors[0];
const lastPlayer = neighbors[neighbors.length - 1];
2023-07-15 01:21:59 +00:00
const branches: Promise<void>[] = [];
if (!players[firstPlayer.number])
branches.push(branchFromPlayer(firstPlayer.spa_id));
if (!players[lastPlayer.number])
branches.push(branchFromPlayer(lastPlayer.spa_id));
neighbors.forEach((neighbor) => {
if (players[neighbor.number]) return;
players[neighbor.number] = neighbor;
registered++;
});
console.log(
`Registered ${registered} / ${PLAYERS} (${(
2023-09-07 01:13:03 +00:00
(registered / PLAYERS!) *
100
).toFixed(2)}%)`,
);
await Promise.all(branches);
}
2023-07-15 01:21:59 +00:00
async function branchFromLeague(id: number) {
const { result } = await fetch(
`https://${server}.wotblitz.com/en/api/rating-leaderboards/league/${id}/top/`,
).then((response) => response.json() as Promise<{ result: RatingsPlayer[] }>);
const firstPlayer = result[0];
const lastPlayer = result[result.length - 1];
await Promise.all([
branchFromPlayer(firstPlayer.spa_id),
branchFromPlayer(lastPlayer.spa_id),
]);
}
2023-07-15 01:21:59 +00:00
console.log('Branching from leagues...');
await Promise.all([
branchFromLeague(0),
branchFromLeague(1),
branchFromLeague(2),
branchFromLeague(3),
branchFromLeague(4),
]);
console.log('Converting to an array...');
for (let index = 0; index < PLAYERS; index++) {
const listing = players[index + 1];
if (!listing) console.warn(`Position ${index + 1} had no player`);
leaderboard[index] = {
id: listing.spa_id,
score: listing.score,
};
}
const leaderboardJSON = JSON.stringify(leaderboard);
if (publish) {
2023-07-14 01:52:05 +00:00
const octokit = new Octokit({ auth: env.GH_TOKEN });
const info = await fetch(
`https://${server}.wotblitz.com/en/api/rating-leaderboards/season/`,
2023-09-07 01:13:03 +00:00
).then(
(response) =>
response.json() as Promise<RatingsInfo & { detail: undefined }>,
);
const normalizedServer = server === 'na' ? 'com' : server;
const infoPath = `${normalizedServer}/ratings/${info.current_season}/info.json`;
const leaderboardPath = `${normalizedServer}/ratings/${info.current_season}/${
2023-07-16 17:51:01 +00:00
latest ? 'latest' : 'midnight'
}.json`;
const infoJSON = JSON.stringify(info);
console.log(`Publishing to season ${info.current_season}...`);
commitMultipleFiles(
octokit,
'tresabhi',
'blitzkrieg-db',
'main',
2023-07-16 17:51:01 +00:00
new Date().toString(),
[
{ path: infoPath, content: infoJSON },
{ path: leaderboardPath, content: leaderboardJSON },
],
);
} else {
console.log('Writing to disk...');
await rm('dist.json', { force: true });
await writeFile('dist.json', leaderboardJSON);
}