Finished uhc genereal stats

This commit is contained in:
2025-09-04 22:25:57 +02:00
parent 1646cb7492
commit 27a8e89d7b
5 changed files with 138 additions and 11 deletions

View File

@@ -0,0 +1,33 @@
import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general"
import { getUhcStar } from "@/lib/hypixel/uhc/level"
import { NonNullStats } from "@/lib/schema/player"
import { BasicStat } from "../../_components/Stats"
export default function UHCGeneralStats(
{ stats, kills, deaths, wins, heads }: { stats: NonNullable<NonNullStats["UHC"]>, kills: number, deaths: number, wins: number, heads: number }
) {
const rank = getUhcStar(stats.score)
const kd = formatNumber(devide(kills, deaths))
const kw = formatNumber(devide(kills, wins))
return (
<div className="flex">
<div className="flex-1">
<BasicStat title="Score: " value={formatNumber(stats.score)} />
<BasicStat title="Title: " value={rank.name} className={`font-bold text-mc-${rank.color}`} />
<BasicStat title="Coins: " value={formatNumber(stats.coins)} className="text-mc-gold" />
</div>
<div className="flex-1">
<BasicStat title="Kills: " value={formatNumber(kills)} />
<BasicStat title="Deaths: " value={formatNumber(deaths)} />
<BasicStat title="Kill/Death Ratio: " value={kd} />
</div>
<div className="flex-1">
<BasicStat title="Wins: " value={formatNumber(wins)} />
<BasicStat title="Kill/Win Ratio: " value={kw} />
<BasicStat title="Heads Eaten: " value={formatNumber(heads)} />
<BasicStat title="Ultimates Crafted: " value={formatNumber(stats.ultimates_crafted + stats.ultimates_crafted_solo)} />
</div>
</div>
)
}

View File

@@ -3,15 +3,18 @@ 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 { getStatsCombined } from "@/lib/hypixel/uhc/general"
import { getUhcStarValue } from "@/lib/hypixel/uhc/level"
import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats"
import UHCProgress from "./progress"
import UHCGeneralStats from "./stats"
export default function UHCStats({ stats }: { stats: NonNullStats["UHC"] }) {
if (!stats) return null
const kd = formatNumber(devide(stats.kills, stats.deaths))
const combined = getStatsCombined(stats)
const kd = formatNumber(devide(combined.kills, combined.deaths))
const star = getUhcStarValue(stats.score)
return (
@@ -33,7 +36,7 @@ export default function UHCStats({ stats }: { stats: NonNullStats["UHC"] }) {
},
{
title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
stat: <p className="text-muted-foreground">{formatNumber(combined.wins)}</p>
}
]}
/>
@@ -42,6 +45,8 @@ export default function UHCStats({ stats }: { stats: NonNullStats["UHC"] }) {
<AccordionContent>
<Separator className="my-4" />
<UHCProgress score={stats.score} />
<Separator className="my-4" />
<UHCGeneralStats stats={stats} kills={combined.kills} deaths={combined.deaths} heads={combined.heads} wins={combined.wins} />
</AccordionContent>
</CardContent>
</Card>

View File

@@ -1,13 +1,13 @@
export const TITLE = "UHC" as const
export const MODES = [
{ id: ["solo"], name: "Solo" },
{ id: [""], name: "Teams" },
{ id: ["red vs blue", "_red_vs_blue"], name: "Red vs. Blue" },
{ id: ["no diamonds", "_no_diamonds"], name: "No Diamonds" },
{ id: ["vanilla doubles", "_vanilla_doubles"], name: "Vanilla Doubles" },
{ id: ["brawl"], name: "Brawl" },
{ id: ["solo brawl", "_solo_brawl"], name: "Solo Brawl" },
{ id: ["duo brawl", "_duo_brawl"], name: "Duo Brawl" }
{ id: "solo", name: "Solo" },
{ id: "", name: "Teams" },
{ id: "red_vs_blue", name: "Red vs. Blue" },
{ id: "no_diamonds", name: "No Diamonds" },
{ id: "vanilla_doubles", name: "Vanilla Doubles" },
{ id: "brawl", name: "Brawl" },
{ id: "solo_brawl", name: "Solo Brawl" },
{ id: "duo_brawl", name: "Duo Brawl" }
] as const
export const STARS = [
{ value: 0, name: "Recruit", color: "gray" },

View File

@@ -0,0 +1,55 @@
import { MODES } from "@/data/hypixel/uhc"
import { NonNullStats } from "@/lib/schema/player"
export function getStatsCombined(stats: NonNullable<NonNullStats["UHC"]>) {
return {
wins: getUHCWins(stats),
kills: getUHCKills(stats),
deaths: getUHCDeaths(stats),
heads: getUHCHeads(stats)
}
}
function getUHCWins(stats: NonNullable<NonNullStats["UHC"]>) {
let wins = 0
const ids = MODES.filter(m => m.id !== "").map(m => m.id)
for (const id of ids) {
wins = wins + stats[`wins_${id}`]
}
return wins + stats.wins
}
function getUHCKills(stats: NonNullable<NonNullStats["UHC"]>) {
let kills = 0
const ids = MODES.filter(m => m.id !== "").map(m => m.id)
for (const id of ids) {
kills = kills + stats[`kills_${id}`]
}
return kills + stats.kills
}
function getUHCDeaths(stats: NonNullable<NonNullStats["UHC"]>) {
let deaths = 0
const ids = MODES.filter(m => m.id !== "").map(m => m.id)
for (const id of ids) {
deaths = deaths + stats[`deaths_${id}`]
}
return deaths + stats.deaths
}
function getUHCHeads(stats: NonNullable<NonNullStats["UHC"]>) {
let heads = 0
const ids = MODES.filter(m => m.id !== "").map(m => m.id)
for (const id of ids) {
heads = heads + stats[`heads_eaten_${id}`]
}
return heads + stats.heads_eaten
}

View File

@@ -405,9 +405,43 @@ export const buildBattleStatsSchema = z.looseObject({
wins_speed_builders_latest: z.number().default(0)
})
function uhcModesStats() {
const ids = [
"solo",
"red_vs_blue",
"no_diamonds",
"vanilla_doubles",
"brawl",
"solo_brawl",
"duo_brawl"
] as const
const stats = [
"wins",
"kills",
"deaths",
"heads_eaten"
] as const
const entries = new Map<string, z.ZodDefault<z.ZodNumber>>()
for (const id of ids) {
for (const stat of stats) {
entries.set(`${stat}_${id}`, z.number().default(0))
}
}
return Object.fromEntries(entries) as Record<`${typeof stats[number]}_${typeof ids[number]}`, z.ZodDefault<z.ZodNumber>>
}
export const uhcSchema = z.looseObject({
kills: z.number().default(0),
deaths: z.number().default(0),
wins: z.number().default(0),
score: z.number().default(0)
heads_eaten: z.number().default(0),
score: z.number().default(0),
coins: z.number().default(0),
ultimates_crafted: z.number().default(0),
ultimates_crafted_solo: z.number().default(0),
...uhcModesStats()
})