Spaces:
Running
Running
{ | |
"version": 3, | |
"sources": ["../../../../server/chat-plugins/randombattles/winrates.ts"], | |
"sourcesContent": ["/**\n * A chat plugin to store, calculate, and view winrates in random battle formats.\n * @author mia-pi-git\n */\n\nimport { FS, Utils } from '../../../lib';\n\ninterface Stats {\n\telo: number;\n\tmonth: string;\n\tformats: Record<string, FormatData>;\n}\n\ninterface MonEntry {\n\ttimesGenerated: number;\n\tnumWins: number;\n}\n\ninterface FormatData {\n\tmons: Record<string, MonEntry>;\n\tperiod?: number; // how often it resets - defaults to 1mo\n}\n\nconst STATS_PATH = Monitor.logPath('randbats/{{MONTH}}-winrates.json').path;\nexport const stats: Stats = getDefaultStats();\n\ntry {\n\tconst path = STATS_PATH.replace('{{MONTH}}', getMonth());\n\tif (!Monitor.logPath('randbats/').existsSync()) {\n\t\tMonitor.logPath('randbats/').mkdirSync();\n\t}\n\tconst savedStats = JSON.parse(FS(path).readSync());\n\tstats.elo = savedStats.elo;\n\tstats.month = savedStats.month;\n\tfor (const k in stats.formats) {\n\t\tstats.formats[k] = savedStats.formats[k] || stats.formats[k];\n\t}\n} catch {}\n\nfunction getDefaultStats() {\n\treturn {\n\t\telo: 1500,\n\t\tmonth: getMonth(),\n\t\tformats: {\n\t\t\t// all of these requested by rands staff. they don't anticipate it being changed much\n\t\t\t// so i'm not spending the time to add commands to toggle this\n\t\t\tgen9randombattle: { mons: {} },\n\t\t\tgen9randomdoublesbattle: { mons: {} },\n\t\t\tgen9babyrandombattle: { mons: {} },\n\t\t\tgen9superstaffbrosultimate: { mons: {} },\n\t\t\tgen8randombattle: { mons: {} },\n\t\t\tgen7randombattle: { mons: {} },\n\t\t\tgen6randombattle: { mons: {} },\n\t\t\tgen5randombattle: { mons: {} },\n\t\t\tgen4randombattle: { mons: {} },\n\t\t\tgen3randombattle: { mons: {} },\n\t\t\tgen2randombattle: { mons: {} },\n\t\t\tgen1randombattle: { mons: {} },\n\t\t},\n\t} as Stats;\n}\n\nexport function saveStats(month = getMonth()) {\n\t// clone to avoid race conditions with the data getting deleted later (on month rollover)\n\tconst curStats = { ...stats };\n\tFS(STATS_PATH.replace('{{MONTH}}', month)).writeUpdate(() => JSON.stringify(curStats));\n}\n\nfunction getMonth() {\n\treturn Chat.toTimestamp(new Date()).split(' ')[0].slice(0, -3);\n}\n\n// no, this cannot be baseSpecies - some formes matter, ex arceus formes\n// no, there is no better way to do this.\n// yes, i tried.\nexport function getSpeciesName(set: PokemonSet, format: Format) {\n\tconst species = set.species;\n\tconst item = Dex.items.get(set.item);\n\tconst moves = set.moves;\n\tconst megaRayquazaPossible = ['gen6', 'gen7'].includes(format.mod) && !format.ruleset.includes('Mega Rayquaza Clause');\n\tif (species.startsWith(\"Pikachu-\")) {\n\t\treturn 'Pikachu';\n\t} else if (species.startsWith(\"Unown-\")) {\n\t\treturn 'Unown';\n\t} else if (species === \"Gastrodon-East\") {\n\t\treturn 'Gastrodon';\n\t} else if (species === \"Magearna-Original\") {\n\t\treturn \"Magearna\";\n\t} else if (species === \"Genesect-Douse\") {\n\t\treturn \"Genesect\";\n\t} else if (species === \"Dudunsparce-Three-Segment\") {\n\t\treturn 'Dudunsparce';\n\t} else if (species === \"Maushold-Four\") {\n\t\treturn 'Maushold';\n\t} else if (species === \"Greninja-Bond\") {\n\t\treturn 'Greninja';\n\t} else if (species === \"Keldeo-Resolute\") {\n\t\treturn 'Keldeo';\n\t} else if (species === \"Zarude-Dada\") {\n\t\treturn 'Zarude';\n\t} else if (species === 'Polteageist-Antique') {\n\t\treturn 'Polteageist';\n\t} else if (species === 'Sinistcha-Masterpiece') {\n\t\treturn 'Sinistcha';\n\t} else if (species === \"Squawkabilly-Blue\") {\n\t\treturn \"Squawkabilly\";\n\t} else if (species === \"Squawkabilly-White\") {\n\t\treturn \"Squawkabilly-Yellow\";\n\t} else if (species.startsWith(\"Basculin-\")) {\n\t\treturn \"Basculin\";\n\t} else if (species.startsWith(\"Sawsbuck-\")) {\n\t\treturn \"Sawsbuck\";\n\t} else if (species.startsWith(\"Vivillon-\")) {\n\t\treturn \"Vivillon\";\n\t} else if (species.startsWith(\"Florges-\")) {\n\t\treturn \"Florges\";\n\t} else if (species.startsWith(\"Furfrou-\")) {\n\t\treturn \"Furfrou\";\n\t} else if (species.startsWith(\"Minior-\")) {\n\t\treturn \"Minior\";\n\t} else if (species.startsWith(\"Toxtricity-\")) {\n\t\treturn 'Toxtricity';\n\t} else if (species.startsWith(\"Tatsugiri-\")) {\n\t\treturn 'Tatsugiri';\n\t} else if (species.startsWith(\"Alcremie-\")) {\n\t\treturn 'Alcremie';\n\t} else if (species === \"Zacian\" && item.name === \"Rusted Sword\") {\n\t\treturn 'Zacian-Crowned';\n\t} else if (species === \"Zamazenta\" && item.name === \"Rusted Shield\") {\n\t\treturn \"Zamazenta-Crowned\";\n\t} else if (species === \"Kyogre\" && item.name === \"Blue Orb\") {\n\t\treturn \"Kyogre-Primal\";\n\t} else if (species === \"Groudon\" && item.name === \"Red Orb\") {\n\t\treturn \"Groudon-Primal\";\n\t} else if (item.megaStone) {\n\t\treturn item.megaStone;\n\t} else if (species === \"Rayquaza\" && moves.includes('Dragon Ascent') && !item.zMove && megaRayquazaPossible) {\n\t\treturn \"Rayquaza-Mega\";\n\t} else if (species === \"Poltchageist-Artisan\") { // Babymons from here on out\n\t\treturn \"Poltchageist\";\n\t} else if (species === \"Shellos-East\") {\n\t\treturn \"Shellos\";\n\t} else if (species === \"Sinistea-Antique\") {\n\t\treturn \"Sinistea\";\n\t} else if (species.startsWith(\"Deerling-\")) {\n\t\treturn \"Deerling\";\n\t} else if (species.startsWith(\"Flabe\\u0301be\\u0301-\")) {\n\t\treturn \"Flabe\\u0301be\\u0301\";\n\t} else {\n\t\treturn species;\n\t}\n}\n\nfunction checkRollover() {\n\tif (stats.month !== getMonth()) {\n\t\tsaveStats(stats.month);\n\t\tObject.assign(stats, getDefaultStats());\n\t\tsaveStats();\n\t}\n}\n\nconst getZScore = (data: MonEntry) => (\n\t2 * Math.sqrt(data.timesGenerated) * (data.numWins / data.timesGenerated - 0.5)\n);\n\nexport const handlers: Chat.Handlers = {\n\tonBattleEnd(battle, winner, players) {\n\t\tvoid collectStats(battle, winner, players);\n\t},\n};\n\nasync function collectStats(battle: RoomBattle, winner: ID, players: ID[]) {\n\tconst formatData = stats.formats[battle.format];\n\tlet eloFloor = stats.elo;\n\tconst format = Dex.formats.get(battle.format);\n\tif (format.mod === 'gen2' || format.team === 'randomBaby') {\n\t\t// ladders are inactive, so use a lower threshold\n\t\teloFloor = 1150;\n\t} else if (format.mod !== `gen${Dex.gen}`) {\n\t\teloFloor = 1300;\n\t} else if (format.gameType === 'doubles') {\n\t\t// may need to be raised again if ladder takes off further\n\t\teloFloor = 1400;\n\t}\n\tif (!formatData || (format.mod !== 'gen9ssb' && battle.rated < eloFloor) || !winner) return;\n\tcheckRollover();\n\tfor (const p of battle.players) {\n\t\tconst team = await battle.getPlayerTeam(p);\n\t\tif (!team) return; // ???\n\t\tconst mons = team.map(f => getSpeciesName(f, format));\n\t\tfor (const mon of mons) {\n\t\t\tif (!formatData.mons[mon]) formatData.mons[mon] = { timesGenerated: 0, numWins: 0 };\n\t\t\tformatData.mons[mon].timesGenerated++;\n\t\t\tif (toID(winner) === toID(p.name)) {\n\t\t\t\tformatData.mons[mon].numWins++;\n\t\t\t}\n\t\t}\n\t}\n\tsaveStats();\n}\n\nexport const commands: Chat.ChatCommands = {\n\trwr: 'randswinrates',\n\trandswinrates(target, room, user) {\n\t\ttarget = toID(target);\n\t\tif (/^(gen|)[0-9]+$/.test(target)) {\n\t\t\tif (target.startsWith('gen')) target = target.slice(3);\n\t\t\ttarget = `gen${target}randombattle`;\n\t\t}\n\t\treturn this.parse(`/j view-winrates-${target ? Dex.formats.get(target).id : `gen${Dex.gen}randombattle`}`);\n\t},\n\trandswinrateshelp: [\n\t\t'/randswinrates OR /rwr [format] - Get a list of the win rates for all Pokemon in the given Random Battles format.',\n\t],\n\n\tasync removewinrates(target, room, user) {\n\t\tthis.checkCan('rangeban');\n\t\tif (!/^[0-9]{4}-[0-9]{2}$/.test(target) || target === getMonth()) {\n\t\t\treturn this.errorReply(`Invalid month: ${target}`);\n\t\t}\n\t\tconst path = STATS_PATH.replace('{{MON}}', target);\n\t\tif (!(await FS(path).exists())) {\n\t\t\treturn this.errorReply(`No stats for the month ${target}.`);\n\t\t}\n\t\tawait FS(path).unlinkIfExists();\n\t\tthis.globalModlog('REMOVEWINRATES', null, target);\n\t\tthis.privateGlobalModAction(`${user.name} removed Random Battle winrates for the month of ${target}`);\n\t},\n};\n\nexport const pages: Chat.PageTable = {\n\tasync winrates(query, user) {\n\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\tquery = query.join('-').split('--');\n\t\tconst format = toID(query.shift());\n\t\tif (!format) return this.errorReply(`Specify a format to view winrates for.`);\n\t\tif (!stats.formats[format]) {\n\t\t\treturn this.errorReply(`That format does not have winrates tracked.`);\n\t\t}\n\t\tcheckRollover();\n\t\tconst sorter = toID(query.shift() || 'zscore');\n\t\tif (!['zscore', 'raw'].includes(sorter)) {\n\t\t\treturn this.errorReply(`Invalid sorting method. Must be either 'zscore' or 'raw'.`);\n\t\t}\n\t\tconst month = query.shift() || getMonth();\n\t\tif (!/^[0-9]{4}-[0-9]{2}$/.test(month)) {\n\t\t\treturn this.errorReply(`Invalid month: ${month}`);\n\t\t}\n\t\tconst isOldMonth = month !== getMonth();\n\t\tif (isOldMonth && !(await FS(STATS_PATH.replace('{{MONTH}}', month)).exists())) {\n\t\t\treturn this.errorReply(`There are no winrates for that month.`);\n\t\t}\n\t\tconst formatTitle = Dex.formats.get(format).name;\n\t\tlet buf = `<div class=\"pad\"><h2>Winrates for ${formatTitle} (${month})</h2>`;\n\t\tconst prevMonth = new Date(new Date(`${month}-15`).getTime() - (30 * 24 * 60 * 60 * 1000)).toISOString().slice(0, 7);\n\t\tlet hasButton = false;\n\t\tif (await FS(STATS_PATH.replace('{{MONTH}}', prevMonth)).exists()) {\n\t\t\tbuf += `<a class=\"button\" href=\"/view-winrates-${format}--${sorter}--${prevMonth}\">Previous month</a>`;\n\t\t\thasButton = true;\n\t\t}\n\t\tconst nextMonth = new Date(new Date(`${month}-15`).getTime() + (30 * 24 * 60 * 60 * 1000)).toISOString().slice(0, 7);\n\t\tif (await FS(STATS_PATH.replace('{{MONTH}}', nextMonth)).exists()) {\n\t\t\tif (hasButton) buf += ` | `;\n\t\t\tbuf += `<a class=\"button\" href=\"/view-winrates-${format}--${sorter}--${nextMonth}\">Next month</a>`;\n\t\t\thasButton = true;\n\t\t}\n\t\tbuf += hasButton ? ` | ` : '';\n\t\tconst otherSort = sorter === 'zscore' ? 'Raw' : 'Z-Score';\n\t\tbuf += `<a class=\"button\" target=\"replace\" href=\"/view-winrates-${format}--${toID(otherSort)}--${month}\">`;\n\t\tbuf += `Sort by ${otherSort} descending</a>`;\n\t\tbuf += `<hr />`;\n\t\tconst statData: Stats = month === stats.month ?\n\t\t\tstats : JSON.parse(await FS(STATS_PATH.replace('{{MONTH}}', month)).read());\n\t\tconst formatData = statData.formats[format];\n\t\tif (!formatData) {\n\t\t\tbuf += `<div class=\"message-error\">No stats for that format found on that month.</div>`;\n\t\t\treturn buf;\n\t\t}\n\t\tthis.title = `[Winrates] [${format}] ${month}`;\n\t\tlet sortFn: (val: [string, MonEntry]) => Utils.Comparable;\n\n\t\tif (sorter === 'zscore') {\n\t\t\tsortFn = ([_, data]) => [-getZScore(data), -data.timesGenerated];\n\t\t} else {\n\t\t\tsortFn = ([_, data]) => [\n\t\t\t\t-(data.numWins / data.timesGenerated), -data.numWins, -data.timesGenerated,\n\t\t\t];\n\t\t}\n\t\tconst mons = Utils.sortBy(Object.entries(formatData.mons), sortFn);\n\t\tbuf += `<div class=\"ladder pad\"><table><tr><th>Pokemon</th><th>Win %</th><th>Z-Score</th>`;\n\t\tbuf += `<th>Raw wins</th><th>Times generated</th></tr>`;\n\t\tfor (const [mon, data] of mons) {\n\t\t\tbuf += `<tr><td>${Dex.species.get(mon).name}</td>`;\n\t\t\tconst { timesGenerated, numWins } = data;\n\t\t\tbuf += `<td>${((numWins / timesGenerated) * 100).toFixed(2)}%</td>`;\n\t\t\tbuf += `<td>${getZScore(data).toFixed(3)}</td>`;\n\t\t\tbuf += `<td>${numWins}</td><td>${timesGenerated}</td>`;\n\t\t\tbuf += `</tr>`;\n\t\t}\n\t\tbuf += `</table></div></div>`;\n\t\treturn buf;\n\t},\n};\n"], | |
"mappings": "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", | |
"names": [] | |
} | |