diff --git a/src/app/tools/player-stats/[id]/page.css.ts b/src/app/tools/player-stats/[id]/page.css.ts deleted file mode 100644 index d31a326c9..000000000 --- a/src/app/tools/player-stats/[id]/page.css.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { style } from '@vanilla-extract/css'; - -export const bkniIndicator = style({ - scale: 0.8, - - '@media': { - 'screen and (min-width: 1024px)': { - scale: 1, - }, - }, -}); diff --git a/src/app/tools/player-stats/[id]/page.tsx b/src/app/tools/player-stats/[id]/page.tsx index 4d41b0f56..66bdcba55 100644 --- a/src/app/tools/player-stats/[id]/page.tsx +++ b/src/app/tools/player-stats/[id]/page.tsx @@ -1,24 +1,31 @@ 'use client'; +import { TimerIcon } from '@radix-ui/react-icons'; import { Box, + Button, Flex, Heading, Link, Popover, + SegmentedControl, Text, Theme, } from '@radix-ui/themes'; import { useState } from 'react'; -import { BkniIndicator } from '../../../../components/BkniIndicator'; import { DatePicker } from '../../../../components/DatePicker'; +import { Speedometer } from '../../../../components/Speedometer'; import { getAccountInfo } from '../../../../core/blitz/getAccountInfo'; import { getClanAccountInfo } from '../../../../core/blitz/getClanAccountInfo'; import { idToRegion } from '../../../../core/blitz/idToRegion'; import { parseBkni } from '../../../../core/blitzkit/parseBkni'; +import { PeriodType } from '../../../../core/discord/addPeriodSubCommands'; +import { + BKNI_COLORS, + BKNI_PERCENTILES, +} from '../../../../core/statistics/getBkniPercentile'; import { useAwait } from '../../../../hooks/useAwait'; import strings from '../../../../lang/en-US.json'; -import * as styles from './page.css'; export default function Page({ params }: { params: { id: string } }) { const id = parseInt(params.id); @@ -26,18 +33,18 @@ export default function Page({ params }: { params: { id: string } }) { const accountInfo = useAwait(getAccountInfo(region, id)); const clanAccountInfo = useAwait(getClanAccountInfo(region, id, ['clan'])); // const bkni = ((Math.round(Date.now() / 1000 / 60) / 100) % 2) - 1; - const bkni = 2 * Math.random() - 1; - const [period, setPeriod] = useState<'custom' | number>(30); - const { bkniColor } = parseBkni(bkni); - const isTracking = false; + const bkni = 0.81; + const winrate = 0.6; + const [period, setPeriod] = useState('30'); + const { bkniColor, bkniMetric, bkniFraction, bkniPercentile } = + parseBkni(bkni); const [customFrom, setCustomFrom] = useState( new Date(Date.now() - 29 * 24 * 60 * 60 * 1000), ); const stats = [ - ['Winrate', '70%'], - ['Survival', '70%'], ['Damage', '3,203'], ['Tier', '9.83'], + ['Survival', '70%'], ['Kills', '1.54'], ['Damage ratio', '2.45'], ['Accuracy', '91%'], @@ -52,110 +59,213 @@ export default function Page({ params }: { params: { id: string } }) { - - - {accountInfo.nickname} - - - {clanAccountInfo?.clan && `[${clanAccountInfo.clan.tag}] • `} - { - (clanAccountInfo?.clan - ? strings.common.regions.short - : strings.common.regions.normal)[region] - } - - - {/* - - - - */} - - - - - - - - {stats.map((stat) => ( - - {stat[1]} - - {stat[0]} - - - ))} - + + + {accountInfo.nickname} + + + {clanAccountInfo?.clan && `[${clanAccountInfo.clan.tag}] • `} + { + (clanAccountInfo?.clan + ? strings.common.regions.short + : strings.common.regions.normal)[region] + } + - {period === 'custom' && ( - - From{' '} - + + setPeriod(value as PeriodType)} + > + + Today + + + 30 days + + + Career + + + Custom + + + + {period === 'custom' && ( + + From{' '} + + + + {customFrom.toLocaleString(undefined, { + month: 'short', + day: 'numeric', + year: 'numeric', + })} + + + + + { + setCustomFrom(date); + setFromSelectorOpen(false); + }} + /> + + {' '} + to{' '} + + + + {customTo.toLocaleString(undefined, { + month: 'short', + day: 'numeric', + year: 'numeric', + })} + + + + + { + setCustomTo(date); + setToSelectorOpen(false); + }} + /> + + + + )} + + + + + - - {customFrom.toLocaleString(undefined, { - month: 'short', - day: 'numeric', - year: 'numeric', - })} - + - - { - setCustomFrom(date); - setFromSelectorOpen(false); + + - - {' '} - to{' '} - - - - {customTo.toLocaleString(undefined, { - month: 'short', - day: 'numeric', - year: 'numeric', - })} - - + > + + + BkNI + + + A next generation performance metric + + - - { - setCustomTo(date); - setToSelectorOpen(false); - }} - /> + {BKNI_PERCENTILES.map(({ percentile, min }, index) => ( + + ))} + - - )} + } + /> + + + {(winrate * 100).toFixed(0)} + + % + + + } + color="green" + fill={0.5 * (Math.cbrt(2 * winrate - 1) + 1)} + label={Winrate} + /> + + + + {stats.map((stat) => ( + + {stat[1]} + + {stat[0]} + + + ))} + {/* + + + + */} + {/* + + + */} + {/* - - - - - - - - {bkniMetric} - - - - - - - - - - - - BkNI - - - A next generation performance metric - - - - {BKNI_PERCENTILES.map(({ percentile, min }, index) => ( - - ))} - - - - - - ); -} diff --git a/src/components/Speedometer.tsx b/src/components/Speedometer.tsx new file mode 100644 index 000000000..8146622a6 --- /dev/null +++ b/src/components/Speedometer.tsx @@ -0,0 +1,60 @@ +import { Flex, FlexProps, Text } from '@radix-ui/themes'; +import { ReactNode } from 'react'; + +type SpeedometerProps = FlexProps & { + value: ReactNode; + color: string; + fill: number; + label: ReactNode; +}; + +export function Speedometer({ + value, + color, + fill, + label, + ...props +}: SpeedometerProps) { + return ( + + + + + + + + + {value} + + + {label} + + + ); +}