mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: composite stats
This commit is contained in:
1 parent
f1767bf5d7
commit
d910ed9f5e
5 files changed
+314
-60
No files matched your search
@@ -113,12 +113,12 @@
|
|||||||
|
|
||||||
"cumulative_accuracy": "Accuracy",
|
"cumulative_accuracy": "Accuracy",
|
||||||
"cumulative_battles": "Battles",
|
"cumulative_battles": "Battles",
|
||||||
"cumulative_capture_points": "Total encounter points",
|
"cumulative_capture_points": "Total capture points",
|
||||||
"cumulative_damage_dealt": "Total damage",
|
"cumulative_damage_dealt": "Total damage",
|
||||||
"cumulative_damage_ratio": "Damage ratio",
|
"cumulative_damage_ratio": "Damage ratio",
|
||||||
"cumulative_damage_received": "Total damage received",
|
"cumulative_damage_received": "Total damage received",
|
||||||
"cumulative_deaths": "Total deaths",
|
"cumulative_deaths": "Total deaths",
|
||||||
"cumulative_dropped_capture_points": "Total dropped encounter points",
|
"cumulative_dropped_capture_points": "Total dropped capture points",
|
||||||
"cumulative_frags": "Total kills",
|
"cumulative_frags": "Total kills",
|
||||||
"cumulative_hits": "Total hits",
|
"cumulative_hits": "Total hits",
|
||||||
"cumulative_inaccuracy": "Inaccuracy",
|
"cumulative_inaccuracy": "Inaccuracy",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { calculateWN8 } from '../calculateWN8';
|
||||||
|
|
||||||
export const blitzStatsKeys = [
|
export const blitzStatsKeys = [
|
||||||
'battles',
|
'battles',
|
||||||
'capture_points',
|
'capture_points',
|
||||||
@@ -131,70 +133,256 @@ export type CompositeStatsKey =
|
|||||||
| `cumulative_${(typeof cumulativeCompositeStatsKeys)[number]}`;
|
| `cumulative_${(typeof cumulativeCompositeStatsKeys)[number]}`;
|
||||||
export type CompositeStats = Record<CompositeStatsKey, number>;
|
export type CompositeStats = Record<CompositeStatsKey, number>;
|
||||||
|
|
||||||
|
enum CumulationType {
|
||||||
|
Sum,
|
||||||
|
WeightedSum,
|
||||||
|
}
|
||||||
|
|
||||||
export const compositeStatsFormatting: {
|
export const compositeStatsFormatting: {
|
||||||
[Key in CompositeStatsKey]: {
|
[Key in CompositeStatsKey]: {
|
||||||
unit?: string;
|
unit?: string;
|
||||||
fixed: number;
|
fixed: number;
|
||||||
coefficient?: number;
|
coefficient?: number;
|
||||||
preview: number;
|
|
||||||
localeFormat?: boolean;
|
localeFormat?: boolean;
|
||||||
|
cumulate: CumulationType;
|
||||||
};
|
};
|
||||||
} = {
|
} = {
|
||||||
normalized_damage_dealt: { fixed: 0, preview: 3246, localeFormat: true },
|
normalized_damage_dealt: {
|
||||||
normalized_damage_received: { fixed: 0, preview: 966, localeFormat: true },
|
fixed: 0,
|
||||||
normalized_deaths: { fixed: 0, unit: '%', coefficient: 100, preview: 0.09 },
|
localeFormat: true,
|
||||||
normalized_frags: { fixed: 2, preview: 2.1 },
|
cumulate: CumulationType.WeightedSum,
|
||||||
normalized_hits: { fixed: 2, preview: 12.33 },
|
},
|
||||||
normalized_losses: { fixed: 0, unit: '%', coefficient: 100, preview: 0.3 },
|
normalized_damage_received: {
|
||||||
normalized_misses: { fixed: 2, preview: 1.02 },
|
fixed: 0,
|
||||||
normalized_shots: { fixed: 2, preview: 14.54 },
|
localeFormat: true,
|
||||||
normalized_spotted: { fixed: 2, preview: 2.02 },
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_deaths: {
|
||||||
|
fixed: 0,
|
||||||
|
unit: '%',
|
||||||
|
coefficient: 100,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_frags: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_hits: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_losses: {
|
||||||
|
fixed: 0,
|
||||||
|
unit: '%',
|
||||||
|
coefficient: 100,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_misses: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_shots: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_spotted: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
normalized_survived_battles: {
|
normalized_survived_battles: {
|
||||||
fixed: 0,
|
fixed: 0,
|
||||||
unit: '%',
|
unit: '%',
|
||||||
coefficient: 100,
|
coefficient: 100,
|
||||||
preview: 0.65,
|
cumulate: CumulationType.WeightedSum,
|
||||||
},
|
},
|
||||||
normalized_win_and_survived: {
|
normalized_win_and_survived: {
|
||||||
fixed: 0,
|
fixed: 0,
|
||||||
unit: '%',
|
unit: '%',
|
||||||
coefficient: 100,
|
coefficient: 100,
|
||||||
preview: 0.59,
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_wins: {
|
||||||
|
fixed: 0,
|
||||||
|
unit: '%',
|
||||||
|
coefficient: 100,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_xp: {
|
||||||
|
fixed: 0,
|
||||||
|
localeFormat: true,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
normalized_battle_life_time: {
|
||||||
|
fixed: 1,
|
||||||
|
coefficient: 1 / 60,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
},
|
},
|
||||||
normalized_wins: { fixed: 0, unit: '%', coefficient: 100, preview: 0.72 },
|
|
||||||
normalized_xp: { fixed: 0, preview: 982, localeFormat: true },
|
|
||||||
normalized_battle_life_time: { fixed: 1, preview: 4.6, coefficient: 1 / 60 },
|
|
||||||
|
|
||||||
cumulative_accuracy: { fixed: 0, unit: '%', coefficient: 100, preview: 0.91 },
|
cumulative_accuracy: {
|
||||||
cumulative_battles: { fixed: 0, preview: 12 },
|
fixed: 0,
|
||||||
cumulative_capture_points: { fixed: 2, preview: 0.12 },
|
unit: '%',
|
||||||
cumulative_damage_dealt: { fixed: 0, preview: 45023, localeFormat: true },
|
coefficient: 100,
|
||||||
cumulative_damage_ratio: { fixed: 2, preview: 2.83 },
|
cumulate: CumulationType.WeightedSum,
|
||||||
cumulative_damage_received: { fixed: 0, preview: 10093, localeFormat: true },
|
},
|
||||||
cumulative_deaths: { fixed: 0, preview: 2 },
|
cumulative_battles: {
|
||||||
cumulative_dropped_capture_points: { fixed: 2, preview: 15 },
|
fixed: 0,
|
||||||
cumulative_frags: { fixed: 0, preview: 26 },
|
cumulate: CumulationType.Sum,
|
||||||
cumulative_hits: { fixed: 0, preview: 480 },
|
},
|
||||||
|
cumulative_capture_points: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_damage_dealt: {
|
||||||
|
fixed: 0,
|
||||||
|
localeFormat: true,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_damage_ratio: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
cumulative_damage_received: {
|
||||||
|
fixed: 0,
|
||||||
|
localeFormat: true,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_deaths: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_dropped_capture_points: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_frags: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_hits: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
cumulative_inaccuracy: {
|
cumulative_inaccuracy: {
|
||||||
fixed: 0,
|
fixed: 0,
|
||||||
unit: '%',
|
unit: '%',
|
||||||
coefficient: 100,
|
coefficient: 100,
|
||||||
preview: 0.08,
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
cumulative_kills_to_death_ratio: {
|
||||||
|
fixed: 2,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
|
},
|
||||||
|
cumulative_losses: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_misses: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_shots: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_spotted: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_survived_battles: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_win_and_survived: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_wins: {
|
||||||
|
fixed: 0,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_xp: {
|
||||||
|
fixed: 0,
|
||||||
|
localeFormat: true,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
|
},
|
||||||
|
cumulative_wn8: {
|
||||||
|
fixed: 0,
|
||||||
|
localeFormat: false,
|
||||||
|
cumulate: CumulationType.WeightedSum,
|
||||||
},
|
},
|
||||||
cumulative_kills_to_death_ratio: { fixed: 2, preview: 2.3 },
|
|
||||||
cumulative_losses: { fixed: 0, preview: 3 },
|
|
||||||
cumulative_misses: { fixed: 0, preview: 13 },
|
|
||||||
cumulative_shots: { fixed: 0, preview: 309 },
|
|
||||||
cumulative_spotted: { fixed: 0, preview: 99 },
|
|
||||||
cumulative_survived_battles: { fixed: 0, preview: 10 },
|
|
||||||
cumulative_win_and_survived: { fixed: 0, preview: 9 },
|
|
||||||
cumulative_wins: { fixed: 0, preview: 8 },
|
|
||||||
cumulative_xp: { fixed: 0, preview: 19403, localeFormat: true },
|
|
||||||
cumulative_wn8: { fixed: 0, preview: 3103, localeFormat: true },
|
|
||||||
cumulative_battle_life_time: {
|
cumulative_battle_life_time: {
|
||||||
fixed: 0,
|
fixed: 0,
|
||||||
preview: 109,
|
|
||||||
coefficient: 1 / 60,
|
coefficient: 1 / 60,
|
||||||
localeFormat: true,
|
localeFormat: true,
|
||||||
|
cumulate: CumulationType.Sum,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function calculateCompositeStats(s: BlitzkitStats, a: BlitzStats) {
|
||||||
|
return {
|
||||||
|
cumulative_accuracy: s.hits / s.shots,
|
||||||
|
cumulative_battle_life_time: s.battle_life_time,
|
||||||
|
cumulative_battles: s.battles,
|
||||||
|
cumulative_capture_points: s.capture_points,
|
||||||
|
cumulative_damage_dealt: s.damage_dealt,
|
||||||
|
cumulative_damage_ratio: s.damage_dealt / s.damage_received,
|
||||||
|
cumulative_damage_received: s.damage_received,
|
||||||
|
cumulative_deaths: s.battles - s.survived_battles,
|
||||||
|
cumulative_dropped_capture_points: s.dropped_capture_points,
|
||||||
|
cumulative_frags: s.frags,
|
||||||
|
cumulative_hits: s.hits,
|
||||||
|
cumulative_inaccuracy: (s.shots - s.hits) / s.shots,
|
||||||
|
cumulative_kills_to_death_ratio: s.frags / (s.battles - s.survived_battles),
|
||||||
|
cumulative_losses: s.losses,
|
||||||
|
cumulative_misses: s.shots - s.hits,
|
||||||
|
cumulative_shots: s.shots,
|
||||||
|
cumulative_spotted: s.spotted,
|
||||||
|
cumulative_survived_battles: s.survived_battles,
|
||||||
|
cumulative_win_and_survived: s.win_and_survived,
|
||||||
|
cumulative_wins: s.wins,
|
||||||
|
cumulative_wn8: calculateWN8(a, s),
|
||||||
|
cumulative_xp: s.xp,
|
||||||
|
normalized_battle_life_time: s.battle_life_time / s.battles,
|
||||||
|
normalized_damage_dealt: s.damage_dealt / s.battles,
|
||||||
|
normalized_damage_received: s.damage_received / s.battles,
|
||||||
|
normalized_deaths: (s.battles - s.survived_battles) / s.battles,
|
||||||
|
normalized_frags: s.frags / s.battles,
|
||||||
|
normalized_hits: s.hits / s.battles,
|
||||||
|
normalized_losses: s.losses / s.battles,
|
||||||
|
normalized_misses: (s.shots - s.hits) / s.battles,
|
||||||
|
normalized_shots: s.shots / s.battles,
|
||||||
|
normalized_spotted: s.spotted / s.battles,
|
||||||
|
normalized_survived_battles: s.survived_battles / s.battles,
|
||||||
|
normalized_win_and_survived: s.win_and_survived / s.battles,
|
||||||
|
normalized_wins: s.wins / s.battles,
|
||||||
|
normalized_xp: s.xp / s.battles,
|
||||||
|
} satisfies CompositeStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sumCompositeStats(stats: CompositeStats[]) {
|
||||||
|
const battles = stats.reduce((a, b) => a + b.cumulative_battles, 0);
|
||||||
|
const summed: Partial<CompositeStats> = {};
|
||||||
|
|
||||||
|
Object.entries(compositeStatsFormatting).forEach(([key, value]) => {
|
||||||
|
switch (value.cumulate) {
|
||||||
|
case CumulationType.Sum: {
|
||||||
|
summed[key as keyof CompositeStats] = stats.reduce(
|
||||||
|
(a, b) => a + b[key as keyof CompositeStats],
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CumulationType.WeightedSum: {
|
||||||
|
summed[key as keyof CompositeStats] =
|
||||||
|
stats.reduce(
|
||||||
|
(a, b) => a + b[key as keyof CompositeStats] * b.cumulative_battles,
|
||||||
|
0,
|
||||||
|
) / battles;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return summed as CompositeStats;
|
||||||
|
}
|
||||||
@@ -49,19 +49,20 @@ export function compositeStats(stats: BlitzkitStats, average: BlitzkitStats) {
|
|||||||
} satisfies CompositeStats;
|
} satisfies CompositeStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatCompositeStat(value: number, key: CompositeStatsKey) {
|
export function formatCompositeStat(
|
||||||
|
value: number,
|
||||||
|
key: CompositeStatsKey,
|
||||||
|
composite: CompositeStats,
|
||||||
|
) {
|
||||||
|
if (composite.cumulative_battles === 0) return '--';
|
||||||
|
|
||||||
const formatting = compositeStatsFormatting[key];
|
const formatting = compositeStatsFormatting[key];
|
||||||
const resolvedValue = (formatting.coefficient ?? 1) * value;
|
const resolvedValue = (formatting.coefficient ?? 1) * value;
|
||||||
return `${
|
return `${
|
||||||
formatting.localeFormat
|
formatting.localeFormat
|
||||||
? resolvedValue.toLocaleString()
|
? Math.round(resolvedValue).toLocaleString()
|
||||||
: resolvedValue.toFixed(formatting.fixed)
|
: resolvedValue.toFixed(formatting.fixed)
|
||||||
}${formatting.unit ?? ''}`;
|
}${formatting.unit ?? ''}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function previewCompositeStat(key: CompositeStatsKey) {
|
|
||||||
const { preview } = compositeStatsFormatting[key];
|
|
||||||
return formatCompositeStat(preview, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
export * from './constants';
|
export * from './constants';
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
|
calculateCompositeStats,
|
||||||
|
compositeStats,
|
||||||
compositeStatsKeys,
|
compositeStatsKeys,
|
||||||
deltaTankStats,
|
deltaTankStats,
|
||||||
|
fetchAverageDefinitions,
|
||||||
fetchTankDefinitions,
|
fetchTankDefinitions,
|
||||||
getTankStats,
|
getTankStats,
|
||||||
idToRegion,
|
idToRegion,
|
||||||
|
sumCompositeStats,
|
||||||
type IndividualTankStats,
|
type IndividualTankStats,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import strings from '@blitzkit/core/lang/en-US.json';
|
import strings from '@blitzkit/core/lang/en-US.json';
|
||||||
@@ -21,6 +25,31 @@ export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const tankDefinitions = await fetchTankDefinitions();
|
const tankDefinitions = await fetchTankDefinitions();
|
||||||
|
const averageDefinitions = await fetchAverageDefinitions();
|
||||||
|
|
||||||
|
export const fakeCompositeStats = compositeStats(
|
||||||
|
{
|
||||||
|
battle_life_time: 5 * 50 * 60,
|
||||||
|
battles: 50,
|
||||||
|
capture_points: 5,
|
||||||
|
damage_dealt: 3201 * 50,
|
||||||
|
damage_received: 1093 * 50,
|
||||||
|
dropped_capture_points: 40,
|
||||||
|
frags: 99,
|
||||||
|
frags8p: 0,
|
||||||
|
hits: 50 * 13,
|
||||||
|
losses: 20,
|
||||||
|
max_frags: 7,
|
||||||
|
max_xp: 1203,
|
||||||
|
shots: 50 * 14,
|
||||||
|
spotted: 50 * 1.5,
|
||||||
|
survived_battles: 32,
|
||||||
|
win_and_survived: 28,
|
||||||
|
wins: 30,
|
||||||
|
xp: 1230 * 50,
|
||||||
|
},
|
||||||
|
averageDefinitions.averages[7297].mu,
|
||||||
|
);
|
||||||
|
|
||||||
export function BreakdownPreview() {
|
export function BreakdownPreview() {
|
||||||
const tanks = Object.values(tankDefinitions.tanks);
|
const tanks = Object.values(tankDefinitions.tanks);
|
||||||
@@ -28,10 +57,16 @@ export function BreakdownPreview() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BreakdownEmbedWrapper>
|
<BreakdownEmbedWrapper>
|
||||||
{useEmbedState('showTotal') && <BreakdownEmbedCard tank={null} />}
|
{useEmbedState('showTotal') && (
|
||||||
|
<BreakdownEmbedCard composite={fakeCompositeStats} tank={null} />
|
||||||
|
)}
|
||||||
|
|
||||||
{tanks.slice(0, useEmbedState('listMaxTanks')).map((tank) => (
|
{tanks.slice(0, useEmbedState('listMaxTanks')).map((tank) => (
|
||||||
<BreakdownEmbedCard key={tank.id} tank={tank} />
|
<BreakdownEmbedCard
|
||||||
|
composite={fakeCompositeStats}
|
||||||
|
key={tank.id}
|
||||||
|
tank={tank}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</BreakdownEmbedWrapper>
|
</BreakdownEmbedWrapper>
|
||||||
);
|
);
|
||||||
@@ -59,6 +94,23 @@ function BreakdownRendererContent() {
|
|||||||
),
|
),
|
||||||
[tankStatsB],
|
[tankStatsB],
|
||||||
);
|
);
|
||||||
|
const compositeStats = diff
|
||||||
|
.map((diff) => {
|
||||||
|
const average = averageDefinitions.averages[diff.tank_id];
|
||||||
|
|
||||||
|
if (average === undefined) return null;
|
||||||
|
|
||||||
|
const compositeStats = calculateCompositeStats(
|
||||||
|
{ battle_life_time: diff.battle_life_time, ...diff.all },
|
||||||
|
average.mu,
|
||||||
|
);
|
||||||
|
|
||||||
|
return { id: diff.tank_id, compositeStats };
|
||||||
|
})
|
||||||
|
.filter((stats) => stats !== null);
|
||||||
|
const sum = sumCompositeStats(
|
||||||
|
compositeStats.map(({ compositeStats }) => compositeStats),
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
@@ -76,13 +128,23 @@ function BreakdownRendererContent() {
|
|||||||
<ContextMenu.Root>
|
<ContextMenu.Root>
|
||||||
<ContextMenu.Trigger>
|
<ContextMenu.Trigger>
|
||||||
<BreakdownEmbedWrapper>
|
<BreakdownEmbedWrapper>
|
||||||
{useEmbedState('showTotal') && <BreakdownEmbedCard tank={null} />}
|
{useEmbedState('showTotal') && (
|
||||||
|
<BreakdownEmbedCard composite={sum} tank={null} />
|
||||||
|
)}
|
||||||
|
|
||||||
{diff.slice(0, useEmbedState('listMaxTanks')).map((diff) => {
|
{compositeStats
|
||||||
const tank = tankDefinitions.tanks[diff.tank_id];
|
.slice(0, useEmbedState('listMaxTanks'))
|
||||||
|
.map(({ id, compositeStats }) => {
|
||||||
|
const tank = tankDefinitions.tanks[id];
|
||||||
|
|
||||||
return <BreakdownEmbedCard key={tank.id} tank={tank} />;
|
return (
|
||||||
})}
|
<BreakdownEmbedCard
|
||||||
|
key={tank.id}
|
||||||
|
tank={tank}
|
||||||
|
composite={compositeStats}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</BreakdownEmbedWrapper>
|
</BreakdownEmbedWrapper>
|
||||||
</ContextMenu.Trigger>
|
</ContextMenu.Trigger>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
previewCompositeStat,
|
formatCompositeStat,
|
||||||
TankClass,
|
TankClass,
|
||||||
TankDefinition,
|
TankDefinition,
|
||||||
TankType,
|
TankType,
|
||||||
|
type CompositeStats,
|
||||||
type CompositeStatsKey,
|
type CompositeStatsKey,
|
||||||
} from '@blitzkit/core';
|
} from '@blitzkit/core';
|
||||||
import strings from '@blitzkit/core/lang/en-US.json';
|
import strings from '@blitzkit/core/lang/en-US.json';
|
||||||
@@ -42,9 +43,13 @@ export function BreakdownEmbedWrapper({
|
|||||||
|
|
||||||
interface BreakdownEmbedCardProps {
|
interface BreakdownEmbedCardProps {
|
||||||
tank: TankDefinition | null | undefined;
|
tank: TankDefinition | null | undefined;
|
||||||
|
composite: CompositeStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
|
export function BreakdownEmbedCard({
|
||||||
|
tank,
|
||||||
|
composite,
|
||||||
|
}: BreakdownEmbedCardProps) {
|
||||||
const { useEmbedState, useRichText } =
|
const { useEmbedState, useRichText } =
|
||||||
useEmbedStateCurry<typeof breakdownConfig>();
|
useEmbedStateCurry<typeof breakdownConfig>();
|
||||||
|
|
||||||
@@ -114,9 +119,7 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
|
|||||||
<Flex p={useEmbedState('cardBodyPadding')}>
|
<Flex p={useEmbedState('cardBodyPadding')}>
|
||||||
{times(4, (index) => {
|
{times(4, (index) => {
|
||||||
const column = (index + 1) as 1 | 2 | 3 | 4;
|
const column = (index + 1) as 1 | 2 | 3 | 4;
|
||||||
const columnState = useEmbedState(
|
const statKey = useEmbedState(`column${column}`) as CompositeStatsKey;
|
||||||
`column${column}`,
|
|
||||||
) as CompositeStatsKey;
|
|
||||||
const customLabel = useEmbedState(`column${column}CustomLabel`);
|
const customLabel = useEmbedState(`column${column}CustomLabel`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -128,11 +131,11 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
|
|||||||
flexGrow="1"
|
flexGrow="1"
|
||||||
>
|
>
|
||||||
<Text {...useRichText('columnValue')}>
|
<Text {...useRichText('columnValue')}>
|
||||||
{previewCompositeStat(columnState)}
|
{formatCompositeStat(composite[statKey], statKey, composite)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text {...useRichText('columnLabel')}>
|
<Text {...useRichText('columnLabel')}>
|
||||||
{customLabel.length === 0
|
{customLabel.length === 0
|
||||||
? strings.common.composite_stats[columnState]
|
? strings.common.composite_stats[statKey]
|
||||||
: customLabel}
|
: customLabel}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
Reference in new issue
Block a user