feat(skywars): add full mode stats rows and best mode detection
This commit is contained in:
142
src/app/(stats)/player/[ign]/_stats/skywars/table.tsx
Normal file
142
src/app/(stats)/player/[ign]/_stats/skywars/table.tsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||||
|
import { formatNumber } from "@/lib/formatters"
|
||||||
|
import { _SkywarsStats, getBestMode, getSkywarsModeStats } from "@/lib/hypixel/skywars"
|
||||||
|
import { NonNullStats } from "@/lib/schema/player"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
export default function SkywarsStatTable({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<SkywarsTableHeader />
|
||||||
|
<TableBody>
|
||||||
|
<Normal stats={stats} />
|
||||||
|
<Insane stats={stats} />
|
||||||
|
<TeamsNormal stats={stats} />
|
||||||
|
<TeamsInsane stats={stats} />
|
||||||
|
<Mega stats={stats} />
|
||||||
|
<MegaDoubles stats={stats} />
|
||||||
|
<Ranked stats={stats} />
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SkywarsTableHeader() {
|
||||||
|
const headerElements = [
|
||||||
|
"Mode",
|
||||||
|
"Kills",
|
||||||
|
"Deaths",
|
||||||
|
"KD",
|
||||||
|
"Wins",
|
||||||
|
"Losses",
|
||||||
|
"WL"
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
{headerElements.map((v, i) => {
|
||||||
|
return <TableHead key={i} className="font-bold">{v}</TableHead>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Normal({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("normal", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "normal"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Solo Normal</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Insane({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("insane", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "insane"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Solo Insane</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TeamsNormal({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("teams_normal", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "teams_normal"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Teams Normal</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TeamsInsane({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("teams_insane", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "teams_insane"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Teams Insane</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Mega({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("mega", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "mega"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Mega</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function MegaDoubles({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("mega_doubles", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "mega_doubles"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Mega Doubles</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ranked({ stats }: { stats: NonNullStats["SkyWars"] }) {
|
||||||
|
const modeStats = getSkywarsModeStats("ranked", stats as _SkywarsStats)
|
||||||
|
const isBest = getBestMode(stats as _SkywarsStats) === "ranked"
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow className={cn(isBest ? "font-bold text-mc-light-purple" : undefined)}>
|
||||||
|
<TableCell>Ranked</TableCell>
|
||||||
|
{modeStats.map((v, i) => {
|
||||||
|
return <TableCell key={i}>{typeof v === "number" ? formatNumber(v) : v}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ICONS, PRESTIGES } from "@/data/hypixel/skywars"
|
import { ICONS, PRESTIGES } from "@/data/hypixel/skywars"
|
||||||
import { floorLevel } from "./formatters"
|
import { floorLevel } from "./formatters"
|
||||||
|
import { devide } from "./general"
|
||||||
|
|
||||||
export function getTextColor(level: number) {
|
export function getTextColor(level: number) {
|
||||||
const floored = floorLevel(level, 5)
|
const floored = floorLevel(level, 5)
|
||||||
@@ -36,3 +37,94 @@ export function getPrestigeName(level: number) {
|
|||||||
|
|
||||||
return PRESTIGES.find(p => p.level === floored)!.name
|
return PRESTIGES.find(p => p.level === floored)!.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type _SkywarsStats = Record<string, number>
|
||||||
|
type Mode =
|
||||||
|
| "normal"
|
||||||
|
| "insane"
|
||||||
|
| "teams_normal"
|
||||||
|
| "teams_insane"
|
||||||
|
| "mega"
|
||||||
|
| "mega_doubles"
|
||||||
|
| "ranked"
|
||||||
|
|
||||||
|
export type SkywarsModeStats = {
|
||||||
|
kills: number
|
||||||
|
deaths: number
|
||||||
|
wins: number
|
||||||
|
losses: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBestMode(stats: _SkywarsStats): Mode | null {
|
||||||
|
const { wins: normal } = getSkywarsModeStats("normal", stats, true)
|
||||||
|
const { wins: insane } = getSkywarsModeStats("insane", stats, true)
|
||||||
|
const { wins: teams_normal } = getSkywarsModeStats("teams_normal", stats, true)
|
||||||
|
const { wins: teams_insane } = getSkywarsModeStats("teams_insane", stats, true)
|
||||||
|
const { wins: mega } = getSkywarsModeStats("mega", stats, true)
|
||||||
|
const { wins: mega_doubles } = getSkywarsModeStats("mega_doubles", stats, true)
|
||||||
|
const { wins: ranked } = getSkywarsModeStats("ranked", stats, true)
|
||||||
|
|
||||||
|
const max = Math.max(normal, insane, teams_normal, teams_insane, mega, mega_doubles, ranked)
|
||||||
|
|
||||||
|
switch (max) {
|
||||||
|
case normal:
|
||||||
|
return "normal"
|
||||||
|
case insane:
|
||||||
|
return "insane"
|
||||||
|
case teams_normal:
|
||||||
|
return "teams_normal"
|
||||||
|
case teams_insane:
|
||||||
|
return "teams_insane"
|
||||||
|
case mega:
|
||||||
|
return "mega"
|
||||||
|
case mega_doubles:
|
||||||
|
return "mega_doubles"
|
||||||
|
case ranked:
|
||||||
|
return "ranked"
|
||||||
|
default:
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSkywarsModeStats(mode: Mode, stats: _SkywarsStats, raw: true): SkywarsModeStats
|
||||||
|
export function getSkywarsModeStats(mode: Mode, stats: _SkywarsStats, raw?: false): (string | number)[]
|
||||||
|
export function getSkywarsModeStats(mode: Mode, stats: _SkywarsStats, raw = false) {
|
||||||
|
switch (mode) {
|
||||||
|
case "normal":
|
||||||
|
return skywarsModeStats("solo_normal", stats, raw)
|
||||||
|
case "insane":
|
||||||
|
return skywarsModeStats("solo_insane", stats, raw)
|
||||||
|
case "teams_normal":
|
||||||
|
return skywarsModeStats("team_normal", stats, raw)
|
||||||
|
case "teams_insane":
|
||||||
|
return skywarsModeStats("team_insane", stats, raw)
|
||||||
|
case "mega":
|
||||||
|
return skywarsModeStats("mega_mega", stats, raw)
|
||||||
|
case "mega_doubles":
|
||||||
|
return skywarsModeStats("mega_doubles", stats, raw)
|
||||||
|
case "ranked":
|
||||||
|
return skywarsModeStats("ranked_normal", stats, raw)
|
||||||
|
default:
|
||||||
|
throw new Error(`${mode satisfies never} does not exist`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function skywarsModeStats(suffix: string, stats: _SkywarsStats, raw = false) {
|
||||||
|
if (raw) {
|
||||||
|
return {
|
||||||
|
kills: stats[`kills_${suffix}`],
|
||||||
|
deaths: stats[`deaths_${suffix}`],
|
||||||
|
wins: stats[`wins_${suffix}`],
|
||||||
|
losses: stats[`losses_${suffix}`]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
stats[`kills_${suffix}`],
|
||||||
|
stats[`deaths_${suffix}`],
|
||||||
|
devide(stats[`kills_${suffix}`], stats[`deaths_${suffix}`]).toFixed(2),
|
||||||
|
stats[`wins_${suffix}`],
|
||||||
|
stats[`losses_${suffix}`],
|
||||||
|
devide(stats[`wins_${suffix}`], stats[`losses_${suffix}`]).toFixed(2)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user