Added warlords stats card

This commit is contained in:
2025-09-18 20:08:49 +02:00
parent 045cbe54ca
commit 0e08c1ab1d
7 changed files with 254 additions and 3 deletions

View File

@@ -26,6 +26,7 @@ import SmashHerosStats from "./_stats/smashheros/smashheros"
import SpeedUHCStats from "./_stats/speeduhc/speeduhc" import SpeedUHCStats from "./_stats/speeduhc/speeduhc"
import TNTGamesStats from "./_stats/tnt-games/tnt-games" import TNTGamesStats from "./_stats/tnt-games/tnt-games"
import UHCStats from "./_stats/uhc/uhc" import UHCStats from "./_stats/uhc/uhc"
import WarlordsStats from "./_stats/warlords/warlords"
import WoolGamesStats from "./_stats/woolgames/woolgames" import WoolGamesStats from "./_stats/woolgames/woolgames"
export function PlayerPageLoadText() { export function PlayerPageLoadText() {
@@ -96,7 +97,8 @@ export function PlayerStats(
"blitz": <BlitzStats stats={stats.Blitz} />, "blitz": <BlitzStats stats={stats.Blitz} />,
"arcade": <ArcadeStats stats={stats.Arcade} />, "arcade": <ArcadeStats stats={stats.Arcade} />,
"speeduhc": <SpeedUHCStats stats={stats.SpeedUHC} uhcCoins={stats.UHC?.coins} />, "speeduhc": <SpeedUHCStats stats={stats.SpeedUHC} uhcCoins={stats.UHC?.coins} />,
"smashheros": <SmashHerosStats stats={stats.SmashHeros} /> "smashheros": <SmashHerosStats stats={stats.SmashHeros} />,
"warlords": <WarlordsStats stats={stats.Warlords} />
} as const } as const
const defaultOrder = Object.keys(statsComponents) const defaultOrder = Object.keys(statsComponents)

View File

@@ -0,0 +1,39 @@
import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general"
import { getWarlordsLosses } from "@/lib/hypixel/warlords/general"
import { NonNullStats } from "@/lib/schema/player"
import { BasicStat } from "../../_components/Stats"
export default function WarlordsGeneralStats({ stats }: { stats: NonNullable<NonNullStats["Warlords"]> }) {
const losses = getWarlordsLosses(stats)
const wl = formatNumber(devide(stats.wins, losses))
const kd = formatNumber(devide(stats.kills, stats.deaths))
const ak = formatNumber(devide(stats.assists, stats.kills))
return (
<div className="flex">
<div className="flex-1">
<BasicStat title="Coins: " value={formatNumber(stats.coins)} className="text-mc-gold" />
<BasicStat title="Magic Dust: " value={formatNumber(stats.magic_dust)} className="text-mc-aqua" />
<BasicStat title="Void Shards: " value={formatNumber(stats.void_shards)} className="text-mc-light-purple" />
<p>
<br />
</p>
<BasicStat title="Wins: " value={formatNumber(stats.wins)} />
<BasicStat title="Losses: " value={formatNumber(losses)} />
<BasicStat title="Win/Loss Ratio: " value={wl} />
</div>
<div className="flex-1">
<BasicStat title="Kills: " value={formatNumber(stats.kills)} />
<BasicStat title="Assists: " value={formatNumber(stats.assists)} />
<BasicStat title="Assist/Kill Ratio: " value={ak} />
<BasicStat title="Deaths: " value={formatNumber(stats.deaths)} />
<BasicStat title="Kill/Death Ratio: " value={kd} />
<p>
<br />
</p>
<BasicStat title="Flags Captured: " value={formatNumber(stats.flag_conquer_self)} />
<BasicStat title="Flags Returned: " value={formatNumber(stats.flag_returns)} />
</div>
</div>
)
}

View File

@@ -0,0 +1,44 @@
import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general"
import { getWarlordsLosses, getWarlordsMostPlayedClass } from "@/lib/hypixel/warlords/general"
import { NonNullStats } from "@/lib/schema/player"
import GeneralStats from "../GeneralStats"
import WarlordsGeneralStats from "./stats"
export default function WarlordsStats({ stats }: { stats: NonNullStats["Warlords"] }) {
if (!stats) return null
const losses = getWarlordsLosses(stats)
const kd = formatNumber(devide(stats.kills, stats.deaths))
const wl = formatNumber(devide(stats.wins, losses))
const mostPlayed = getWarlordsMostPlayedClass(stats)
return (
<GeneralStats
id="warlords"
title="Warlords"
collapsedStats={[
{
title: <p>Main</p>,
stat: <p className="text-mc-gold">{mostPlayed !== null ? mostPlayed.name : "Unknown"}</p>
},
{
title: <p>KD</p>,
stat: <p className="text-muted-foreground">{kd}</p>
},
{
title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
},
{
title: <p>WL</p>,
stat: <p className="text-muted-foreground">{wl}</p>
}
]}
>
<Separator className="my-4" />
<WarlordsGeneralStats stats={stats} />
</GeneralStats>
)
}

View File

@@ -0,0 +1,114 @@
export const CLASSES = [
{ id: "mage", name: "Mage" },
{ id: "paladin", name: "Paladin" },
{ id: "shaman", name: "Shaman" },
{ id: "warrior", name: "Warrior" },
{ id: "", name: "Overall" }
] as const
export const MODES = [
{ id: "capturetheflag", name: "Capture the Flag" },
{ id: "domination", name: "Domination" },
{ id: "teamdeathmatch", name: "Team Deathmatch" },
{ id: "", name: "Overall" }
] as const
export const RARITIES = [
{ id: "common", name: "Common", color: "green" },
{ id: "rare", name: "Rare", color: "blue" },
{ id: "epic", name: "Epic", color: "purple" },
{ id: "legendary", name: "Legendary", color: "gold" }
] as const
export const UPGRADES = [
{ id: "cooldown", name: "Cooldown" },
{ id: "critchance", name: "Crit Chance" },
{ id: "critmultiplier", name: "Crit Multiplier" },
{ id: "energy", name: "Energy" },
{ id: "health", name: "Health" },
{ id: "skill1", name: "First Skill" },
{ id: "skill2", name: "Second Skill" },
{ id: "skill3", name: "Third Skill" },
{ id: "skill4", name: "Fourth Skill" },
{ id: "skill5", name: "Ultimate SKill" }
] as const
export const MATERIALS = {
"WOOD_AXE": "Steel Sword",
"STONE_AXE": "Training Sword",
"IRON_AXE": "Demonblade",
"GOLD_AXE": "Venomstrike",
"DIAMOND_AXE": "Diamondspark",
"WOOD_HOE": "Zweireaper",
"STONE_HOE": "Runeblade",
"IRON_HOE": "Elven Greatsword",
"GOLD_HOE": "Hatchet",
"DIAMOND_HOE": "Gem Axe",
"WOOD_SPADE": "Nomegusta",
"STONE_SPADE": "Drakefang",
"IRON_SPADE": "Hammer",
"GOLD_SPADE": "Stone Mallet",
"DIAMOND_SPADE": "Gemcrusher",
"WOOD_PICKAXE": "Abbadon",
"STONE_PICKAXE": "Walking Stick",
"IRON_PICKAXE": "World Tree Branch",
"GOLD_PICKAXE": "Flameweaver",
"DIAMOND_PICKAXE": "Void Twig",
"SALMON": "Scimitar",
"PUFFERFISH": "Golden Gladius",
"CLOWNFISH": "Magmasword",
"COD": "Frostbite",
"ROTTEN_FLESH": "Pike",
"POTATO": "Halberd",
"MELON": "Divine Reach",
"POISONOUS_POTATO": "Ruby Thorn",
"STRING": "Hammer of Light",
"RAW_CHICKEN": "Nethersteel Katana",
"MUTTON": "Claws",
"PORK": "Mandibles",
"RAW_BEEF": "Katar",
"APPLE": "Enderfist",
"PUMPKIN_PIE": "Orc Axe",
"COOKED_COD": "Doubleaxe",
"BREAD": "Runic Axe",
"MUSHROOM_STEW": "Lunar Relic",
"RABBIT_STEW": "Bludgeon",
"COOKED_RABBIT": "Cudgel",
"COOKED_CHICKEN": "Tenderizer",
"BAKED_POTATO": "Broccomace",
"COOKED_SALMON": "Felflame Blade",
"COOKED_MUTTON": "Amaranth",
"COOKED_BEEF": "Armblade",
"GRILLED_PORK": "Gemini",
"COOKED_PORKCHOP": "Gemini",
"GOLDEN_CARROT": "Void Edge"
} as const
export const PLAYERCLASSES = {
mage: ["Pyromancer", "Cryomancer", "Aquamancer"],
warrior: ["Berserker", "Defender", "Revenant"],
paladin: ["Avenger", "Crusader", "Protector"],
shaman: ["Thunderlord", "Earthwarden", "Spiritguard"]
} as const
export const SCORES = {
COMMON: [
{ score: 276, prefix: "Crumbly" },
{ score: 302, prefix: "Flimsy" },
{ score: 327, prefix: "Rough" },
{ score: 352, prefix: "Honed" },
{ score: 378, prefix: "Refined" },
{ score: 403, prefix: "Balanced" }
],
RARE: [
{ score: 359, prefix: "Savage" },
{ score: 400, prefix: "Vicious" },
{ score: 440, prefix: "Deadly" },
{ score: 481, prefix: "Perfect" }
],
EPIC: [
{ score: 450, prefix: "Fierce" },
{ score: 489, prefix: "Mighty" },
{ score: 527, prefix: "Brutal" },
{ score: 566, prefix: "Gladiator's" }
],
LEGENDARY: [
{ score: 595, prefix: "Vanquisher's" },
{ score: 665, prefix: "Champion's" },
{ score: 735, prefix: "Warlord's" }
]
} as const

View File

@@ -0,0 +1,24 @@
import { CLASSES } from "@/data/hypixel/warlords"
import { NonNullStats } from "@/lib/schema/player"
export function getWarlordsLosses(stats: NonNullable<NonNullStats["Warlords"]>) {
return stats.mage_plays + stats.paladin_plays + stats.shaman_plays + stats.warrior_plays - stats.wins
}
export function getWarlordsMostPlayedClass(stats: NonNullable<NonNullStats["Warlords"]>) {
let mostPlayedClass: typeof CLASSES[number] | null = null
let maxPlays = 0
for (const classObj of CLASSES) {
if (classObj.id === "") continue
const plays = stats[`${classObj.id}_plays`]
if (plays > maxPlays) {
maxPlays = plays
mostPlayedClass = classObj
}
}
return mostPlayedClass
}

View File

@@ -13,6 +13,7 @@ import { smashHerosStats } from "./stats/smashheros"
import { speedUhcStatsSchema } from "./stats/speeduhc" import { speedUhcStatsSchema } from "./stats/speeduhc"
import { tntGamesStatsSchema } from "./stats/tnt-games" import { tntGamesStatsSchema } from "./stats/tnt-games"
import { uhcSchema } from "./stats/uhc" import { uhcSchema } from "./stats/uhc"
import { warlordsStatsSchema } from "./stats/warlords"
import { woolGamesStatsSchema } from "./stats/woolgames" import { woolGamesStatsSchema } from "./stats/woolgames"
export const playerSchema = z.looseObject({ export const playerSchema = z.looseObject({
@@ -42,13 +43,15 @@ export const playerSchema = z.looseObject({
HungerGames: blitzStatsSchema.optional(), HungerGames: blitzStatsSchema.optional(),
Arcade: arcadeStatsSchema.optional(), Arcade: arcadeStatsSchema.optional(),
SpeedUHC: speedUhcStatsSchema.optional(), SpeedUHC: speedUhcStatsSchema.optional(),
SuperSmash: smashHerosStats.optional() SuperSmash: smashHerosStats.optional(),
}).transform(({ Walls3, MCGO, HungerGames, SuperSmash, ...rest }) => { Battleground: warlordsStatsSchema.optional()
}).transform(({ Walls3, MCGO, HungerGames, SuperSmash, Battleground, ...rest }) => {
return { return {
MegaWalls: Walls3, MegaWalls: Walls3,
CopsAndCrims: MCGO, CopsAndCrims: MCGO,
Blitz: HungerGames, Blitz: HungerGames,
SmashHeros: SuperSmash, SmashHeros: SuperSmash,
Warlords: Battleground,
...rest ...rest
} }
}).optional(), }).optional(),

View File

@@ -0,0 +1,25 @@
import z from "zod"
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),
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)
})