Finished general stats
This commit is contained in:
@@ -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 (
|
||||
<div className="flex mb-10">
|
||||
<div className="flex-1">
|
||||
<BasicStat title="Tokens: " value={formatNumber(stats.coins)} className="font-bold text-mc-dark-green" />
|
||||
<p>
|
||||
<br />
|
||||
</p>
|
||||
<BasicStat title="Kills: " value={formatNumber(stats.kills)} />
|
||||
<BasicStat title="Kills as Murderer: " value={formatNumber(stats.kills_as_murderer)} />
|
||||
<BasicStat title="Thrown Knife Kills: " value={formatNumber(stats.thrown_knife_kills)} />
|
||||
<BasicStat title="Deaths: " value={formatNumber(stats.deaths)} />
|
||||
<BasicStat title="Kill/Death Ratio: " value={kd} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<BasicStat title="Murder Weapon: " value={weapon} className="font-bold text-mc-red" />
|
||||
<p>
|
||||
<br />
|
||||
</p>
|
||||
<BasicStat title="Wins: " value={formatNumber(stats.wins)} />
|
||||
<BasicStat title="Losses: " value={formatNumber(stats.losses)} />
|
||||
<BasicStat title="Win/Loss Ratio: " value={wl} />
|
||||
<BasicStat title="Fastest Detective Win: " value={formatSecondsToTime(stats.quickest_detective_win_time_seconds)} />
|
||||
<BasicStat title="Fastest Murderer Win: " value={formatSecondsToTime(stats.quickest_murderer_win_time_seconds)} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
49
src/data/hypixel/murder-mystery.ts
Normal file
49
src/data/hypixel/murder-mystery.ts
Normal file
@@ -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
|
||||
@@ -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()
|
||||
|
||||
11
src/lib/hypixel/murder-mystery/general.ts
Normal file
11
src/lib/hypixel/murder-mystery/general.ts
Normal file
@@ -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<string, string>)[name]
|
||||
|
||||
if (!skin) return KNIFESKINS.undefined
|
||||
|
||||
return skin
|
||||
}
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user