import { BlitzStats, calculateWN8, getAccountInfo, getClanAccountInfo, getTankStats, getWN8Percentile, TankDefinition, } from "@blitzkit/core"; import { literals } from "@blitzkit/i18n"; import { Locale } from "discord.js"; import { chunk } from "lodash-es"; import * as Breakdown from "../../components/Breakdown"; import { CommandWrapper } from "../../components/CommandWrapper"; import { NoData } from "../../components/NoData"; import { TitleBar } from "../../components/TitleBar"; import { filtersToDescription } from "../../core/blitzkit/filtersToDescription"; import { tankDefinitions } from "../../core/blitzkit/nonBlockingPromises"; import { UserError } from "../../core/blitzkit/userError"; import { filterStats, StatFilters } from "../../core/blitzstars/filterStats"; import { getStatsInPeriod } from "../../core/blitzstars/getStatsInPeriod"; import { blitzStarsTankAverages } from "../../core/blitzstars/tankAverages"; import { ResolvedPeriod } from "../../core/discord/resolvePeriodFromCommand"; import { ResolvedPlayer } from "../../core/discord/resolvePlayerFromCommand"; import { translator } from "../../core/localization/translator"; const ROWS_PER_PAGE = 8; const MAX_PAGES = 9; export async function renderBreakdown( { region, id }: ResolvedPlayer, { start, end, name }: ResolvedPeriod, filters: StatFilters, locale: Locale ) { const { strings, unwrap } = translator(locale); const awaitedTankDefinitions = await tankDefinitions; const awaitedTankAverages = await blitzStarsTankAverages; const statsInPeriod = await getStatsInPeriod(region, id, start, end, locale); const { filteredOrder } = await filterStats(statsInPeriod, filters); const accountInfo = await getAccountInfo(region, id); const clanData = await getClanAccountInfo(region, id, ["clan"]); const tankStats = await getTankStats(region, id); const filterDescriptions = await filtersToDescription(filters, locale); const orderedCurrentStats: BlitzStats[] = []; const orderedCareerStats: BlitzStats[] = []; const orderedCurrentWN8: (number | undefined)[] = []; const orderedCareerWN8: (number | undefined)[] = []; const orderedCareerWN8Full: (number | undefined)[] = []; if (tankStats === null) { throw new UserError(strings.bot.common.errors.no_tank_stats); } filteredOrder.forEach((id) => { const tankAveragesEntry = awaitedTankAverages[id]; const current = statsInPeriod.diff[id]; const career = tankStats.find((tank) => tank.tank_id === id)!.all; const currentWN8 = tankAveragesEntry ? calculateWN8(tankAveragesEntry.all, current) : undefined; const careerWN8 = tankAveragesEntry ? calculateWN8(tankAveragesEntry.all, career) : undefined; orderedCurrentStats.push(current); orderedCareerStats.push(career); orderedCurrentWN8.push(currentWN8); orderedCareerWN8.push(careerWN8); }); tankStats.forEach((tank) => { const tankAveragesEntry = awaitedTankAverages[tank.tank_id]; orderedCareerWN8Full.push( tankAveragesEntry ? calculateWN8(tankAveragesEntry.all, tank.all) : undefined ); }); const currentBattles = orderedCurrentStats.reduce( (accumulator, current) => accumulator + current.battles, 0 ); const careerBattles = tankStats.reduce( (accumulator, current) => accumulator + current.all.battles, 0 ); const currentWinrate = orderedCurrentStats.reduce( (accumulator, current) => accumulator + current.wins, 0 ) / currentBattles; const careerWinrate = tankStats.reduce( (accumulator, current) => accumulator + current.all.wins, 0 ) / careerBattles; const currentWN8 = orderedCurrentWN8.reduce( (accumulator, current, index) => accumulator + (current ?? 0) * orderedCurrentStats[index].battles, 0 ) / orderedCurrentStats.reduce( (accumulator, current, index) => accumulator + (orderedCurrentWN8[index] === undefined ? 0 : current.battles), 0 ); const careerWN8 = orderedCareerWN8Full.reduce( (accumulator, current) => accumulator + (current ?? 0), 0 ) / tankStats.reduce( (accumulator, current, index) => accumulator + (orderedCareerWN8Full[index] === undefined ? 0 : current.all.battles), 0 ); const currentDamage = orderedCurrentStats.reduce( (accumulator, current) => accumulator + current.damage_dealt, 0 ) / currentBattles; const careerDamage = tankStats.reduce( (accumulator, current) => accumulator + current.all.damage_dealt, 0 ) / careerBattles; const children: React.JSX.Element[] = []; if (filteredOrder.length > 0) { children.push( ); filteredOrder.forEach((id, index) => { const tankDefinition = awaitedTankDefinitions.tanks[id] as | TankDefinition | undefined; const current = orderedCurrentStats[index]; const career = orderedCareerStats[index]; const currentWN8 = orderedCurrentWN8[index]; const careerWN8 = orderedCareerWN8[index]; children.push( ); }); } const pages = chunk( children, Math.max(Math.ceil(children.length / MAX_PAGES), ROWS_PER_PAGE) ); if (filteredOrder.length > 0) { return pages .map((page, index) => ( {index === 0 && ( )} {page} )) .reverse(); } else { return [ , ]; } }