From 405bc4370c7be61153cb0debc0e2223fd3a8fea2 Mon Sep 17 00:00:00 2001 From: Taken Date: Thu, 18 Sep 2025 12:47:18 +0200 Subject: [PATCH] Added smash heros hero stat table --- .../[ign]/_stats/smashheros/smashheros.tsx | 4 +- .../player/[ign]/_stats/smashheros/table.tsx | 76 ++++++++++++++++++- src/data/hypixel/smashheros.ts | 3 +- src/lib/hypixel/smashhero/general.ts | 45 ++++++++++- src/lib/schema/stats/smashheros.ts | 38 +++++++++- 5 files changed, 161 insertions(+), 5 deletions(-) diff --git a/src/app/(stats)/player/[ign]/_stats/smashheros/smashheros.tsx b/src/app/(stats)/player/[ign]/_stats/smashheros/smashheros.tsx index a4f929a..d676992 100644 --- a/src/app/(stats)/player/[ign]/_stats/smashheros/smashheros.tsx +++ b/src/app/(stats)/player/[ign]/_stats/smashheros/smashheros.tsx @@ -5,7 +5,7 @@ import { getSmashHerosDifficultyColor, getSmashHerosMostPlayedHero } from "@/lib import { NonNullStats } from "@/lib/schema/player" import GeneralStats from "../GeneralStats" import SmashHerosGeneralStats from "./stats" -import { SmashHerosModeTable } from "./table" +import { SmashHerosHeroTable, SmashHerosModeTable } from "./table" export default function SmashHerosStats({ stats }: { stats: NonNullStats["SmashHeros"] }) { if (!stats) return null @@ -52,6 +52,8 @@ export default function SmashHerosStats({ stats }: { stats: NonNullStats["SmashH + + ) } diff --git a/src/app/(stats)/player/[ign]/_stats/smashheros/table.tsx b/src/app/(stats)/player/[ign]/_stats/smashheros/table.tsx index d608adc..d2ba151 100644 --- a/src/app/(stats)/player/[ign]/_stats/smashheros/table.tsx +++ b/src/app/(stats)/player/[ign]/_stats/smashheros/table.tsx @@ -1,9 +1,83 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { formatNumber } from "@/lib/formatters" -import { getSmashHerosModeName, getSmashHerosModeStats, getSmashHerosMostPlayedMode } from "@/lib/hypixel/smashhero/general" +import { + getSmashHerosAllHerosStats, + getSmashHerosDifficultyColor, + getSmashHerosHero, + getSmashHerosHeroLvlPres, + getSmashHerosHeroPrestigeColor, + getSmashHerosModeName, + getSmashHerosModeStats, + getSmashHerosMostPlayedHero, + getSmashHerosMostPlayedMode +} from "@/lib/hypixel/smashhero/general" import { NonNullStats } from "@/lib/schema/player" import { cn } from "@/lib/utils" +export function SmashHerosHeroTable({ stats }: { stats: NonNullable }) { + return ( + + + +
+ ) +} + +function SmashHerosHeroTableStats({ stats }: { stats: NonNullable }) { + const heroStats = getSmashHerosAllHerosStats(stats) + return ( + + {heroStats.map((v, i) => { + const { id, nums } = v + const hero = getSmashHerosHero(id) + const difficultyColor = getSmashHerosDifficultyColor(hero.difficulty) + const mostPlayed = getSmashHerosMostPlayedHero(stats)?.id === id + const { lvl, pg: pres } = getSmashHerosHeroLvlPres(id, stats) + const presColor = getSmashHerosHeroPrestigeColor(pres) + return ( + + + {hero.name} + {" Lv"} + {lvl} + {pres > 0 && ( + + {` 【${pres}】`} + + )} + + {nums.map((n, j) => { + return {formatNumber(n)} + })} + + ) + })} + + ) +} + +function SmashHerosHeroTableHeader() { + const headerElements = [ + "Hero", + "Kills", + "Deaths", + "KD", + "Wins", + "Losses", + "WL" + ] + + return ( + + + {headerElements.map((v, i) => { + return {v} + })} + + + ) +} + export function SmashHerosModeTable({ stats }: { stats: NonNullable }) { return ( diff --git a/src/data/hypixel/smashheros.ts b/src/data/hypixel/smashheros.ts index 5134a3b..48f5701 100644 --- a/src/data/hypixel/smashheros.ts +++ b/src/data/hypixel/smashheros.ts @@ -1,7 +1,8 @@ export const MODES = [ { id: "normal", name: "1v1v1v1" }, - { id: "2v2", name: "2v2" }, + { id: "teams", name: "2v2v2v2" }, { id: "teams", name: "2v2v2" }, + { id: "2v2", name: "2v2" }, { id: "", name: "Overall" } ] as const export const HEROES = [ diff --git a/src/lib/hypixel/smashhero/general.ts b/src/lib/hypixel/smashhero/general.ts index 92ae11c..57af442 100644 --- a/src/lib/hypixel/smashhero/general.ts +++ b/src/lib/hypixel/smashhero/general.ts @@ -1,7 +1,50 @@ -import { DIFFICULTY, HEROES, MODES } from "@/data/hypixel/smashheros" +import { DIFFICULTY, HEROES, MODES, PRESTIGECOLORS } from "@/data/hypixel/smashheros" import { NonNullStats } from "@/lib/schema/player" import { devide } from "../general" +export function getSmashHerosHeroPrestigeColor(pres: number) { + if (pres < 1) return PRESTIGECOLORS.at(0)! + if (pres > PRESTIGECOLORS.length) return PRESTIGECOLORS.at(0)! + + return PRESTIGECOLORS.at(pres - 1)! +} + +export function getSmashHerosHeroLvlPres(heroId: typeof HEROES[number]["id"], stats: NonNullable) { + return { + lvl: stats[`lastLevel_${heroId}`], + pg: stats[`pg_${heroId}`] + } +} + +export function getSmashHerosHero(heroId: typeof HEROES[number]["id"]) { + return HEROES.find(h => h.id === heroId)! +} + +export function getSmashHerosAllHerosStats(stats: NonNullable) { + const vals: { id: typeof HEROES[number]["id"], nums: number[] }[] = [] + + for (const hero of HEROES) { + vals.push({ id: hero.id, nums: getSmashHerosHeroStats(hero.id, stats) }) + } + + return vals +} + +export function getSmashHerosHeroStats(heroId: typeof HEROES[number]["id"], stats: NonNullable) { + if (!stats.class_stats) return [0, 0, 0, 0, 0, 0] + + const cStats = stats.class_stats[heroId] + + return [ + cStats?.kills || 0, + cStats?.deaths || 0, + devide(cStats?.kills || 0, cStats?.deaths || 0), + cStats?.wins || 0, + cStats?.losses || 0, + devide(cStats?.wins || 0, cStats?.losses || 0) + ] +} + export function getSmashHerosModeName(modeId: Exclude | "all") { if (modeId === "all") return MODES.find(m => m.id === "")!.name return MODES.find(m => m.id === modeId)!.name diff --git a/src/lib/schema/stats/smashheros.ts b/src/lib/schema/stats/smashheros.ts index 0c1332d..ddb36ab 100644 --- a/src/lib/schema/stats/smashheros.ts +++ b/src/lib/schema/stats/smashheros.ts @@ -1,7 +1,11 @@ import z from "zod" const classStats = z.object({ - games: z.number().default(0) + games: z.number().default(0), + kills: z.number().default(0), + deaths: z.number().default(0), + wins: z.number().default(0), + losses: z.number().default(0) }).optional() export const smashHerosStats = z.object({ @@ -30,6 +34,38 @@ export const smashHerosStats = z.object({ TINMAN: classStats, DUSK_CRAWLER: classStats }).optional(), + lastLevel_BOTMUN: z.number().default(0), + lastLevel_THE_BULK: z.number().default(0), + lastLevel_CAKE_MONSTER: z.number().default(0), + lastLevel_FROSTY: z.number().default(0), + lastLevel_GENERAL_CLUCK: z.number().default(0), + lastLevel_GREEN_HOOD: z.number().default(0), + lastLevel_GOKU: z.number().default(0), + lastLevel_MARAUDER: z.number().default(0), + lastLevel_PUG: z.number().default(0), + lastLevel_SANIC: z.number().default(0), + lastLevel_SERGEANT_SHIELD: z.number().default(0), + lastLevel_SHOOP_DA_WHOOP: z.number().default(0), + lastLevel_SKULLFIRE: z.number().default(0), + lastLevel_SPODERMAN: z.number().default(0), + lastLevel_TINMAN: z.number().default(0), + lastLevel_DUSK_CRAWLER: z.number().default(0), + pg_BOTMUN: z.number().default(0), + pg_THE_BULK: z.number().default(0), + pg_CAKE_MONSTER: z.number().default(0), + pg_FROSTY: z.number().default(0), + pg_GENERAL_CLUCK: z.number().default(0), + pg_GREEN_HOOD: z.number().default(0), + pg_GOKU: z.number().default(0), + pg_MARAUDER: z.number().default(0), + pg_PUG: z.number().default(0), + pg_SANIC: z.number().default(0), + pg_SERGEANT_SHIELD: z.number().default(0), + pg_SHOOP_DA_WHOOP: z.number().default(0), + pg_SKULLFIRE: z.number().default(0), + pg_SPODERMAN: z.number().default(0), + pg_TINMAN: z.number().default(0), + pg_DUSK_CRAWLER: z.number().default(0), kills_normal: z.number().default(0), deaths_normal: z.number().default(0), wins_normal: z.number().default(0),