diff --git a/src/app/(stats)/player/[ign]/_stats/murder-mystery/stats.tsx b/src/app/(stats)/player/[ign]/_stats/murder-mystery/stats.tsx index de23ece..185bd2e 100644 --- a/src/app/(stats)/player/[ign]/_stats/murder-mystery/stats.tsx +++ b/src/app/(stats)/player/[ign]/_stats/murder-mystery/stats.tsx @@ -1,22 +1,39 @@ -import { formatNumber } from "@/lib/formatters" +import { formatNumber, formatSecondsToTime } from "@/lib/formatters" +import { devide } from "@/lib/hypixel/general" +import { getKnifeName } from "@/lib/hypixel/murder-mystery/general" import { NonNullStats } from "@/lib/schema/player" import { BasicStat } from "../../_components/Stats" export default function MurderMysteryGeneralStats({ statsChecked }: { statsChecked: NonNullStats["MurderMystery"] }) { const stats = statsChecked! - const kd = formatNumber(stats.kills / stats.deaths) + const kd = formatNumber(devide(stats.kills, stats.deaths)) + const wl = formatNumber(devide(stats.wins, stats.losses)) + const weapon = getKnifeName(stats.active_knife_skin) return (
+

+
+

+
+ +

+
+

+ + + + +
) diff --git a/src/data/hypixel/murder-mystery.ts b/src/data/hypixel/murder-mystery.ts new file mode 100644 index 0000000..d5323ba --- /dev/null +++ b/src/data/hypixel/murder-mystery.ts @@ -0,0 +1,49 @@ +export const TITLE = "Murder Mystery" as const +export const MODES = [ + { id: "_MURDER_CLASSIC", name: "Classic" }, + { id: "_MURDER_ASSASSINS", name: "Assassins" }, + { id: "_MURDER_DOUBLE_UP", name: "Double Up" }, + { id: "_MURDER_HARDCORE", name: "Hardcore" }, + { id: "_MURDER_SHOWDOWN", name: "Showdown" }, + { id: "", name: "Overall" } +] as const +export const KNIFESKINS = { + knife_skin_apple: "Healthy Treat", + knife_skin_basted_turkey: "Basted Turkey", + knife_skin_bone: "Big Bone", + knife_skin_blaze_stick: "Blaze Rod", + knife_skin_bloody_brick: "Bloody Brick", + knife_skin_carrot_on_stick: "Carrot on a Stick", + knife_skin_cheapo: "Cheapo Sword", + knife_skin_cheese: "Cheese", + knife_skin_chewed_bush: "Chewed Up Bush", + knife_skin_diamond_shovel: "Only the Best", + knife_skin_easter_basket: "Easter Basket", + knife_skin_feather: "Jagged Knife", + knife_skin_glistening_melon: "Glistening Melon", + knife_skin_gold_digger: "Gold Digger", + knife_skin_grilled_steak: "Grilled Steak", + knife_skin_grimoire: "Grimoire", + knife_skin_ice_shard: "Ice Shard", + knife_skin_mouse_trap: "Mouse Trap", + knife_skin_mvp: "MVP Diamond Sword", + knife_skin_none: "Iron Sword", + knife_skin_prickly: "Prickly", + knife_skin_pumpkin_pie: "Pumpkin Pie", + knife_skin_scythe: "Reaper Scythe", + knife_skin_rudolphs_snack: "Rudolph's Favourite Snack", + knife_skin_rudolphs_nose: "Rudolph's Nose", + knife_skin_salmon: "Salmon", + knife_skin_shears: "Shears", + knife_skin_shovel: "Shovel", + knife_skin_shiny_snack: "Sparkly Snack", + knife_skin_stake: "Stake", + knife_skin_stick: "Stick", + knife_skin_stick_with_hat: "Stick with a Hat", + knife_skin_sweet_treat: "Sweet Treat", + knife_skin_timber: "Timber", + knife_skin_vip: "VIP Gold Sword", + knife_skin_wood_axe: "Wood Axe", + random_cosmetic: "Random", + undefined: "Iron Sword" +} as const diff --git a/src/lib/formatters.ts b/src/lib/formatters.ts index f444b87..4f78fbf 100644 --- a/src/lib/formatters.ts +++ b/src/lib/formatters.ts @@ -13,12 +13,31 @@ const dateFormatter = new Intl.DateTimeFormat("en-GB", { hour12: false }) -export function formatNumber(num: number): string { +export function formatNumber(num: number) { return numberFormatter.format(num) } -export function formatDate(timestamp: number): string { +export function formatDate(timestamp: number) { return dateFormatter.format(new Date(timestamp)) } +export function formatSecondsToTime(seconds: number) { + if (!Number.isFinite(seconds)) return "0s" + seconds = Math.floor(Math.max(0, seconds)) + const days = Math.floor(seconds / 86400) + const hours = Math.floor((seconds % 86400) / 3600) + const minutes = Math.floor((seconds % 3600) / 60) + const secs = seconds % 60 + + const parts: string[] = [] + if (days) parts.push(days + "d") + if (hours) parts.push(hours + "h") + if (minutes) parts.push(minutes + "m") + if (secs || parts.length === 0) parts.push(secs + "s") + + if (parts.length === 1) return parts[0] + if (parts.length === 2) return parts[0] + " and " + parts[1] + // For 3+ parts: separate first n-1 by comma+space, last preceded by 'and' + return parts.slice(0, -1).join(", ") + " and " + parts[parts.length - 1] +} export function formatRelativeTime(timestamp: number, type: "past" | "future") { const now = Date.now() diff --git a/src/lib/hypixel/murder-mystery/general.ts b/src/lib/hypixel/murder-mystery/general.ts new file mode 100644 index 0000000..d8b0254 --- /dev/null +++ b/src/lib/hypixel/murder-mystery/general.ts @@ -0,0 +1,11 @@ +import { KNIFESKINS } from "@/data/hypixel/murder-mystery" + +export function getKnifeName(name?: string) { + if (!name) return KNIFESKINS.undefined + + const skin = (KNIFESKINS as Record)[name] + + if (!skin) return KNIFESKINS.undefined + + return skin +} diff --git a/src/lib/schema/stats.ts b/src/lib/schema/stats.ts index 9064bab..f476967 100644 --- a/src/lib/schema/stats.ts +++ b/src/lib/schema/stats.ts @@ -333,8 +333,13 @@ export const duelsStatsSchema = z.looseObject({ export const murderMysteryStatsSchema = z.looseObject({ kills: z.number().default(0), + deaths: z.number().default(0), wins: z.number().default(0), + losses: z.number().default(0), coins: z.number().default(0), kills_as_murderer: z.number().default(0), - deaths: z.number().default(0) + thrown_knife_kills: z.number().default(0), + active_knife_skin: z.string().optional(), + quickest_detective_win_time_seconds: z.number().default(0), + quickest_murderer_win_time_seconds: z.number().default(0) })