From 0a99fa0ac0b92c7d9db09e13b5a461bcac9d0af8 Mon Sep 17 00:00:00 2001 From: Taken Date: Wed, 3 Sep 2025 22:27:23 +0200 Subject: [PATCH] Added first duel stats --- .../_stats/build-battle/build-battle.tsx | 45 +++++++++++++++++++ .../[ign]/_stats/build-battle/stats.tsx | 21 +++++++++ src/app/(stats)/player/[ign]/page.tsx | 2 + src/data/hypixel/build-battle.ts | 23 ++++++++++ src/lib/hypixel/build-battle/general.ts | 8 ++++ src/lib/schema/player.ts | 5 ++- src/lib/schema/stats.ts | 6 +++ 7 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 src/app/(stats)/player/[ign]/_stats/build-battle/build-battle.tsx create mode 100644 src/app/(stats)/player/[ign]/_stats/build-battle/stats.tsx create mode 100644 src/data/hypixel/build-battle.ts create mode 100644 src/lib/hypixel/build-battle/general.ts diff --git a/src/app/(stats)/player/[ign]/_stats/build-battle/build-battle.tsx b/src/app/(stats)/player/[ign]/_stats/build-battle/build-battle.tsx new file mode 100644 index 0000000..8ac5b16 --- /dev/null +++ b/src/app/(stats)/player/[ign]/_stats/build-battle/build-battle.tsx @@ -0,0 +1,45 @@ +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 { getBuildBattleRank } from "@/lib/hypixel/build-battle/general" +import { NonNullStats } from "@/lib/schema/player" +import CollapsedStats from "../../_components/CollapsedStats" +import BuildBattleGeneralStats from "./stats" + +export default function BuildBattleStats({ stats }: { stats: NonNullStats["BuildBattle"] }) { + if (!stats) return null + + const rank = getBuildBattleRank(stats.score) + + return ( + + + + +

Build Battle

+
+ Title

, + stat:

{rank.name}

+ }, + { + title:

Wins

, + stat:

{formatNumber(stats.wins)}

+ } + ]} + /> +
+
+ + + + + +
+
+
+ ) +} diff --git a/src/app/(stats)/player/[ign]/_stats/build-battle/stats.tsx b/src/app/(stats)/player/[ign]/_stats/build-battle/stats.tsx new file mode 100644 index 0000000..1b78174 --- /dev/null +++ b/src/app/(stats)/player/[ign]/_stats/build-battle/stats.tsx @@ -0,0 +1,21 @@ +import { formatNumber } from "@/lib/formatters" +import { getBuildBattleRank } from "@/lib/hypixel/build-battle/general" +import { NonNullStats } from "@/lib/schema/player" +import { BasicStat } from "../../_components/Stats" + +export default function BuildBattleGeneralStats({ stats }: { stats: NonNullable }) { + const rank = getBuildBattleRank(stats.score) + return ( +
+
+ + + +
+
+
+
+
+
+ ) +} diff --git a/src/app/(stats)/player/[ign]/page.tsx b/src/app/(stats)/player/[ign]/page.tsx index d2b6ba7..ee50cf6 100644 --- a/src/app/(stats)/player/[ign]/page.tsx +++ b/src/app/(stats)/player/[ign]/page.tsx @@ -10,6 +10,7 @@ import { Metadata } from "next" import { Suspense } from "react" 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 MurderMysteryStats from "./_stats/murder-mystery/murder-mystery" import SkyWarsStats from "./_stats/skywars/skywars" @@ -98,6 +99,7 @@ async function SuspendedPage({ ign: pign }: { ign: string }) { /> + ) : diff --git a/src/data/hypixel/build-battle.ts b/src/data/hypixel/build-battle.ts new file mode 100644 index 0000000..34c4a50 --- /dev/null +++ b/src/data/hypixel/build-battle.ts @@ -0,0 +1,23 @@ +export const TITLE = "Build Battle" as const +export const MODES = [ + { id: "_solo_normal", name: "Solo" }, + { id: "_teams_normal", name: "Teams" }, + { id: "_guess_the_build", name: "Guess the Build" }, + { id: "_solo_pro", name: "Pro" }, + { id: "_speed_builders", name: "Speed Builders" }, + { id: "", name: "Overall" } +] as const +export const STARS = [ + { value: 0, name: "Rookie", color: "white" }, + { value: 100, name: "Untrained", color: "gray" }, + { value: 250, name: "Amateur", color: "yellow" }, + { value: 500, name: "Apprentice", color: "green" }, + { value: 1000, name: "Experienced", color: "light-purple" }, + { value: 2000, name: "Seasoned", color: "blue" }, + { value: 3500, name: "Trained", color: "dark-green" }, + { value: 5000, name: "Skilled", color: "dark-aqua" }, + { value: 7500, name: "Talented", color: "red" }, + { value: 10000, name: "Professional", color: "dark-purple" }, + { value: 15000, name: "Expert", color: "dark-blue" }, + { value: 20000, name: "Master", color: "dark-red" } +] as const diff --git a/src/lib/hypixel/build-battle/general.ts b/src/lib/hypixel/build-battle/general.ts new file mode 100644 index 0000000..930a85d --- /dev/null +++ b/src/lib/hypixel/build-battle/general.ts @@ -0,0 +1,8 @@ +import { STARS } from "@/data/hypixel/build-battle" + +export function getBuildBattleRank(score: number) { + for (let i = STARS.length - 1; i >= 0; i--) { + if (score >= STARS[i].value) return STARS[i] + } + return STARS[0] +} diff --git a/src/lib/schema/player.ts b/src/lib/schema/player.ts index 34a4004..7b180fa 100644 --- a/src/lib/schema/player.ts +++ b/src/lib/schema/player.ts @@ -1,5 +1,5 @@ import z from "zod" -import { bedwarsStatsSchema, duelsStatsSchema, murderMysteryStatsSchema, skywarsStatsSchema } from "./stats" +import { bedwarsStatsSchema, buildBattleStatsSchema, duelsStatsSchema, murderMysteryStatsSchema, skywarsStatsSchema } from "./stats" export const playerSchema = z.looseObject({ player: z.looseObject({ @@ -17,7 +17,8 @@ export const playerSchema = z.looseObject({ Bedwars: bedwarsStatsSchema.optional(), SkyWars: skywarsStatsSchema.optional(), Duels: duelsStatsSchema.optional(), - MurderMystery: murderMysteryStatsSchema.optional() + MurderMystery: murderMysteryStatsSchema.optional(), + BuildBattle: buildBattleStatsSchema.optional() }).optional(), quests: z.record( z.string(), diff --git a/src/lib/schema/stats.ts b/src/lib/schema/stats.ts index a254e1d..34b3f2f 100644 --- a/src/lib/schema/stats.ts +++ b/src/lib/schema/stats.ts @@ -385,3 +385,9 @@ export const murderMysteryStatsSchema = z.looseObject({ coins_pickedup_MURDER_INFECTION: z.number().default(0), ...murderMysteryModeStats() }) + +export const buildBattleStatsSchema = z.looseObject({ + wins: z.number().default(0), + score: z.number().default(0), + coins: z.number().default(0) +})