Added first
This commit is contained in:
59
src/app/(stats)/player/[ign]/_stats/pit/pit.tsx
Normal file
59
src/app/(stats)/player/[ign]/_stats/pit/pit.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import { formatNumber } from "@/lib/formatters"
|
||||
import { devide, romanize } from "@/lib/hypixel/general"
|
||||
import { getLevelColor, getPrestige, getPrestigeColor } from "@/lib/hypixel/pit/general"
|
||||
import { getPitLevel } from "@/lib/hypixel/pit/level"
|
||||
import { NonNullStats } from "@/lib/schema/player"
|
||||
import CollapsedStats from "../../_components/CollapsedStats"
|
||||
|
||||
export default function PitStats({ stats }: { stats: NonNullStats["Pit"] }) {
|
||||
if (!stats) return null
|
||||
|
||||
const kd = formatNumber(devide(stats.kills, stats.deaths))
|
||||
const prestige = getPrestige(stats)
|
||||
const level = getPitLevel(stats.profile.xp, prestige)
|
||||
const prestigeColor = getPrestigeColor(prestige)
|
||||
const levelColor = getLevelColor(level)
|
||||
|
||||
return (
|
||||
<AccordionItem value="pit">
|
||||
<Card className="py-0">
|
||||
<CardContent>
|
||||
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer">
|
||||
<h1 className="text-xl font-bold">Pit</h1>
|
||||
<div className="flex gap-4">
|
||||
<CollapsedStats
|
||||
stats={[
|
||||
{
|
||||
title: <p>Level</p>,
|
||||
stat: (
|
||||
<p className="font-bold">
|
||||
<span className={`text-mc-${prestigeColor}`}>[</span>
|
||||
<span className="text-mc-yellow">{romanize(prestige)}</span>
|
||||
<span className={`text-mc-${levelColor}`}>{`-${level}`}</span>
|
||||
<span className={`text-mc-${prestigeColor}`}>]</span>
|
||||
</p>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: <p>Kills</p>,
|
||||
stat: <p className="text-muted-foreground">{formatNumber(stats.kills)}</p>
|
||||
},
|
||||
{
|
||||
title: <p>KD</p>,
|
||||
stat: <p className="text-muted-foreground">{kd}</p>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Separator className="my-4" />
|
||||
</AccordionContent>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</AccordionItem>
|
||||
)
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import BedwarsStats from "./_stats/bedwars/bedwars"
|
||||
import BuildBattleStats from "./_stats/build-battle/build-battle"
|
||||
import DuelsStats from "./_stats/duels/duels"
|
||||
import MurderMysteryStats from "./_stats/murder-mystery/murder-mystery"
|
||||
import PitStats from "./_stats/pit/pit"
|
||||
import SkyWarsStats from "./_stats/skywars/skywars"
|
||||
import UHCStats from "./_stats/uhc/uhc"
|
||||
|
||||
@@ -114,6 +115,7 @@ async function SuspendedPage({ ign: pign }: { ign: string }) {
|
||||
<MurderMysteryStats stats={player.stats.MurderMystery} />
|
||||
<BuildBattleStats stats={player.stats.BuildBattle} />
|
||||
<UHCStats stats={player.stats.UHC} />
|
||||
<PitStats stats={player.stats.Pit} />
|
||||
</Accordion>
|
||||
</div>
|
||||
) :
|
||||
|
||||
98
src/data/hypixel/pit.ts
Normal file
98
src/data/hypixel/pit.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
export const TITLE = "Pit" as const
|
||||
export const MAXPRESTIGE = 40 as const
|
||||
export const MAXLEVEL = 120 as const
|
||||
export const PRESTIGE_MULTIPLIERS = [
|
||||
{ "Multiplier": 1, "SumXp": 65950 },
|
||||
{ "Multiplier": 1.1, "SumXp": 138510 },
|
||||
{ "Multiplier": 1.2, "SumXp": 217680 },
|
||||
{ "Multiplier": 1.3, "SumXp": 303430 },
|
||||
{ "Multiplier": 1.4, "SumXp": 395760 },
|
||||
{ "Multiplier": 1.5, "SumXp": 494700 },
|
||||
{ "Multiplier": 1.75, "SumXp": 610140 },
|
||||
{ "Multiplier": 2, "SumXp": 742040 },
|
||||
{ "Multiplier": 2.5, "SumXp": 906930 },
|
||||
{ "Multiplier": 3, "SumXp": 1104780 },
|
||||
{ "Multiplier": 4, "SumXp": 1368580 },
|
||||
{ "Multiplier": 5, "SumXp": 1698330 },
|
||||
{ "Multiplier": 6, "SumXp": 2094030 },
|
||||
{ "Multiplier": 7, "SumXp": 2555680 },
|
||||
{ "Multiplier": 8, "SumXp": 3083280 },
|
||||
{ "Multiplier": 9, "SumXp": 3676830 },
|
||||
{ "Multiplier": 10, "SumXp": 4336330 },
|
||||
{ "Multiplier": 12, "SumXp": 5127730 },
|
||||
{ "Multiplier": 14, "SumXp": 6051030 },
|
||||
{ "Multiplier": 16, "SumXp": 7106230 },
|
||||
{ "Multiplier": 18, "SumXp": 8293330 },
|
||||
{ "Multiplier": 20, "SumXp": 9612330 },
|
||||
{ "Multiplier": 24, "SumXp": 11195130 },
|
||||
{ "Multiplier": 28, "SumXp": 13041730 },
|
||||
{ "Multiplier": 32, "SumXp": 15152130 },
|
||||
{ "Multiplier": 36, "SumXp": 17526330 },
|
||||
{ "Multiplier": 40, "SumXp": 20164330 },
|
||||
{ "Multiplier": 45, "SumXp": 23132080 },
|
||||
{ "Multiplier": 50, "SumXp": 26429580 },
|
||||
{ "Multiplier": 75, "SumXp": 31375830 },
|
||||
{ "Multiplier": 100, "SumXp": 37970830 },
|
||||
{ "Multiplier": 101, "SumXp": 44631780 },
|
||||
{ "Multiplier": 101, "SumXp": 51292730 },
|
||||
{ "Multiplier": 101, "SumXp": 57953680 },
|
||||
{ "Multiplier": 101, "SumXp": 64614630 },
|
||||
{ "Multiplier": 101, "SumXp": 71275580 },
|
||||
{ "Multiplier": 200, "SumXp": 84465580 },
|
||||
{ "Multiplier": 300, "SumXp": 104250580 },
|
||||
{ "Multiplier": 400, "SumXp": 130630580 },
|
||||
{ "Multiplier": 500, "SumXp": 163605580 },
|
||||
{ "Multiplier": 750, "SumXp": 213068080 },
|
||||
{ "Multiplier": 1000, "SumXp": 279018080 },
|
||||
{ "Multiplier": 1250, "SumXp": 361455580 },
|
||||
{ "Multiplier": 1500, "SumXp": 460380580 },
|
||||
{ "Multiplier": 1750, "SumXp": 575793080 },
|
||||
{ "Multiplier": 2000, "SumXp": 707693080 },
|
||||
{ "Multiplier": 3000, "SumXp": 905543080 },
|
||||
{ "Multiplier": 5000, "SumXp": 1235293080 },
|
||||
{ "Multiplier": 10000, "SumXp": 1894793080 },
|
||||
{ "Multiplier": 50000, "SumXp": 5192293080 },
|
||||
{ "Multiplier": 100000, "SumXp": 11787293080 }
|
||||
] as const
|
||||
export const LEVEL_REQUIREMENTS = [
|
||||
15,
|
||||
30,
|
||||
50,
|
||||
75,
|
||||
125,
|
||||
300,
|
||||
600,
|
||||
800,
|
||||
900,
|
||||
1000,
|
||||
1200,
|
||||
1500,
|
||||
0
|
||||
] as const
|
||||
export const LEVELCOLORS = [
|
||||
{ level: 0, color: "gray" },
|
||||
{ level: 10, color: "blue" },
|
||||
{ level: 20, color: "dark-aqua" },
|
||||
{ level: 30, color: "dark-green" },
|
||||
{ level: 40, color: "green" },
|
||||
{ level: 50, color: "yellow" },
|
||||
{ level: 60, color: "gold" },
|
||||
{ level: 70, color: "red" },
|
||||
{ level: 80, color: "dark-red" },
|
||||
{ level: 90, color: "dark-purple" },
|
||||
{ level: 100, color: "light-purple" },
|
||||
{ level: 110, color: "white" },
|
||||
{ level: 120, color: "aqua" }
|
||||
] as const
|
||||
export const PRESTIGECOLORS = [
|
||||
{ prestige: 0, color: "gray" },
|
||||
{ prestige: 1, color: "blue" },
|
||||
{ prestige: 5, color: "yellow" },
|
||||
{ prestige: 10, color: "gold" },
|
||||
{ prestige: 15, color: "red" },
|
||||
{ prestige: 20, color: "dark-purple" },
|
||||
{ prestige: 25, color: "light-purple" },
|
||||
{ prestige: 30, color: "white" },
|
||||
{ prestige: 35, color: "aqua" },
|
||||
{ prestige: 40, color: "dark-blue" }
|
||||
] as const
|
||||
22
src/lib/hypixel/pit/general.ts
Normal file
22
src/lib/hypixel/pit/general.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { LEVELCOLORS, PRESTIGECOLORS } from "@/data/hypixel/pit"
|
||||
import { NonNullStats } from "@/lib/schema/player"
|
||||
|
||||
export function getLevelColor(level: number) {
|
||||
for (const lvl of LEVELCOLORS.slice().reverse()) {
|
||||
if (lvl.level <= level) return lvl.color
|
||||
}
|
||||
|
||||
return LEVELCOLORS.at(0)!.color
|
||||
}
|
||||
|
||||
export function getPrestigeColor(prestige: number) {
|
||||
for (const pres of PRESTIGECOLORS.slice().reverse()) {
|
||||
if (pres.prestige <= prestige) return pres.color
|
||||
}
|
||||
|
||||
return PRESTIGECOLORS.at(0)!.color
|
||||
}
|
||||
|
||||
export function getPrestige(stats: NonNullable<NonNullStats["Pit"]>) {
|
||||
return stats.profile.prestiges.length
|
||||
}
|
||||
27
src/lib/hypixel/pit/level.ts
Normal file
27
src/lib/hypixel/pit/level.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { LEVEL_REQUIREMENTS, PRESTIGE_MULTIPLIERS } from "@/data/hypixel/pit"
|
||||
|
||||
export function getPitLevel(xp: number, prestige: number) {
|
||||
let xps = xp
|
||||
|
||||
if (prestige > 0) {
|
||||
xps = xps - PRESTIGE_MULTIPLIERS[prestige - 1]["SumXp"]
|
||||
}
|
||||
|
||||
const multiplier = PRESTIGE_MULTIPLIERS[prestige]["Multiplier"]
|
||||
let level = 0
|
||||
|
||||
while (xps > 0 && level < 120) {
|
||||
const levelXp = LEVEL_REQUIREMENTS[Math.floor(level / 10)] * multiplier
|
||||
if (xps >= levelXp * 10) {
|
||||
xps -= levelXp * 10
|
||||
level += 10
|
||||
} else {
|
||||
const gain = Math.floor(xps / levelXp)
|
||||
level += gain
|
||||
xps -= gain * levelXp
|
||||
xps = 0
|
||||
}
|
||||
}
|
||||
|
||||
return level
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
import z from "zod"
|
||||
import { bedwarsStatsSchema, buildBattleStatsSchema, duelsStatsSchema, murderMysteryStatsSchema, skywarsStatsSchema, uhcSchema } from "./stats"
|
||||
import {
|
||||
bedwarsStatsSchema,
|
||||
buildBattleStatsSchema,
|
||||
duelsStatsSchema,
|
||||
murderMysteryStatsSchema,
|
||||
pitStats,
|
||||
skywarsStatsSchema,
|
||||
uhcSchema
|
||||
} from "./stats"
|
||||
|
||||
export const playerSchema = z.looseObject({
|
||||
player: z.looseObject({
|
||||
@@ -19,7 +27,8 @@ export const playerSchema = z.looseObject({
|
||||
Duels: duelsStatsSchema.optional(),
|
||||
MurderMystery: murderMysteryStatsSchema.optional(),
|
||||
BuildBattle: buildBattleStatsSchema.optional(),
|
||||
UHC: uhcSchema.optional()
|
||||
UHC: uhcSchema.optional(),
|
||||
Pit: pitStats.optional()
|
||||
}).optional(),
|
||||
quests: z.record(
|
||||
z.string(),
|
||||
|
||||
@@ -445,3 +445,22 @@ export const uhcSchema = z.looseObject({
|
||||
ultimates_crafted_solo: z.number().default(0),
|
||||
...uhcModesStats()
|
||||
})
|
||||
|
||||
export const pitStats = z.looseObject({
|
||||
pit_stats_ptl: z.looseObject({
|
||||
kills: z.number().default(0),
|
||||
deaths: z.number().default(0)
|
||||
}),
|
||||
profile: z.looseObject({
|
||||
prestiges: z.array(z.looseObject({
|
||||
index: z.number(),
|
||||
xp_on_prestige: z.number(),
|
||||
timestamp: z.number()
|
||||
})),
|
||||
xp: z.number().default(0)
|
||||
})
|
||||
}).transform(({ profile, pit_stats_ptl, ...rest }) => ({
|
||||
profile,
|
||||
...pit_stats_ptl,
|
||||
...rest
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user