Added warlords class stats table

This commit is contained in:
2025-09-19 12:08:29 +02:00
parent 5609fe2ba3
commit 6ce2775058
5 changed files with 179 additions and 27 deletions

View File

@@ -10,7 +10,7 @@ import { CSS } from "@dnd-kit/utilities"
import Cookies from "js-cookie"
import { GripVertical } from "lucide-react"
import { usePathname } from "next/navigation"
import { useEffect, useMemo, useState } from "react"
import { useEffect, useRef, useState } from "react"
import ArcadeStats from "./_stats/arcade/arcade"
import BedwarsStats from "./_stats/bedwars/bedwars"
@@ -114,17 +114,14 @@ export function PlayerStats(
})
)
const cookieOpts = useMemo(() => {
const cookieOpts: Parameters<typeof Cookies.set>[2] = {
const cookieOpts = useRef<Parameters<typeof Cookies.set>[2]>({
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
expires: 365
}
return cookieOpts
}, [])
})
function updateStatsOrder(arr: string[]) {
Cookies.set(COOKIE_VALUES.statsOrder, JSON.stringify(arr), cookieOpts)
Cookies.set(COOKIE_VALUES.statsOrder, JSON.stringify(arr), cookieOpts.current)
}
function handleDragEnd(event: DragEndEvent) {
@@ -147,7 +144,7 @@ export function PlayerStats(
}
const cookie = Cookies.get(COOKIE_VALUES.statsOrder)
if (cookie) {
Cookies.set(COOKIE_VALUES.statsOrder, cookie, cookieOpts)
Cookies.set(COOKIE_VALUES.statsOrder, cookie, cookieOpts.current)
}
}, [layout, cookieOpts])

View File

@@ -1,9 +1,82 @@
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { formatNumber } from "@/lib/formatters"
import { getWarlordsModeName, getWarlordsModeStats, getWarlordsMostPlayedMode } from "@/lib/hypixel/warlords/general"
import {
getWarlordsClassLevel,
getWarlordsClassName,
getWarlordsClassStats,
getWarlordsModeName,
getWarlordsModeStats,
getWarlordsMostPlayedClass,
getWarlordsMostPlayedMode
} from "@/lib/hypixel/warlords/general"
import { NonNullStats } from "@/lib/schema/player"
import { cn } from "@/lib/utils"
export function WarlordsClassStatsTable({ stats }: { stats: NonNullable<NonNullStats["Warlords"]> }) {
return (
<Table>
<WarlordsClassStatsTableHeader />
<TableBody>
<WarlordsClassStatsTableStat classId="mage" stats={stats} />
<WarlordsClassStatsTableStat classId="paladin" stats={stats} />
<WarlordsClassStatsTableStat classId="shaman" stats={stats} />
<WarlordsClassStatsTableStat classId="warrior" stats={stats} />
<WarlordsClassStatsTableStat classId="all" stats={stats} />
</TableBody>
</Table>
)
}
function WarlordsClassStatsTableStat(
{ classId, stats }: { classId: Parameters<typeof getWarlordsClassStats>[0], stats: NonNullable<NonNullStats["Warlords"]> }
) {
const classStats = getWarlordsClassStats(classId, stats)
const klassName = getWarlordsClassName(classId)
const mostPlayed = getWarlordsMostPlayedClass(stats)?.id === classId
return (
<TableRow className={cn(mostPlayed && "text-mc-light-purple")}>
{classId === "all" ?
(
<TableCell>
{klassName}
</TableCell>
)
: (
<TableCell>
<span className="text-mc-gray">{`Lv ${getWarlordsClassLevel(classId, stats)} `}</span>
<span className="text-mc-gold">{klassName}</span>
</TableCell>
)}
{classStats.map((v, i) => {
return <TableCell key={i}>{formatNumber(v)}</TableCell>
})}
</TableRow>
)
}
function WarlordsClassStatsTableHeader() {
const headerElements = [
"Class",
"Damage",
"Damage Prevented",
"Healing",
"Wins",
"Losses",
"WL"
]
return (
<TableHeader>
<TableRow>
{headerElements.map((v, i) => {
return <TableHead key={i} className="font-bold">{v}</TableHead>
})}
</TableRow>
</TableHeader>
)
}
export function WarlordsModeStatsTable({ stats }: { stats: NonNullable<NonNullStats["Warlords"]> }) {
return (
<Table>

View File

@@ -6,7 +6,7 @@ import { NonNullStats } from "@/lib/schema/player"
import GeneralStats from "../GeneralStats"
import { WarlordsWeaponsBar } from "./client"
import WarlordsGeneralStats from "./stats"
import { WarlordsModeStatsTable } from "./table"
import { WarlordsClassStatsTable, WarlordsModeStatsTable } from "./table"
export default function WarlordsStats({ stats }: { stats: NonNullStats["Warlords"] }) {
if (!stats) return null
@@ -44,6 +44,8 @@ export default function WarlordsStats({ stats }: { stats: NonNullStats["Warlords
<Separator className="my-4" />
<WarlordsWeaponsBar stats={stats} />
<Separator className="my-4" />
<WarlordsClassStatsTable stats={stats} />
<Separator className="my-4" />
<WarlordsModeStatsTable stats={stats} />
<Separator className="my-4" />
</GeneralStats>

View File

@@ -1,5 +1,45 @@
import { CLASSES, MODES, RARITIES } from "@/data/hypixel/warlords"
import { CLASSES, MODES, RARITIES, UPGRADES } from "@/data/hypixel/warlords"
import { NonNullStats } from "@/lib/schema/player"
import { devide } from "../general"
export function getWarlordsClassLevel(classId: Exclude<typeof CLASSES[number]["id"], "">, stats: NonNullable<NonNullStats["Warlords"]>) {
let level = 0
for (const upgrade of UPGRADES) {
level += stats[`${classId}_${upgrade.id}`]
}
return level
}
export function getWarlordsClassName(classId: Exclude<typeof CLASSES[number]["id"], ""> | "all") {
if (classId === "all") return CLASSES.find(c => c.id === "")!.name
return CLASSES.find(c => c.id === classId)!.name
}
export function getWarlordsClassStats(classId: Exclude<typeof CLASSES[number]["id"], ""> | "all", stats: NonNullable<NonNullStats["Warlords"]>) {
const losses = getWarlordsLosses(stats)
if (classId === "all") {
return [
stats.damage,
stats.damage_prevented,
stats.heal,
stats.wins,
losses,
devide(stats.wins, losses)
]
}
return [
stats[`damage_${classId}`],
stats[`damage_prevented_${classId}`],
stats[`heal_${classId}`],
stats[`wins_${classId}`],
stats[`${classId}_plays`] - stats[`wins_${classId}`],
devide(stats[`${classId}_plays`] - stats[`wins_${classId}`], stats[`wins_${classId}`])
]
}
export function getWarlordsModeName(modeId: Exclude<typeof MODES[number]["id"], ""> | "all") {
if (modeId === "all") {

View File

@@ -1,27 +1,65 @@
import z from "zod"
function warlordsClassStats() {
const ids = [
"mage",
"paladin",
"shaman",
"warrior"
] as const
const stats = [
"cooldown",
"critchance",
"critmultiplier",
"energy",
"health",
"skill1",
"skill2",
"skill3",
"skill4",
"skill5",
"wins",
"losses",
"plays"
] as const
const stats2 = [
"damage",
"damage_prevented",
"heal",
"wins"
] as const
const entries = new Map<string, z.ZodDefault<z.ZodNumber>>()
const entries2 = new Map<string, z.ZodDefault<z.ZodNumber>>()
for (const id of ids) {
for (const stat of stats) {
entries.set(`${id}_${stat}`, z.number().default(0))
}
for (const stat of stats2) {
entries2.set(`${stat}_${id}`, z.number().default(0))
}
}
return {
left_right: Object.fromEntries(entries) as Record<`${typeof ids[number]}_${typeof stats[number]}`, z.ZodDefault<z.ZodNumber>>,
right_left: Object.fromEntries(entries2) as Record<`${typeof stats2[number]}_${typeof ids[number]}`, z.ZodDefault<z.ZodNumber>>
}
}
export const warlordsStatsSchema = z.object({
kills: z.number().default(0),
assists: z.number().default(0),
deaths: z.number().default(0),
wins: z.number().default(0),
coins: z.number().default(0),
damage: z.number().default(0),
damage_prevented: z.number().default(0),
heal: z.number().default(0),
magic_dust: z.number().default(0),
void_shards: z.number().default(0),
flag_conquer_self: z.number().default(0),
flag_returns: z.number().default(0),
mage_plays: z.number().default(0),
paladin_plays: z.number().default(0),
shaman_plays: z.number().default(0),
warrior_plays: z.number().default(0),
mage_wins: z.number().default(0),
paladin_wins: z.number().default(0),
shaman_wins: z.number().default(0),
warrior_wins: z.number().default(0),
mage_losses: z.number().default(0),
paladin_losses: z.number().default(0),
shaman_losses: z.number().default(0),
warrior_losses: z.number().default(0),
repaired: z.number().default(0),
repaired_common: z.number().default(0),
repaired_rare: z.number().default(0),
@@ -32,5 +70,7 @@ export const warlordsStatsSchema = z.object({
wins_teamdeathmatch: z.number().default(0),
kills_capturetheflag: z.number().default(0),
kills_domination: z.number().default(0),
kills_teamdeathmatch: z.number().default(0)
kills_teamdeathmatch: z.number().default(0),
...warlordsClassStats().left_right,
...warlordsClassStats().right_left
})