11const axios = require ( "axios" ) ;
22const fs = require ( "fs" ) ;
3- const { ArgumentParser } = require ( ' argparse' ) ;
3+ const { ArgumentParser } = require ( " argparse" ) ;
44
55regional_form_name = ( str ) => {
6- return str
7- . replace ( / A l o l a / g, "Alolan" )
8- . replace ( / G a l a r / g, "Galarian" )
9- . replace ( / H i s u i / g, "Hisuian" ) ;
10- }
6+ return str
7+ . replace ( / A l o l a / g, "Alolan" )
8+ . replace ( / G a l a r / g, "Galarian" )
9+ . replace ( / H i s u i / g, "Hisuian" ) ;
10+ } ;
1111
1212noBars = ( str ) => {
13- return str . replace ( / \| / g, "" ) ;
14- }
15-
16- const parser = new ArgumentParser ( { description : "Smogon usage statistics scraping tool." } ) ;
17- parser . add_argument ( '-d' , '--date' , { help : 'Data in YYYY-MM format, example: 2022-01. Required.' , required : true } ) ;
18- parser . add_argument ( '-g' , '--gen' , { help : 'Pokemon generation number, example: 6. Required.' , required : true } ) ;
19- parser . add_argument ( '-t' , '--tier' , { help : 'Tier name, example: OU, National Dex. Required.' , required : true } ) ;
20- parser . add_argument ( '-c' , '--cutline' , { help : 'Usage stats cutline. Must be: 0, 1500, 1630, 1760. Default: 0.' , default : 0 } ) ;
21-
22- ( async ( ) => {
23-
24- const _date = parser . parse_args ( ) [ 'date' ] ;
25- const _gen = "gen" + parseInt ( parser . parse_args ( ) [ 'gen' ] ) ;
26- const _tier = ( parser . parse_args ( ) [ 'tier' ] ) . toLowerCase ( ) . replace ( / / g, "" ) ;
27- const _cutline = parser . parse_args ( ) [ 'cutline' ] ;
28- const _scrape = _gen + _tier + "-" + _cutline ;
29-
30- const _stat = await axios . get ( 'https://www.smogon.com/stats/' + _date + '/moveset/' + _scrape + '.txt' ) ;
31- const _rank = await axios . get ( 'https://www.smogon.com/stats/' + _date + '/' + _scrape + '.txt' ) ;
32-
33- var pokemonData = { } ;
34-
35- // get ranking/usage data:
36- for ( let x = 5 ; x < _rank . data . split ( "\n" ) . length - 2 ; x ++ ) {
37-
38- let pokemon = _rank . data . split ( "\n" ) [ x ] . split ( "|" ) ;
39-
40- let name_reg = / ( [ A - Z a - z ' - : . ] + (?: [ A - Z a - z \s ] + ) ? (?: [ A - Z a - z ( ) ] + ) ) / ;
41- let pokemonName = regional_form_name ( String ( pokemon [ 2 ] ) . match ( name_reg ) [ 0 ] ) ;
42-
43- let rank = parseInt ( pokemon [ 1 ] ) ;
44- let usage_p = parseFloat ( pokemon [ 3 ] ) ;
45- let usage_r = parseInt ( pokemon [ 4 ] ) ;
46-
47- pokemonData [ pokemonName ] = { "name" : pokemonName , "rank" : rank , "usage_percent" : usage_p , "usage_raw" : usage_r } ;
48-
49- }
13+ return str . replace ( / \| / g, "" ) ;
14+ } ;
15+
16+ const parser = new ArgumentParser ( {
17+ description : "Smogon usage statistics scraping tool." ,
18+ } ) ;
19+ parser . add_argument ( "-d" , "--date" , {
20+ help : "Data in YYYY-MM format, example: 2022-01. Required." ,
21+ required : true ,
22+ } ) ;
23+ parser . add_argument ( "-g" , "--gen" , {
24+ help : "Pokemon generation number, example: 6. Required." ,
25+ required : true ,
26+ } ) ;
27+ parser . add_argument ( "-t" , "--tier" , {
28+ help : "Tier name, example: OU, National Dex. Required." ,
29+ required : true ,
30+ } ) ;
31+ parser . add_argument ( "-c" , "--cutline" , {
32+ help : "Usage stats cutline. Must be: 0, 1500, 1630, 1760. Default: 0." ,
33+ default : 0 ,
34+ } ) ;
35+
36+ ( async ( ) => {
37+ const _date = parser . parse_args ( ) [ "date" ] ;
38+ const _gen = "gen" + parseInt ( parser . parse_args ( ) [ "gen" ] ) ;
39+ const _tier = parser . parse_args ( ) [ "tier" ] . toLowerCase ( ) . replace ( / / g, "" ) ;
40+ const _cutline = parser . parse_args ( ) [ "cutline" ] ;
41+ const _scrape = _gen + _tier + "-" + _cutline ;
42+
43+ const _stat = await axios . get (
44+ "https://www.smogon.com/stats/" + _date + "/moveset/" + _scrape + ".txt"
45+ ) ;
46+ const _rank = await axios . get (
47+ "https://www.smogon.com/stats/" + _date + "/" + _scrape + ".txt"
48+ ) ;
49+
50+ var pokemonData = { } ;
51+
52+ // get ranking/usage data:
53+ for ( let x = 5 ; x < _rank . data . split ( "\n" ) . length - 2 ; x ++ ) {
54+ let pokemon = _rank . data . split ( "\n" ) [ x ] . split ( "|" ) ;
55+
56+ let name_reg = / ( [ A - Z a - z ' - : . ] + (?: [ A - Z a - z \s ] + ) ? (?: [ A - Z a - z ( ) ] + ) ) / ;
57+ let pokemonName = regional_form_name ( String ( pokemon [ 2 ] ) . match ( name_reg ) [ 0 ] ) ;
58+
59+ let rank = parseInt ( pokemon [ 1 ] ) ;
60+ let usage_p = parseFloat ( pokemon [ 3 ] ) ;
61+ let usage_r = parseInt ( pokemon [ 4 ] ) ;
62+
63+ pokemonData [ pokemonName ] = {
64+ name : pokemonName ,
65+ rank : rank ,
66+ usage_percent : usage_p ,
67+ usage_raw : usage_r ,
68+ } ;
69+ }
70+
71+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
72+
73+ const _stat_data = _stat . data . split (
74+ "+----------------------------------------+ \n +----------------------------------------+"
75+ ) ;
76+ const _name_percent_reg =
77+ / ( [ A - Z a - z ' - : . ] + (?: [ A - Z a - z \s ] + ) ? (?: [ A - Z a - z ( ) ] + ) ) ( [ \s ] + ) ( [ 0 - 9 . % ] + ) / ;
78+ const _name_reg = / ( [ A - Z a - z ' - : . ] + (?: [ A - Z a - z \s ] + ) ? (?: [ A - Z a - z ( ) ] + ) ) / ;
79+
80+ for ( let x = 0 ; x < _stat_data . length ; x ++ ) {
81+ let pokemon = _stat_data [ x ] . split (
82+ "+----------------------------------------+ \n"
83+ ) ;
84+
85+ // Workaround for problem with the way the page is formatted:
86+ if ( x == 0 ) pokemon . shift ( ) ;
5087
5188 ///////////////////////////////////////////////////////////////////////////////////////////////////////
5289
90+ let pokemonName = regional_form_name (
91+ String ( pokemon [ 0 ] ) . match ( _name_reg ) [ 0 ]
92+ ) ;
5393
54- const _stat_data = _stat . data . split ( "+----------------------------------------+ \n +----------------------------------------+" ) ;
55- const _name_percent_reg = / ( [ A - Z a - z ' - : . ] + (?: [ A - Z a - z \s ] + ) ? (?: [ A - Z a - z ( ) ] + ) ) ( [ \s ] + ) ( [ 0 - 9 . % ] + ) / ;
56- const _name_reg = / ( [ A - Z a - z ' - : . ] + (?: [ A - Z a - z \s ] + ) ? (?: [ A - Z a - z ( ) ] + ) ) / ;
57-
58- for ( let x = 0 ; x < _stat_data . length ; x ++ ) {
59-
60- let pokemon = _stat_data [ x ] . split ( "+----------------------------------------+ \n" ) ;
61-
62- // Workaround for problem with the way the page is formatted:
63- if ( x == 0 ) pokemon . shift ( ) ;
64-
65- ///////////////////////////////////////////////////////////////////////////////////////////////////////
66-
67- let pokemonName = regional_form_name ( String ( pokemon [ 0 ] ) . match ( _name_reg ) [ 0 ] ) ;
68-
69- ///////////////////////////////////////////////////////////////////////////////////////////////////////
70-
71- let pokemAbils = { } ;
72- let pokemAbil = noBars ( pokemon [ 2 ] ) . split ( "\n" ) ;
73-
74- for ( let x = 1 ; x < pokemAbil . length - 1 ; x ++ )
75- pokemAbils [ String ( pokemAbil [ x ] . match ( _name_percent_reg ) [ 1 ] ) ] = parseFloat ( pokemAbil [ x ] . match ( _name_percent_reg ) [ 3 ] ) ;
76- pokemonData [ pokemonName ] [ "abilities_percent" ] = pokemAbils ;
77-
78- ///////////////////////////////////////////////////////////////////////////////////////////////////////
94+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
7995
80- let pokemItems = { } ;
81- let pokemItem = noBars ( pokemon [ 3 ] ) . split ( "\n" ) ;
96+ let pokemAbils = { } ;
97+ let pokemAbil = noBars ( pokemon [ 2 ] ) . split ( "\n" ) ;
8298
83- for ( let x = 1 ; x < pokemItem . length - 1 ; x ++ )
84- pokemItems [ String ( pokemItem [ x ] . match ( _name_percent_reg ) [ 1 ] ) ] = parseFloat ( pokemItem [ x ] . match ( _name_percent_reg ) [ 3 ] ) ;
85- pokemonData [ pokemonName ] [ "items_percent" ] = pokemItems ;
99+ for ( let x = 1 ; x < pokemAbil . length - 1 ; x ++ )
100+ pokemAbils [ String ( pokemAbil [ x ] . match ( _name_percent_reg ) [ 1 ] ) ] = parseFloat (
101+ pokemAbil [ x ] . match ( _name_percent_reg ) [ 3 ]
102+ ) ;
103+ pokemonData [ pokemonName ] [ "abilities_percent" ] = pokemAbils ;
86104
87- ///////////////////////////////////////////////////////////////////////////////////////////////////////
105+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
88106
89- let pokemSpreads = { } ;
90- let pokemSpread = noBars ( pokemon [ 4 ] ) . split ( "\n" ) ;
107+ let pokemItems = { } ;
108+ let pokemItem = noBars ( pokemon [ 3 ] ) . split ( "\n" ) ;
91109
92- let spread_reg = / ( [ a - z A - Z : 0 - 9 \/ ] + ) ( [ ] + ) ( [ 0 - 9 . % ] + ) / ;
110+ for ( let x = 1 ; x < pokemItem . length - 1 ; x ++ )
111+ pokemItems [ String ( pokemItem [ x ] . match ( _name_percent_reg ) [ 1 ] ) ] = parseFloat (
112+ pokemItem [ x ] . match ( _name_percent_reg ) [ 3 ]
113+ ) ;
114+ pokemonData [ pokemonName ] [ "items_percent" ] = pokemItems ;
93115
94- for ( let x = 1 ; x < pokemSpread . length - 1 ; x ++ )
95- pokemSpreads [ String ( pokemSpread [ x ] . match ( spread_reg ) [ 1 ] ) ] = parseFloat ( pokemSpread [ x ] . match ( spread_reg ) [ 3 ] ) ;
96- pokemonData [ pokemonName ] [ "stat_spreads" ] = pokemSpreads ;
116+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
97117
98- ///////////////////////////////////////////////////////////////////////////////////////////////////////
118+ let pokemSpreads = { } ;
119+ let pokemSpread = noBars ( pokemon [ 4 ] ) . split ( "\n" ) ;
99120
100- let pokemMoves = { } ;
101- let pokemMove = noBars ( pokemon [ 5 ] ) . split ( "\n" ) ;
121+ let spread_reg = / ( [ a - z A - Z : 0 - 9 \/ ] + ) ( [ ] + ) ( [ 0 - 9 . % ] + ) / ;
102122
103- for ( let x = 1 ; x < pokemMove . length - 1 ; x ++ )
104- pokemMoves [ String ( pokemMove [ x ] . match ( _name_percent_reg ) [ 1 ] ) ] = parseFloat ( pokemMove [ x ] . match ( _name_percent_reg ) [ 3 ] ) ;
105- pokemonData [ pokemonName ] [ "common_moves" ] = pokemMoves ;
123+ for ( let x = 1 ; x < pokemSpread . length - 1 ; x ++ )
124+ pokemSpreads [ String ( pokemSpread [ x ] . match ( spread_reg ) [ 1 ] ) ] = parseFloat (
125+ pokemSpread [ x ] . match ( spread_reg ) [ 3 ]
126+ ) ;
127+ pokemonData [ pokemonName ] [ "stat_spreads" ] = pokemSpreads ;
106128
107- ///////////////////////////////////////////////////////////////////////////////////////////////////////
129+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
108130
109- let pokemTeams = { } ;
110- let pokemTeam = noBars ( pokemon [ 6 ] ) . split ( "\n" ) ;
131+ let pokemMoves = { } ;
132+ let pokemMove = noBars ( pokemon [ 5 ] ) . split ( "\n" ) ;
111133
112- for ( let x = 1 ; x < pokemTeam . length - 1 ; x ++ ) {
113- try {
114- pokemTeams [ regional_form_name ( String ( pokemTeam [ x ] . match ( _name_percent_reg ) [ 1 ] ) ) ] = parseFloat ( pokemTeam [ x ] . match ( _name_percent_reg ) [ 3 ] ) ;
115- } catch ( e ) { continue } ;
116- }
117- pokemonData [ pokemonName ] [ "common_teammates" ] = pokemTeams ;
134+ for ( let x = 1 ; x < pokemMove . length - 1 ; x ++ )
135+ pokemMoves [ String ( pokemMove [ x ] . match ( _name_percent_reg ) [ 1 ] ) ] = parseFloat (
136+ pokemMove [ x ] . match ( _name_percent_reg ) [ 3 ]
137+ ) ;
138+ pokemonData [ pokemonName ] [ "common_moves" ] = pokemMoves ;
118139
119- ///////////////////////////////////////////////////////////////////////////////////////////////////////
140+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
120141
121- let pokemCCs = { } ;
122- let pokemCC = noBars ( pokemon [ 7 ] ) . split ( "\n" ) ;
142+ let pokemTeams = { } ;
143+ let pokemTeam = noBars ( pokemon [ 6 ] ) . split ( "\n" ) ;
144+
145+ for ( let x = 1 ; x < pokemTeam . length - 1 ; x ++ ) {
146+ try {
147+ pokemTeams [
148+ regional_form_name ( String ( pokemTeam [ x ] . match ( _name_percent_reg ) [ 1 ] ) )
149+ ] = parseFloat ( pokemTeam [ x ] . match ( _name_percent_reg ) [ 3 ] ) ;
150+ } catch ( e ) {
151+ continue ;
152+ }
153+ }
154+ pokemonData [ pokemonName ] [ "common_teammates" ] = pokemTeams ;
123155
124- let stat_reg = / \( ( [ 0 - 9 . % ] + K O e d \/ [ 0 - 9 . % ] + s w i t c h e d o u t ) \) / ;
156+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
125157
126- for ( let x = 1 ; x < pokemCC . length ; x ++ ) {
127- if ( x % 2 !== 0 ) continue ;
128- try {
129- pokemCCs [ regional_form_name ( String ( pokemCC [ x - 1 ] . match ( _name_reg ) [ 1 ] ) ) ] = String ( pokemCC [ x ] . match ( stat_reg ) [ 1 ] ) ;
130- } catch ( e ) { continue } ;
131- }
132- pokemonData [ pokemonName ] [ "checks_counters" ] = pokemCCs ;
158+ let pokemCCs = { } ;
159+ let pokemCC = noBars ( pokemon [ 7 ] ) . split ( "\n" ) ;
133160
134- ///////////////////////////////////////////////////////////////////////////////////////////////////////
161+ let stat_reg = / \( ( [ 0 - 9 . % ] + K O e d \/ [ 0 - 9 . % ] + s w i t c h e d o u t ) \) / ;
135162
163+ for ( let x = 1 ; x < pokemCC . length ; x ++ ) {
164+ if ( x % 2 !== 0 ) continue ;
165+ try {
166+ pokemCCs [
167+ regional_form_name ( String ( pokemCC [ x - 1 ] . match ( _name_reg ) [ 1 ] ) )
168+ ] = String ( pokemCC [ x ] . match ( stat_reg ) [ 1 ] ) ;
169+ } catch ( e ) {
170+ continue ;
171+ }
136172 }
173+ pokemonData [ pokemonName ] [ "checks_counters" ] = pokemCCs ;
137174
138- fs . writeFileSync ( _scrape + ".json" , JSON . stringify ( pokemonData , null , 4 ) ) ;
175+ ///////////////////////////////////////////////////////////////////////////////////////////////////////
176+ }
139177
140- } ) ( ) ;
178+ fs . writeFileSync ( _scrape + ".json" , JSON . stringify ( pokemonData , null , 4 ) ) ;
179+ } ) ( ) ;
0 commit comments