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 BuildBattleStats from "./_stats/build-battle/build-battle"
|
||||||
import DuelsStats from "./_stats/duels/duels"
|
import DuelsStats from "./_stats/duels/duels"
|
||||||
import MurderMysteryStats from "./_stats/murder-mystery/murder-mystery"
|
import MurderMysteryStats from "./_stats/murder-mystery/murder-mystery"
|
||||||
|
import PitStats from "./_stats/pit/pit"
|
||||||
import SkyWarsStats from "./_stats/skywars/skywars"
|
import SkyWarsStats from "./_stats/skywars/skywars"
|
||||||
import UHCStats from "./_stats/uhc/uhc"
|
import UHCStats from "./_stats/uhc/uhc"
|
||||||
|
|
||||||
@@ -114,6 +115,7 @@ async function SuspendedPage({ ign: pign }: { ign: string }) {
|
|||||||
<MurderMysteryStats stats={player.stats.MurderMystery} />
|
<MurderMysteryStats stats={player.stats.MurderMystery} />
|
||||||
<BuildBattleStats stats={player.stats.BuildBattle} />
|
<BuildBattleStats stats={player.stats.BuildBattle} />
|
||||||
<UHCStats stats={player.stats.UHC} />
|
<UHCStats stats={player.stats.UHC} />
|
||||||
|
<PitStats stats={player.stats.Pit} />
|
||||||
</Accordion>
|
</Accordion>
|
||||||
</div>
|
</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 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({
|
export const playerSchema = z.looseObject({
|
||||||
player: z.looseObject({
|
player: z.looseObject({
|
||||||
@@ -19,7 +27,8 @@ export const playerSchema = z.looseObject({
|
|||||||
Duels: duelsStatsSchema.optional(),
|
Duels: duelsStatsSchema.optional(),
|
||||||
MurderMystery: murderMysteryStatsSchema.optional(),
|
MurderMystery: murderMysteryStatsSchema.optional(),
|
||||||
BuildBattle: buildBattleStatsSchema.optional(),
|
BuildBattle: buildBattleStatsSchema.optional(),
|
||||||
UHC: uhcSchema.optional()
|
UHC: uhcSchema.optional(),
|
||||||
|
Pit: pitStats.optional()
|
||||||
}).optional(),
|
}).optional(),
|
||||||
quests: z.record(
|
quests: z.record(
|
||||||
z.string(),
|
z.string(),
|
||||||
|
|||||||
@@ -445,3 +445,22 @@ export const uhcSchema = z.looseObject({
|
|||||||
ultimates_crafted_solo: z.number().default(0),
|
ultimates_crafted_solo: z.number().default(0),
|
||||||
...uhcModesStats()
|
...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