footballdata-api 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|