diff --git a/src/app/(stats)/player/[ign]/_stats/pit/pit.tsx b/src/app/(stats)/player/[ign]/_stats/pit/pit.tsx new file mode 100644 index 0000000..1a0fa17 --- /dev/null +++ b/src/app/(stats)/player/[ign]/_stats/pit/pit.tsx @@ -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 ( + + + + +

Pit

+
+ Level

, + stat: ( +

+ [ + {romanize(prestige)} + {`-${level}`} + ] +

+ ) + }, + { + title:

Kills

, + stat:

{formatNumber(stats.kills)}

+ }, + { + title:

KD

, + stat:

{kd}

+ } + ]} + /> +
+
+ + + +
+
+
+ ) +} diff --git a/src/app/(stats)/player/[ign]/page.tsx b/src/app/(stats)/player/[ign]/page.tsx index b7ba8d2..de836e7 100644 --- a/src/app/(stats)/player/[ign]/page.tsx +++ b/src/app/(stats)/player/[ign]/page.tsx @@ -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 }) { + ) : diff --git a/src/data/hypixel/pit.ts b/src/data/hypixel/pit.ts new file mode 100644 index 0000000..c0999cd --- /dev/null +++ b/src/data/hypixel/pit.ts @@ -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 diff --git a/src/lib/hypixel/pit/general.ts b/src/lib/hypixel/pit/general.ts new file mode 100644 index 0000000..dabaf4a --- /dev/null +++ b/src/lib/hypixel/pit/general.ts @@ -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) { + return stats.profile.prestiges.length +} diff --git a/src/lib/hypixel/pit/level.ts b/src/lib/hypixel/pit/level.ts new file mode 100644 index 0000000..e8b35b1 --- /dev/null +++ b/src/lib/hypixel/pit/level.ts @@ -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 +} diff --git a/src/lib/schema/player.ts b/src/lib/schema/player.ts index 93c58f7..6209a61 100644 --- a/src/lib/schema/player.ts +++ b/src/lib/schema/player.ts @@ -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(), diff --git a/src/lib/schema/stats.ts b/src/lib/schema/stats.ts index 59cad22..a930b88 100644 --- a/src/lib/schema/stats.ts +++ b/src/lib/schema/stats.ts @@ -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 +}))