Finished first sw stats
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { getSkyWarsIcon, getTextColor } from "@/lib/hypixel/skywars"
|
import { getPrestigeName, getSkyWarsIcon, getTextColor } from "@/lib/hypixel/skywars"
|
||||||
import { getSkywarsLevel } from "@/lib/hypixel/skyWarsLevel"
|
import { getSkywarsLevel } from "@/lib/hypixel/skyWarsLevel"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
export function SkywarsLevel({ xp, icon }: { xp: number, icon: string | undefined }) {
|
export function SkywarsLevel({ xp, icon }: { xp: number, icon: string | undefined }) {
|
||||||
const level = getSkywarsLevel(xp)
|
const level = getSkywarsLevel(xp)
|
||||||
@@ -49,3 +50,77 @@ export function SkywarsLevel({ xp, icon }: { xp: number, icon: string | undefine
|
|||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SkywarsProgress({ level, percent }: { level: number, percent: number }) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center mb-10">
|
||||||
|
<LevelNumber level={level} className="mr-2" />
|
||||||
|
<Progress level={level} percent={percent} />
|
||||||
|
<div className="flex-1 h-5 rounded-r-md bg-background"></div>
|
||||||
|
<LevelNumber level={level + 1} className="ml-2" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function LevelNumber({ level, className }: { level: number, className?: string }) {
|
||||||
|
if (level > 150 || level === 50) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(level > 150 ? "font-bold" : undefined, className)}
|
||||||
|
style={{
|
||||||
|
backgroundImage: "linear-gradient(to left,#a0a,#f5f,#5ff,#5f5,#ff5,#fa0,#f55)",
|
||||||
|
WebkitBackgroundClip: "text",
|
||||||
|
color: "transparent"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{level}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={cn(`text-mc-${getTextColor(level).text}`, className)}>{level}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Progress({ level, percent }: { level: number, percent: number }) {
|
||||||
|
if (level > 150 || level === 50) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="h-5 rounded-l-md"
|
||||||
|
style={{
|
||||||
|
width: `${percent}%`,
|
||||||
|
background: "repeating-linear-gradient(to right,#f55,#fa0,#ff5,#5f5,#5ff,#f5f,#a0a,#f55 16rem)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={`h-5 bg-mc-${getTextColor(level).text} rounded-l-md`} style={{ width: `${percent}%` }}></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SkywarsPrestige({ level, icon }: { level: number, icon?: string }) {
|
||||||
|
const swIcon = getSkyWarsIcon(icon)
|
||||||
|
const pres = getPrestigeName(level)
|
||||||
|
const val = `${pres} ${swIcon}`
|
||||||
|
|
||||||
|
if (level > 150 || level === 50) {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
backgroundImage: "linear-gradient(to left,#a0a,#f5f,#5ff,#5f5,#ff5,#fa0,#f55)",
|
||||||
|
WebkitBackgroundClip: "text",
|
||||||
|
color: "transparent"
|
||||||
|
}}
|
||||||
|
className={level > 150 ? "font-bold" : undefined}
|
||||||
|
>
|
||||||
|
{val}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className={`text-mc-${getTextColor(level).text}`}>
|
||||||
|
{val}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import { Card, CardContent } from "@/components/ui/card"
|
|||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
import { formatNumber } from "@/lib/formatters"
|
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 { Player } from "@/lib/schema/player"
|
||||||
import { ChevronDown, ChevronUp } from "lucide-react"
|
import { ChevronDown, ChevronUp } from "lucide-react"
|
||||||
import { useEffect, useRef, useState } from "react"
|
import { useEffect, useRef, useState } from "react"
|
||||||
import CollapsedStats from "../../_components/CollapsedStats"
|
import CollapsedStats from "../../_components/CollapsedStats"
|
||||||
import { SkywarsLevel } from "./skywars-components"
|
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: Player["player"]["stats"]["SkyWars"] }) {
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
@@ -36,9 +39,16 @@ export default function SkyWarsStats({ stats }: { stats: Player["player"]["stats
|
|||||||
|
|
||||||
if (!stats) return null
|
if (!stats) return null
|
||||||
|
|
||||||
|
const level = getSkywarsLevel(stats.skywars_experience)
|
||||||
const kd = (stats.kills / stats.deaths).toFixed(2)
|
const kd = (stats.kills / stats.deaths).toFixed(2)
|
||||||
const wl = (stats.wins / stats.losses).toFixed(2)
|
const wl = (stats.wins / stats.losses).toFixed(2)
|
||||||
|
|
||||||
|
const percent = getProgress(
|
||||||
|
getSkywarsXpForLevel(Math.floor(level)),
|
||||||
|
stats.skywars_experience,
|
||||||
|
getSkywarsXpForLevel(Math.floor(level) + 1)
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@@ -73,6 +83,8 @@ export default function SkyWarsStats({ stats }: { stats: Player["player"]["stats
|
|||||||
</div>
|
</div>
|
||||||
<CollapsibleContent>
|
<CollapsibleContent>
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
|
<SkywarsProgress level={Math.floor(level)} percent={percent} />
|
||||||
|
<SkyWarsGeneralStats statsChecked={stats} level={level} />
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
29
src/app/(stats)/player/[ign]/_stats/skywars/stats.tsx
Normal file
29
src/app/(stats)/player/[ign]/_stats/skywars/stats.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { formatNumber } from "@/lib/formatters"
|
||||||
|
import { Player } from "@/lib/schema/player"
|
||||||
|
import { BasicStat, Stat } from "../../_components/Stats"
|
||||||
|
import { SkywarsPrestige } from "./skywars-components"
|
||||||
|
|
||||||
|
export default function SkyWarsGeneralStats({
|
||||||
|
statsChecked,
|
||||||
|
level
|
||||||
|
}: {
|
||||||
|
statsChecked: Player["player"]["stats"]["SkyWars"]
|
||||||
|
level: number
|
||||||
|
}) {
|
||||||
|
const stats = statsChecked!
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex mb-10">
|
||||||
|
<div className="flex-1">
|
||||||
|
<BasicStat title="Level: " value={level.toFixed(2)} />
|
||||||
|
<Stat title="Prestige: ">
|
||||||
|
<SkywarsPrestige level={Math.floor(level)} icon={stats.selected_prestige_icon} />
|
||||||
|
</Stat>
|
||||||
|
<BasicStat title="Coins: " value={formatNumber(stats.coins)} className="text-mc-gold" />
|
||||||
|
<BasicStat title="Token: " value={formatNumber(stats.cosmetic_tokens)} className="text-mc-dark-green" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-1"></div>
|
||||||
|
<div className="flex-1"></div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -11,3 +11,27 @@ export function getSkywarsLevel(xp: number) {
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSkywarsXpForLevel(level: number) {
|
||||||
|
const xps = [0, 20, 70, 150, 250, 500, 1000, 2000, 3500, 6000, 10000, 15000]
|
||||||
|
|
||||||
|
if (level >= 12) {
|
||||||
|
return (level - 12) * 10000 + 15000
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseLevel = Math.floor(level)
|
||||||
|
const progress = level - baseLevel
|
||||||
|
|
||||||
|
if (baseLevel >= xps.length) {
|
||||||
|
return xps[xps.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseLevel === 0) {
|
||||||
|
return progress * xps[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseXp = xps[baseLevel]
|
||||||
|
const nextXp = xps[baseLevel + 1] || 15000
|
||||||
|
|
||||||
|
return baseXp + progress * (nextXp - baseXp)
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,3 +28,11 @@ export function getSkyWarsIcon(icon?: string) {
|
|||||||
|
|
||||||
return icons[icon] ?? ICONS.default
|
return icons[icon] ?? ICONS.default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPrestigeName(level: number) {
|
||||||
|
const floored = floorLevel(level, 5)
|
||||||
|
|
||||||
|
if (level > 150) return PRESTIGES.at(-1)!.name
|
||||||
|
|
||||||
|
return PRESTIGES.find(p => p.level === floored)!.name
|
||||||
|
}
|
||||||
|
|||||||
@@ -195,5 +195,7 @@ export const skywarsStatsSchema = z.looseObject({
|
|||||||
kills: z.number().default(0),
|
kills: z.number().default(0),
|
||||||
deaths: z.number().default(0),
|
deaths: z.number().default(0),
|
||||||
wins: z.number().default(0),
|
wins: z.number().default(0),
|
||||||
losses: z.number().default(0)
|
losses: z.number().default(0),
|
||||||
|
cosmetic_tokens: z.number().default(0),
|
||||||
|
coins: z.number().default(0)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user