From 33d02113da510ae3cc647d00d6d3d98a82d22aee Mon Sep 17 00:00:00 2001 From: Taken Date: Sun, 7 Sep 2025 11:36:19 +0200 Subject: [PATCH] Added mega walls card --- .../[ign]/_stats/megawalls/megawalls.tsx | 64 +++++++++++++++++++ src/app/(stats)/player/[ign]/page.tsx | 2 + src/data/hypixel/megawalls.ts | 40 ++++++++++++ src/lib/hypixel/megawalls/general.ts | 24 +++++++ src/lib/schema/player.ts | 9 ++- src/lib/schema/stats.ts | 57 +++++++++++++++++ 6 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 src/app/(stats)/player/[ign]/_stats/megawalls/megawalls.tsx create mode 100644 src/data/hypixel/megawalls.ts create mode 100644 src/lib/hypixel/megawalls/general.ts diff --git a/src/app/(stats)/player/[ign]/_stats/megawalls/megawalls.tsx b/src/app/(stats)/player/[ign]/_stats/megawalls/megawalls.tsx new file mode 100644 index 0000000..41f58fd --- /dev/null +++ b/src/app/(stats)/player/[ign]/_stats/megawalls/megawalls.tsx @@ -0,0 +1,64 @@ +import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" +import { Card, CardContent } from "@/components/ui/card" +import { Separator } from "@/components/ui/separator" +import { formatNumber } from "@/lib/formatters" +import { devide } from "@/lib/hypixel/general" +import { getDifficultyColor, getMostPlayed } from "@/lib/hypixel/megawalls/general" +import { NonNullStats } from "@/lib/schema/player" +import { cn } from "@/lib/utils" +import CollapsedStats from "../../_components/CollapsedStats" + +export default function MegaWallsStats({ stats }: { stats: NonNullStats["MegaWalls"] }) { + if (!stats) return null + + const kd = formatNumber(devide(stats.kills, stats.deaths)) + const fkd = formatNumber(devide(stats.final_kills, stats.final_deaths)) + const wl = formatNumber(devide(stats.wins, stats.losses)) + const mostPlayed = getMostPlayed(stats) + const difficultyColor = getDifficultyColor(mostPlayed !== null ? mostPlayed.difficulty : 1) + + return ( + + + + +

Mega Walls

+
+ Main

, + stat: ( +

+ {mostPlayed !== null ? mostPlayed.name : "Unknown"} +

+ ) + }, + { + title:

KD

, + stat:

{kd}

+ }, + { + title:

FKD

, + stat:

{fkd}

+ }, + { + title:

Wins

, + stat:

{formatNumber(stats.wins)}

+ }, + { + title:

WL

, + stat:

{wl}

+ } + ]} + /> +
+
+ + + +
+
+
+ ) +} diff --git a/src/app/(stats)/player/[ign]/page.tsx b/src/app/(stats)/player/[ign]/page.tsx index efc35aa..e7667e7 100644 --- a/src/app/(stats)/player/[ign]/page.tsx +++ b/src/app/(stats)/player/[ign]/page.tsx @@ -13,6 +13,7 @@ import Sidebar from "./_components/Sidebar" import BedwarsStats from "./_stats/bedwars/bedwars" import BuildBattleStats from "./_stats/build-battle/build-battle" import DuelsStats from "./_stats/duels/duels" +import MegaWallsStats from "./_stats/megawalls/megawalls" import MurderMysteryStats from "./_stats/murder-mystery/murder-mystery" import PitStats from "./_stats/pit/pit" import SkyWarsStats from "./_stats/skywars/skywars" @@ -119,6 +120,7 @@ async function SuspendedPage({ ign: pign }: { ign: string }) { + ) : diff --git a/src/data/hypixel/megawalls.ts b/src/data/hypixel/megawalls.ts new file mode 100644 index 0000000..353bb02 --- /dev/null +++ b/src/data/hypixel/megawalls.ts @@ -0,0 +1,40 @@ +export const CLASSES = [ + { id: "angel", name: "Angel", difficulty: 3 }, + { id: "arcanist", name: "Arcanist", difficulty: 1 }, + { id: "assassin", name: "Assassin", difficulty: 2 }, + { id: "automaton", name: "Automaton", difficulty: 4 }, + { id: "blaze", name: "Blaze", difficulty: 2 }, + { id: "cow", name: "Cow", difficulty: 1 }, + { id: "creeper", name: "Creeper", difficulty: 3 }, + { id: "dragon", name: "Dragon", difficulty: 4 }, + { id: "dreadlord", name: "Dreadlord", difficulty: 1 }, + { id: "enderman", name: "Enderman", difficulty: 2 }, + { id: "golem", name: "Golem", difficulty: 1 }, + { id: "herobrine", name: "Herobrine", difficulty: 1 }, + { id: "hunter", name: "Hunter", difficulty: 2 }, + { id: "moleman", name: "Moleman", difficulty: 3 }, + { id: "phoenix", name: "Phoenix", difficulty: 3 }, + { id: "pigman", name: "Pigman", difficulty: 1 }, + { id: "pirate", name: "Pirate", difficulty: 3 }, + { id: "renegade", name: "Renegade", difficulty: 4 }, + { id: "shaman", name: "Shaman", difficulty: 2 }, + { id: "shark", name: "Shark", difficulty: 3 }, + { id: "sheep", name: "Sheep", difficulty: 3 }, + { id: "skeleton", name: "Skeleton", difficulty: 3 }, + { id: "snowman", name: "Snowman", difficulty: 4 }, + { id: "spider", name: "Spider", difficulty: 3 }, + { id: "squid", name: "Squid", difficulty: 2 }, + { id: "werewolf", name: "Werewolf", difficulty: 2 }, + { id: "zombie", name: "Zombie", difficulty: 1 } +] as const +export const DIFFICULTIES = { + 1: "green", + 2: "yellow", + 3: "red", + 4: "dark-red" +} as const +export const MODES = [ + { id: "standard", name: "Normal" }, + { id: "face_off", name: "Face Off" }, + { id: "gvg", name: "Casual Brawl" } +] as const diff --git a/src/lib/hypixel/megawalls/general.ts b/src/lib/hypixel/megawalls/general.ts new file mode 100644 index 0000000..f49ec5d --- /dev/null +++ b/src/lib/hypixel/megawalls/general.ts @@ -0,0 +1,24 @@ +import { CLASSES, DIFFICULTIES } from "@/data/hypixel/megawalls" +import { NonNullStats } from "@/lib/schema/player" + +export function getMostPlayed(stats: NonNullable) { + let mostPlayedClass: typeof CLASSES[number] | null = null + let maxPlays = 0 + + for (const classObj of CLASSES) { + const wins = stats[`${classObj.id}_wins`] || 0 + const losses = stats[`${classObj.id}_losses`] || 0 + const totalPlays = wins + losses + + if (totalPlays > maxPlays) { + maxPlays = totalPlays + mostPlayedClass = classObj + } + } + + return mostPlayedClass +} + +export function getDifficultyColor(val: 1 | 2 | 3 | 4) { + return DIFFICULTIES[val] +} diff --git a/src/lib/schema/player.ts b/src/lib/schema/player.ts index d9a1d14..83e48ab 100644 --- a/src/lib/schema/player.ts +++ b/src/lib/schema/player.ts @@ -3,6 +3,7 @@ import { bedwarsStatsSchema, buildBattleStatsSchema, duelsStatsSchema, + megawallsStats, murderMysteryStatsSchema, pitStats, skywarsStatsSchema, @@ -30,7 +31,13 @@ export const playerSchema = z.looseObject({ BuildBattle: buildBattleStatsSchema.optional(), UHC: uhcSchema.optional(), Pit: pitStats.optional(), - TNTGames: tntGamesStatsSchema.optional() + TNTGames: tntGamesStatsSchema.optional(), + Walls3: megawallsStats.optional() + }).transform(({ Walls3, ...rest }) => { + return { + MegaWalls: Walls3, + ...rest + } }).optional(), quests: z.record( z.string(), diff --git a/src/lib/schema/stats.ts b/src/lib/schema/stats.ts index 064b975..a0574ae 100644 --- a/src/lib/schema/stats.ts +++ b/src/lib/schema/stats.ts @@ -553,3 +553,60 @@ export const tntGamesStatsSchema = z.looseObject({ deaths_capture: z.number().default(0), ...tntGamesModeStats() }) + +function megawallsModeStats() { + const ids = [ + "angel", + "arcanist", + "assassin", + "automaton", + "blaze", + "cow", + "creeper", + "dragon", + "dreadlord", + "enderman", + "golem", + "herobrine", + "hunter", + "moleman", + "phoenix", + "pigman", + "pirate", + "renegade", + "shaman", + "shark", + "sheep", + "skeleton", + "snowman", + "spider", + "squid", + "werewolf", + "zombie" + ] as const + + const stats = [ + "wins", + "losses" + ] as const + + const entries = new Map>() + + for (const id of ids) { + for (const stat of stats) { + entries.set(`${id}_${stat}`, z.number().default(0)) + } + } + + return Object.fromEntries(entries) as Record<`${typeof ids[number]}_${typeof stats[number]}`, z.ZodDefault> +} + +export const megawallsStats = z.looseObject({ + kills: z.number().default(0), + deaths: z.number().default(0), + wins: z.number().default(0), + losses: z.number().default(0), + final_kills: z.number().default(0), + final_deaths: z.number().default(0), + ...megawallsModeStats() +})