mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
feat: data driven latest archived season number
This commit is contained in:
1 parent
d1ebb79432
commit
f02db2a2d8
13 files changed
+145
-96
No files matched your search
@@ -0,0 +1,12 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { Region } from '../../../../../../constants/regions';
|
||||
import { getArchivedRatingsLeaderboard } from '../../../../../../core/blitzkrieg/getArchivedRatingsLeaderboard';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
{ params }: { params: { region: Region; season: number } },
|
||||
) {
|
||||
return NextResponse.json(
|
||||
await getArchivedRatingsLeaderboard(params.region, params.season),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { getArchivedLatestSeasonNumber } from '../../../../core/blitzkrieg/getArchivedLatestSeasonNumber';
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json(await getArchivedLatestSeasonNumber());
|
||||
}
|
||||
@@ -7,11 +7,11 @@ import { useEffect, useState } from 'react';
|
||||
import { RatingsInfo } from '../../../commands/ratings';
|
||||
import PageWrapper from '../../../components/PageWrapper';
|
||||
import { REGIONS, REGION_NAMES, Region } from '../../../constants/regions';
|
||||
import getRatingsInfo from '../../../core/blitz/getRatingsInfo';
|
||||
import {
|
||||
FIRST_ARCHIVED_RATINGS_SEASON,
|
||||
getLatestArchivedSeasonNumber,
|
||||
} from '../../../core/blitz/getLatestArchivedSeasonNumber';
|
||||
import getRatingsInfo from '../../../core/blitz/getRatingsInfo';
|
||||
getArchivedLatestSeasonNumberAPI,
|
||||
} from '../../../core/blitzkrieg/getArchivedLatestSeasonNumberAPI';
|
||||
import { useRatings } from '../../../stores/ratings';
|
||||
|
||||
export default function Page() {
|
||||
@@ -27,8 +27,8 @@ export default function Page() {
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const [newRatingsInfo, newLatestArchivedSeasonNumber] = await Promise.all(
|
||||
[getRatingsInfo(ratings.region), getLatestArchivedSeasonNumber()],
|
||||
);
|
||||
[getRatingsInfo(ratings.region), getArchivedLatestSeasonNumberAPI()],
|
||||
);
|
||||
|
||||
setRatingsInfo(newRatingsInfo);
|
||||
setLatestArchivedSeasonNumber(newLatestArchivedSeasonNumber);
|
||||
|
||||
+30
-72
@@ -4,6 +4,7 @@ import {
|
||||
SlashCommandSubcommandBuilder,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
} from 'discord.js';
|
||||
import { range } from 'lodash';
|
||||
import { BlitzkriegRatingsLeaderboard } from '../../scripts/buildRatingsLeaderboard';
|
||||
import * as Leaderboard from '../components/Leaderboard';
|
||||
import TitleBar from '../components/TitleBar';
|
||||
@@ -13,11 +14,11 @@ import { getAccountInfo } from '../core/blitz/getAccountInfo';
|
||||
import { getClanAccountInfo } from '../core/blitz/getClanAccountInfo';
|
||||
import getRatingsInfo from '../core/blitz/getRatingsInfo';
|
||||
import regionToRegionSubdomain from '../core/blitz/regionToRegionSubdomain';
|
||||
import { getArchivedLatestSeasonNumber } from '../core/blitzkrieg/getArchivedLatestSeasonNumber';
|
||||
import { FIRST_ARCHIVED_RATINGS_SEASON } from '../core/blitzkrieg/getArchivedLatestSeasonNumberAPI';
|
||||
import getArchivedRatingsInfo from '../core/blitzkrieg/getArchivedRatingsInfo';
|
||||
import getMidnightLeaderboard, {
|
||||
DATABASE_REPO,
|
||||
} from '../core/blitzkrieg/getMidnightLeaderboard';
|
||||
import { octokit } from '../core/blitzkrieg/octokit';
|
||||
import { getArchivedRatingsLeaderboard } from '../core/blitzkrieg/getArchivedRatingsLeaderboard';
|
||||
import getArchivedRatingsMidnightLeaderboard from '../core/blitzkrieg/getArchivedRatingsMidnightLeaderboard';
|
||||
import { UserError } from '../core/blitzkrieg/userError';
|
||||
import addRegionChoices from '../core/discord/addRegionChoices';
|
||||
import addUsernameChoices from '../core/discord/addUsernameChoices';
|
||||
@@ -178,23 +179,17 @@ const noOngoingSeason = embedNegative(
|
||||
|
||||
export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
async (resolve) => {
|
||||
const seasonChoices = await octokit.repos
|
||||
.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: 'com/ratings',
|
||||
})
|
||||
.then(({ data }) => {
|
||||
if (!Array.isArray(data)) {
|
||||
throw new Error('Archived ratings data is malformed');
|
||||
}
|
||||
return data.map(
|
||||
(folder) =>
|
||||
({
|
||||
name: `Season ${folder.name}`,
|
||||
value: folder.name,
|
||||
}) satisfies APIApplicationCommandOptionChoice<string>,
|
||||
);
|
||||
});
|
||||
const latestArchivedSeasonNumber = await getArchivedLatestSeasonNumber();
|
||||
const seasonChoices = range(
|
||||
FIRST_ARCHIVED_RATINGS_SEASON,
|
||||
latestArchivedSeasonNumber + 1,
|
||||
).map(
|
||||
(number) =>
|
||||
({
|
||||
name: `Season ${number}`,
|
||||
value: `${number}`,
|
||||
}) satisfies APIApplicationCommandOptionChoice<string>,
|
||||
);
|
||||
|
||||
const command = new SlashCommandBuilder()
|
||||
.setName('ratings')
|
||||
@@ -262,7 +257,7 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
const region = interaction.options.getString('region') as Region;
|
||||
regionRatingsInfo = await (subcommandGroup === 'current'
|
||||
? getRatingsInfo(region)
|
||||
: getArchivedRatingsInfo(season!, region));
|
||||
: getArchivedRatingsInfo(region, season!));
|
||||
|
||||
if (regionRatingsInfo.detail !== undefined) return noOngoingSeason;
|
||||
|
||||
@@ -285,19 +280,8 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
}) satisfies SimplifiedPlayer,
|
||||
),
|
||||
)
|
||||
: await octokit.repos
|
||||
.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: `${region}/ratings/${season}/latest.json`,
|
||||
})
|
||||
.then(async ({ data }) => {
|
||||
if (Array.isArray(data) || data.type !== 'file') {
|
||||
throw new Error('Archived ratings data is malformed');
|
||||
}
|
||||
|
||||
const players = (await fetch(data.download_url!).then(
|
||||
(response) => response.json(),
|
||||
)) as BlitzkriegRatingsLeaderboard;
|
||||
: await getArchivedRatingsLeaderboard(region, season!).then(
|
||||
async (players) => {
|
||||
const firstPlayerIndex =
|
||||
leagueIndex === 0
|
||||
? 0
|
||||
@@ -328,15 +312,16 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
`Unknown Player ${player.id}`,
|
||||
}) satisfies SimplifiedPlayer,
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
const leagueInfo = regionRatingsInfo.leagues[leagueIndex];
|
||||
midnightLeaderboard =
|
||||
subcommandGroup === 'current'
|
||||
? await getMidnightLeaderboard(
|
||||
? await getArchivedRatingsMidnightLeaderboard(
|
||||
region,
|
||||
regionRatingsInfo.current_season,
|
||||
)
|
||||
: await getMidnightLeaderboard(region, season!);
|
||||
: await getArchivedRatingsMidnightLeaderboard(region, season!);
|
||||
|
||||
players = result;
|
||||
playersBefore = result ? result[0].position - 1 : 0;
|
||||
@@ -354,21 +339,7 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
regionRatingsInfo =
|
||||
subcommandGroup === 'current'
|
||||
? await getRatingsInfo(region)
|
||||
: await octokit.repos
|
||||
.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: `${region}/ratings/${season}/info.json`,
|
||||
})
|
||||
.then(async ({ data }) => {
|
||||
if (Array.isArray(data) || data.type !== 'file') {
|
||||
throw new Error('Archived ratings info is malformed');
|
||||
}
|
||||
|
||||
const response = fetch(data.download_url!);
|
||||
return (await response.then((response) =>
|
||||
response.json(),
|
||||
)) as RatingsInfo;
|
||||
});
|
||||
: await getArchivedRatingsInfo(region, season!);
|
||||
|
||||
if (regionRatingsInfo.detail !== undefined) return noOngoingSeason;
|
||||
|
||||
@@ -397,22 +368,8 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
}) satisfies SimplifiedPlayer,
|
||||
),
|
||||
)
|
||||
: await octokit.repos
|
||||
.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: `${region}/ratings/${season}/latest.json`,
|
||||
})
|
||||
.then(async ({ data }) => {
|
||||
if (Array.isArray(data) || data.type !== 'file') {
|
||||
throw new Error(
|
||||
'Archived ratings latest data is malformed',
|
||||
);
|
||||
}
|
||||
|
||||
const response = fetch(data.download_url!);
|
||||
const players = (await response.then((response) =>
|
||||
response.json(),
|
||||
)) as BlitzkriegRatingsLeaderboard;
|
||||
: await getArchivedRatingsLeaderboard(region, season!).then(
|
||||
async (players) => {
|
||||
const playerIndex = players.findIndex(
|
||||
(player) => player.id === id,
|
||||
);
|
||||
@@ -445,14 +402,15 @@ export const ratingsCommand = new Promise<CommandRegistryRaw>(
|
||||
clan: clanData[player.id]!.clan?.tag,
|
||||
nickname: clanData[player.id]!.account_name,
|
||||
}));
|
||||
});
|
||||
},
|
||||
);
|
||||
midnightLeaderboard =
|
||||
subcommandGroup === 'current'
|
||||
? await getMidnightLeaderboard(
|
||||
? await getArchivedRatingsMidnightLeaderboard(
|
||||
region,
|
||||
regionRatingsInfo.current_season,
|
||||
)
|
||||
: await getMidnightLeaderboard(region, season!);
|
||||
: await getArchivedRatingsMidnightLeaderboard(region, season!);
|
||||
|
||||
if (clan && neighbors) titleNameDiscriminator = `[${clan.tag}]`;
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* The first every season that Blitzkrieg tracked :)
|
||||
*/
|
||||
export const FIRST_ARCHIVED_RATINGS_SEASON = 49;
|
||||
|
||||
export async function getLatestArchivedSeasonNumber() {
|
||||
return 51;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
type Context = 'website' | 'bot';
|
||||
type Context = 'website' | 'server';
|
||||
|
||||
export const context: Context =
|
||||
typeof window === 'undefined' ? 'bot' : 'website';
|
||||
typeof window === 'undefined' ? 'server' : 'website';
|
||||
@@ -0,0 +1,25 @@
|
||||
import { DATABASE_REPO } from './getArchivedRatingsMidnightLeaderboard';
|
||||
import { octokit } from './octokit';
|
||||
|
||||
let cachedLatestArchivedSeasonNumber: number | null = null;
|
||||
|
||||
export async function getArchivedLatestSeasonNumber() {
|
||||
if (cachedLatestArchivedSeasonNumber) {
|
||||
return cachedLatestArchivedSeasonNumber;
|
||||
}
|
||||
|
||||
const { data } = await octokit.repos.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: 'com/ratings',
|
||||
});
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
throw new Error('Archived ratings data is malformed');
|
||||
}
|
||||
|
||||
cachedLatestArchivedSeasonNumber = Math.max(
|
||||
...data.map(({ name }) => parseInt(name)),
|
||||
);
|
||||
|
||||
return cachedLatestArchivedSeasonNumber;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
let cachedLatestArchivedSeasonNumber: number | null = null;
|
||||
|
||||
/**
|
||||
* The first every season that Blitzkrieg tracked :)
|
||||
*/
|
||||
export const FIRST_ARCHIVED_RATINGS_SEASON = 49;
|
||||
|
||||
export async function getArchivedLatestSeasonNumberAPI() {
|
||||
if (cachedLatestArchivedSeasonNumber) {
|
||||
return cachedLatestArchivedSeasonNumber;
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/ratings/latest-archived-season-number`);
|
||||
const number = parseInt(await response.text());
|
||||
cachedLatestArchivedSeasonNumber = number;
|
||||
|
||||
return cachedLatestArchivedSeasonNumber;
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { RatingsInfo } from '../../commands/ratings';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { DATABASE_REPO } from './getMidnightLeaderboard';
|
||||
import { DATABASE_REPO } from './getArchivedRatingsMidnightLeaderboard';
|
||||
import { octokit } from './octokit';
|
||||
|
||||
const ARCHIVED_RATINGS_CACHE: Record<
|
||||
const INFO_CACHE: Record<
|
||||
Region,
|
||||
Record<
|
||||
number,
|
||||
@@ -18,11 +18,11 @@ const ARCHIVED_RATINGS_CACHE: Record<
|
||||
};
|
||||
|
||||
export default async function getArchivedRatingsInfo(
|
||||
season: number,
|
||||
region: Region,
|
||||
season: number,
|
||||
) {
|
||||
if (ARCHIVED_RATINGS_CACHE[region][season]) {
|
||||
return ARCHIVED_RATINGS_CACHE[region][season];
|
||||
if (INFO_CACHE[region][season]) {
|
||||
return INFO_CACHE[region][season];
|
||||
}
|
||||
|
||||
const { data } = await octokit.repos.getContent({
|
||||
@@ -38,7 +38,7 @@ export default async function getArchivedRatingsInfo(
|
||||
detail: undefined;
|
||||
};
|
||||
|
||||
ARCHIVED_RATINGS_CACHE[region][season] = jsonContent;
|
||||
INFO_CACHE[region][season] = jsonContent;
|
||||
|
||||
return jsonContent;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { BlitzkriegRatingsLeaderboard } from '../../../scripts/buildRatingsLeaderboard';
|
||||
import { Region } from '../../constants/regions';
|
||||
import { DATABASE_REPO } from './getArchivedRatingsMidnightLeaderboard';
|
||||
import { octokit } from './octokit';
|
||||
|
||||
const LEADERBOARD_CACHE: Record<
|
||||
Region,
|
||||
Record<number, BlitzkriegRatingsLeaderboard>
|
||||
> = {
|
||||
asia: {},
|
||||
eu: {},
|
||||
com: {},
|
||||
};
|
||||
|
||||
export async function getArchivedRatingsLeaderboard(
|
||||
region: Region,
|
||||
season: number,
|
||||
) {
|
||||
if (LEADERBOARD_CACHE[region][season]) {
|
||||
return LEADERBOARD_CACHE[region][season];
|
||||
}
|
||||
|
||||
const { data } = await octokit.repos.getContent({
|
||||
...DATABASE_REPO,
|
||||
path: `${region}/ratings/${season}/latest.json`,
|
||||
});
|
||||
|
||||
if (Array.isArray(data) || data.type !== 'file') {
|
||||
throw new Error('Archived ratings data is malformed');
|
||||
}
|
||||
|
||||
const response = await fetch(data.download_url!);
|
||||
const json = (await response.json()) as BlitzkriegRatingsLeaderboard;
|
||||
|
||||
LEADERBOARD_CACHE[region][season] = json;
|
||||
|
||||
return json;
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ const MIDNIGHT_LEADERBOARD_CACHE: Record<
|
||||
asia: {},
|
||||
};
|
||||
|
||||
export default async function getMidnightLeaderboard(
|
||||
export default async function getArchivedRatingsMidnightLeaderboard(
|
||||
region: Region,
|
||||
season: number,
|
||||
) {
|
||||
@@ -90,7 +90,7 @@ export const tankAverages = fetch(
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((json) => {
|
||||
if (context === 'bot') {
|
||||
if (context === 'server') {
|
||||
const partialTankAverages: TankAverages = {};
|
||||
|
||||
(json as IndividualTankAverage[]).forEach((individualTankAverage) => {
|
||||
|
||||
@@ -23,7 +23,7 @@ export const tankopedia = fetch(
|
||||
)
|
||||
.then(async (response) => response.json())
|
||||
.then((wrapperTankopedia) =>
|
||||
context === 'bot'
|
||||
context === 'server'
|
||||
? (wrapperTankopedia as { data: Tankopedia }).data
|
||||
: (wrapperTankopedia as Tankopedia),
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user