mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: updated /fullstats with figma
This commit is contained in:
1 parent
fedad8df3e
commit
21158e9081
10 files changed
+246
-67
No files matched your search
@@ -2,8 +2,8 @@
|
||||
|
||||
What is considered a "day's worth of games" is determined by the reset time. The reset time is generally at midnight everyday after which newer games are counted towards the next day. Reset times vary from region to region:
|
||||
|
||||
- North America: UTC-5:00 (Central North American Time midnight)
|
||||
- Europe: UTC+1:00 (Central European Time midnight)
|
||||
- Asia: UTC+7:00 (Central Asia Standard Time midnight)
|
||||
- North America: `UTC-5:00` (Central North American Time midnight)
|
||||
- Europe: `UTC+1:00` (Central European Time midnight)
|
||||
- Asia: `UTC+7:00` (Central Asia Standard Time midnight)
|
||||
|
||||
**Reset times are different from Blitz Stars** (Blitz Stars resets at 5:00 am locally relative to the user opening their website). Inconsistencies with Blitz Stars only occur with sleep-deprived players and players who play in the wrong region.
|
||||
@@ -19,7 +19,7 @@ import { AccountInfo } from '../types/accountInfo.js';
|
||||
|
||||
export const fullStatsCommand: CommandRegistry = {
|
||||
inProduction: true,
|
||||
inDevelopment: false,
|
||||
inDevelopment: true,
|
||||
inPublic: true,
|
||||
|
||||
command: addStatTypeSubCommandGroups(
|
||||
|
||||
@@ -33,7 +33,7 @@ function addDocsSubcommands(option: SlashCommandSubcommandsOnlyBuilder) {
|
||||
|
||||
export const helpCommand: CommandRegistry = {
|
||||
inProduction: true,
|
||||
inDevelopment: true,
|
||||
inDevelopment: false,
|
||||
inPublic: true,
|
||||
|
||||
command: addDocsSubcommands(
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import getWN8Percentile from '../core/blitz/getWN8Percentile.js';
|
||||
import isNumber from '../core/node/isNumber.js';
|
||||
import { AllStats, SupplementaryStats } from '../types/accountInfo.js';
|
||||
import GenericStats from './GenericStats/index.js';
|
||||
|
||||
export interface GenericAllStatsProps {
|
||||
stats: AllStats;
|
||||
supplementaryStats?: SupplementaryStats;
|
||||
}
|
||||
|
||||
export default function GenericAllStats({
|
||||
stats,
|
||||
supplementaryStats,
|
||||
}: GenericAllStatsProps) {
|
||||
const damageRatio = stats.damage_dealt / stats.damage_received;
|
||||
const killsToDeathRatio =
|
||||
stats.frags / (stats.battles - stats.survived_battles);
|
||||
|
||||
return (
|
||||
<GenericStats
|
||||
stats={[
|
||||
['Winrate', `${(100 * (stats.wins / stats.battles)).toFixed(2)}%`],
|
||||
[
|
||||
'WN8',
|
||||
supplementaryStats
|
||||
? isNumber(supplementaryStats.WN8)
|
||||
? supplementaryStats.WN8!.toFixed(0)
|
||||
: '--'
|
||||
: undefined,
|
||||
isNumber(supplementaryStats?.WN8)
|
||||
? getWN8Percentile(supplementaryStats!.WN8!)
|
||||
: undefined,
|
||||
],
|
||||
[
|
||||
'Survival',
|
||||
`${(100 * (stats.survived_battles / stats.battles)).toFixed(2)}%`,
|
||||
],
|
||||
['Accuracy', `${((stats.hits / stats.shots) * 100).toFixed(2)}%`],
|
||||
['Battles', stats.battles],
|
||||
['Wins', stats.wins],
|
||||
['Losses', stats.losses],
|
||||
['Average damage', (stats.damage_dealt / stats.battles).toFixed(0)],
|
||||
[
|
||||
'Average tier',
|
||||
supplementaryStats?.tier ? supplementaryStats?.tier.toFixed(2) : '--',
|
||||
],
|
||||
['Average XP', (stats.xp / stats.battles).toFixed(0)],
|
||||
['Average shots', (stats.shots / stats.battles).toFixed(2)],
|
||||
['Average hits', (stats.hits / stats.battles).toFixed(2)],
|
||||
['Average kills', (stats.frags / stats.battles).toFixed(2)],
|
||||
['Average spots', (stats.spotted / stats.battles).toFixed(2)],
|
||||
['Damage ratio', isFinite(damageRatio) ? damageRatio.toFixed(2) : '--'],
|
||||
[
|
||||
'Kills to death ratio',
|
||||
isFinite(killsToDeathRatio) ? killsToDeathRatio.toFixed(2) : '--',
|
||||
],
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { Percentile } from '../../../constants/percentiles.js';
|
||||
import { theme } from '../../../stitches.config.js';
|
||||
import PercentileIndicator from '../../PercentileIndicator.js';
|
||||
|
||||
export interface CardItem {
|
||||
label: string;
|
||||
value: string | number | undefined;
|
||||
percentile?: Percentile;
|
||||
}
|
||||
|
||||
export interface CardProps {
|
||||
items: CardItem[];
|
||||
title: string;
|
||||
}
|
||||
|
||||
export function Card({ items, title }: CardProps) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 16,
|
||||
flex: 1,
|
||||
borderRadius: 4,
|
||||
backgroundColor: theme.colors.componentInteractive,
|
||||
padding: 8,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
color: theme.colors.textHighContrast,
|
||||
fontSize: 24,
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
{items.map((item) => (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: 16, color: theme.colors.textLowContrast }}>
|
||||
{item.label}
|
||||
</span>
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
height: 1,
|
||||
borderRadius: 0.5,
|
||||
backgroundColor: theme.colors.borderNonInteractive,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
gap: 4,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{item.percentile !== undefined && (
|
||||
<PercentileIndicator percentile={item.percentile} />
|
||||
)}
|
||||
<span
|
||||
style={{ fontSize: 16, color: theme.colors.textHighContrast }}
|
||||
>
|
||||
{item.value === undefined || Number.isNaN(item.value)
|
||||
? '--'
|
||||
: item.value}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
export interface RootProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function Root({ children }: RootProps) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 8,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export interface RowProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function Row({ children }: RowProps) {
|
||||
return <div style={{ display: 'flex', gap: 8 }}>{children}</div>;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
import getWN8Percentile from '../../core/blitz/getWN8Percentile.js';
|
||||
import isNumber from '../../core/node/isNumber.js';
|
||||
import { AllStats, SupplementaryStats } from '../../types/accountInfo.js';
|
||||
import { Card } from './components/Card.js';
|
||||
import { Root } from './components/Root.js';
|
||||
import { Row } from './components/Row.js';
|
||||
|
||||
// TODO: remove the .js endings
|
||||
|
||||
export interface GenericAllStatsProps {
|
||||
stats: AllStats;
|
||||
supplementaryStats?: SupplementaryStats;
|
||||
}
|
||||
|
||||
export default function GenericAllStats({
|
||||
stats,
|
||||
supplementaryStats,
|
||||
}: GenericAllStatsProps) {
|
||||
const damageRatio = stats.damage_dealt / stats.damage_received;
|
||||
const killsToDeathRatio =
|
||||
stats.frags / (stats.battles - stats.survived_battles);
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<Row>
|
||||
<Card
|
||||
title="Games"
|
||||
items={[
|
||||
{
|
||||
label: 'Winrate',
|
||||
value: `${(100 * (stats.wins / stats.battles)).toFixed(2)}%`,
|
||||
},
|
||||
{
|
||||
label: 'Battles',
|
||||
value: stats.battles,
|
||||
},
|
||||
{
|
||||
label: 'Wins / Losses',
|
||||
value: `${stats.wins} / ${stats.losses}`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card
|
||||
title="Efficiency"
|
||||
items={[
|
||||
{
|
||||
label: 'WN8',
|
||||
value:
|
||||
supplementaryStats && isNumber(supplementaryStats.WN8)
|
||||
? supplementaryStats.WN8!.toFixed(0)
|
||||
: undefined,
|
||||
percentile: isNumber(supplementaryStats?.WN8)
|
||||
? getWN8Percentile(supplementaryStats!.WN8!)
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
label: 'Survival',
|
||||
value: `${(
|
||||
100 *
|
||||
(stats.survived_battles / stats.battles)
|
||||
).toFixed(2)}%`,
|
||||
},
|
||||
{
|
||||
label: 'Accuracy',
|
||||
value: `${((stats.hits / stats.shots) * 100).toFixed(2)}%`,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Row>
|
||||
<Row>
|
||||
<Card
|
||||
title="Lethality"
|
||||
items={[
|
||||
{
|
||||
label: 'Average damage',
|
||||
value: (stats.damage_dealt / stats.battles).toFixed(0),
|
||||
},
|
||||
{
|
||||
label: 'Damage per tier',
|
||||
value: supplementaryStats?.tier
|
||||
? (
|
||||
stats.damage_dealt /
|
||||
stats.battles /
|
||||
supplementaryStats.tier
|
||||
).toFixed(0)
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
label: 'Damage ratio',
|
||||
value: isFinite(damageRatio) ? damageRatio.toFixed(2) : undefined,
|
||||
},
|
||||
{
|
||||
label: 'Average kills',
|
||||
value: (stats.frags / stats.battles).toFixed(0),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card
|
||||
title="Efficiency"
|
||||
items={[
|
||||
{
|
||||
label: 'Average tier',
|
||||
value: supplementaryStats?.tier?.toFixed(2),
|
||||
},
|
||||
{
|
||||
label: 'Average spots',
|
||||
value: (stats.spotted / stats.battles).toFixed(2),
|
||||
},
|
||||
{
|
||||
label: 'Average XP',
|
||||
value: (stats.xp / stats.battles).toFixed(0),
|
||||
},
|
||||
{
|
||||
label: 'Kills to death ratio',
|
||||
value: isFinite(killsToDeathRatio)
|
||||
? killsToDeathRatio.toFixed(2)
|
||||
: undefined,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Row>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import GenericAllStats from '../components/GenericAllStats.js';
|
||||
import GenericAllStats from '../components/GenericAllStats/index.js';
|
||||
import NoData, { NoDataType } from '../components/NoData.js';
|
||||
import PoweredBy, { PoweredByType } from '../components/PoweredBy.js';
|
||||
import TierWeights, { TierWeightsRecord } from '../components/TierWeights.js';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { RouteRegistry } from '../server.js';
|
||||
export const todayRoute: RouteRegistry = {
|
||||
route: '/today',
|
||||
inProduction: true,
|
||||
inDevelopment: true,
|
||||
inDevelopment: false,
|
||||
|
||||
async handler(req) {
|
||||
const player = resolvePlayerFromRequest(req);
|
||||
|
||||
Reference in new issue
Block a user