footballdata-api 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +1 -1
- data/bin/fbdat +96 -47
- data/config/leagues_tier1.csv +44 -0
- data/lib/footballdata/convert.rb +54 -25
- data/lib/footballdata/leagues.rb +1 -1
- data/lib/footballdata/prettyprint.rb +6 -1
- data/lib/footballdata/version.rb +1 -1
- metadata +3 -3
- data/config/leagues.csv +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97e75a5cbf4b952cb018a40c4ff790a201c26cbd95af1027bae3e7ac2153d1b5
|
4
|
+
data.tar.gz: a4d0cfd2e6ff636f030cd6c4d4d949f2173763cc39352b28b3425ad9aa077796
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1c8650effbb80caec23410ee3fc739f379976359f044b29eff3a02d7bd82f23d76f7daffd6b2cfa76dfbdcbc6be53e178a04929b02401a30641f29cb3d0bd18
|
7
|
+
data.tar.gz: 39d810683288fc35703f19fd1643af8bb0b8332168ae4d4e819eb681444ea4c27e7c0b36daccf27fc97d02704aa6325696579a6d5b3941988cd6bef8f400d0ec
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
data/bin/fbdat
CHANGED
@@ -16,14 +16,6 @@ Webcache.root = if File.exist?( '/sports/cache' )
|
|
16
16
|
'./cache'
|
17
17
|
end
|
18
18
|
|
19
|
-
## note - free tier (tier one) plan - 10 requests/minute
|
20
|
-
## (one request every 6 seconds 6*10=60 secs)
|
21
|
-
## 10 API calls per minute max.
|
22
|
-
## note - default sleep (delay in secs) is 3 sec(s)
|
23
|
-
|
24
|
-
## change from 10 to 1 sec(s) for interactive use
|
25
|
-
Webget.config.sleep = 1
|
26
|
-
|
27
19
|
|
28
20
|
Footballdata.config.convert.out_dir = if File.exist?( '/sports/cache.api.fbdat' )
|
29
21
|
puts " setting convert out_dir to >/sports/cache.api.fbdat<"
|
@@ -43,6 +35,7 @@ def self.main( args=ARGV )
|
|
43
35
|
opts = {
|
44
36
|
cached: false,
|
45
37
|
convert: true,
|
38
|
+
file: nil,
|
46
39
|
}
|
47
40
|
|
48
41
|
parser = OptionParser.new do |parser|
|
@@ -53,9 +46,20 @@ parser = OptionParser.new do |parser|
|
|
53
46
|
opts[:cached] = cached
|
54
47
|
end
|
55
48
|
|
56
|
-
parser.on( "--no-convert",
|
57
|
-
"turn off conversion to .csv in #{Footballdata.config.convert.out_dir} - default is (#{
|
58
|
-
opts[:convert] =
|
49
|
+
parser.on( "--[no-]convert",
|
50
|
+
"turn on/off conversion to .csv in #{Footballdata.config.convert.out_dir} - default is (#{opts[:convert]})" ) do |convert|
|
51
|
+
opts[:convert] = convert
|
52
|
+
end
|
53
|
+
|
54
|
+
parser.on( "--print", "--pp",
|
55
|
+
"pretty print cached data in #{Webcache.root}; no download & conversion") do |print|
|
56
|
+
opts[:cached] = true
|
57
|
+
opts[:convert] = false
|
58
|
+
end
|
59
|
+
|
60
|
+
parser.on( "-f FILE", "--file FILE",
|
61
|
+
"read leagues (and seasons) via .csv file") do |file|
|
62
|
+
opts[:file] = file
|
59
63
|
end
|
60
64
|
end
|
61
65
|
parser.parse!( args )
|
@@ -68,6 +72,19 @@ puts "ARGV:"
|
|
68
72
|
p args
|
69
73
|
|
70
74
|
|
75
|
+
## note - free tier (tier one) plan - 10 requests/minute
|
76
|
+
## (one request every 6 seconds 6*10=60 secs)
|
77
|
+
## 10 API calls per minute max.
|
78
|
+
## note - default sleep (delay in secs) is 3 sec(s)
|
79
|
+
|
80
|
+
## change from 10 to 1 sec(s) for interactive use
|
81
|
+
## assume --file/-f as non-interactive/batch use for now
|
82
|
+
Webget.config.sleep = opts[:file] ? 10 : 1
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
71
88
|
## try special args
|
72
89
|
|
73
90
|
if ['plan', 'plans',
|
@@ -118,11 +135,13 @@ end
|
|
118
135
|
##
|
119
136
|
## todo - add more date offsets - t+2,t+3,t+4, etc.
|
120
137
|
|
138
|
+
|
139
|
+
|
121
140
|
date = if ['y', 'yesterday', 't-1', '-1'].include?( args[0] )
|
122
141
|
Date.today-1
|
123
142
|
elsif ['t', 'tomorrow', 't+1', '1', '+1'].include?( args[0] )
|
124
143
|
Date.today+1
|
125
|
-
elsif ['m', 'match', 'matches', 'today'].include?( args[0]
|
144
|
+
elsif ['m', 'match', 'matches', 'today'].include?( args[0] )
|
126
145
|
Date.today
|
127
146
|
else
|
128
147
|
nil
|
@@ -170,51 +189,81 @@ end
|
|
170
189
|
##
|
171
190
|
## note - only use "generic" uniform league codes for now!!
|
172
191
|
|
173
|
-
league_code = (args[0] || 'eng.1').downcase
|
174
|
-
|
175
|
-
## todo - find a better name
|
176
|
-
## use internal_league_code or such - why? why not?
|
177
|
-
### convenience helpers - lets you use eng.1, euro, etc.
|
178
|
-
## check if mapping for league_code
|
179
|
-
metal_league_code = find_league!( league_code )
|
180
192
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
193
|
+
datasets = if opts[:file]
|
194
|
+
read_datasets( opts[:file] )
|
195
|
+
else
|
196
|
+
parse_datasets_args( args )
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
## step 0 - validate and fill-up seasons etc.
|
201
|
+
datasets.each do |dataset|
|
202
|
+
league_key, seasons = dataset
|
203
|
+
|
204
|
+
## todo - find a better name
|
205
|
+
## use internal_league_code or such - why? why not?
|
206
|
+
### convenience helpers - lets you use eng.1, euro, etc.
|
207
|
+
## check if mapping for league_code
|
208
|
+
metal_league_code = find_league!( league_key )
|
209
|
+
|
210
|
+
## note - default to latest season of league
|
211
|
+
## might be 2024/25 or 2024 or
|
212
|
+
# for world cup 2022 or such
|
213
|
+
if seasons.empty?
|
214
|
+
seasons = case league_key
|
215
|
+
when 'world' then [Season('2022')]
|
216
|
+
when 'euro' then [Season('2024')]
|
217
|
+
when 'br.1', 'copa.l' then [Season('2024')]
|
218
|
+
else [Season('2024/25')]
|
219
|
+
end
|
220
|
+
dataset[1] = seasons
|
221
|
+
end
|
199
222
|
end
|
200
223
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
224
|
+
## step 1 - download
|
225
|
+
datasets.each do |league_key, seasons|
|
226
|
+
## todo - find a better name
|
227
|
+
## use internal_league_code or such - why? why not?
|
228
|
+
### convenience helpers - lets you use eng.1, euro, etc.
|
229
|
+
## check if mapping for league_code
|
230
|
+
metal_league_code = find_league!( league_key )
|
231
|
+
seasons.each do |season|
|
232
|
+
season_start_year = season.start_year ## use year - why? why not?
|
233
|
+
pp [metal_league_code, season_start_year]
|
234
|
+
|
235
|
+
if opts[:cached]
|
236
|
+
## do nothing
|
237
|
+
else
|
238
|
+
## download dataset(s)
|
239
|
+
## try download
|
240
|
+
## note: include teams (for convert) for now too!!
|
241
|
+
Metal.teams( metal_league_code, season_start_year )
|
242
|
+
Metal.matches( metal_league_code, season_start_year )
|
243
|
+
end
|
244
|
+
|
245
|
+
url = Metal.competition_matches_url( metal_league_code,
|
246
|
+
season_start_year )
|
247
|
+
pp url
|
248
|
+
#=> "http://api.football-data.org/v4/competitions/EC/matches?season=2024"
|
205
249
|
|
206
|
-
data = Webcache.read_json( url )
|
207
|
-
## pp data
|
250
|
+
data = Webcache.read_json( url )
|
251
|
+
## pp data
|
208
252
|
|
209
|
-
pp_matches( data )
|
253
|
+
pp_matches( data )
|
254
|
+
end # each season
|
255
|
+
end # each dataset
|
210
256
|
|
211
257
|
|
212
258
|
if opts[:convert]
|
213
|
-
|
214
|
-
|
259
|
+
puts "==> converting to .csv"
|
260
|
+
datasets.each do |league_key, seasons|
|
261
|
+
seasons.each do |season|
|
262
|
+
convert( league: league_key, season: season )
|
263
|
+
end
|
264
|
+
end
|
215
265
|
end
|
216
266
|
|
217
|
-
|
218
267
|
end # def self.main
|
219
268
|
end # module Footballdata
|
220
269
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
key, code, seasons
|
2
|
+
|
3
|
+
eng.1, PL, 2024/25 2023/24 2022/23 2021/22 2020/21
|
4
|
+
# incl. team(s) from wales
|
5
|
+
eng.2, ELC, 2024/25 2023/24 2022/23 2021/22 2020/21
|
6
|
+
# PL - Premier League, England 27 seasons | 2019-08-09 - 2020-07-25 / matchday 31
|
7
|
+
# ELC - Championship, England 3 seasons | 2019-08-02 - 2020-07-22 / matchday 38
|
8
|
+
|
9
|
+
es.1, PD, 2024/25 2023/24 2022/23 2021/22 2020/21
|
10
|
+
# PD - Primera Division, Spain 27 seasons | 2019-08-16 - 2020-07-19 / matchday 31
|
11
|
+
|
12
|
+
pt.1, PPL, 2024/25 2023/24 2022/23 2021/22 2020/21
|
13
|
+
# PPL - Primeira Liga, Portugal 9 seasons | 2019-08-10 - 2020-07-26 / matchday 28
|
14
|
+
|
15
|
+
de.1, BL1, 2024/25 2023/24 2022/23 2021/22 2020/21
|
16
|
+
# BL1 - Bundesliga, Germany 24 seasons | 2019-08-16 - 2020-06-27 / matchday 34
|
17
|
+
|
18
|
+
nl.1, DED, 2024/25 2023/24 2022/23 2021/22 2020/21
|
19
|
+
# DED - Eredivisie, Netherlands 10 seasons | 2019-08-09 - 2020-03-08 / matchday 34
|
20
|
+
|
21
|
+
fr.1, FL1, 2024/25 2023/24 2022/23 2021/22 2020/21
|
22
|
+
# incl. team(s) monaco
|
23
|
+
|
24
|
+
it.1, SA, 2024/25 2023/24 2022/23 2021/22 2020/21
|
25
|
+
# SA - Serie A, Italy 15 seasons | 2019-08-24 - 2020-08-02 / matchday 27
|
26
|
+
|
27
|
+
br.1, BSA, 2024 2023 2022 2021 2020
|
28
|
+
|
29
|
+
|
30
|
+
########
|
31
|
+
## int'l cups
|
32
|
+
uefa.cl, CL, 2024/25 2023/24 2022/23 2021/22 2020/21
|
33
|
+
## note: cl is country code for chile!! - use champs - why? why not?
|
34
|
+
## was europe.cl / cl
|
35
|
+
## todo/check: use champs and NOT cl - why? why not?
|
36
|
+
|
37
|
+
copa.l, CLI, 2024 2023 2022 2021
|
38
|
+
## Copa Libertadores
|
39
|
+
|
40
|
+
|
41
|
+
############
|
42
|
+
## national teams
|
43
|
+
euro, EC, 2024 2021
|
44
|
+
world, WC, 2022
|
data/lib/footballdata/convert.rb
CHANGED
@@ -6,15 +6,16 @@ module Footballdata
|
|
6
6
|
STAGES = {
|
7
7
|
'REGULAR_SEASON' => ['Regular'],
|
8
8
|
|
9
|
+
'QUALIFICATION' => ['Qualifying'],
|
9
10
|
'PRELIMINARY_ROUND' => ['Qualifying', 'Preliminary Round' ],
|
10
11
|
'PRELIMINARY_SEMI_FINALS' => ['Qualifying', 'Preliminary Semifinals' ],
|
11
12
|
'PRELIMINARY_FINAL' => ['Qualifying', 'Preliminary Final' ],
|
12
|
-
'1ST_QUALIFYING_ROUND' => ['Qualifying', '
|
13
|
-
'2ND_QUALIFYING_ROUND' => ['Qualifying', '
|
14
|
-
'3RD_QUALIFYING_ROUND' => ['Qualifying', '
|
15
|
-
'QUALIFICATION_ROUND_1' => ['Qualifying', '
|
16
|
-
'QUALIFICATION_ROUND_2' => ['Qualifying', '
|
17
|
-
'QUALIFICATION_ROUND_3' => ['Qualifying', '
|
13
|
+
'1ST_QUALIFYING_ROUND' => ['Qualifying', 'Round 1' ],
|
14
|
+
'2ND_QUALIFYING_ROUND' => ['Qualifying', 'Round 2' ],
|
15
|
+
'3RD_QUALIFYING_ROUND' => ['Qualifying', 'Round 3' ],
|
16
|
+
'QUALIFICATION_ROUND_1' => ['Qualifying', 'Round 1' ],
|
17
|
+
'QUALIFICATION_ROUND_2' => ['Qualifying', 'Round 2' ],
|
18
|
+
'QUALIFICATION_ROUND_3' => ['Qualifying', 'Round 3' ],
|
18
19
|
'ROUND_1' => ['Qualifying', 'Round 1'], ## use Qual. Round 1 - why? why not?
|
19
20
|
'ROUND_2' => ['Qualifying', 'Round 2'],
|
20
21
|
'ROUND_3' => ['Qualifying', 'Round 3'],
|
@@ -29,6 +30,7 @@ STAGES = {
|
|
29
30
|
'LAST_16' => ['Finals', 'Round of 16'], ## use Last 16 - why? why not?
|
30
31
|
'QUARTER_FINALS' => ['Finals', 'Quarterfinals'],
|
31
32
|
'SEMI_FINALS' => ['Finals', 'Semifinals'],
|
33
|
+
'THIRD_PLACE' => ['Finals', 'Third place play-off'],
|
32
34
|
'FINAL' => ['Finals', 'Final'],
|
33
35
|
}
|
34
36
|
|
@@ -95,12 +97,40 @@ matches.each do |m|
|
|
95
97
|
score = m['score']
|
96
98
|
|
97
99
|
|
98
|
-
stage_key = m['stage']
|
99
100
|
|
101
|
+
group = m['group']
|
102
|
+
## GROUP_A
|
103
|
+
## shorten group to A|B|C etc.
|
104
|
+
if group && group =~ /^(GROUP_|Group )/
|
105
|
+
group = group.sub( /^(GROUP_|Group )/, '' )
|
106
|
+
else
|
107
|
+
if group.nil?
|
108
|
+
group = ''
|
109
|
+
else
|
110
|
+
puts "!! WARN - group defined with NON GROUP!? >#{group}< reset to empty"
|
111
|
+
puts " and matchday to >#{m['matchday']}<"
|
112
|
+
## reset group to empty
|
113
|
+
group = ''
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
stage_key = m['stage']
|
100
119
|
stats['stage'][ stage_key ] += 1 ## track stage counts
|
101
120
|
|
102
|
-
|
103
|
-
stage, stage_round
|
121
|
+
|
122
|
+
stage, stage_round = if group.empty?
|
123
|
+
## map stage to stage + round
|
124
|
+
STAGES[ stage_key ]
|
125
|
+
else
|
126
|
+
## if group defined ignore stage
|
127
|
+
## hard-core always to group for now
|
128
|
+
if stage_key != 'GROUP_STAGE'
|
129
|
+
puts "!! WARN - group defined BUT stage set to >#{stage_key}<"
|
130
|
+
puts " and matchday to >#{m['matchday']}<"
|
131
|
+
end
|
132
|
+
['Group', nil]
|
133
|
+
end
|
104
134
|
|
105
135
|
if stage.nil?
|
106
136
|
puts "!! ERROR - no stage mapping found for stage >#{stage_key}<"
|
@@ -115,23 +145,12 @@ matches.each do |m|
|
|
115
145
|
## matchday 1, 2 etc.
|
116
146
|
matchday = matchday_num.to_s
|
117
147
|
else
|
118
|
-
## note - if matchday defined
|
119
|
-
##
|
120
|
-
matchday =
|
121
|
-
matchday << stage_round
|
122
|
-
matchday << " | Leg #{matchday_num}" if matchday_num &&
|
123
|
-
(matchday_num == 1 || matchday_num == 2)
|
148
|
+
## note - if matchday/round defined, use it
|
149
|
+
## note - ignore possible leg in matchday for now
|
150
|
+
matchday = stage_round
|
124
151
|
end
|
125
152
|
|
126
153
|
|
127
|
-
|
128
|
-
group = m['group'] || ''
|
129
|
-
## GROUP_A
|
130
|
-
## shorten group to A|B|C etc.
|
131
|
-
group = group.sub( /^GROUP_/, '' )
|
132
|
-
|
133
|
-
|
134
|
-
|
135
154
|
teams[ team1 ] += 1
|
136
155
|
teams[ team2 ] += 1
|
137
156
|
|
@@ -164,7 +183,7 @@ matches.each do |m|
|
|
164
183
|
ht = ''
|
165
184
|
when 'FINISHED'
|
166
185
|
ft, ht, et, pen = convert_score( score )
|
167
|
-
when 'AWARDED'
|
186
|
+
when 'AWARDED' # AWARDED
|
168
187
|
assert( score['duration'] == 'REGULAR', 'score.duration REGULAR expected' )
|
169
188
|
ft = "#{score['fullTime']['home']}-#{score['fullTime']['away']}"
|
170
189
|
ft << ' (*)'
|
@@ -206,7 +225,17 @@ matches.each do |m|
|
|
206
225
|
local = tz.to_local( utc )
|
207
226
|
date = local.strftime( '%Y-%m-%d' )
|
208
227
|
time = local.strftime( '%H:%M' )
|
209
|
-
|
228
|
+
|
229
|
+
## pretty print timezone
|
230
|
+
### todo/fix - bundle into fmt_timezone method or such for reuse
|
231
|
+
tz_abbr = local.strftime( '%Z' ) ## e.g. EEST or if not available +03 or such
|
232
|
+
tz_offset = local.strftime( '%z' ) ## e.g. +0300
|
233
|
+
|
234
|
+
timezone = if tz_abbr =~ /^[+-][0-9]+$/ ## only digits (no abbrev.)
|
235
|
+
tz_offset
|
236
|
+
else
|
237
|
+
"#{tz_abbr}/#{tz_offset}"
|
238
|
+
end
|
210
239
|
end
|
211
240
|
|
212
241
|
|
data/lib/footballdata/leagues.rb
CHANGED
@@ -2,7 +2,7 @@ module Footballdata
|
|
2
2
|
|
3
3
|
def self.find_league!( league )
|
4
4
|
@leagues ||= begin
|
5
|
-
recs = read_csv( "#{FootballdataApi.root}/config/
|
5
|
+
recs = read_csv( "#{FootballdataApi.root}/config/leagues_tier1.csv" )
|
6
6
|
leagues = {}
|
7
7
|
recs.each do |rec|
|
8
8
|
leagues[ rec['key'] ] = rec['code']
|
@@ -39,6 +39,7 @@ def self.fmt_match( rec )
|
|
39
39
|
TIMED
|
40
40
|
FINISHED
|
41
41
|
POSTPONED
|
42
|
+
AWARDED
|
42
43
|
IN_PLAY
|
43
44
|
].include?( status ), "unknown status - #{status}" )
|
44
45
|
|
@@ -89,7 +90,11 @@ def self.fmt_match( rec )
|
|
89
90
|
score << "#{et} a.e.t. "
|
90
91
|
score << "(#{ft}, #{ht})"
|
91
92
|
else
|
92
|
-
|
93
|
+
if !ht.empty?
|
94
|
+
score << "#{ft} (#{ht})"
|
95
|
+
else
|
96
|
+
score << "#{ft}"
|
97
|
+
end
|
93
98
|
end
|
94
99
|
|
95
100
|
buf << score
|
data/lib/footballdata/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: footballdata-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: football-timezones
|
@@ -88,7 +88,7 @@ files:
|
|
88
88
|
- README.md
|
89
89
|
- Rakefile
|
90
90
|
- bin/fbdat
|
91
|
-
- config/
|
91
|
+
- config/leagues_tier1.csv
|
92
92
|
- lib/footballdata.rb
|
93
93
|
- lib/footballdata/convert-score.rb
|
94
94
|
- lib/footballdata/convert.rb
|
data/config/leagues.csv
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
key, code
|
2
|
-
|
3
|
-
eng.1, PL # incl. team(s) from wales
|
4
|
-
eng.2, ELC
|
5
|
-
# PL - Premier League, England 27 seasons | 2019-08-09 - 2020-07-25 / matchday 31
|
6
|
-
# ELC - Championship, England 3 seasons | 2019-08-02 - 2020-07-22 / matchday 38
|
7
|
-
#
|
8
|
-
# 2019 => 2019/20
|
9
|
-
# 2018 => 2018/19
|
10
|
-
# 2017 => xxx 2017-18 - requires subscription !!!
|
11
|
-
|
12
|
-
es.1, PD
|
13
|
-
# PD - Primera Division, Spain 27 seasons | 2019-08-16 - 2020-07-19 / matchday 31
|
14
|
-
|
15
|
-
pt.1, PPL
|
16
|
-
# PPL - Primeira Liga, Portugal 9 seasons | 2019-08-10 - 2020-07-26 / matchday 28
|
17
|
-
|
18
|
-
de.1, BL1
|
19
|
-
# BL1 - Bundesliga, Germany 24 seasons | 2019-08-16 - 2020-06-27 / matchday 34
|
20
|
-
|
21
|
-
nl.1, DED
|
22
|
-
# DED - Eredivisie, Netherlands 10 seasons | 2019-08-09 - 2020-03-08 / matchday 34
|
23
|
-
|
24
|
-
fr.1, FL1 # incl. team(s) monaco
|
25
|
-
# FL1 - Ligue 1, France
|
26
|
-
# 9 seasons | 2019-08-09 - 2020-05-31 / matchday 38
|
27
|
-
#
|
28
|
-
# 2019 => 2019/20
|
29
|
-
# 2018 => 2018/19
|
30
|
-
# 2017 => xxx 2017-18 - requires subscription !!!
|
31
|
-
|
32
|
-
it.1, SA
|
33
|
-
# SA - Serie A, Italy 15 seasons | 2019-08-24 - 2020-08-02 / matchday 27
|
34
|
-
|
35
|
-
br.1, BSA
|
36
|
-
# BSA - Série A, Brazil
|
37
|
-
# 4 seasons | 2020-05-03 - 2020-12-06 / matchday 10
|
38
|
-
#
|
39
|
-
# 2020 => 2020
|
40
|
-
# 2019 => 2019
|
41
|
-
# 2018 => 2018
|
42
|
-
# 2017 => xxx 2017 - requires subscription !!!
|
43
|
-
|
44
|
-
uefa.cl, CL ## note: cl is country code for chile!! - use champs - why? why not?
|
45
|
-
## was europe.cl / cl
|
46
|
-
## todo/check: use champs and NOT cl - why? why not?
|
47
|
-
|
48
|
-
copa.l, CLI
|
49
|
-
## Copa Libertadores
|
50
|
-
|
51
|
-
############
|
52
|
-
## national teams
|
53
|
-
euro, EC
|
54
|
-
world, WC
|