Updated stats

This commit is contained in:
2025-08-23 21:29:49 +02:00
parent 96df2a6c45
commit f876ad15fa
10 changed files with 122 additions and 45 deletions

View File

@@ -2,10 +2,10 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
import { formatNumber } from "@/lib/formatters"
import { concatStatArrays } from "@/lib/funcs"
import { _BedwarsStats, getBedwarsModeStats, getBestMode } from "@/lib/hypixel/bedwars"
import { Player } from "@/lib/schema/player"
import { NonNullStats } from "@/lib/schema/player"
import { cn } from "@/lib/utils"
export default function BedwarsStatTable({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
export default function BedwarsStatTable({ stats }: { stats: NonNullStats["Bedwars"] }) {
return (
<Table>
<BedwarsTableHeader />
@@ -69,7 +69,7 @@ function BedwarsTableHeader() {
)
}
function SoloStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function SoloStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("solo", stats as _BedwarsStats)
const isBest = getBestMode(stats as _BedwarsStats) === "solo"
@@ -83,7 +83,7 @@ function SoloStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
)
}
function DoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function DoublesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("doubles", stats as _BedwarsStats)
const isBest = getBestMode(stats as _BedwarsStats) === "doubles"
@@ -97,7 +97,7 @@ function DoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }
)
}
function ThreesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function ThreesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("3s", stats as _BedwarsStats)
const isBest = getBestMode(stats as _BedwarsStats) === "3s"
@@ -111,7 +111,7 @@ function ThreesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] })
)
}
function FoursStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function FoursStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("4s", stats as _BedwarsStats)
const isBest = getBestMode(stats as _BedwarsStats) === "4s"
@@ -125,7 +125,7 @@ function FoursStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] })
)
}
function CoreModeStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function CoreModeStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const soloStats = getBedwarsModeStats("solo", stats as _BedwarsStats, true)
const doublesStats = getBedwarsModeStats("doubles", stats as _BedwarsStats, true)
const threesStats = getBedwarsModeStats("3s", stats as _BedwarsStats, true)
@@ -143,7 +143,7 @@ function CoreModeStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"]
)
}
function FourVFourStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function FourVFourStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("4v4", stats as _BedwarsStats)
return (
@@ -156,7 +156,7 @@ function FourVFourStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"]
)
}
function RushDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function RushDoublesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("rush_2s", stats as _BedwarsStats)
return (
@@ -169,7 +169,7 @@ function RushDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars
)
}
function Rush4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Rush4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("rush_4s", stats as _BedwarsStats)
return (
@@ -182,7 +182,7 @@ function Rush4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] })
)
}
function UltimateDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function UltimateDoublesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("ultimate_2s", stats as _BedwarsStats)
return (
@@ -195,7 +195,7 @@ function UltimateDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bed
)
}
function Ultimate4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Ultimate4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("ultimate_4s", stats as _BedwarsStats)
return (
@@ -208,7 +208,7 @@ function Ultimate4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"
)
}
function LuckyDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function LuckyDoublesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("lucky_2s", stats as _BedwarsStats)
return (
@@ -221,7 +221,7 @@ function LuckyDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwar
)
}
function Lucky4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Lucky4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("lucky_4s", stats as _BedwarsStats)
return (
@@ -234,7 +234,7 @@ function Lucky4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }
)
}
function VoidlessDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function VoidlessDoublesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("voidless_2s", stats as _BedwarsStats)
return (
@@ -247,7 +247,7 @@ function VoidlessDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bed
)
}
function Voidless4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Voidless4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("voidless_4s", stats as _BedwarsStats)
return (
@@ -260,7 +260,7 @@ function Voidless4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"
)
}
function ArmedDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function ArmedDoublesStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("armed_2s", stats as _BedwarsStats)
return (
@@ -273,7 +273,7 @@ function ArmedDoublesStats({ stats }: { stats: Player["player"]["stats"]["Bedwar
)
}
function Armed4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Armed4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("armed_4s", stats as _BedwarsStats)
return (
@@ -286,7 +286,7 @@ function Armed4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }
)
}
function Swap4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Swap4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("swap_4s", stats as _BedwarsStats)
return (
@@ -299,7 +299,7 @@ function Swap4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] })
)
}
function Underworld4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function Underworld4sStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("underworld_4s", stats as _BedwarsStats)
return (
@@ -312,7 +312,7 @@ function Underworld4sStats({ stats }: { stats: Player["player"]["stats"]["Bedwar
)
}
function CastleStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function CastleStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const modeStats = getBedwarsModeStats("castle", stats as _BedwarsStats)
return (
@@ -325,7 +325,7 @@ function CastleStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] })
)
}
function AllModeStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
function AllModeStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const soloStats = getBedwarsModeStats("solo", stats as _BedwarsStats, true)
const doublesStats = getBedwarsModeStats("doubles", stats as _BedwarsStats, true)
const threesStats = getBedwarsModeStats("3s", stats as _BedwarsStats, true)

View File

@@ -5,7 +5,7 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/component
import { Separator } from "@/components/ui/separator"
import { getBWLevelForExp, getTotalExpForLevel } from "@/lib/hypixel/bedwarsLevel"
import { getProgress } from "@/lib/hypixel/general"
import { Player } from "@/lib/schema/player"
import { NonNullStats } from "@/lib/schema/player"
import { ChevronDown, ChevronUp } from "lucide-react"
import { useEffect, useRef, useState } from "react"
import CollapsedStats from "../../_components/CollapsedStats"
@@ -13,7 +13,7 @@ import { BedwarsLevel, BedwarsProgress } from "./bedwars-components"
import BedwarsStatTable from "./bedwars-table"
import BedwarsGeneralStats from "./stats"
export default function BedwarsStats({ stats }: { stats: Player["player"]["stats"]["Bedwars"] }) {
export default function BedwarsStats({ stats }: { stats: NonNullStats["Bedwars"] }) {
const ref = useRef<HTMLDivElement>(null)
const [opened, setOpened] = useState(false)

View File

@@ -1,12 +1,12 @@
import { formatNumber } from "@/lib/formatters"
import { getLatestRoom, getWalletMax } from "@/lib/hypixel/bedwars"
import { Player } from "@/lib/schema/player"
import { NonNullStats } from "@/lib/schema/player"
import { BasicStat, Stat } from "../../_components/Stats"
import { BedWarsPrestige } from "./bedwars-components"
export default function BedwarsGeneralStats(
{ statsChecked, level, percent, kd, fkd, bbl, wl }: {
statsChecked: Player["player"]["stats"]["Bedwars"]
statsChecked: NonNullStats["Bedwars"]
level: number
percent: number
kd: string

View File

@@ -6,14 +6,14 @@ import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters"
import { getProgress } from "@/lib/hypixel/general"
import { getSkywarsLevel, getSkywarsXpForLevel } from "@/lib/hypixel/skyWarsLevel"
import { Player } from "@/lib/schema/player"
import { NonNullStats } from "@/lib/schema/player"
import { ChevronDown, ChevronUp } from "lucide-react"
import { useEffect, useRef, useState } from "react"
import CollapsedStats from "../../_components/CollapsedStats"
import { SkywarsLevel, SkywarsProgress } from "./skywars-components"
import SkyWarsGeneralStats from "./stats"
export default function SkyWarsStats({ stats }: { stats: Player["player"]["stats"]["SkyWars"] }) {
export default function SkyWarsStats({ stats }: { stats: NonNullStats["SkyWars"] }) {
const ref = useRef<HTMLDivElement>(null)
const [opened, setOpened] = useState(false)

View File

@@ -1,5 +1,5 @@
import { formatNumber } from "@/lib/formatters"
import { Player } from "@/lib/schema/player"
import { NonNullStats } from "@/lib/schema/player"
import { BasicStat, Stat } from "../../_components/Stats"
import { SkywarsPrestige } from "./skywars-components"
@@ -7,7 +7,7 @@ export default function SkyWarsGeneralStats({
statsChecked,
level
}: {
statsChecked: Player["player"]["stats"]["SkyWars"]
statsChecked: NonNullStats["SkyWars"]
level: number
}) {
const stats = statsChecked!

View File

@@ -1,4 +1,5 @@
import DisplayName from "@/components/player/displayname"
import { Card, CardContent } from "@/components/ui/card"
import { getGuild } from "@/lib/hypixel/api/guild"
import { getUuid } from "@/lib/hypixel/api/mojang"
import { getPlayer } from "@/lib/hypixel/api/player"
@@ -65,6 +66,7 @@ async function SuspendedPage({ ign: pign }: { ign: string }) {
plusColor={player.rankPlusColor}
guildTag={guild?.tag}
tagColor={guild?.tagColor}
specialRank={player.rank}
/>
</h1>
<h1>
@@ -72,10 +74,24 @@ async function SuspendedPage({ ign: pign }: { ign: string }) {
</h1>
<div className="flex gap-6 px-6 mt-8 w-full max-w-7xl">
<Sidebar level={level} ign={pign} player={player} guild={guild ?? undefined} />
<div className="pb-4 space-y-4 w-3/4">
<BedwarsStats stats={player.stats.Bedwars} />
<SkyWarsStats stats={player.stats.SkyWars} />
</div>
{player.stats !== undefined ?
(
<div className="pb-4 space-y-4 w-3/4">
<BedwarsStats stats={player.stats.Bedwars} />
<SkyWarsStats stats={player.stats.SkyWars} />
</div>
) :
(
<div className="w-3/4">
<Card>
<CardContent className="flex justify-center">
<h1 className="text-xl font-bold">
No stats avaiable. If they are staff then they most likely have their api off.
</h1>
</CardContent>
</Card>
</div>
)}
</div>
</div>
)

View File

@@ -6,7 +6,7 @@ type MonthlyPackageRank = Player["player"]["monthlyPackageRank"]
type RankColor = Player["player"]["monthlyRankColor"]
export default function DisplayName(
{ ign, rank, monthly, rankColor, plusColor, guildTag, tagColor }: {
{ ign, rank, monthly, rankColor, plusColor, guildTag, tagColor, specialRank }: {
ign: string
rank: NewPackageRank
monthly: MonthlyPackageRank
@@ -14,17 +14,37 @@ export default function DisplayName(
plusColor: string | undefined
guildTag: string | undefined
tagColor: string | undefined
specialRank: string | undefined
}
) {
return (
<>
<PlayerRank rank={rank} monthly={monthly} plusColor={plusColor} rankColor={rankColor} />{" "}
<PlayerIGN ign={ign} rank={rank} monthly={monthly} rankColor={rankColor} /> <GuildTag tag={guildTag} tagColor={tagColor} />
<PlayerRank rank={rank} monthly={monthly} plusColor={plusColor} rankColor={rankColor} specialRank={specialRank} />{" "}
<PlayerIGN ign={ign} rank={rank} monthly={monthly} rankColor={rankColor} specialRank={specialRank} />{" "}
<GuildTag tag={guildTag} tagColor={tagColor} />
</>
)
}
function PlayerIGN({ ign, rank, monthly, rankColor }: { ign: string, rank: NewPackageRank, monthly: MonthlyPackageRank, rankColor: RankColor }) {
function PlayerIGN(
{ ign, rank, monthly, rankColor, specialRank }: {
ign: string
rank: NewPackageRank
monthly: MonthlyPackageRank
rankColor: RankColor
specialRank: string | undefined
}
) {
if (specialRank) {
if (specialRank === "YOUTUBER") {
return <span className="text-mc-red">{ign}</span>
}
if (specialRank === "STAFF") {
return <span className="text-mc-red">{ign}</span>
}
}
if (monthly === "SUPERSTAR") {
if (rankColor === "GOLD") {
return <span className="text-mc-gold">{ign}</span>
@@ -48,8 +68,36 @@ function PlayerIGN({ ign, rank, monthly, rankColor }: { ign: string, rank: NewPa
}
function PlayerRank(
{ rank, monthly, plusColor, rankColor }: { rank: NewPackageRank, monthly: MonthlyPackageRank, plusColor?: string, rankColor: RankColor }
{ rank, monthly, plusColor, rankColor, specialRank }: {
rank: NewPackageRank
monthly: MonthlyPackageRank
plusColor?: string
rankColor: RankColor
specialRank: string | undefined
}
) {
if (specialRank) {
if (specialRank === "YOUTUBER") {
return (
<>
<span className="text-mc-red">[</span>
<span className="text-mc-white">YOUTUBE</span>
<span className="text-mc-red">]</span>
</>
)
}
if (specialRank === "STAFF") {
return (
<>
<span className="text-mc-red">[</span>
<span className="text-mc-gold"></span>
<span className="text-mc-red">]</span>
</>
)
}
}
if (monthly === "SUPERSTAR") {
if (rankColor === "GOLD") {
return (

View File

@@ -6,9 +6,16 @@ export function getGuildMember(guild: Guild["guild"], uuid: string) {
export function getGuildRankTag(guild: Guild["guild"], uuid: string) {
const member = getGuildMember(guild, uuid)
return member?.rank === "Guild Master"
? "[GM]"
: `[${guild.ranks.find(r => r.name === member?.rank)?.tag}]`
if (member?.rank === "Guild Master") return "[GM]"
const rank = guild.ranks.find(r => r.name === member?.rank)?.tag
if (rank == null) {
return ""
} else {
return `[${rank}]`
}
}
export function getMemberGEXP(guild: Guild["guild"], uuid: string, days: number = 0) {

View File

@@ -15,7 +15,11 @@ export function getCoinMultiplier(level: number) {
return MULTIPLIER[0].value
}
export function getTotalCoins(stats: Record<string, Record<"coins", number | undefined>>) {
export function getTotalCoins(stats: Record<string, Record<"coins", number | undefined>> | undefined) {
if (!stats) {
return 0
}
return Object.values(stats).reduce((total, stat) => total + (stat.coins || 0), 0)
}

View File

@@ -15,7 +15,7 @@ export const playerSchema = z.looseObject({
stats: z.looseObject({
Bedwars: bedwarsStatsSchema.optional(),
SkyWars: skywarsStatsSchema.optional()
}),
}).optional(),
quests: z.record(
z.string(),
z.looseObject({
@@ -47,8 +47,10 @@ export const playerSchema = z.looseObject({
TWITTER: z.string().optional(),
YOUTUBE: z.string().optional()
}).optional()
}).optional()
}).optional(),
rank: z.string().optional()
})
})
export type Player = z.infer<typeof playerSchema>
export type NonNullStats = NonNullable<Player["player"]["stats"]>