From 853755493c4d36901f2d852580988b2817c7d1ba Mon Sep 17 00:00:00 2001 From: Kirk Scheibelhut Date: Tue, 27 Aug 2024 15:39:30 -0700 Subject: [PATCH] update formats lists closes #9. as covered in the comments, it is not feasible to programmatically determine these at runtime --- stats/convert | 2 +- stats/src/parser.ts | 2 +- stats/src/stats.ts | 4 +- stats/src/util.ts | 176 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 154 insertions(+), 30 deletions(-) diff --git a/stats/convert b/stats/convert index 8bdc921..ed43758 100755 --- a/stats/convert +++ b/stats/convert @@ -92,7 +92,7 @@ async function convert(month, out, split) { async function write(out, gen, dir, base, split) { const format = base.slice(0, base.lastIndexOf('-')); - const leads = !stats.isNonSinglesFormat(format) && !UNSUPPORTED.includes(format); + const leads = !stats.isNonSinglesFormat(format, false) && !UNSUPPORTED.includes(format); const metagame = !UNSUPPORTED.includes(format); const display = stats.Display.fromReports(gen, diff --git a/stats/src/parser.ts b/stats/src/parser.ts index 3cb980e..246cd66 100644 --- a/stats/src/parser.ts +++ b/stats/src/parser.ts @@ -117,7 +117,7 @@ export const Parser = new class { if (winner !== 'tie') player.outcome = winner === side ? 'win' : 'loss'; battle[side] = player; } - if (!raw.log || util.isNonSinglesFormat(format)) return battle; + if (!raw.log || util.isNonSinglesFormat(format, legacy)) return battle; const emptyFlags = () => ({ roar: false, diff --git a/stats/src/stats.ts b/stats/src/stats.ts index e4e0842..12b5573 100644 --- a/stats/src/stats.ts +++ b/stats/src/stats.ts @@ -132,9 +132,9 @@ export const Stats = new class { ) { stats = stats || {total: {}, tags: {}}; - const singles = !util.isNonSinglesFormat(format); + const singles = !util.isNonSinglesFormat(format, legacy); const short = - !util.isNon6v6Format(format) && (battle.turns < 2 || (battle.turns < 3 && singles)); + !util.isNon6v6Format(format, legacy) && (battle.turns < 2 || (battle.turns < 3 && singles)); const playerWeights: number[][] = []; for (const player of [battle.p1, battle.p2]) { diff --git a/stats/src/util.ts b/stats/src/util.ts index d31e51b..2085846 100644 --- a/stats/src/util.ts +++ b/stats/src/util.ts @@ -106,40 +106,164 @@ export function revertFormes(gen: Generation, id: ID, legacy: boolean) { return getBaseSpecies(gen, species.id, legacy).id; } -// FIXME: Generate this based on gameType from config/formats.js +const NON_SINGLES_FORMATS_LEGACY = new Set([ + 'battlespotdoubles', + 'battlespotspecial7', + 'battlespottriples', + 'gen5doublesou', + 'gen5smogondoubles', + 'gen7battlespotdoubles', + 'gen7doublesanythinggoes', + 'gen7doublesanythinggoesbeta', + 'gen7doublesou', + 'gen7doublesoubeta', + 'gen7pokebankdoublesag', + 'gen7pokebankdoublesanythinggoes', + 'gen7pokebankdoublesou', + 'gen7pokebankdoublesoubeta', + 'gen7randomdoublesbattle', + 'gen7vgc2017', + 'gen7vgc2017beta', + 'gen7vgc2018', + 'gen7vgc2019', + 'gen8doublesou', + 'gen8doublesubers', + 'gen8doublesuu', + 'gen8vgc2020', + 'gen8vgc2021', + 'gen8vgc2022', + 'orassmogondoubles', + 'randomdoublesbattle', + 'randomtriplesbattle', + 'smogondoubles', + 'smogondoublessuspecttest', + 'smogondoublesubers', + 'smogondoublesuu', + 'smogontriples', + 'vgc2014', + 'vgc2015', + 'vgc2016', + 'vgc2017', +]); + const NON_SINGLES_FORMATS = new Set([ - 'battlespotdoubles', 'battlespotspecial7', 'battlespottriples', 'doublesou', 'doublesubers', - 'doublesuu', 'gen5doublesou', 'gen5smogondoubles', 'gen7battlespotdoubles', - 'gen7doublesanythinggoes', 'gen7doublesanythinggoesbeta', 'gen7doublesou', 'gen7doublesoubeta', - 'gen7pokebankdoubleaanythinggoes', 'gen7pokebankdoublesag', 'gen7pokebankdoublesanythinggoes', - 'gen7pokebankdoublesou', 'gen7pokebankdoublesoubeta', 'gen7randomdoublesbattle', - 'gen7vgc2017', 'gen7vgc2017beta', 'orassmogondoubles', 'randomdoublesbattle', 'smogondoublesuu', - 'randomtriplesbattle', 'smogondoubles', 'smogondoublesubers', 'smogontriples', 'smogontriples', - 'gen8doublesou', 'gen8doublesubers', 'gen8doublesuu', 'vgc2014', 'vgc2015', 'vgc2016', - 'gen6vgc2016', 'gen7vgc2017', 'gen7vgc2018', 'gen7vgc2019', 'gen7vgc2019sunseries', - 'gen7vgc2019moonseries', 'gen7vgc2019ultraseries', 'gen8vgc2020', 'gen8vgc2021', - 'gen8vgc2021series9', 'gen8vgc2021series9limitonerestrictedrestrictedlegendary', 'gen8vgc2022', - // TODO: add gen9 formats + ...NON_SINGLES_FORMATS_LEGACY, + // old + 'doublesou', + 'doublesubers', + 'doublesuu', + 'gen6vgc2016', + 'gen7vgc2019sunseries', + 'gen7vgc2019moonseries', + 'gen7vgc2019ultraseries', + 'gen8vgc2021series9', + 'gen8vgc2021series9limitonerestrictedrestrictedlegendary', + // format.gameType !== 'singles' && !format.id.endsWith('customgame') && !format.team + 'gen3doublesou', + 'gen4doublesou', + 'gen4vgc2010', + 'gen5vgc2013', + 'gen6battlespotdoubles', + 'gen6battlespottriples', + 'gen6doublesou', + 'gen6vgc2015', + 'gen7doublesuu', + 'gen92v2doubles', + 'gen9doubleslc', + 'gen9doublesou', + 'gen9doublesubers', + 'gen9doublesuu', + 'gen9freeforall', + 'gen9nationaldexdoubles', + 'gen9triples', + 'gen9vgc2024regg', + 'gen9vgc2024reggbo3', + 'gen9vgc2024regh', + 'gen9vgc2024reghbo3', ]); -export function isNonSinglesFormat(format: ID) { - return NON_SINGLES_FORMATS.has(format.endsWith('suspecttest') ? format.slice(0, -11) : format); +// Note: Generations doesn't have the concept of "format", so looking up a formats's `gameType` as +// one might expect to be able to do with a Dex doesn't work. Furthermore, formats are configurable +// and change over time -- many of these formats are no longer present in Pokémon Showdown's +// canonical config/formats.ts data +export function isNonSinglesFormat(format: ID, legacy: boolean) { + if (format.endsWith('suspecttest')) format = format.slice(0, -11) as ID; + return (legacy ? NON_SINGLES_FORMATS_LEGACY : NON_SINGLES_FORMATS).has(format); } -// FIXME: Generate this based on teamLength from config/formats.js +const NON_6V6_FORMATS_LEGACY = new Set([ + 'battlespotdoubles', + 'battlespotsingles', + 'battlespotspecial7', + 'challengecup1v1', + 'gen5gbusingles', + 'gen71v1', + 'gen7alolafriendly', + 'gen7battlespotdoubles', + 'gen7battlespotsingles', + 'gen7challengecup1v1', + 'gen7vgc2017', + 'gen7vgc2017beta', + 'gen81v1', + 'gen8firstblood', + 'gen8tagteamsingles', + 'gen91v1', + 'pgllittlecup', + 'vgc2014', + 'vgc2015', + 'vgc2016', + 'vgc2017', +]); + const NON_6V6_FORMATS = new Set([ - '1v1', 'battlespotdoubles', 'battlespotsingles', 'battlespotspecial7', 'challengecup1v1', - 'gen5gbusingles', 'gen71v1', 'gen7alolafriendly', 'gen7battlespotdoubles', 'gen81v1', - 'gen7battlespotsingles', 'gen7challengecup1v1', 'gen7vgc2017', 'gen7vgc2017beta', 'pgllittlecup', - 'vgc2014', 'vgc2015', 'vgc2016', 'gen6vgc2016', 'gen7vgc2017', 'gen7vgc2018', 'gen7vgc2019', - 'gen7vgc2019sunseries', 'gen7vgc2019moonseries', 'fen7vgc2019ultraseries', 'gen8vgc2020', - 'gen8vgc2021', 'gen8vgc2021series9', 'gen8vgc2021series9limitonerestrictedrestrictedlegendary', - 'gen8vgc2022', 'gen8firstblood', 'gen8tagteamsingles', - // TODO: add gen9 formats + ...NON_6V6_FORMATS_LEGACY, + // old + '1v1', + 'gen5gbusingles', + 'gen6vgc2016', + 'gen7vgc2018', + 'gen7vgc2019', + 'gen7vgc2019moonseries', + 'gen7vgc2019sunseries', + 'gen7vgc2019ultraseries', + 'gen8firstblood', + 'gen8tagteamsingles', + 'gen8vgc2020', + 'gen8vgc2021', + 'gen8vgc2021series9', + 'gen8vgc2021series9limitonerestrictedrestrictedlegendary', + 'gen8vgc2022', + // format.teamLength !== 'singles' && Dex.formats.getRuleTable(format).pickedTeamSize < 6 + 'gen9bssregg', + 'gen9bssregh', + 'gen9vgc2024regg', + 'gen9vgc2024reggbo3', + 'gen9vgc2024regh', + 'gen9vgc2024reghbo3', + 'gen92v2doubles', + 'gen9bssfactory', + 'gen9challengecup1v1', + 'gen9challengecup2v2', + 'gen8bssfactory', + 'gen8cap1v1', + 'gen7bssfactory', + 'gen8battlestadiumsingles', + 'gen61v1', + 'gen6battlespotsingles', + 'gen6vgc2015', + 'gen6battlespotdoubles', + 'gen51v1', + 'gen5vgc2013', + 'gen41v1', + 'gen31v1', + 'gen21v1', + 'gen11v1', ]); -export function isNon6v6Format(format: ID) { - return NON_6V6_FORMATS.has(format.endsWith('suspecttest') ? format.slice(0, -11) : format); +// See comment above regarding why we can't just rely on a format's `pickedTeamSize` to compute this +export function isNon6v6Format(format: ID, legacy: boolean) { + if (format.endsWith('suspecttest')) format = format.slice(0, -11) as ID; + return (legacy ? NON_6V6_FORMATS_LEGACY : NON_6V6_FORMATS).has(format); } export function canonicalizeFormat(format: ID) {