import { BlitzStats, calculateWN8, getAccountInfo, getClanAccountInfo, getTankStats, getWN8Percentile, TankDefinition, } from '@blitzkit/core'; 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 { t, translate } = 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(t`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: 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 [ , ]; } }