{ "version": 3, "sources": ["../../../../../server/chat-plugins/randombattles/winrates.ts"], "sourcesContent": ["/**\r\n * A chat plugin to store, calculate, and view winrates in random battle formats.\r\n * @author mia-pi-git\r\n */\r\n\r\nimport {FS, Utils} from '../../../lib';\r\n\r\ninterface Stats {\r\n\telo: number;\r\n\tmonth: string;\r\n\tformats: Record;\r\n}\r\n\r\ninterface MonEntry {\r\n\ttimesGenerated: number;\r\n\tnumWins: number;\r\n}\r\n\r\ninterface FormatData {\r\n\tmons: Record;\r\n\tperiod?: number; // how often it resets - defaults to 1mo\r\n}\r\n\r\nconst STATS_PATH = 'logs/randbats/{{MONTH}}-winrates.json';\r\nexport let stats: Stats;\r\n\r\ntry {\r\n\tconst path = STATS_PATH.replace('{{MONTH}}', getMonth());\r\n\tif (!FS('logs/randbats/').existsSync()) {\r\n\t\tFS('logs/randbats/').mkdirSync();\r\n\t}\r\n\tstats = JSON.parse(FS(path).readSync());\r\n} catch {\r\n\tstats = getDefaultStats();\r\n}\r\n\r\nfunction getDefaultStats() {\r\n\treturn {\r\n\t\telo: 1500,\r\n\t\tmonth: getMonth(),\r\n\t\tformats: {\r\n\t\t\t// all of these requested by rands staff. they don't anticipate it being changed much\r\n\t\t\t// so i'm not spending the time to add commands to toggle this\r\n\t\t\tgen9randombattle: {mons: {}},\r\n\t\t\tgen7randombattle: {mons: {}},\r\n\t\t\tgen6randombattle: {mons: {}},\r\n\t\t\tgen5randombattle: {mons: {}},\r\n\t\t\tgen4randombattle: {mons: {}},\r\n\t\t\tgen3randombattle: {mons: {}},\r\n\t\t\tgen2randombattle: {mons: {}},\r\n\t\t},\r\n\t} as Stats;\r\n}\r\n\r\nexport function saveStats(month = getMonth()) {\r\n\t// clone to avoid race conditions with the data getting deleted later (on month rollover)\r\n\tconst curStats = {...stats};\r\n\tFS(STATS_PATH.replace('{{MONTH}}', month)).writeUpdate(() => JSON.stringify(curStats));\r\n}\r\n\r\nfunction getMonth() {\r\n\treturn Chat.toTimestamp(new Date()).split(' ')[0].slice(0, -3);\r\n}\r\n\r\n// no, this cannot be baseSpecies - some formes matter, ex arceus formes\r\n// no, there is no better way to do this.\r\n// yes, i tried.\r\nfunction getSpeciesName(set: PokemonSet, format: Format) {\r\n\tconst species = set.species;\r\n\tconst item = Dex.items.get(set.item);\r\n\tconst moves = set.moves;\r\n\tconst megaRayquazaPossible = ['gen6', 'gen7'].includes(format.mod) && !format.ruleset.includes('Mega Rayquaza Clause');\r\n\tif (species.startsWith(\"Pikachu-\")) {\r\n\t\treturn 'Pikachu';\r\n\t} else if (species.startsWith(\"Unown-\")) {\r\n\t return 'Unown';\r\n\t} else if (species === \"Gastrodon-East\") {\r\n\t\treturn 'Gastrodon';\r\n\t} else if (species === \"Magearna-Original\") {\r\n\t return \"Magearna\";\r\n\t} else if (species === \"Genesect-Douse\") {\r\n\t\treturn \"Genesect\";\r\n\t} else if (species === \"Dudunsparce-Three-Segment\") {\r\n\t\treturn 'Dudunsparce';\r\n\t} else if (species === \"Maushold-Four\") {\r\n\t\treturn 'Maushold';\r\n\t} else if (species === \"Squawkabilly-Blue\") {\r\n\t\treturn \"Squawkabilly\";\r\n\t} else if (species === \"Squawkabilly-White\") {\r\n\t\treturn \"Squawkabilly-Yellow\";\r\n\t} else if (species.startsWith(\"Basculin-\")) {\r\n\t\treturn \"Basculin\";\r\n\t} else if (species.startsWith(\"Sawsbuck-\")) {\r\n\t\treturn \"Sawsbuck\";\r\n\t} else if (species.startsWith(\"Vivillon-\")) {\r\n\t\treturn \"Vivillon\";\r\n\t} else if (species.startsWith(\"Florges-\")) {\r\n\t\treturn \"Florges\";\r\n\t} else if (species.startsWith(\"Furfrou-\")) {\r\n\t\treturn \"Furfrou\";\r\n\t} else if (species.startsWith(\"Minior-\")) {\r\n\t\treturn \"Minior\";\r\n\t} else if (species.startsWith(\"Toxtricity-\")) {\r\n\t\treturn 'Toxtricity';\r\n\t} else if (species.startsWith(\"Tatsugiri-\")) {\r\n\t\treturn 'Tatsugiri';\r\n\t} else if (species === \"Zacian\" && item.name === \"Rusted Sword\") {\r\n\t\treturn 'Zacian-Crowned';\r\n\t} else if (species === \"Zamazenta\" && item.name === \"Rusted Shield\") {\r\n\t\treturn \"Zamazenta-Crowned\";\r\n\t} else if (species === \"Kyogre\" && item.name === \"Blue Orb\") {\r\n\t\treturn \"Kyogre-Primal\";\r\n\t} else if (species === \"Groudon\" && item.name === \"Red Orb\") {\r\n\t\treturn \"Groudon-Primal\";\r\n\t} else if (item.megaStone) {\r\n\t\treturn item.megaStone;\r\n\t} else if (species === \"Rayquaza\" && moves.includes('Dragon Ascent') && megaRayquazaPossible) {\r\n\t\treturn \"Rayquaza-Mega\";\r\n\t} else {\r\n\t\treturn species;\r\n\t}\r\n}\r\n\r\nfunction checkRollover() {\r\n\tif (stats.month !== getMonth()) {\r\n\t\tsaveStats(stats.month);\r\n\t\tObject.assign(stats, getDefaultStats());\r\n\t\tsaveStats();\r\n\t}\r\n}\r\n\r\nconst getZScore = (data: MonEntry) => (\r\n\t2 * Math.sqrt(data.timesGenerated) * (data.numWins / data.timesGenerated - 0.5)\r\n);\r\n\r\n\r\nexport const handlers: Chat.Handlers = {\r\n\tonBattleEnd(battle, winner, players) {\r\n\t\tvoid collectStats(battle, winner, players);\r\n\t},\r\n};\r\n\r\nasync function collectStats(battle: RoomBattle, winner: ID, players: ID[]) {\r\n\tconst formatData = stats.formats[battle.format];\r\n\tlet eloFloor = stats.elo;\r\n\tconst format = Dex.formats.get(battle.format);\r\n\tif (format.mod !== `gen${Dex.gen}`) {\r\n\t\teloFloor = 1300;\r\n\t}\r\n\tif (!formatData || battle.rated < eloFloor) return;\r\n\tcheckRollover();\r\n\tfor (const p of players) {\r\n\t\tconst team = await battle.getTeam(p);\r\n\t\tif (!team) return; // ???\r\n\t\tconst mons = team.map(f => getSpeciesName(f, format));\r\n\t\tfor (const mon of mons) {\r\n\t\t\tif (!formatData.mons[mon]) formatData.mons[mon] = {timesGenerated: 0, numWins: 0};\r\n\t\t\tformatData.mons[mon].timesGenerated++;\r\n\t\t\tif (toID(winner) === toID(p)) {\r\n\t\t\t\tformatData.mons[mon].numWins++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tsaveStats();\r\n}\r\n\r\nexport const commands: Chat.ChatCommands = {\r\n\trwr: 'randswinrates',\r\n\trandswinrates(target, room, user) {\r\n\t\treturn this.parse(`/j view-winrates-${toID(target) || `gen${Dex.gen}randombattle`}`);\r\n\t},\r\n\trandswinrateshelp: [\r\n\t\t'/randswinrates OR /rwr [format] - Get a list of the win rates for all Pokemon in the given Random Battles format.',\r\n\t],\r\n\r\n\tasync removewinrates(target, room, user) {\r\n\t\tthis.checkCan('rangeban');\r\n\t\tif (!/^[0-9]{4}-[0-9]{2}$/.test(target) || target === getMonth()) {\r\n\t\t\treturn this.errorReply(`Invalid month: ${target}`);\r\n\t\t}\r\n\t\tconst path = STATS_PATH.replace('{{MON}}', target);\r\n\t\tif (!(await FS(path).exists())) {\r\n\t\t\treturn this.errorReply(`No stats for the month ${target}.`);\r\n\t\t}\r\n\t\tawait FS(path).unlinkIfExists();\r\n\t\tthis.globalModlog('REMOVEWINRATES', null, target);\r\n\t\tthis.privateGlobalModAction(`${user.name} removed Random Battle winrates for the month of ${target}`);\r\n\t},\r\n};\r\n\r\nexport const pages: Chat.PageTable = {\r\n\tasync winrates(query, user) {\r\n\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\r\n\t\tquery = query.join('-').split('--');\r\n\t\tconst format = toID(query.shift());\r\n\t\tif (!format) return this.errorReply(`Specify a format to view winrates for.`);\r\n\t\tif (!stats.formats[format]) {\r\n\t\t\treturn this.errorReply(`That format does not have winrates tracked.`);\r\n\t\t}\r\n\t\tcheckRollover();\r\n\t\tconst sorter = toID(query.shift() || 'zscore');\r\n\t\tif (!['zscore', 'raw'].includes(sorter)) {\r\n\t\t\treturn this.errorReply(`Invalid sorting method. Must be either 'zscore' or 'raw'.`);\r\n\t\t}\r\n\t\tconst month = query.shift() || getMonth();\r\n\t\tif (!/^[0-9]{4}-[0-9]{2}$/.test(month)) {\r\n\t\t\treturn this.errorReply(`Invalid month: ${month}`);\r\n\t\t}\r\n\t\tconst isOldMonth = month !== getMonth();\r\n\t\tif (isOldMonth && !(await FS(STATS_PATH.replace('{{MONTH}}', month)).exists())) {\r\n\t\t\treturn this.errorReply(`There are no winrates for that month.`);\r\n\t\t}\r\n\t\tconst formatTitle = Dex.formats.get(format).name;\r\n\t\tlet buf = `

Winrates for ${formatTitle} (${month})

`;\r\n\t\tconst prevMonth = new Date(new Date(`${month}-15`).getTime() - (30 * 24 * 60 * 60 * 1000)).toISOString().slice(0, 7);\r\n\t\tlet hasButton = false;\r\n\t\tif (await FS(STATS_PATH.replace('{{MONTH}}', prevMonth)).exists()) {\r\n\t\t\tbuf += `Previous month`;\r\n\t\t\thasButton = true;\r\n\t\t}\r\n\t\tconst nextMonth = new Date(new Date(`${month}-15`).getTime() + (30 * 24 * 60 * 60 * 1000)).toISOString().slice(0, 7);\r\n\t\tif (await FS(STATS_PATH.replace('{{MONTH}}', nextMonth)).exists()) {\r\n\t\t\tif (hasButton) buf += ` | `;\r\n\t\t\tbuf += `Next month`;\r\n\t\t\thasButton = true;\r\n\t\t}\r\n\t\tbuf += hasButton ? ` | ` : '';\r\n\t\tconst otherSort = sorter === 'zscore' ? 'Raw' : 'Z-Score';\r\n\t\tbuf += ``;\r\n\t\tbuf += `Sort by ${otherSort} descending`;\r\n\t\tbuf += `
`;\r\n\t\tconst statData: Stats = month === stats.month ?\r\n\t\t\tstats : JSON.parse(await FS(STATS_PATH.replace('{{MONTH}}', month)).read());\r\n\t\tconst formatData = statData.formats[format];\r\n\t\tif (!formatData) {\r\n\t\t\tbuf += `
No stats for that format found on that month.
`;\r\n\t\t\treturn buf;\r\n\t\t}\r\n\t\tthis.title = `[Winrates] [${format}] ${month}`;\r\n\t\tlet sortFn: (val: [string, MonEntry]) => Utils.Comparable;\r\n\r\n\t\tif (sorter === 'zscore') {\r\n\t\t\tsortFn = ([_, data]) => [-getZScore(data), -data.timesGenerated];\r\n\t\t} else {\r\n\t\t\tsortFn = ([_, data]) => [\r\n\t\t\t\t-(data.numWins / data.timesGenerated), -data.numWins, -data.timesGenerated,\r\n\t\t\t];\r\n\t\t}\r\n\t\tconst mons = Utils.sortBy(Object.entries(formatData.mons), sortFn);\r\n\t\tbuf += `
`;\r\n\t\tbuf += ``;\r\n\t\tfor (const [mon, data] of mons) {\r\n\t\t\tbuf += ``;\r\n\t\t\tconst {timesGenerated, numWins} = data;\r\n\t\t\tbuf += ``;\r\n\t\t\tbuf += ``;\r\n\t\t\tbuf += ``;\r\n\t\t\tbuf += ``;\r\n\t\t}\r\n\t\tbuf += `
PokemonWin %Z-ScoreRaw winsTimes generated
${Dex.species.get(mon).name}${((numWins / timesGenerated) * 100).toFixed(2)}%${getZScore(data).toFixed(3)}${numWins}${timesGenerated}
`;\r\n\t\treturn buf;\r\n\t},\r\n};\r\n"], "mappings": "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", "names": [] }