feat: core chunk 1

This commit is contained in:
TrèsAbhi committed 2023-10-12 13:00:33 -05:00
1 parent 7447ccc487
commit e96538bae0
31 files changed
+463 -466

No files matched your search

-45
View File
@@ -1,45 +0,0 @@
import { AllStats } from '../../types/accountInfo';
/**
* Formula from https://web.archive.org/web/20190105064817/http://wiki.wnefficiency.net/pages/WN8
*/
export default function calculateWN8(expected: AllStats, average: AllStats) {
const avgDmg = average.damage_dealt / average.battles;
const avgSpot = average.spotted / average.battles;
const avgFrag = average.frags / average.battles;
const avgDef = average.dropped_capture_points / average.battles;
const avgWinRate = average.wins / average.battles;
const expDmg = expected.damage_dealt / expected.battles;
const expSpot = expected.spotted / expected.battles;
const expFrag = expected.frags / expected.battles;
const expDef = expected.dropped_capture_points / expected.battles;
const expWinRate = expected.wins / expected.battles;
const rDAMAGE = avgDmg / expDmg;
const rSPOT = avgSpot / expSpot;
const rFRAG = avgFrag / expFrag;
const rDEF = avgDef / expDef;
const rWIN = avgWinRate / expWinRate;
const rWINc = Math.max(0, (rWIN - 0.71) / (1 - 0.71));
const rDAMAGEc = Math.max(0, (rDAMAGE - 0.22) / (1 - 0.22));
const rFRAGc = Math.max(
0,
Math.min(rDAMAGEc + 0.2, (rFRAG - 0.12) / (1 - 0.12)),
);
const rSPOTc = Math.max(
0,
Math.min(rDAMAGEc + 0.1, (rSPOT - 0.38) / (1 - 0.38)),
);
const rDEFc = Math.max(0, Math.min(rDAMAGEc + 0.1, (rDEF - 0.1) / (1 - 0.1)));
const WN8 =
980 * rDAMAGEc +
210 * rDAMAGEc * rFRAGc +
155 * rFRAGc * rSPOTc +
75 * rDEFc * rFRAGc +
145 * Math.min(1.8, rWINc);
return WN8;
}
-66
View File
@@ -1,66 +0,0 @@
import {
IndividualTankStats,
NormalizedTankStats,
emptyIndividualTankStats,
} from '../../types/tanksStats';
export function diffNormalizedTankStats(
a: NormalizedTankStats,
b: NormalizedTankStats,
) {
const bTanks = Object.keys(b);
const changedTanks = bTanks.filter((id) => {
return (
a[id as unknown as number]?.all.battles !==
b[id as unknown as number].all.battles
);
});
const diff = changedTanks.map((id) => {
const aTank = a[id as unknown as number] ?? emptyIndividualTankStats;
const bTank = b[id as unknown as number];
const tankDiff = {
account_id: bTank.account_id,
battle_life_time: bTank.battle_life_time,
frags: (bTank.frags ?? aTank.frags ?? 0) - (aTank.frags ?? 0),
max_frags: Math.max(aTank.max_frags, bTank.max_frags),
in_garage: bTank.in_garage,
max_xp: Math.max(aTank.max_xp, bTank.max_xp),
in_garage_updated: bTank.in_garage_updated,
last_battle_time: bTank.last_battle_time - aTank.last_battle_time,
mark_of_mastery: bTank.mark_of_mastery,
tank_id: bTank.tank_id,
all: {
battles: bTank.all.battles - aTank.all.battles,
wins: bTank.all.wins - aTank.all.wins,
capture_points: bTank.all.capture_points - aTank.all.capture_points,
damage_dealt: bTank.all.damage_dealt - aTank.all.damage_dealt,
damage_received: bTank.all.damage_received - aTank.all.damage_received,
dropped_capture_points:
bTank.all.dropped_capture_points - aTank.all.dropped_capture_points,
frags: bTank.all.frags - aTank.all.frags,
frags8p: bTank.all.frags8p - aTank.all.frags8p,
hits: bTank.all.hits - aTank.all.hits,
losses: bTank.all.losses - aTank.all.losses,
max_frags: Math.max(aTank.max_frags, bTank.max_frags),
max_xp: Math.max(aTank.max_xp, bTank.max_xp),
shots: bTank.all.shots - aTank.all.shots,
spotted: bTank.all.spotted - aTank.all.spotted,
survived_battles:
bTank.all.survived_battles - aTank.all.survived_battles,
win_and_survived:
bTank.all.win_and_survived - aTank.all.win_and_survived,
xp: bTank.all.xp - aTank.all.xp,
},
} satisfies IndividualTankStats;
return tankDiff;
});
const normalized = diff.reduce<NormalizedTankStats>(
(accumulator, diff) => ({ ...accumulator, [diff.tank_id]: diff }),
{},
);
return normalized;
}
-79
View File
@@ -1,79 +0,0 @@
// BIG TODO: reorganize code folder
import { TreeTypeString } from '../../components/Tanks';
import { DiffedTankStats } from '../blitzstars/getDiffedTankStats';
import { tankAverages } from '../blitzstars/tankAverages';
import calculateWN8 from './calculateWN8';
import sumStats from './sumStats';
import { tankopedia } from './tankopedia';
export interface StatFilters {
nation?: string;
tier?: number;
tankType?: string;
treeType?: TreeTypeString;
tank?: number;
}
export async function filterStats(
{ diff, order }: DiffedTankStats,
filters: StatFilters,
) {
// tank, if provided, takes priority over all other filters
if (filters.tank) filters = { tank: filters.tank };
const awaitedTankopedia = await tankopedia;
const awaitedTankAverages = await tankAverages;
const filteredOrder = order.filter((id) => {
const entry = awaitedTankopedia[id];
return (
entry &&
(filters.nation === undefined || entry.nation === filters.nation) &&
(filters.tier === undefined || entry.tier === filters.tier) &&
(filters.tankType === undefined || entry.type === filters.tankType) &&
(filters.treeType === undefined ||
(filters.treeType === 'collector' && entry.is_collectible) ||
(filters.treeType === 'premium' &&
entry.is_premium &&
!entry.is_collectible) ||
(filters.treeType === 'tech-tree' &&
!entry.is_collectible &&
!entry.is_premium)) &&
(filters.tank === undefined || entry.tank_id === filters.tank)
);
});
const stats = sumStats(filteredOrder.map((id) => diff[id]));
const battlesOfTanksWithAverages = filteredOrder.reduce<number>(
(accumulator, id) =>
awaitedTankAverages[id] ? accumulator + diff[id].battles : accumulator,
0,
);
const battlesOfTanksWithTankopediaEntry = filteredOrder.reduce<number>(
(accumulator, id) =>
awaitedTankopedia[id] ? accumulator + diff[id].battles : accumulator,
0,
);
const supplementary = {
WN8:
filteredOrder.reduce<number>(
(accumulator, id) =>
awaitedTankAverages[id]
? accumulator +
calculateWN8(awaitedTankAverages[id].all, diff[id]) *
diff[id].battles
: accumulator,
0,
) / battlesOfTanksWithAverages,
tier:
filteredOrder.reduce<number>(
(accumulator, id) =>
awaitedTankopedia[id]
? accumulator + awaitedTankopedia[id]!.tier * diff[id].battles
: accumulator,
0,
) / battlesOfTanksWithTankopediaEntry,
};
return { stats, supplementary, filteredOrder };
}
-11
View File
@@ -1,11 +0,0 @@
import { Region } from '../../constants/regions';
import { WARGAMING_APPLICATION_ID } from '../../constants/wargamingApplicationID';
import { AccountInfo } from '../../types/accountInfo';
import getWargamingResponse from './getWargamingResponse';
// BIG TODO: generalize all get wargaming calls
export function getAccountInfo(region: Region, id: number) {
return getWargamingResponse<AccountInfo>(
`https://api.wotblitz.${region}/wotb/account/info/?application_id=${WARGAMING_APPLICATION_ID}&account_id=${id}`,
);
}