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)
})