mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
purge some dead code
This commit is contained in:
1 parent
878ada0d10
commit
2ee72b40ab
65 files changed
+30
-4376
No files matched your search
@@ -1,89 +0,0 @@
|
||||
import { assertSecret, EventManager } from "../blitzkit";
|
||||
import { patientFetch } from "../blitzkit/patientFetch";
|
||||
import type { Region } from "./regions";
|
||||
|
||||
const RETRY_ERRORS = ["REQUEST_LIMIT_EXCEEDED", "SOURCE_NOT_AVAILABLE"];
|
||||
|
||||
export const retryAbleBlitzFetchEvent = new EventManager();
|
||||
export const blitzFetchQueueAvailableEvent = new EventManager();
|
||||
|
||||
type BlitzResponse<Data extends object> =
|
||||
| {
|
||||
status: "error";
|
||||
error: { field: string; message: string; code: 402; value: null };
|
||||
}
|
||||
| {
|
||||
status: "ok";
|
||||
data: Data;
|
||||
};
|
||||
|
||||
const MAX_CALLS_PER_SECOND = 10;
|
||||
|
||||
const queue: { url: string; resolve: (data: object) => void }[] = [];
|
||||
let inProgress = 0;
|
||||
|
||||
function decrement() {
|
||||
inProgress--;
|
||||
blitzFetchQueueAvailableEvent.emit(undefined);
|
||||
manageQueue();
|
||||
}
|
||||
|
||||
async function manageQueue() {
|
||||
if (queue.length > 0 && inProgress < MAX_CALLS_PER_SECOND) {
|
||||
inProgress++;
|
||||
|
||||
const timeout = setTimeout(decrement, 1000);
|
||||
const request = queue.shift()!;
|
||||
const data = (await patientFetch(request.url)
|
||||
.then((response) => response.json())
|
||||
.catch((error) => ({ status: "error", error }))) as BlitzResponse<
|
||||
typeof request.resolve
|
||||
>;
|
||||
|
||||
if (data.status === "ok") {
|
||||
request.resolve(data.data);
|
||||
} else {
|
||||
if (RETRY_ERRORS.includes(data.error.message)) {
|
||||
retryAbleBlitzFetchEvent.emit(undefined);
|
||||
clearTimeout(timeout);
|
||||
setTimeout(() => {
|
||||
queue.push(request);
|
||||
decrement();
|
||||
}, 1000 / MAX_CALLS_PER_SECOND);
|
||||
} else {
|
||||
clearTimeout(timeout);
|
||||
decrement();
|
||||
|
||||
throw new Error(`Wargaming response error status: "${data.status}"`, {
|
||||
cause: `Message: "${data.error.message}"\nURL: "${request.url}"`,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type FetchBlitzParams = Record<string, string | number | undefined>;
|
||||
|
||||
export function fetchBlitz<Data extends object>(
|
||||
region: Region,
|
||||
path: string,
|
||||
params: FetchBlitzParams = {}
|
||||
) {
|
||||
return new Promise<Data>((resolve) => {
|
||||
queue.push({
|
||||
url: `https://api.wotblitz.${region}/wotb/${path}/?${Object.entries({
|
||||
application_id: assertSecret(
|
||||
import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID
|
||||
),
|
||||
...params,
|
||||
})
|
||||
.filter(([_, value]) => value !== undefined)
|
||||
.map(([key, value]) => `${key}=${encodeURIComponent(value!)}`)
|
||||
.join("&")}`,
|
||||
resolve(data) {
|
||||
resolve(data as Data);
|
||||
},
|
||||
});
|
||||
manageQueue();
|
||||
});
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { assertSecret } from "../blitzkit";
|
||||
import type { BlitzGlossary } from "../types";
|
||||
|
||||
export async function fetchGlossary(locale: string) {
|
||||
const response = await fetch(
|
||||
`${assertSecret(
|
||||
import.meta.env.WOTB_GLOSSARY_DOMAIN
|
||||
)}/${locale}${assertSecret(import.meta.env.WOTB_GLOSSARY_PATH)}`
|
||||
);
|
||||
return (await response.json()) as BlitzGlossary;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { fetchBlitz } from "./fetchBlitz";
|
||||
import { normalizeIds } from "./normalizeIds";
|
||||
import type { Region } from "./regions";
|
||||
|
||||
interface IndividualAccountAchievements {
|
||||
achievements: {
|
||||
[achievement: string]: number;
|
||||
};
|
||||
max_series: {
|
||||
[achievement: string]: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AccountAchievements {
|
||||
[id: number]: IndividualAccountAchievements;
|
||||
}
|
||||
|
||||
export async function getAccountAchievements<
|
||||
Ids extends number | number[],
|
||||
ReturnType = Ids extends number
|
||||
? IndividualAccountAchievements
|
||||
: IndividualAccountAchievements[],
|
||||
>(region: Region, ids: Ids) {
|
||||
const object = await fetchBlitz<AccountAchievements>(
|
||||
region,
|
||||
"account/achievements",
|
||||
{ account_id: normalizeIds(ids) }
|
||||
);
|
||||
|
||||
if (typeof ids === "number") {
|
||||
return object[ids as number] as ReturnType;
|
||||
} else {
|
||||
return ids.map((id) => object[id]) as ReturnType;
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
import { BlitzStats } from "../statistics";
|
||||
import { FetchBlitzParams, fetchBlitz } from "./fetchBlitz";
|
||||
import { normalizeIds } from "./normalizeIds";
|
||||
import { Region } from "./regions";
|
||||
|
||||
export interface SupplementaryStats {
|
||||
WN8?: number;
|
||||
tier?: number;
|
||||
}
|
||||
|
||||
export interface ClanStats {
|
||||
spotted: number;
|
||||
max_frags_tank_id: number;
|
||||
hits: number;
|
||||
frags: number;
|
||||
max_xp: number;
|
||||
max_xp_tank_id: number;
|
||||
wins: number;
|
||||
losses: number;
|
||||
capture_points: number;
|
||||
battles: number;
|
||||
damage_dealt: number;
|
||||
damage_received: number;
|
||||
max_frags: number;
|
||||
shots: number;
|
||||
frags8p: number;
|
||||
xp: number;
|
||||
win_and_survived: number;
|
||||
survived_battles: number;
|
||||
dropped_capture_points: number;
|
||||
}
|
||||
|
||||
export interface RatingStats {
|
||||
spotted: number;
|
||||
calibration_battles_left: number;
|
||||
hits: number;
|
||||
frags: number;
|
||||
recalibration_start_time: number;
|
||||
mm_rating: number;
|
||||
wins: number;
|
||||
losses: number;
|
||||
is_recalibration: boolean;
|
||||
capture_points: number;
|
||||
battles: number;
|
||||
damage_dealt: number;
|
||||
damage_received: number;
|
||||
shots: number;
|
||||
frags8p: number;
|
||||
xp: number;
|
||||
win_and_survived: number;
|
||||
survived_battles: number;
|
||||
dropped_capture_points: number;
|
||||
}
|
||||
|
||||
export interface IndividualAccountInfo {
|
||||
account_id: number;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
private: null;
|
||||
last_battle_time: number;
|
||||
nickname: string;
|
||||
statistics: {
|
||||
all: BlitzStats;
|
||||
clan: ClanStats;
|
||||
rating?: RatingStats;
|
||||
frags: null | number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AccountInfo {
|
||||
[accountId: number]: IndividualAccountInfo;
|
||||
}
|
||||
|
||||
export async function getAccountInfo<
|
||||
Ids extends number | number[],
|
||||
ReturnType = Ids extends number
|
||||
? IndividualAccountInfo
|
||||
: IndividualAccountInfo[],
|
||||
>(
|
||||
region: Region,
|
||||
ids: Ids,
|
||||
extra: string[] = [],
|
||||
params: FetchBlitzParams = {}
|
||||
) {
|
||||
const object = await fetchBlitz<AccountInfo>(region, "account/info", {
|
||||
account_id: normalizeIds(ids),
|
||||
extra: extra.length === 0 ? undefined : extra.join(","),
|
||||
...params,
|
||||
});
|
||||
|
||||
if (typeof ids === "number") {
|
||||
return object[ids as number] as ReturnType;
|
||||
} else {
|
||||
return ids.map((id) => object[id]) as ReturnType;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { fetchBlitz } from "./fetchBlitz";
|
||||
import { normalizeIds } from "./normalizeIds";
|
||||
import type { Region } from "./regions";
|
||||
|
||||
type IndividualClanAccountInfo = {
|
||||
account_id: number;
|
||||
joined_at: number;
|
||||
clan_id: number;
|
||||
role: string;
|
||||
account_name: string;
|
||||
|
||||
clan?: {
|
||||
members_count: number;
|
||||
name: string;
|
||||
created_at: number;
|
||||
tag: string;
|
||||
clan_id: number;
|
||||
emblem_set_id: number;
|
||||
};
|
||||
} | null;
|
||||
|
||||
interface ClanAccountInfo {
|
||||
[accountId: number]: IndividualClanAccountInfo;
|
||||
}
|
||||
|
||||
export async function getClanAccountInfo<
|
||||
Ids extends number | number[],
|
||||
ReturnType = Ids extends number
|
||||
? IndividualClanAccountInfo
|
||||
: IndividualClanAccountInfo[],
|
||||
>(region: Region, ids: Ids, extra: string[] = []) {
|
||||
const object = await fetchBlitz<ClanAccountInfo>(
|
||||
region,
|
||||
"clans/accountinfo",
|
||||
{
|
||||
account_id: normalizeIds(ids),
|
||||
extra: extra.length === 0 ? undefined : extra.join(","),
|
||||
}
|
||||
);
|
||||
|
||||
if (typeof ids === "number") {
|
||||
return object[ids as number] as ReturnType;
|
||||
} else {
|
||||
return ids.map((id) => object[id]) as ReturnType;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import { fetchBlitz } from "./fetchBlitz";
|
||||
import { normalizeIds } from "./normalizeIds";
|
||||
import type { Region } from "./regions";
|
||||
|
||||
interface IndividualClanInfo {
|
||||
recruiting_options: {
|
||||
vehicles_level: number;
|
||||
wins_ratio: number;
|
||||
average_battles_per_day: number;
|
||||
battles: number;
|
||||
average_damage: number;
|
||||
};
|
||||
members_count: number;
|
||||
name: string;
|
||||
creator_name: string;
|
||||
clan_id: number;
|
||||
created_at: number;
|
||||
updated_at: number;
|
||||
leader_name: string;
|
||||
members_ids: number[];
|
||||
recruiting_policy: string;
|
||||
tag: string;
|
||||
is_clan_disbanded: boolean;
|
||||
old_name: string;
|
||||
emblem_set_id: number;
|
||||
creator_id: number;
|
||||
motto: string;
|
||||
renamed_at: number;
|
||||
old_tag: null;
|
||||
leader_id: number;
|
||||
description: string;
|
||||
}
|
||||
|
||||
interface ClanInfo {
|
||||
[clanId: number]: IndividualClanInfo;
|
||||
}
|
||||
|
||||
export async function getClanInfo<
|
||||
Ids extends number | number[],
|
||||
ReturnType = Ids extends number ? IndividualClanInfo : IndividualClanInfo[],
|
||||
>(region: Region, ids: Ids) {
|
||||
const object = await fetchBlitz<ClanInfo>(region, "clans/info", {
|
||||
clan_id: normalizeIds(ids),
|
||||
});
|
||||
|
||||
if (typeof ids === "number") {
|
||||
return object[ids as number] as ReturnType;
|
||||
} else {
|
||||
return ids.map((id) => object[id]) as ReturnType;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { TanksStats } from "../types";
|
||||
import { type FetchBlitzParams, fetchBlitz } from "./fetchBlitz";
|
||||
import type { Region } from "./regions";
|
||||
|
||||
export async function getTankStats(
|
||||
region: Region,
|
||||
id: number,
|
||||
params?: FetchBlitzParams
|
||||
) {
|
||||
const tankStats = await fetchBlitz<TanksStats>(region, "tanks/stats", {
|
||||
account_id: id,
|
||||
...params,
|
||||
});
|
||||
|
||||
return tankStats[id];
|
||||
}
|
||||
@@ -3,21 +3,13 @@ export * from "./clans";
|
||||
export * from "./classes";
|
||||
export * from "./constants";
|
||||
export * from "./equipmentPrice";
|
||||
export * from "./fetchBlitz";
|
||||
export * from "./fetchGlossary";
|
||||
export * from "./generateStats";
|
||||
export * from "./getAccountAchievements";
|
||||
export * from "./getAccountInfo";
|
||||
export * from "./getClanAccountInfo";
|
||||
export * from "./getClanInfo";
|
||||
export * from "./getLeagueFromScore";
|
||||
export * from "./getRatingInfo";
|
||||
export * from "./getRatingLeague";
|
||||
export * from "./getRatingNeighbors";
|
||||
export * from "./getTankStats";
|
||||
export * from "./idToRegion";
|
||||
export * from "./isOnGoingRatingSeason";
|
||||
export * from "./isValidBlitzId";
|
||||
export * from "./nations";
|
||||
export * from "./normalizeExtra";
|
||||
export * from "./normalizeIds";
|
||||
@@ -27,7 +19,5 @@ export * from "./readDVPL";
|
||||
export * from "./regions";
|
||||
export * from "./regionSubdomainToRegion";
|
||||
export * from "./regionToRegionSubdomain";
|
||||
export * from "./searchClansAcrossRegions";
|
||||
export * from "./searchCurrentRatingPlayers";
|
||||
export * from "./searchPlayersAcrossRegions";
|
||||
export * from "./toUniqueId";
|
||||
@@ -1,32 +0,0 @@
|
||||
import { assertSecret } from "../blitzkit";
|
||||
import { idToRegion } from "./idToRegion";
|
||||
import { Region } from "./regions";
|
||||
|
||||
export async function isValidBlitzId(id: number, token?: string) {
|
||||
let region: Region;
|
||||
|
||||
try {
|
||||
region = idToRegion(id);
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const json = await fetch(
|
||||
`https://api.wotblitz.${region}/wotb/account/info/?account_id=${id}&application_id=${assertSecret(
|
||||
import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID
|
||||
)}${
|
||||
token === undefined ? "" : `&access_token=${token}`
|
||||
}&fields=account_id%2C-account_id`
|
||||
).then(
|
||||
(response) =>
|
||||
response.json() as Promise<
|
||||
| {
|
||||
status: "ok";
|
||||
data: Record<number, {} | null>;
|
||||
}
|
||||
| { status: "error" }
|
||||
>
|
||||
);
|
||||
|
||||
return json.status === "ok" && json.data[id] !== null;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import type { ClanList } from "./clans";
|
||||
import { fetchBlitz } from "./fetchBlitz";
|
||||
import type { Region } from "./regions";
|
||||
|
||||
export async function searchClansAcrossRegions(search: string, limit = 25) {
|
||||
const trimmed = search.trim();
|
||||
if (trimmed.length < 3 && trimmed.length > 100) return [];
|
||||
const normalizedLimit = Math.floor(limit / 3);
|
||||
|
||||
// TODO: remove splice once wargaming fixes the functionality of the limit felid
|
||||
|
||||
return (
|
||||
await Promise.all([
|
||||
fetchBlitz<ClanList>("com", "clans/list", {
|
||||
search,
|
||||
limit: normalizedLimit,
|
||||
}).then((value) =>
|
||||
value
|
||||
.map((account) => ({
|
||||
...account,
|
||||
region: "com" as Region,
|
||||
}))
|
||||
.splice(0, normalizedLimit)
|
||||
),
|
||||
fetchBlitz<ClanList>("eu", "clans/list", {
|
||||
search,
|
||||
limit: normalizedLimit,
|
||||
}).then((value) =>
|
||||
value
|
||||
.map((account) => ({
|
||||
...account,
|
||||
region: "eu" as Region,
|
||||
}))
|
||||
.splice(0, normalizedLimit)
|
||||
),
|
||||
fetchBlitz<ClanList>("asia", "clans/list", {
|
||||
search,
|
||||
limit: normalizedLimit,
|
||||
}).then((value) =>
|
||||
value
|
||||
.map((account) => ({
|
||||
...account,
|
||||
region: "asia" as Region,
|
||||
}))
|
||||
.splice(0, normalizedLimit)
|
||||
),
|
||||
])
|
||||
)
|
||||
.filter(Boolean)
|
||||
.flat();
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export const usernamePattern = /^[a-zA-Z0-9_]{3,24}$/;
|
||||
export const usernamePatternWithoutPosition = /[a-zA-Z0-9_]{3,24}/;
|
||||
@@ -1,64 +0,0 @@
|
||||
import { fetchBlitz } from "../fetchBlitz";
|
||||
import type { Region } from "../regions";
|
||||
import { usernamePattern } from "./constants";
|
||||
|
||||
export interface AccountListItem {
|
||||
nickname: string;
|
||||
account_id: number;
|
||||
}
|
||||
export type AccountList = AccountListItem[];
|
||||
export type AccountListWithServer = (AccountListItem & {
|
||||
region: Region;
|
||||
})[];
|
||||
|
||||
export async function searchPlayersAcrossRegions(search: string, limit = 25) {
|
||||
const trimmed = search.trim();
|
||||
if (trimmed.length < 3 && trimmed.length > 100) return [];
|
||||
const normalizedLimit = Math.floor(limit / 3);
|
||||
|
||||
if (usernamePattern.test(trimmed)) {
|
||||
return (
|
||||
await Promise.all([
|
||||
fetchBlitz<AccountList>("com", "account/list", {
|
||||
search,
|
||||
limit: normalizedLimit,
|
||||
}).then(
|
||||
(value) =>
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
region: "com" as Region,
|
||||
}))
|
||||
),
|
||||
fetchBlitz<AccountList>("eu", "account/list", {
|
||||
search,
|
||||
limit: normalizedLimit,
|
||||
}).then(
|
||||
(value) =>
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
region: "eu" as Region,
|
||||
}))
|
||||
),
|
||||
fetchBlitz<AccountList>("asia", "account/list", {
|
||||
search,
|
||||
limit: normalizedLimit,
|
||||
}).then(
|
||||
(value) =>
|
||||
value &&
|
||||
value.map((account) => ({
|
||||
...account,
|
||||
region: "asia" as Region,
|
||||
}))
|
||||
),
|
||||
])
|
||||
)
|
||||
.filter(Boolean)
|
||||
.flat() as AccountListWithServer;
|
||||
} else {
|
||||
return [] as AccountListWithServer;
|
||||
}
|
||||
}
|
||||
|
||||
export * from "./constants";
|
||||
@@ -1,5 +0,0 @@
|
||||
import { assertSecret } from "./assertSecret";
|
||||
|
||||
export function asset(path: string) {
|
||||
return `${assertSecret(import.meta.env.PUBLIC_ASSET_BASE)}/${path}`;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { emptyAllStats } from '../../blitz/constants';
|
||||
import { Samples } from '../../protos';
|
||||
import type { BlitzkitStats } from '../../statistics';
|
||||
|
||||
export const emptyAverageDefinitionsAllStats: BlitzkitStats = {
|
||||
...emptyAllStats,
|
||||
battle_life_time: 0,
|
||||
};
|
||||
|
||||
export const averageDefinitionsAllStatsKeys = Object.keys(
|
||||
emptyAverageDefinitionsAllStats,
|
||||
) as (keyof BlitzkitStats)[];
|
||||
|
||||
export const emptySamples: Samples = {
|
||||
d_1: 0,
|
||||
d_7: 0,
|
||||
d_30: 0,
|
||||
d_60: 0,
|
||||
d_90: 0,
|
||||
d_120: 0,
|
||||
total: 0,
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
import { fetchPB } from '../../protobuf';
|
||||
import { AverageDefinitions } from '../../protos';
|
||||
import { asset } from '../asset';
|
||||
|
||||
export interface AverageDefinitionsManifest {
|
||||
version: 1;
|
||||
/**
|
||||
* epoch in days
|
||||
*/
|
||||
latest: number;
|
||||
}
|
||||
|
||||
export async function fetchAverageDefinitions() {
|
||||
const manifestResponse = await fetch(asset('averages/manifest.json'));
|
||||
const manifestJson =
|
||||
(await manifestResponse.json()) as AverageDefinitionsManifest;
|
||||
return await fetchPB(
|
||||
asset(`averages/${manifestJson.latest}.pb`),
|
||||
AverageDefinitions,
|
||||
);
|
||||
}
|
||||
|
||||
export * from './constants';
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { CamouflageDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchCamouflageDefinitions() {
|
||||
return fetchPB(asset('definitions/camouflages.pb'), CamouflageDefinitions);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { ConsumableDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchConsumableDefinitions() {
|
||||
return fetchPB(asset('definitions/consumables.pb'), ConsumableDefinitions);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { asset } from './asset';
|
||||
|
||||
export interface DiscoveredIdsDefinitions {
|
||||
time: number;
|
||||
chunks: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export async function fetchDiscoveredIdsDefinitions() {
|
||||
const response = await fetch(asset('ids/manifest.json'));
|
||||
return response.json() as Promise<DiscoveredIdsDefinitions>;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { EquipmentDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchEquipmentDefinitions() {
|
||||
return fetchPB(asset('definitions/equipment.pb'), EquipmentDefinitions);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { Gallery } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchGallery() {
|
||||
return fetchPB(asset('definitions/gallery.pb'), Gallery);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { GameDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchGameDefinitions() {
|
||||
return fetchPB(asset('definitions/game.pb'), GameDefinitions);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { getRatingInfo } from "../blitz/getRatingInfo";
|
||||
import { assertSecret } from "./assertSecret";
|
||||
|
||||
interface GitHubTrees {
|
||||
tree: { path: string; url: string }[];
|
||||
}
|
||||
|
||||
let cachedLatestArchivedSeasonNumber: number | null = null;
|
||||
|
||||
export async function getArchivedLatestSeasonNumber() {
|
||||
if (cachedLatestArchivedSeasonNumber !== null) {
|
||||
return cachedLatestArchivedSeasonNumber;
|
||||
}
|
||||
|
||||
const ratingInfo = await getRatingInfo("com");
|
||||
|
||||
if (ratingInfo.detail) {
|
||||
const regionsURL = (
|
||||
(await fetch(
|
||||
`https://api.github.com/repos/${assertSecret(
|
||||
import.meta.env.PUBLIC_ASSET_REPO
|
||||
)}/git/trees/main`
|
||||
).then((response) => response.json())) as GitHubTrees
|
||||
).tree.find(({ path }) => path === "regions")!.url;
|
||||
const comURL = (
|
||||
(await fetch(regionsURL).then((response) =>
|
||||
response.json()
|
||||
)) as GitHubTrees
|
||||
).tree.find(({ path }) => path === "com")!.url;
|
||||
const ratingURL = (
|
||||
(await fetch(comURL).then((response) => response.json())) as {
|
||||
tree: [{ url: string }];
|
||||
}
|
||||
).tree[0].url;
|
||||
const latestSeason = Math.max(
|
||||
...(
|
||||
(await fetch(ratingURL).then((response) => response.json())) as {
|
||||
tree: { path: string }[];
|
||||
}
|
||||
).tree.map(({ path }) => Number(path))
|
||||
);
|
||||
|
||||
cachedLatestArchivedSeasonNumber = latestSeason;
|
||||
} else {
|
||||
cachedLatestArchivedSeasonNumber = ratingInfo.current_season - 1;
|
||||
}
|
||||
|
||||
return cachedLatestArchivedSeasonNumber;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import type { Region } from "../blitz/regions";
|
||||
import { RatingLeaderboard } from "../protos";
|
||||
import { asset } from "./asset";
|
||||
|
||||
const cache: Record<Region, Record<number, RatingLeaderboard>> = {
|
||||
asia: {},
|
||||
eu: {},
|
||||
com: {},
|
||||
};
|
||||
|
||||
export async function getArchivedRatingLeaderboard(
|
||||
region: Region,
|
||||
season: number
|
||||
) {
|
||||
if (!cache[region][season]) {
|
||||
const info = await fetch(asset(`regions/${region}/rating/${season}.pb`))
|
||||
.then((response) => response.arrayBuffer())
|
||||
.then((buffer) => RatingLeaderboard.decode(new Uint8Array(buffer)));
|
||||
cache[region][season] = info;
|
||||
}
|
||||
|
||||
return cache[region][season];
|
||||
}
|
||||
@@ -1,50 +1,22 @@
|
||||
export * from "./assertSecret";
|
||||
export * from "./asset";
|
||||
export * from "./availableProvisions";
|
||||
export * from "./averageDefinitions";
|
||||
// export * from './camouflageDefinitions';
|
||||
// export * from './checkConsumableProvisionInclusivity';
|
||||
export * from "./coefficient";
|
||||
export * from "./consumableDefinitions";
|
||||
// export * from './context';
|
||||
export * from "./createDefaultSkills";
|
||||
export * from "./degressiveStat";
|
||||
export * from "./discoveredIdDefinitions";
|
||||
export * from "./emblemURL";
|
||||
export * from "./equipmentDefinitions";
|
||||
export * from "./eventManager";
|
||||
export * from "./gameDefinitions";
|
||||
export * from "./getArchivedLatestSeasonNumber";
|
||||
// export * from './getArchivedRatingInfo';
|
||||
export * from "./getArchivedRatingLeaderboard";
|
||||
// export * from './getArchivedRatingMidnightLeaderboard';
|
||||
export * from "./getTimeDaysAgo";
|
||||
export * from "./isExplosive";
|
||||
export * from "./mapDefinitions";
|
||||
export * from "./modelDefinitions";
|
||||
export * from "./normalizeBoundingBox";
|
||||
// export * from './parseBkni';
|
||||
// export * from './patientFetch';
|
||||
export * from "./patientFetchJSON";
|
||||
export * from "./progressiveStat";
|
||||
export * from "./provisionDefinitions";
|
||||
export * from "./resolveDpm";
|
||||
export * from "./resolvePenetrationCoefficient";
|
||||
export * from "./reviews";
|
||||
export * from "./skillDefinitions";
|
||||
export * from "./sum";
|
||||
export * from "./tankDefinitions";
|
||||
export * from "./tankIcon";
|
||||
export * from "./tankNames";
|
||||
export * from "./unionBoundingBox";
|
||||
export * from "./uniqueGuns";
|
||||
export * from "./unwrapBlitzkitResponse";
|
||||
export * from "./votes";
|
||||
// export * from './withCORSProxy';
|
||||
export * from "./createDefaultProvisions";
|
||||
export * from "./gallery";
|
||||
export * from "./metaSortTank";
|
||||
export * from "./popularTanks";
|
||||
export * from "./romanize";
|
||||
export * from "./sluggify.ts";
|
||||
export * from "./youtubers";
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { MapDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchMapDefinitions() {
|
||||
return fetchPB(asset('definitions/maps.pb'), MapDefinitions);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { ModelDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchModelDefinitions() {
|
||||
return fetchPB(asset('definitions/models.pb'), ModelDefinitions);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { PopularTanks } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchPopularTanks() {
|
||||
return fetchPB(asset('definitions/popular-tanks.pb'), PopularTanks);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { ProvisionDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchProvisionDefinitions() {
|
||||
return fetchPB(asset('definitions/provisions.pb'), ProvisionDefinitions);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { Reviews } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchReviews() {
|
||||
return fetchPB(asset('definitions/reviews.pb'), Reviews);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { fetchPB } from '../protobuf';
|
||||
import { SkillDefinitions } from '../protos';
|
||||
import { asset } from './asset';
|
||||
|
||||
export function fetchSkillDefinitions() {
|
||||
return fetchPB(asset('definitions/skills.pb'), SkillDefinitions);
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import { times } from "lodash-es";
|
||||
import { CrewType, ShellType, TankClass, TankType } from "../../protos";
|
||||
|
||||
export const SHELL_NAMES: Record<ShellType, string> = {
|
||||
[ShellType.SHELL_TYPE_AP]: "AP",
|
||||
[ShellType.SHELL_TYPE_APCR]: "APCR",
|
||||
[ShellType.SHELL_TYPE_HEAT]: "HEAT",
|
||||
[ShellType.SHELL_TYPE_HE]: "HE",
|
||||
};
|
||||
export const CREW_MEMBER_NAMES = {
|
||||
[CrewType.CREW_TYPE_COMMANDER]: "commander",
|
||||
[CrewType.CREW_TYPE_DRIVER]: "driver",
|
||||
[CrewType.CREW_TYPE_GUNNER]: "gunner",
|
||||
[CrewType.CREW_TYPE_LOADER]: "loader",
|
||||
[CrewType.CREW_TYPE_RADIOMAN]: "radioman",
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* @deprecated use svg
|
||||
*/
|
||||
export const TANK_ICONS: Record<TankClass, string> = {
|
||||
[TankClass.TANK_CLASS_TANK_DESTROYER]: "https://i.imgur.com/BIHSEH0.png",
|
||||
[TankClass.TANK_CLASS_LIGHT]: "https://i.imgur.com/CSNha5V.png",
|
||||
[TankClass.TANK_CLASS_MEDIUM]: "https://i.imgur.com/wvf3ltm.png",
|
||||
[TankClass.TANK_CLASS_HEAVY]: "https://i.imgur.com/ECeqlZa.png",
|
||||
};
|
||||
/**
|
||||
* @deprecated use svg
|
||||
*/
|
||||
export const TANK_ICONS_PREMIUM: Record<TankClass, string> = {
|
||||
[TankClass.TANK_CLASS_TANK_DESTROYER]: "https://i.imgur.com/TCu3EdR.png",
|
||||
[TankClass.TANK_CLASS_LIGHT]: "https://i.imgur.com/zdkpTRb.png",
|
||||
[TankClass.TANK_CLASS_MEDIUM]: "https://i.imgur.com/3z7eHX6.png",
|
||||
[TankClass.TANK_CLASS_HEAVY]: "https://i.imgur.com/P3vbmyA.png",
|
||||
};
|
||||
/**
|
||||
* @deprecated use svg
|
||||
*/
|
||||
export const TANK_ICONS_COLLECTOR: Record<TankClass, string> = {
|
||||
[TankClass.TANK_CLASS_TANK_DESTROYER]: "https://i.imgur.com/WTjeirB.png",
|
||||
[TankClass.TANK_CLASS_LIGHT]: "https://i.imgur.com/EwhtKkU.png",
|
||||
[TankClass.TANK_CLASS_MEDIUM]: "https://i.imgur.com/u8YDMBh.png",
|
||||
[TankClass.TANK_CLASS_HEAVY]: "https://i.imgur.com/8xRf3nc.png",
|
||||
};
|
||||
export const TIERS = times(10, (index) => index + 1);
|
||||
export const TIER_ROMAN_NUMERALS: Record<number, string> = {
|
||||
1: "I",
|
||||
2: "II",
|
||||
3: "III",
|
||||
4: "IV",
|
||||
5: "V",
|
||||
6: "VI",
|
||||
7: "VII",
|
||||
8: "VIII",
|
||||
9: "IX",
|
||||
10: "X",
|
||||
};
|
||||
|
||||
export const flags: Record<string, string> = {
|
||||
ussr: "<:ussr:1218421042033197197>",
|
||||
germany: "🇩🇪",
|
||||
usa: "🇺🇸",
|
||||
china: "🇨🇳",
|
||||
uk: "🇬🇧",
|
||||
france: "🇫🇷",
|
||||
japan: "🇯🇵",
|
||||
european: "🇪🇺",
|
||||
other: "<:other:1218421572243558482>",
|
||||
};
|
||||
export const TREE_TYPE_ICONS: Record<TankType, Record<TankClass, string>> = {
|
||||
[TankType.TANK_TYPE_RESEARCHABLE]: TANK_ICONS,
|
||||
[TankType.TANK_TYPE_PREMIUM]: TANK_ICONS_PREMIUM,
|
||||
[TankType.TANK_TYPE_COLLECTOR]: TANK_ICONS_COLLECTOR,
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
import { fetchPB } from '../../protobuf';
|
||||
import { TankDefinitions } from '../../protos';
|
||||
import { asset } from '../asset';
|
||||
|
||||
export function fetchTankDefinitions() {
|
||||
return fetchPB(asset('definitions/tanks.pb'), TankDefinitions);
|
||||
}
|
||||
|
||||
export * from './constants';
|
||||
@@ -1,7 +0,0 @@
|
||||
import { asset } from "./asset";
|
||||
|
||||
export const BLITZKIT_TANK_ICON_SIZE = { width: 40 * 16, height: 30 * 16 };
|
||||
|
||||
export function tankIcon(id: number, size: "big" | "small" = "big") {
|
||||
return asset(`icons/tanks/${size}/${id}.webp`);
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import locales from "@blitzkit/i18n/locales.json";
|
||||
import { deburr } from "lodash-es";
|
||||
import { I18nString } from "../protos";
|
||||
import { fetchCamouflageDefinitions } from "./camouflageDefinitions";
|
||||
import { fetchTankDefinitions } from "./tankDefinitions";
|
||||
|
||||
export async function fetchTankNames() {
|
||||
const [tankDefinitions, camouflageDefinitions] = await Promise.all([
|
||||
fetchTankDefinitions(),
|
||||
fetchCamouflageDefinitions(),
|
||||
]);
|
||||
const tankDefinitionsArray = Object.values(tankDefinitions.tanks);
|
||||
|
||||
return await Promise.all(
|
||||
tankDefinitionsArray.map(async (tank) => {
|
||||
const searchableNameDeburr: I18nString = { locales: {} };
|
||||
|
||||
Object.entries(tank.name!).forEach(([key, value]) => {
|
||||
searchableNameDeburr.locales[key] = deburr(value);
|
||||
});
|
||||
|
||||
return {
|
||||
id: tank.id,
|
||||
name: tank.name,
|
||||
searchableName: tank.name,
|
||||
searchableNameDeburr,
|
||||
camouflages: tank.camouflages
|
||||
?.map((id) =>
|
||||
locales.supported.map(
|
||||
({ locale }) =>
|
||||
camouflageDefinitions.camouflages[id]?.name!.locales[locale],
|
||||
),
|
||||
)
|
||||
.flat()
|
||||
.filter(Boolean)
|
||||
.map(deburr)
|
||||
.join(" "),
|
||||
treeType: tank.type,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export const SEARCH_KEYS = [
|
||||
...locales.supported
|
||||
.map(({ locale }) => [
|
||||
`searchableName.locales.${locale}`,
|
||||
`searchableNameDeburr.locales.${locale}`,
|
||||
])
|
||||
.flat(),
|
||||
"camouflages",
|
||||
];
|
||||
@@ -1,11 +1,11 @@
|
||||
import { assertSecret } from '../blitzkit/assertSecret';
|
||||
import { secret } from "../secrets";
|
||||
|
||||
export function patreonLoginUrl() {
|
||||
const params = new URLSearchParams({
|
||||
response_type: 'code',
|
||||
client_id: assertSecret(import.meta.env.PUBLIC_PATREON_CLIENT_ID),
|
||||
redirect_uri: assertSecret(import.meta.env.PUBLIC_PATREON_REDIRECT_URI),
|
||||
scope: 'identity',
|
||||
response_type: "code",
|
||||
client_id: secret("PUBLIC_PATREON_CLIENT_ID"),
|
||||
redirect_uri: secret("PUBLIC_PATREON_REDIRECT_URI"),
|
||||
scope: "identity",
|
||||
});
|
||||
|
||||
return `https://www.patreon.com/oauth2/authorize?${params}`;
|
||||
|
||||
@@ -6,7 +6,7 @@ export enum SecretType {
|
||||
Number,
|
||||
}
|
||||
|
||||
export type PassableSecretName = WellKnownSecret | (string & {});
|
||||
export type PassableSecretName = WellKnownSecret;
|
||||
|
||||
export function secret(
|
||||
name: PassableSecretName,
|
||||
@@ -18,10 +18,7 @@ export function secret(
|
||||
type: SecretType.Number,
|
||||
): number;
|
||||
|
||||
export function secret(
|
||||
name: WellKnownSecret | (string & {}),
|
||||
type = SecretType.String,
|
||||
) {
|
||||
export function secret(name: PassableSecretName, type = SecretType.String) {
|
||||
if (!hasSecret(name)) {
|
||||
throw new Error(`Secret "${name}" not defined`);
|
||||
}
|
||||
@@ -30,7 +27,7 @@ export function secret(
|
||||
|
||||
switch (type) {
|
||||
case SecretType.String:
|
||||
return value;
|
||||
return String(value);
|
||||
|
||||
case SecretType.Number:
|
||||
return Number(value);
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
export type WellKnownSecret =
|
||||
// development set-up
|
||||
| "TEMP"
|
||||
// website
|
||||
| "BUILD_CHUNK"
|
||||
| "TEXTURE_CHUNKS"
|
||||
| "TEMP"
|
||||
// wotb
|
||||
| "WOTB_SERVER"
|
||||
| "WOTB_VERSION"
|
||||
| "PUBLIC_WOTB_CLIENT"
|
||||
| "WOTB_USMAP"
|
||||
// google
|
||||
| "GOOGLE_APPLICATION_CREDENTIALS"
|
||||
| "PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID";
|
||||
| "PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID"
|
||||
// patreon
|
||||
| "PUBLIC_PATREON_CLIENT_ID"
|
||||
| "PUBLIC_PATREON_REDIRECT_URI";
|
||||
@@ -1,22 +0,0 @@
|
||||
import { fetchTankDefinitions } from '../blitzkit';
|
||||
import type { BlitzStats } from './compositeStats/constants';
|
||||
|
||||
export async function getTierWeights(
|
||||
stats: Record<number, BlitzStats>,
|
||||
order: number[] = Object.keys(stats).map(parseInt),
|
||||
) {
|
||||
const tankDefinitions = await fetchTankDefinitions();
|
||||
const tierWeights: TierWeightsRecord = {};
|
||||
|
||||
order.forEach((id) => {
|
||||
const entry = tankDefinitions.tanks[id];
|
||||
|
||||
if (!entry) return;
|
||||
if (!tierWeights[entry.tier]) tierWeights[entry.tier] = 0;
|
||||
|
||||
tierWeights[entry.tier]! += stats[id].battles;
|
||||
});
|
||||
|
||||
return tierWeights;
|
||||
}
|
||||
export type TierWeightsRecord = Partial<Record<number, number>>;
|
||||
@@ -1,9 +1,8 @@
|
||||
export * from './calculateWN8';
|
||||
export * from './compositeStats';
|
||||
export * from './deltaBkrlBlitzStats';
|
||||
export * from './deltaTankStats';
|
||||
export * from './getBkniPercentile';
|
||||
export * from './getTierWeights';
|
||||
export * from './getWN8Percentile';
|
||||
export * from './percentiles';
|
||||
export * from './sumAllStats';
|
||||
export * from "./calculateWN8";
|
||||
export * from "./compositeStats";
|
||||
export * from "./deltaBkrlBlitzStats";
|
||||
export * from "./deltaTankStats";
|
||||
export * from "./getBkniPercentile";
|
||||
export * from "./getWN8Percentile";
|
||||
export * from "./percentiles";
|
||||
export * from "./sumAllStats";
|
||||
Reference in new issue
Block a user