mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-29 21:49:50 +01:00
feat: all stats row
This commit is contained in:
1 parent
7a6de17c1c
commit
513bea6f09
6 files changed
+142
-66
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "blitzkrieg",
|
"name": "blitzkrieg",
|
||||||
"version": "1.3.3",
|
"version": "1.4.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
+11
-15
@@ -24,9 +24,8 @@ import { AccountInfo, AllStats } from '../types/accountInfo.js';
|
|||||||
import { PlayerClanData } from '../types/playerClanData.js';
|
import { PlayerClanData } from '../types/playerClanData.js';
|
||||||
import { BlitzStartsComputedPeriodicStatistics } from '../types/statistics.js';
|
import { BlitzStartsComputedPeriodicStatistics } from '../types/statistics.js';
|
||||||
|
|
||||||
type Period = 'today' | '30' | '90' | 'career';
|
export type StatPeriod = 'today' | '30' | '90' | 'career';
|
||||||
|
export const statPeriodNames: Record<StatPeriod, string> = {
|
||||||
const periodNames: Record<Period, string> = {
|
|
||||||
today: "Today's statistics",
|
today: "Today's statistics",
|
||||||
30: '30-day statistics',
|
30: '30-day statistics',
|
||||||
90: '90-day statistics',
|
90: '90-day statistics',
|
||||||
@@ -35,7 +34,7 @@ const periodNames: Record<Period, string> = {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
inProduction: true,
|
inProduction: true,
|
||||||
inDevelopment: true,
|
inDevelopment: false,
|
||||||
inPublic: true,
|
inPublic: true,
|
||||||
|
|
||||||
command: new SlashCommandBuilder()
|
command: new SlashCommandBuilder()
|
||||||
@@ -46,17 +45,17 @@ export default {
|
|||||||
.setName('period')
|
.setName('period')
|
||||||
.setDescription('The last number of days of stats')
|
.setDescription('The last number of days of stats')
|
||||||
.setChoices(
|
.setChoices(
|
||||||
{ name: 'Today', value: 'today' satisfies Period },
|
{ name: 'Today', value: 'today' satisfies StatPeriod },
|
||||||
{ name: '30 Days', value: '30' satisfies Period },
|
{ name: '30 Days', value: '30' satisfies StatPeriod },
|
||||||
{ name: '90 Days', value: '90' satisfies Period },
|
{ name: '90 Days', value: '90' satisfies StatPeriod },
|
||||||
{ name: 'Career', value: 'career' satisfies Period },
|
{ name: 'Career', value: 'career' satisfies StatPeriod },
|
||||||
)
|
)
|
||||||
.setRequired(true),
|
.setRequired(true),
|
||||||
)
|
)
|
||||||
.addStringOption(addUsernameOption),
|
.addStringOption(addUsernameOption),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const period = interaction.options.getString('period') as Period;
|
const period = interaction.options.getString('period') as StatPeriod;
|
||||||
const username = interaction.options.getString('username')!;
|
const username = interaction.options.getString('username')!;
|
||||||
const blitzAccount = await getBlitzAccount(interaction, username);
|
const blitzAccount = await getBlitzAccount(interaction, username);
|
||||||
const { id, server } = blitzAccount;
|
const { id, server } = blitzAccount;
|
||||||
@@ -74,9 +73,6 @@ export default {
|
|||||||
const a2 = accountInfo[id].statistics;
|
const a2 = accountInfo[id].statistics;
|
||||||
const battles = a2.all.battles - a1.all.battles;
|
const battles = a2.all.battles - a1.all.battles;
|
||||||
|
|
||||||
function max(value: (allStats: AllStats) => number) {
|
|
||||||
return Math.max(value(a2.all), value(a1.all));
|
|
||||||
}
|
|
||||||
function diff(value: (allStats: AllStats) => number) {
|
function diff(value: (allStats: AllStats) => number) {
|
||||||
return value(a2.all) - value(a1.all);
|
return value(a2.all) - value(a1.all);
|
||||||
}
|
}
|
||||||
@@ -92,8 +88,8 @@ export default {
|
|||||||
frags8p: diff((a) => a.frags8p),
|
frags8p: diff((a) => a.frags8p),
|
||||||
hits: diff((a) => a.hits),
|
hits: diff((a) => a.hits),
|
||||||
losses: diff((a) => a.losses),
|
losses: diff((a) => a.losses),
|
||||||
max_frags: max((a) => a.max_frags),
|
max_frags: a2.all.max_frags,
|
||||||
max_xp: max((a) => a.max_xp),
|
max_xp: a2.all.max_xp,
|
||||||
shots: diff((a) => a.shots),
|
shots: diff((a) => a.shots),
|
||||||
spotted: diff((a) => a.spotted),
|
spotted: diff((a) => a.spotted),
|
||||||
survived_battles: diff((a) => a.survived_battles),
|
survived_battles: diff((a) => a.survived_battles),
|
||||||
@@ -125,7 +121,7 @@ export default {
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
description={`${
|
description={`${
|
||||||
periodNames[period]
|
statPeriodNames[period]
|
||||||
} • ${new Date().toDateString()} • ${BLITZ_SERVERS[server]}`}
|
} • ${new Date().toDateString()} • ${BLITZ_SERVERS[server]}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
+44
-26
@@ -14,6 +14,7 @@ import { supportBlitzStars } from '../core/actions/supportBlitzStars.js';
|
|||||||
import usernameAutocomplete from '../core/autocomplete/username.js';
|
import usernameAutocomplete from '../core/autocomplete/username.js';
|
||||||
import getBlitzAccount from '../core/blitz/getBlitzAccount.js';
|
import getBlitzAccount from '../core/blitz/getBlitzAccount.js';
|
||||||
import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
|
import getWargamingResponse from '../core/blitz/getWargamingResponse.js';
|
||||||
|
import sumStats from '../core/blitz/sumStats.js';
|
||||||
import getTankStatsOverTime from '../core/blitzstars/getTankStatsOverTime.js';
|
import getTankStatsOverTime from '../core/blitzstars/getTankStatsOverTime.js';
|
||||||
import last5AM from '../core/blitzstars/last5AM.js';
|
import last5AM from '../core/blitzstars/last5AM.js';
|
||||||
import { tankopedia } from '../core/blitzstars/tankopedia.js';
|
import { tankopedia } from '../core/blitzstars/tankopedia.js';
|
||||||
@@ -56,38 +57,55 @@ export default {
|
|||||||
const careerTankStatsRaw = await getWargamingResponse<TanksStats>(
|
const careerTankStatsRaw = await getWargamingResponse<TanksStats>(
|
||||||
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${args['wargaming-application-id']}&account_id=${id}`,
|
`https://api.wotblitz.${server}/wotb/tanks/stats/?application_id=${args['wargaming-application-id']}&account_id=${id}`,
|
||||||
);
|
);
|
||||||
const careerStats: Record<number, AllStats> = {};
|
const careerStats: Record<number, AllStats> = {
|
||||||
|
0: accountInfo[id].statistics.all,
|
||||||
|
};
|
||||||
|
const allStatsToAccumulate: AllStats[] = [];
|
||||||
|
|
||||||
|
Object.entries(tankStatsOverTime).forEach(([, tankStats]) => {
|
||||||
|
allStatsToAccumulate.push(tankStats);
|
||||||
|
});
|
||||||
Object.entries(careerTankStatsRaw[id]).forEach(([, tankStats]) => {
|
Object.entries(careerTankStatsRaw[id]).forEach(([, tankStats]) => {
|
||||||
careerStats[tankStats.tank_id] = tankStats.all;
|
careerStats[tankStats.tank_id] = tankStats.all;
|
||||||
});
|
});
|
||||||
|
|
||||||
const rows = Object.entries(tankStatsOverTime).map(
|
const accumulatedStats = sumStats(allStatsToAccumulate);
|
||||||
([tankId, tankStats]) => {
|
|
||||||
const career = careerStats[tankId as unknown as number];
|
|
||||||
|
|
||||||
return (
|
const rows = Object.entries({
|
||||||
<Breakdown.Row
|
0: accumulatedStats,
|
||||||
key={tankId}
|
...tankStatsOverTime,
|
||||||
name={resolveTankName({
|
}).map(([tankId, tankStats]) => {
|
||||||
tank_id: tankId as unknown as number,
|
const career = careerStats[tankId as unknown as number];
|
||||||
name: tankopedia[tankId as unknown as number].name,
|
|
||||||
})}
|
return (
|
||||||
winrate={tankStats.wins / tankStats.battles}
|
<Breakdown.Row
|
||||||
careerWinrate={career.wins / career.battles}
|
key={tankId}
|
||||||
WN8={-Infinity}
|
name={
|
||||||
careerWN8={-Infinity}
|
tankId === '0'
|
||||||
damage={tankStats.damage_dealt / tankStats.battles}
|
? 'Today'
|
||||||
careerDamage={career.damage_dealt / career.battles}
|
: resolveTankName({
|
||||||
survival={tankStats.survived_battles / tankStats.battles}
|
tank_id: tankId as unknown as number,
|
||||||
careerSurvival={career.survived_battles / career.battles}
|
name: tankopedia[tankId as unknown as number].name,
|
||||||
battles={tankStats.battles}
|
})
|
||||||
careerBattles={career.battles}
|
}
|
||||||
icon={tankopedia[tankId as unknown as number].images.normal}
|
winrate={tankStats.wins / tankStats.battles}
|
||||||
/>
|
careerWinrate={career.wins / career.battles}
|
||||||
);
|
WN8={-Infinity}
|
||||||
},
|
careerWN8={-Infinity}
|
||||||
);
|
damage={tankStats.damage_dealt / tankStats.battles}
|
||||||
|
careerDamage={career.damage_dealt / career.battles}
|
||||||
|
survival={tankStats.survived_battles / tankStats.battles}
|
||||||
|
careerSurvival={career.survived_battles / career.battles}
|
||||||
|
battles={tankStats.battles}
|
||||||
|
careerBattles={career.battles}
|
||||||
|
icon={
|
||||||
|
tankId === '0'
|
||||||
|
? undefined
|
||||||
|
: tankopedia[tankId as unknown as number].images.normal
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const image = await render(
|
const image = await render(
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { AllStats } from '../../types/accountInfo.js';
|
||||||
|
|
||||||
|
export default function diffStats(stats1: AllStats, stats2: AllStats) {
|
||||||
|
function diff(value: (allStats: AllStats) => number) {
|
||||||
|
return value(stats2) - value(stats1);
|
||||||
|
}
|
||||||
|
function max(value: (allStats: AllStats) => number) {
|
||||||
|
return Math.max(value(stats1), value(stats2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
battles: diff((a) => a.battles),
|
||||||
|
wins: diff((a) => a.wins),
|
||||||
|
capture_points: diff((a) => a.capture_points),
|
||||||
|
damage_dealt: diff((a) => a.damage_dealt),
|
||||||
|
damage_received: diff((a) => a.damage_received),
|
||||||
|
dropped_capture_points: diff((a) => a.dropped_capture_points),
|
||||||
|
frags: diff((a) => a.frags),
|
||||||
|
frags8p: diff((a) => a.frags8p),
|
||||||
|
hits: diff((a) => a.hits),
|
||||||
|
losses: diff((a) => a.losses),
|
||||||
|
max_frags: max((a) => a.max_frags),
|
||||||
|
max_xp: max((a) => a.max_xp),
|
||||||
|
shots: diff((a) => a.shots),
|
||||||
|
spotted: diff((a) => a.spotted),
|
||||||
|
survived_battles: diff((a) => a.survived_battles),
|
||||||
|
win_and_survived: diff((a) => a.win_and_survived),
|
||||||
|
xp: diff((a) => a.xp),
|
||||||
|
} satisfies AllStats;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { AllStats } from '../../types/accountInfo.js';
|
||||||
|
import { emptyAllStats } from '../blitzstars/getTankStatsOverTime.js';
|
||||||
|
|
||||||
|
export default function sumStats(allStatsCollection: AllStats[]) {
|
||||||
|
return allStatsCollection.reduce((accumulated, current) => {
|
||||||
|
function sum(value: (allStats: AllStats) => number) {
|
||||||
|
return value(accumulated) + value(current);
|
||||||
|
}
|
||||||
|
function max(value: (allStats: AllStats) => number) {
|
||||||
|
return Math.max(value(accumulated), value(current));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
battles: sum((a) => a.battles),
|
||||||
|
wins: sum((a) => a.wins),
|
||||||
|
capture_points: sum((a) => a.capture_points),
|
||||||
|
damage_dealt: sum((a) => a.damage_dealt),
|
||||||
|
damage_received: sum((a) => a.damage_received),
|
||||||
|
dropped_capture_points: sum((a) => a.dropped_capture_points),
|
||||||
|
frags: sum((a) => a.frags),
|
||||||
|
frags8p: sum((a) => a.frags8p),
|
||||||
|
hits: sum((a) => a.hits),
|
||||||
|
losses: sum((a) => a.losses),
|
||||||
|
max_frags: max((a) => a.max_frags),
|
||||||
|
max_xp: max((a) => a.max_xp),
|
||||||
|
shots: sum((a) => a.shots),
|
||||||
|
spotted: sum((a) => a.spotted),
|
||||||
|
survived_battles: sum((a) => a.survived_battles),
|
||||||
|
win_and_survived: sum((a) => a.win_and_survived),
|
||||||
|
xp: sum((a) => a.xp),
|
||||||
|
} satisfies AllStats;
|
||||||
|
}, emptyAllStats);
|
||||||
|
}
|
||||||
@@ -13,31 +13,33 @@ export interface TankHistoryNode {
|
|||||||
tank_id: number;
|
tank_id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const emptyAllStats: AllStats = {
|
||||||
|
battles: 0,
|
||||||
|
capture_points: 0,
|
||||||
|
damage_dealt: 0,
|
||||||
|
damage_received: 0,
|
||||||
|
dropped_capture_points: 0,
|
||||||
|
frags: 0,
|
||||||
|
frags8p: 0,
|
||||||
|
hits: 0,
|
||||||
|
losses: 0,
|
||||||
|
max_frags: 0,
|
||||||
|
max_xp: 0,
|
||||||
|
shots: 0,
|
||||||
|
spotted: 0,
|
||||||
|
survived_battles: 0,
|
||||||
|
xp: 0,
|
||||||
|
win_and_survived: 0,
|
||||||
|
wins: 0,
|
||||||
|
};
|
||||||
|
|
||||||
export const emptyTankHistoryNode: TankHistoryNode = {
|
export const emptyTankHistoryNode: TankHistoryNode = {
|
||||||
account_id: 0,
|
account_id: 0,
|
||||||
battle_life_time: 0,
|
battle_life_time: 0,
|
||||||
last_battle_time: 0,
|
last_battle_time: 0,
|
||||||
mark_of_mastery: 0,
|
mark_of_mastery: 0,
|
||||||
tank_id: 0,
|
tank_id: 0,
|
||||||
all: {
|
all: emptyAllStats,
|
||||||
battles: 0,
|
|
||||||
capture_points: 0,
|
|
||||||
damage_dealt: 0,
|
|
||||||
damage_received: 0,
|
|
||||||
dropped_capture_points: 0,
|
|
||||||
frags: 0,
|
|
||||||
frags8p: 0,
|
|
||||||
hits: 0,
|
|
||||||
losses: 0,
|
|
||||||
max_frags: 0,
|
|
||||||
max_xp: 0,
|
|
||||||
shots: 0,
|
|
||||||
spotted: 0,
|
|
||||||
survived_battles: 0,
|
|
||||||
xp: 0,
|
|
||||||
win_and_survived: 0,
|
|
||||||
wins: 0,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TankHistory = TankHistoryNode[];
|
export type TankHistory = TankHistoryNode[];
|
||||||
@@ -91,9 +93,6 @@ export default async function getTankStatsOverTime(
|
|||||||
function diff(get: (allStats: AllStats) => number) {
|
function diff(get: (allStats: AllStats) => number) {
|
||||||
return get(latest.all) - get(previous.all);
|
return get(latest.all) - get(previous.all);
|
||||||
}
|
}
|
||||||
function max(get: (allStats: AllStats) => number) {
|
|
||||||
return Math.max(get(latest.all), get(previous.all));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if there was a change in battles as games in ratings do update last_battle_time
|
// check if there was a change in battles as games in ratings do update last_battle_time
|
||||||
if (diff((a) => a.battles) > 0) {
|
if (diff((a) => a.battles) > 0) {
|
||||||
@@ -107,8 +106,8 @@ export default async function getTankStatsOverTime(
|
|||||||
frags8p: diff((a) => a.frags8p),
|
frags8p: diff((a) => a.frags8p),
|
||||||
hits: diff((a) => a.hits),
|
hits: diff((a) => a.hits),
|
||||||
losses: diff((a) => a.losses),
|
losses: diff((a) => a.losses),
|
||||||
max_frags: max((a) => a.max_frags),
|
max_frags: latest.all.max_frags,
|
||||||
max_xp: max((a) => a.max_xp),
|
max_xp: latest.all.max_xp,
|
||||||
shots: diff((a) => a.shots),
|
shots: diff((a) => a.shots),
|
||||||
spotted: diff((a) => a.spotted),
|
spotted: diff((a) => a.spotted),
|
||||||
survived_battles: diff((a) => a.survived_battles),
|
survived_battles: diff((a) => a.survived_battles),
|
||||||
|
|||||||
Reference in new issue
Block a user