diff --git a/apps/discord-bot/src/commands/arcade/modes/overall-arcade.tsx b/apps/discord-bot/src/commands/arcade/modes/overall-arcade.tsx index f074cae81..81b78a339 100644 --- a/apps/discord-bot/src/commands/arcade/modes/overall-arcade.tsx +++ b/apps/discord-bot/src/commands/arcade/modes/overall-arcade.tsx @@ -9,6 +9,7 @@ import { Arcade } from "@statsify/schemas"; import { LocalizeFunction } from "@statsify/discord"; import { Table } from "#components"; +import { arcadeWins } from "../wins.js"; import { arrayGroup } from "@statsify/util"; interface OverallArcadeTableProps { @@ -19,30 +20,7 @@ interface OverallArcadeTableProps { export const OverallArcadeTable = ({ stats, t }: OverallArcadeTableProps) => { const rowSize = 3; - const games: [string, number][] = [ - ["Blocking Dead", stats.blockingDead.wins], - ["Bounty Hunters", stats.bountyHunters.wins], - ["Dragon Wars", stats.dragonWars.wins], - ["Dropper", stats.dropper.wins], - ["Ender Spleef", stats.enderSpleef.wins], - ["Farm Hunt", stats.farmHunt.wins], - ["Football", stats.football.wins], - ["Galaxy Wars", stats.galaxyWars.wins], - ["Hide And Seek", stats.hideAndSeek.overall.wins], - ["Hole In The Wall", stats.holeInTheWall.wins], - ["Hypixel Says", stats.hypixelSays.wins], - ["Mini Walls", stats.miniWalls.wins], - ["Party Games", stats.partyGames.wins], - ["Pixel Painters", stats.pixelPainters.wins], - ["Pixel Party", stats.pixelParty.overall.wins], - ["Seasonal", stats.seasonal.totalWins], - ["Throw Out", stats.throwOut.wins], - ["Zombies", stats.zombies.overall.wins], - ]; - - games.sort((a, b) => b[1] - a[1]); - - const rows = arrayGroup(games, rowSize); + const rows = arrayGroup(arcadeWins(stats), rowSize); const colors = ["§d", "§b", "§a", "§e", "§6", "§c"]; diff --git a/apps/discord-bot/src/commands/arcade/wins.ts b/apps/discord-bot/src/commands/arcade/wins.ts new file mode 100644 index 000000000..c14b3b0d2 --- /dev/null +++ b/apps/discord-bot/src/commands/arcade/wins.ts @@ -0,0 +1,36 @@ +/** + * Copyright (c) Statsify + * + * This source code is licensed under the GNU GPL v3 license found in the + * LICENSE file in the root directory of this source tree. + * https://github.com/Statsify/statsify/blob/main/LICENSE + */ + +import { Arcade } from "@statsify/schemas"; + +export function arcadeWins(stats: Arcade): [string, number][] { + const games: [string, number][] = [ + ["Blocking Dead", stats.blockingDead.wins], + ["Bounty Hunters", stats.bountyHunters.wins], + ["Dragon Wars", stats.dragonWars.wins], + ["Dropper", stats.dropper.wins], + ["Ender Spleef", stats.enderSpleef.wins], + ["Farm Hunt", stats.farmHunt.wins], + ["Football", stats.football.wins], + ["Galaxy Wars", stats.galaxyWars.wins], + ["Hide And Seek", stats.hideAndSeek.overall.wins], + ["Hole In The Wall", stats.holeInTheWall.wins], + ["Hypixel Says", stats.hypixelSays.wins], + ["Mini Walls", stats.miniWalls.wins], + ["Party Games", stats.partyGames.wins], + ["Pixel Painters", stats.pixelPainters.wins], + ["Pixel Party", stats.pixelParty.overall.wins], + ["Seasonal", stats.seasonal.totalWins], + ["Throw Out", stats.throwOut.wins], + ["Zombies", stats.zombies.overall.wins], + ]; + + games.sort((a, b) => b[1] - a[1]); + + return games; +} diff --git a/apps/discord-bot/src/commands/general/general.profile.tsx b/apps/discord-bot/src/commands/general/general.profile.tsx index 60361afd2..71cb9e31a 100644 --- a/apps/discord-bot/src/commands/general/general.profile.tsx +++ b/apps/discord-bot/src/commands/general/general.profile.tsx @@ -8,8 +8,9 @@ import { Container, Footer, Header, If, Table } from "#components"; import { DateTime } from "luxon"; -import { FormattedGame, Guild, PlayerStatus } from "@statsify/schemas"; +import { FormattedGame, Guild, PlayerStats, PlayerStatus } from "@statsify/schemas"; import { LocalizeFunction } from "@statsify/discord"; +import { arcadeWins } from "#commands/arcade/wins"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; interface GeneralProfileHeaderBodyProps { @@ -79,6 +80,8 @@ export const GeneralProfile = ({ const { status } = player; const member = guild?.members.find((m) => m.uuid === player.uuid); + const mostPlayedGame = findMostPlayedGame(player.stats); + return (
- + + + + + {(member) => ( - - - - - + + + + + + + )} @@ -156,3 +161,654 @@ export const GeneralProfile = ({ ); }; + +function findMostPlayedGame(stats: PlayerStats): PlayableGame { + const keys = Object.keys(stats) as Array; + const games = keys.filter((game) => game !== "parkour" && game !== "general" && game !== "quests" && game !== "challenges"); + const weights = games.map((game) => gameWeight(stats, game)); + + let max = weights[0]; + let index = 0; + + for (const [i, weight] of weights.entries()) { + if (weight > max) { + index = i; + max = weight; + } + } + + return games[index]; +} + +type PlayableGame = Exclude; + +function gameWeight(stats: PlayerStats, game: PlayableGame) { + const [mean, stdev] = GameNormal[game]; + + let score: number; + + switch (game) { + case "arcade": + score = stats.arcade.wins; + break; + + case "arenabrawl": + score = stats.arenabrawl.overall.wins; + break; + + case "bedwars": + score = stats.bedwars.overall.wins; + break; + + case "blitzsg": + score = stats.blitzsg.overall.wins; + break; + + case "buildbattle": + score = stats.buildbattle.overall.wins; + break; + + case "copsandcrims": + score = stats.copsandcrims.overall.wins; + break; + + case "duels": + score = stats.duels.overall.wins; + break; + + case "megawalls": + score = stats.megawalls.overall.wins; + break; + + case "murdermystery": + score = stats.murdermystery.overall.wins; + break; + + case "paintball": + score = stats.paintball.wins; + break; + + case "pit": + score = stats.pit.trueLevel; + break; + + case "quake": + score = stats.quake.overall.wins; + break; + + case "skywars": + score = stats.skywars.overall.wins; + break; + + case "smashheroes": + score = stats.smashheroes.overall.wins; + break; + + case "speeduhc": + score = stats.speeduhc.overall.wins; + break; + + case "tntgames": + score = stats.tntgames.wins; + break; + + case "turbokartracers": + score = stats.turbokartracers.gold + stats.turbokartracers.silver + stats.turbokartracers.bronze; + break; + + case "uhc": + score = stats.uhc.overall.wins; + break; + + case "vampirez": + score = stats.vampirez.wins; + break; + + case "walls": + score = stats.walls.wins; + break; + + case "warlords": + score = stats.warlords.wins; + break; + + case "woolgames": + score = stats.woolgames.wins; + break; + } + + return (score - mean) / stdev; +} + +interface GamePreviewTableProps { + game: PlayableGame; + stats: PlayerStats; + t: LocalizeFunction; +} + +function GamePreviewTable({ game, stats, t }: GamePreviewTableProps) { + switch (game) { + case "arcade":{ + const [first, second, third] = arcadeWins(stats[game]); + + return ( + <> + + + + + + ); + } + case "arenabrawl": + return ( + <> + + + + + ); + case "bedwars": + return ( + <> + + + + + + ); + case "blitzsg": + return ( + <> + + + + + ); + case "buildbattle": + return ( + <> + + + + + ); + case "copsandcrims": + return ( + <> + + + + + ); + case "duels": + return ( + <> + + + + + + ); + case "megawalls": + return ( + <> + + + + + ); + case "murdermystery": + return ( + <> + + + + + ); + case "paintball": + return ( + <> + + + + + ); + case "pit": + return ( + <> + + + + + + ); + case "quake": + return ( + <> + + + + + ); + case "skywars": + return ( + <> + + + + + + ); + case "smashheroes": + return ( + <> + + + + + + ); + case "speeduhc": + return ( + <> + + + + + + ); + case "tntgames": + // [TODO]: Add TNT Games stats + return [t("stats.wins"), t(stats[game].wins)]; + case "turbokartracers": + return ( + <> + + + + + ); + case "uhc": + return ( + <> + + + + + ); + case "vampirez": + return ( + <> + + + + + ); + case "walls": + return ( + <> + + + + + ); + case "warlords": + return ( + <> + + + + + ); + case "woolgames": + return ( + <> + + + + + + ); + } +} + +const FormattedPlayableGame: Record = { + arcade: FormattedGame.ARCADE, + arenabrawl: FormattedGame.ARENA_BRAWL, + bedwars: FormattedGame.BEDWARS, + blitzsg: FormattedGame.BLITZSG, + buildbattle: FormattedGame.BUILD_BATTLE, + copsandcrims: FormattedGame.COPS_AND_CRIMS, + duels: FormattedGame.DUELS, + megawalls: FormattedGame.MEGAWALLS, + murdermystery: FormattedGame.MURDER_MYSTERY, + paintball: FormattedGame.PAINTBALL, + pit: FormattedGame.PIT, + quake: FormattedGame.QUAKE, + skywars: FormattedGame.SKYWARS, + smashheroes: FormattedGame.SMASH_HEROES, + speeduhc: FormattedGame.SPEED_UHC, + tntgames: FormattedGame.TNT_GAMES, + turbokartracers: FormattedGame.TURBO_KART_RACERS, + uhc: FormattedGame.UHC, + vampirez: FormattedGame.VAMPIREZ, + walls: FormattedGame.WALLS, + warlords: FormattedGame.WARLORDS, + woolgames: FormattedGame.WOOLGAMES, +}; + +/* eslint-disable unicorn/numeric-separators-style */ +const GameNormal: Record = { + arcade: [47.943456623159285, 345.45462984480355], + arenabrawl: [54.54271059484758, 456.7449242807322], + bedwars: [258.74934632116793, 748.0327413158763], + blitzsg: [66.62482760173609, 462.74593393363017], + buildbattle: [14.501026965691436, 96.75410919555686], + challenges: [703.3189660164868, 1121.0524615976233], + copsandcrims: [24.66711634640695, 209.2012305609239], + duels: [498.4884596072068, 2105.437063866322], + general: [2093.1178095654386, 1720.0900266142357], + megawalls: [24.53680465485529, 131.15816805113383], + murdermystery: [150.76623514552855, 915.9276449171637], + paintball: [23.34181091905699, 117.86448713259242], + parkour: [0, 0], + pit: [102.56580072764409, 277.06822675957835], + quake: [26.814050527274105, 430.61202349308223], + quests: [413.50770716841487, 981.7769202969056], + skywars: [228.95944991807306, 987.3697381192043], + smashheroes: [52.99487443574538, 495.9379499033822], + speeduhc: [9.100884466556108, 68.29294762132967], + tntgames: [30.684695073419277, 369.0345100173687], + turbokartracers: [71.54076539101497, 427.8901349133345], + uhc: [26.139986346957933, 84.59519407156014], + vampirez: [20.305040582036874, 231.25314292785842], + walls: [8.220307526093416, 79.08187919057073], + warlords: [27.839182249700166, 217.31182795352672], + woolgames: [21.583678620368413, 285.09386895294614], +}; + diff --git a/apps/discord-bot/src/commands/vampirez/vampirez.profile.tsx b/apps/discord-bot/src/commands/vampirez/vampirez.profile.tsx index a22e8d699..5bfd4c4f2 100644 --- a/apps/discord-bot/src/commands/vampirez/vampirez.profile.tsx +++ b/apps/discord-bot/src/commands/vampirez/vampirez.profile.tsx @@ -38,7 +38,7 @@ export const VampireZProfile = ({ const sidebar: SidebarItem[] = [ [t("stats.coins"), t(vampirez.coins), "§6"], [t("stats.tokens"), t(vampirez.tokens), "§e"], - [t("stats.overallWins"), t(vampirez.overallWins), "§a"], + [t("stats.overallWins"), t(vampirez.wins), "§a"], [t("stats.zombieKills"), t(vampirez.zombieKills), "§2"], ]; diff --git a/apps/discord-bot/src/components/Table/TableData.tsx b/apps/discord-bot/src/components/Table/TableData.tsx index 5a38b1574..6b7ccbe82 100644 --- a/apps/discord-bot/src/components/Table/TableData.tsx +++ b/apps/discord-bot/src/components/Table/TableData.tsx @@ -52,7 +52,8 @@ export const TableData = ({ title, value, color, size = "regular" }: TableDataPr {`${color}${title}`} {`§^4^${color}${value}`} + size={4} + >{`${color}${value}`} ); diff --git a/packages/schemas/src/player/gamemodes/vampirez/index.ts b/packages/schemas/src/player/gamemodes/vampirez/index.ts index 2c2485f13..afc9757a0 100644 --- a/packages/schemas/src/player/gamemodes/vampirez/index.ts +++ b/packages/schemas/src/player/gamemodes/vampirez/index.ts @@ -23,7 +23,7 @@ export class VampireZ { public tokens: number; @Field() - public overallWins: number; + public wins: number; @Field({ historical: { enabled: false } }) public mostVampireKills: number; @@ -57,7 +57,7 @@ export class VampireZ { this.human = new VampireZHuman(data, "human"); this.vampire = new VampireZVampire(data, "vampire"); - this.overallWins = add(this.human.wins, this.vampire.wins); + this.wins = add(this.human.wins, this.vampire.wins); } }