From 26023cd9cacdbc68a94cffcc638887ed257891e7 Mon Sep 17 00:00:00 2001 From: jacobk999 Date: Fri, 9 Aug 2024 12:13:01 -0400 Subject: [PATCH 1/2] feat(general): show stats from 'best' game on /general --- .../src/commands/general/general.profile.tsx | 678 +++++++++++++++++- .../commands/vampirez/vampirez.profile.tsx | 2 +- .../src/components/Table/TableData.tsx | 3 +- .../src/player/gamemodes/vampirez/index.ts | 4 +- 4 files changed, 659 insertions(+), 28 deletions(-) diff --git a/apps/discord-bot/src/commands/general/general.profile.tsx b/apps/discord-bot/src/commands/general/general.profile.tsx index 60361afd2..b8673ff7c 100644 --- a/apps/discord-bot/src/commands/general/general.profile.tsx +++ b/apps/discord-bot/src/commands/general/general.profile.tsx @@ -8,7 +8,7 @@ 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 type { BaseProfileProps } from "#commands/base.hypixel-command"; @@ -79,6 +79,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 +160,629 @@ 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 "woolwars": + score = stats.woolwars.overall.wins; + break; + } + + return (score - mean) / stdev; +} + +interface GamePreviewTableProps { + game: PlayableGame; + stats: PlayerStats; + t: LocalizeFunction; +} + +function GamePreviewTable({ game, stats, t }: GamePreviewTableProps) { + switch (game) { + case "arcade": + // [TODO]: Add Arcade stats + return [t("stats.wins"), t(stats[game].wins)]; + 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 "woolwars": + 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, + woolwars: FormattedGame.WOOLWARS, +}; + +/* 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: [13.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], + woolwars: [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 8fcdc3855..aa7fd6962 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 423e6e4f1..185424647 100644 --- a/apps/discord-bot/src/components/Table/TableData.tsx +++ b/apps/discord-bot/src/components/Table/TableData.tsx @@ -42,7 +42,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 22281ecca..6de67b52d 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); } } From 12f9138123be7094958bc5947e4381fd0bf02892 Mon Sep 17 00:00:00 2001 From: jacobk999 Date: Mon, 6 Jan 2025 11:39:35 -0500 Subject: [PATCH 2/2] add few game stats --- .../commands/arcade/modes/overall-arcade.tsx | 26 +------- apps/discord-bot/src/commands/arcade/wins.ts | 36 +++++++++++ .../src/commands/general/general.profile.tsx | 62 +++++++++++++------ 3 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 apps/discord-bot/src/commands/arcade/wins.ts 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 b8673ff7c..71cb9e31a 100644 --- a/apps/discord-bot/src/commands/general/general.profile.tsx +++ b/apps/discord-bot/src/commands/general/general.profile.tsx @@ -10,6 +10,7 @@ import { Container, Footer, Header, If, Table } from "#components"; import { DateTime } from "luxon"; 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 { @@ -127,7 +128,7 @@ export const GeneralProfile = ({ color="§d" /> - + @@ -271,8 +272,8 @@ function gameWeight(stats: PlayerStats, game: PlayableGame) { score = stats.warlords.wins; break; - case "woolwars": - score = stats.woolwars.overall.wins; + case "woolgames": + score = stats.woolgames.wins; break; } @@ -287,9 +288,34 @@ interface GamePreviewTableProps { function GamePreviewTable({ game, stats, t }: GamePreviewTableProps) { switch (game) { - case "arcade": - // [TODO]: Add Arcade stats - return [t("stats.wins"), t(stats[game].wins)]; + case "arcade":{ + const [first, second, third] = arcadeWins(stats[game]); + + return ( + <> + + + + + + ); + } case "arenabrawl": return ( <> @@ -316,7 +342,7 @@ function GamePreviewTable({ game, stats, t }: GamePreviewTableProps) { ); - case "woolwars": + case "woolgames": return ( <> @@ -753,7 +779,7 @@ const FormattedPlayableGame: Record = { vampirez: FormattedGame.VAMPIREZ, walls: FormattedGame.WALLS, warlords: FormattedGame.WARLORDS, - woolwars: FormattedGame.WOOLWARS, + woolgames: FormattedGame.WOOLGAMES, }; /* eslint-disable unicorn/numeric-separators-style */ @@ -769,7 +795,7 @@ const GameNormal: Record = { general: [2093.1178095654386, 1720.0900266142357], megawalls: [24.53680465485529, 131.15816805113383], murdermystery: [150.76623514552855, 915.9276449171637], - paintball: [13.34181091905699, 117.86448713259242], + paintball: [23.34181091905699, 117.86448713259242], parkour: [0, 0], pit: [102.56580072764409, 277.06822675957835], quake: [26.814050527274105, 430.61202349308223], @@ -783,6 +809,6 @@ const GameNormal: Record = { vampirez: [20.305040582036874, 231.25314292785842], walls: [8.220307526093416, 79.08187919057073], warlords: [27.839182249700166, 217.31182795352672], - woolwars: [21.583678620368413, 285.09386895294614], + woolgames: [21.583678620368413, 285.09386895294614], };