Updated pixel party stats

This commit is contained in:
2025-09-14 20:19:10 +02:00
parent 708146786d
commit 3711b43b4e
8 changed files with 239 additions and 4 deletions

View File

@@ -1,7 +1,10 @@
import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters"
import { getArcadeTotalWins } from "@/lib/hypixel/arcade/general"
import { NonNullStats } from "@/lib/schema/player"
import { BasicStat } from "../../_components/Stats"
import GeneralStats from "../GeneralStats"
import { ArcadeMiniWallsStats, ArcadePixelPartyStats } from "./stats"
export default function ArcadeStats({ stats }: { stats: NonNullStats["Arcade"] }) {
if (!stats) return null
@@ -18,6 +21,14 @@ export default function ArcadeStats({ stats }: { stats: NonNullStats["Arcade"] }
}]}
>
<Separator className="my-4" />
<div>
<BasicStat title="Arcade Coins: " value={formatNumber(stats.coins)} className="text-mc-gold" />
</div>
<Separator className="my-4" />
<ArcadeMiniWallsStats stats={stats} />
<Separator className="my-4" />
<ArcadePixelPartyStats stats={stats} />
<Separator className="my-4" />
</GeneralStats>
)
}

View File

@@ -0,0 +1,65 @@
import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general"
import { NonNullStats } from "@/lib/schema/player"
import { capitalizeFirstLetter } from "@/lib/utils"
import { BasicStat } from "../../_components/Stats"
import { PixelPartyStatsTable } from "./table"
export function ArcadePixelPartyStats({ stats }: { stats: NonNullable<NonNullStats["Arcade"]> }) {
const losses = (stats.pixel_party?.games_played || 0) - (stats.pixel_party?.wins || 0)
const wl = formatNumber(devide(stats.pixel_party?.wins || 0, losses))
return (
<>
<h2 className="pb-5 text-xl font-bold">Pixel Party</h2>
<div className="flex pb-5">
<div className="flex-1">
<BasicStat title="Wins: " value={formatNumber(stats.pixel_party?.wins || 0)} />
<BasicStat title="Losses: " value={formatNumber(losses)} />
<BasicStat title="Win/Loss Ratio: " value={wl} />
</div>
<div className="flex-1">
<BasicStat title="Games Played: " value={formatNumber(stats.pixel_party?.games_played || 0)} />
<BasicStat title="Rounds Completed: " value={formatNumber(stats.pixel_party?.rounds_completed || 0)} />
<BasicStat title="Highest Round: " value={formatNumber(stats.pixel_party?.highest_round || 0)} />
</div>
<div className="flex-1">
<BasicStat title="Power-ups Collected: " value={formatNumber(stats.pixel_party?.power_ups_collected || 0)} />
</div>
</div>
<PixelPartyStatsTable stats={stats.pixel_party} />
</>
)
}
export function ArcadeMiniWallsStats({ stats }: { stats: NonNullable<NonNullStats["Arcade"]> }) {
const kd = formatNumber(devide(stats.kills_mini_walls + stats.final_kills_mini_walls, stats.deaths_mini_walls))
const ac = formatNumber(devide(stats.arrows_hit_mini_walls, stats.arrows_shot_mini_walls))
return (
<>
<h2 className="pb-5 text-xl font-bold">Mini Walls</h2>
<div className="flex">
<div className="flex-1">
<BasicStat title="Wins: " value={stats.wins_mini_walls} />
<BasicStat
title="Kit Seleted: "
value={stats.miniwalls_activeKit !== undefined
? capitalizeFirstLetter(stats.miniwalls_activeKit)
: "Unknown"}
/>
<BasicStat title="Withers Killed: " value={stats.wither_kills_mini_walls} />
</div>
<div className="flex-1">
<BasicStat title="Kills: " value={stats.kills_mini_walls} />
<BasicStat title="Final Kills: " value={stats.final_kills_mini_walls} />
<BasicStat title="Deaths: " value={stats.deaths_mini_walls} />
<BasicStat title="Kill/Death Ratio: " value={kd} />
</div>
<div className="flex-1">
<BasicStat title="Arrows Hit: " value={stats.arrows_hit_mini_walls} />
<BasicStat title="Arrows Shot: " value={stats.arrows_shot_mini_walls} />
<BasicStat title="Arrow Hit Accuracy: " value={ac} />
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,56 @@
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { formatNumber } from "@/lib/formatters"
import { getArcadeMostPlayedPixelPartyMode, getArcadePixelPartyModeName, getArcadePixelPartyModeStats } from "@/lib/hypixel/arcade/general"
import { NonNullStats } from "@/lib/schema/player"
import { cn } from "@/lib/utils"
export function PixelPartyStatsTable({ stats }: { stats: NonNullable<NonNullStats["Arcade"]>["pixel_party"] }) {
return (
<Table>
<PixelPartyStatsTableHeader />
<TableBody>
<PixelPartyTableStat modeId="normal" stats={stats} />
<PixelPartyTableStat modeId="hyper" stats={stats} />
<PixelPartyTableStat modeId="all_modes" stats={stats} />
</TableBody>
</Table>
)
}
function PixelPartyTableStat(
{ modeId, stats }: { modeId: Parameters<typeof getArcadePixelPartyModeStats>[0], stats: NonNullable<NonNullStats["Arcade"]>["pixel_party"] }
) {
const modeName = getArcadePixelPartyModeName(modeId)
const modeStats = getArcadePixelPartyModeStats(modeId, stats)
const mostPlayed = getArcadeMostPlayedPixelPartyMode(stats) === modeId
const isMostPlayed = modeId !== "all_modes" && mostPlayed
return (
<TableRow className={cn(modeName === "Overall" && "font-bold", isMostPlayed && "text-mc-light-purple")}>
<TableCell>{modeName}</TableCell>
{modeStats.map((v, i) => {
return <TableCell key={i}>{formatNumber(v)}</TableCell>
})}
</TableRow>
)
}
function PixelPartyStatsTableHeader() {
const headerElements = [
"Mode",
"Wins",
"Losses",
"WL",
"Games Played",
"Rounds Completed",
"Power-Ups Collected"
]
return (
<TableHeader>
<TableRow>
{headerElements.map((v, i) => <TableHead key={i} className="font-bold">{v}</TableHead>)}
</TableRow>
</TableHeader>
)
}

View File

@@ -2,6 +2,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
import { formatNumber } from "@/lib/formatters"
import { getUHCModeName, getUHCModeStats } from "@/lib/hypixel/uhc/general"
import { NonNullStats } from "@/lib/schema/player"
import { cn } from "@/lib/utils"
export default function UHCStatTable({ stats }: { stats: NonNullable<NonNullStats["UHC"]> }) {
return (
@@ -50,8 +51,8 @@ function TableStat(
const modeName = getUHCModeName(modeId === "teams" || modeId === "all_modes" ? "" : modeId)
return (
<TableRow>
<TableCell className={modeId === "all_modes" ? "font-bold" : undefined}>{modeId === "all_modes" ? "Overall" : modeName}</TableCell>
<TableRow className={cn(modeId === "all_modes" && "font-bold")}>
<TableCell>{modeId === "all_modes" ? "Overall" : modeName}</TableCell>
{modeStats.map((v, i) => {
return (
<TableCell key={i}>

View File

@@ -22,3 +22,37 @@ export const WINS = [
"wins_mini_walls",
"wins_zombies"
] as const
export const ZOMBIESMODES = [
{ id: "deadend", name: "Dead End", color: "gold" },
{ id: "badblood", name: "Bad Blood", color: "red" },
{ id: "alienarcadium", name: "Alien Arcadium", color: "pink" }
] as const
export const ZOMBIESTYPES = [
{ id: "basic", name: "Basic" },
{ id: "blaze", name: "Blaze" },
{ id: "empowered", name: "Empowered" },
{ id: "ender", name: "Ender" },
{ id: "endermite", name: "Endermite" },
{ id: "fire", name: "Fire" },
{ id: "guardian", name: "Guardian" },
{ id: "magma", name: "Magma" },
{ id: "magma_cube", name: "Magma Cube" },
{ id: "pig_zombie", name: "Pig Zombie" },
{ id: "skelefish", name: "Skelefish" },
{ id: "tnt_baby", name: "TNT Baby" },
{ id: "tnt", name: "Bombie", color: "gold" },
{ id: "inferno", name: "Inferno", color: "gold" },
{ id: "broodmother", name: "Broodmother", color: "gold" },
{ id: "king_slime", name: "King Slime", color: "red" },
{ id: "wither", name: "Wither", color: "red" },
{ id: "herobrine", name: "Herobrine", color: "red" },
{ id: "mega_blob", name: "Mega Blob", color: "pink" },
{ id: "mega_magma", name: "Mega Magma", color: "pink" },
{ id: "world_ender", name: "World Ender", color: "pink" }
] as const
export const PIXELPARTYMODES = [
{ id: "normal", name: "Normal" },
{ id: "hyper", name: "Hyper" },
{ id: "", name: "Overall" }
] as const

View File

@@ -1,5 +1,50 @@
import { WINS } from "@/data/hypixel/arcade"
import { PIXELPARTYMODES, WINS } from "@/data/hypixel/arcade"
import { NonNullStats } from "@/lib/schema/player"
import { devide } from "../general"
export function getArcadeMostPlayedPixelPartyMode(stats: NonNullable<NonNullStats["Arcade"]>["pixel_party"]) {
if (!stats) return null
const played = [
{ games: stats.games_played_normal, modeId: "normal" as const },
{ games: stats.games_played_hyper, modeId: "hyper" as const }
]
const mostPlayed = played.reduce((max, current) => current.games > max.games ? current : max)
return mostPlayed.modeId
}
export function getArcadePixelPartyModeName(modeId: Exclude<typeof PIXELPARTYMODES[number]["id"], ""> | "all_modes") {
if (modeId === "all_modes") return PIXELPARTYMODES.find(m => m.id === "")!.name
return PIXELPARTYMODES.find(m => m.id === modeId)!.name
}
export function getArcadePixelPartyModeStats(
modeId: Exclude<typeof PIXELPARTYMODES[number]["id"], ""> | "all_modes",
stats: NonNullable<NonNullStats["Arcade"]>["pixel_party"]
) {
if (!stats) return [0, 0, 0, 0, 0, 0]
if (modeId === "all_modes") {
return [
stats["wins"],
stats["games_played"] - stats["wins"],
devide(stats["wins"], stats["games_played"] - stats["wins"]),
stats["games_played"],
stats["rounds_completed"],
stats["power_ups_collected"]
]
}
return [
stats[`wins_${modeId}`],
stats[`games_played_${modeId}`] - stats[`wins_${modeId}`],
devide(stats[`wins_${modeId}`], stats[`games_played_${modeId}`] - stats[`wins_${modeId}`]),
stats[`games_played_${modeId}`],
stats[`rounds_completed_${modeId}`],
stats[`power_ups_collected_${modeId}`]
]
}
export function getArcadeTotalWins(stats: NonNullable<NonNullStats["Arcade"]>) {
let wins = 0

View File

@@ -913,9 +913,28 @@ function arcadeModeWins() {
}
export const arcadeStatsSchema = z.object({
miniwalls_activeKit: z.string().optional(),
wither_kills_mini_walls: z.number().default(0),
kills_mini_walls: z.number().default(0),
final_kills_mini_walls: z.number().default(0),
deaths_mini_walls: z.number().default(0),
arrows_hit_mini_walls: z.number().default(0),
arrows_shot_mini_walls: z.number().default(0),
coins: z.number().default(0),
pixel_party: z.object({
wins: z.number().default(0)
wins: z.number().default(0),
games_played: z.number().default(0),
rounds_completed: z.number().default(0),
highest_round: z.number().default(0),
power_ups_collected: z.number().default(0),
wins_normal: z.number().default(0),
games_played_normal: z.number().default(0),
rounds_completed_normal: z.number().default(0),
power_ups_collected_normal: z.number().default(0),
wins_hyper: z.number().default(0),
games_played_hyper: z.number().default(0),
rounds_completed_hyper: z.number().default(0),
power_ups_collected_hyper: z.number().default(0)
}).optional(),
dropper: z.object({
wins: z.number().default(0)

View File

@@ -4,3 +4,7 @@ import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function capitalizeFirstLetter(str: string) {
return str[0].toUpperCase() + str.slice(1, str.length)
}