footballdata-api 0.3.0 → 0.4.1
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 +2 -0
- data/Rakefile +1 -3
- data/bin/fbdat +11 -13
- data/config/leagues.csv +54 -0
- data/lib/footballdata/convert-score.rb +44 -0
- data/lib/footballdata/convert.rb +22 -110
- data/lib/footballdata/download.rb +11 -11
- data/lib/footballdata/leagues.rb +20 -55
- data/lib/footballdata/teams.rb +13 -14
- data/lib/footballdata/version.rb +2 -2
- data/lib/footballdata.rb +3 -7
- metadata +5 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0556b03185d985c2f364151400a6dfe04ee9160e8560739e005e00a3e872b806
|
4
|
+
data.tar.gz: 17711037928d5c213a7915245a2d511e7fba6f4c47ff582357616c87a1ffd7cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1bbeef48c5633b97e984e535857ba294a3326cddf1fd6d20ea426d33c95c0e0c7d6e9d12f9fa4a97a12291ba3c1d12e4751f57a5f0bfe3e736ebcf34be56f51
|
7
|
+
data.tar.gz: 2640f463715d6a0ff697502dfdd8af38e3c7cf0d6dafc0fb575d44360b548a692ff9c256d6e3ad4e9673dd108636969f372d7a2e153d872ee8c240b2e470e4c6
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -18,10 +18,8 @@ Hoe.spec 'footballdata-api' do
|
|
18
18
|
self.history_file = 'CHANGELOG.md'
|
19
19
|
|
20
20
|
self.extra_deps = [
|
21
|
-
['
|
22
|
-
['season-formats'],
|
21
|
+
['football-timezones'],
|
23
22
|
['webget'],
|
24
|
-
['cocos'], ## later pull in with sportsdb-writers
|
25
23
|
]
|
26
24
|
|
27
25
|
self.licenses = ['Public Domain']
|
data/bin/fbdat
CHANGED
@@ -20,12 +20,17 @@ Webcache.root = if File.exist?( '/sports/cache' )
|
|
20
20
|
## (one request every 6 seconds 6*10=60 secs)
|
21
21
|
## 10 API calls per minute max.
|
22
22
|
## note - default sleep (delay in secs) is 3 sec(s)
|
23
|
-
Webget.config.sleep = 10
|
24
23
|
|
25
|
-
|
26
|
-
|
24
|
+
## change from 10 to 1 sec(s) for interactive use
|
25
|
+
Webget.config.sleep = 1
|
27
26
|
|
28
27
|
|
28
|
+
Footballdata.config.convert.out_dir = if File.exist?( '/sports/cache.api.fbdat' )
|
29
|
+
puts " setting convert out_dir to >/sports/cache.api.fbdat<"
|
30
|
+
'/sports/cache.api.fbdat'
|
31
|
+
else
|
32
|
+
'.' ## use working dir
|
33
|
+
end
|
29
34
|
|
30
35
|
|
31
36
|
require 'optparse'
|
@@ -166,19 +171,12 @@ end
|
|
166
171
|
## note - only use "generic" uniform league codes for now!!
|
167
172
|
|
168
173
|
league_code = (args[0] || 'eng.1').downcase
|
169
|
-
metal_league_code = nil ## todo - find a better name
|
170
|
-
## use internal_league_code or such - why? why not?
|
171
174
|
|
175
|
+
## todo - find a better name
|
176
|
+
## use internal_league_code or such - why? why not?
|
172
177
|
### convenience helpers - lets you use eng.1, euro, etc.
|
173
178
|
## check if mapping for league_code
|
174
|
-
|
175
|
-
metal_league_code = LEAGUES[ league_code ]
|
176
|
-
else
|
177
|
-
puts "!! ERROR - no code/mapping found for league >#{league_code}<"
|
178
|
-
puts " mappings include:"
|
179
|
-
pp LEAGUES
|
180
|
-
exit 1
|
181
|
-
end
|
179
|
+
metal_league_code = find_league!( league_code )
|
182
180
|
|
183
181
|
|
184
182
|
season = Season( args[1] ||
|
data/config/leagues.csv
ADDED
@@ -0,0 +1,54 @@
|
|
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
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module Footballdata
|
3
|
+
|
4
|
+
def self.convert_score( score )
|
5
|
+
## duration: REGULAR · PENALTY_SHOOTOUT · EXTRA_TIME
|
6
|
+
ft, ht, et, pen = ["","","",""]
|
7
|
+
|
8
|
+
if score['duration'] == 'REGULAR'
|
9
|
+
ft = "#{score['fullTime']['home']}-#{score['fullTime']['away']}"
|
10
|
+
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
11
|
+
elsif score['duration'] == 'EXTRA_TIME'
|
12
|
+
et = "#{score['regularTime']['home']+score['extraTime']['home']}"
|
13
|
+
et << "-"
|
14
|
+
et << "#{score['regularTime']['away']+score['extraTime']['away']}"
|
15
|
+
|
16
|
+
ft = "#{score['regularTime']['home']}-#{score['regularTime']['away']}"
|
17
|
+
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
18
|
+
elsif score['duration'] == 'PENALTY_SHOOTOUT'
|
19
|
+
if score['extraTime']
|
20
|
+
## quick & dirty hack - calc et via regulartime+extratime
|
21
|
+
pen = "#{score['penalties']['home']}-#{score['penalties']['away']}"
|
22
|
+
et = "#{score['regularTime']['home']+score['extraTime']['home']}"
|
23
|
+
et << "-"
|
24
|
+
et << "#{score['regularTime']['away']+score['extraTime']['away']}"
|
25
|
+
|
26
|
+
ft = "#{score['regularTime']['home']}-#{score['regularTime']['away']}"
|
27
|
+
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
28
|
+
else ### south american-style (no extra time)
|
29
|
+
## quick & dirty hacke - calc ft via fullTime-penalties
|
30
|
+
pen = "#{score['penalties']['home']}-#{score['penalties']['away']}"
|
31
|
+
ft = "#{score['fullTime']['home']-score['penalties']['home']}"
|
32
|
+
ft << "-"
|
33
|
+
ft << "#{score['fullTime']['away']-score['penalties']['away']}"
|
34
|
+
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
puts "!! unknown score duration:"
|
38
|
+
pp score
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
[ft,ht,et,pen]
|
43
|
+
end
|
44
|
+
end # module Footballdata
|
data/lib/footballdata/convert.rb
CHANGED
@@ -1,83 +1,6 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
2
|
module Footballdata
|
5
3
|
|
6
|
-
|
7
|
-
TIMEZONES = {
|
8
|
-
'eng.1' => 'Europe/London',
|
9
|
-
'eng.2' => 'Europe/London',
|
10
|
-
|
11
|
-
'es.1' => 'Europe/Madrid',
|
12
|
-
|
13
|
-
'de.1' => 'Europe/Berlin',
|
14
|
-
'fr.1' => 'Europe/Paris',
|
15
|
-
'it.1' => 'Europe/Rome',
|
16
|
-
'nl.1' => 'Europe/Amsterdam',
|
17
|
-
|
18
|
-
'pt.1' => 'Europe/Lisbon',
|
19
|
-
|
20
|
-
## for champs default for not to cet (central european time) - why? why not?
|
21
|
-
'uefa.cl' => 'Europe/Paris',
|
22
|
-
'euro' => 'Europe/Paris',
|
23
|
-
|
24
|
-
## todo/fix - pt.1
|
25
|
-
## one team in madeira!!! check for different timezone??
|
26
|
-
## CD Nacional da Madeira
|
27
|
-
|
28
|
-
'br.1' => 'America/Sao_Paulo',
|
29
|
-
## todo/fix - brazil has 4 timezones
|
30
|
-
## really only two in use for clubs
|
31
|
-
## west and east (amazonas et al)
|
32
|
-
## for now use west for all - why? why not?
|
33
|
-
'copa.l' => 'America/Sao_Paulo',
|
34
|
-
}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def self.convert_score( score )
|
40
|
-
## duration: REGULAR · PENALTY_SHOOTOUT · EXTRA_TIME
|
41
|
-
ft, ht, et, pen = ["","","",""]
|
42
|
-
|
43
|
-
if score['duration'] == 'REGULAR'
|
44
|
-
ft = "#{score['fullTime']['home']}-#{score['fullTime']['away']}"
|
45
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
46
|
-
elsif score['duration'] == 'EXTRA_TIME'
|
47
|
-
et = "#{score['regularTime']['home']+score['extraTime']['home']}"
|
48
|
-
et << "-"
|
49
|
-
et << "#{score['regularTime']['away']+score['extraTime']['away']}"
|
50
|
-
|
51
|
-
ft = "#{score['regularTime']['home']}-#{score['regularTime']['away']}"
|
52
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
53
|
-
elsif score['duration'] == 'PENALTY_SHOOTOUT'
|
54
|
-
if score['extraTime']
|
55
|
-
## quick & dirty hack - calc et via regulartime+extratime
|
56
|
-
pen = "#{score['penalties']['home']}-#{score['penalties']['away']}"
|
57
|
-
et = "#{score['regularTime']['home']+score['extraTime']['home']}"
|
58
|
-
et << "-"
|
59
|
-
et << "#{score['regularTime']['away']+score['extraTime']['away']}"
|
60
|
-
|
61
|
-
ft = "#{score['regularTime']['home']}-#{score['regularTime']['away']}"
|
62
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
63
|
-
else ### south american-style (no extra time)
|
64
|
-
## quick & dirty hacke - calc ft via fullTime-penalties
|
65
|
-
pen = "#{score['penalties']['home']}-#{score['penalties']['away']}"
|
66
|
-
ft = "#{score['fullTime']['home']-score['penalties']['home']}"
|
67
|
-
ft << "-"
|
68
|
-
ft << "#{score['fullTime']['away']-score['penalties']['away']}"
|
69
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
70
|
-
end
|
71
|
-
else
|
72
|
-
puts "!! unknown score duration:"
|
73
|
-
pp score
|
74
|
-
exit 1
|
75
|
-
end
|
76
|
-
|
77
|
-
[ft,ht,et,pen]
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
4
|
#######
|
82
5
|
## map round-like to higher-level stages
|
83
6
|
STAGES = {
|
@@ -114,16 +37,9 @@ STAGES = {
|
|
114
37
|
|
115
38
|
def self.convert( league:, season: )
|
116
39
|
|
117
|
-
### note/fix: cl (champions league for now is a "special" case)
|
118
|
-
# if league.downcase == 'cl'
|
119
|
-
# convert_cl( league: league,
|
120
|
-
# season: season )
|
121
|
-
# return
|
122
|
-
# end
|
123
|
-
|
124
40
|
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
125
41
|
|
126
|
-
league_code =
|
42
|
+
league_code = find_league!( league )
|
127
43
|
|
128
44
|
matches_url = Metal.competition_matches_url( league_code, season.start_year )
|
129
45
|
teams_url = Metal.competition_teams_url( league_code, season.start_year )
|
@@ -132,14 +48,10 @@ def self.convert( league:, season: )
|
|
132
48
|
data_teams = Webcache.read_json( teams_url )
|
133
49
|
|
134
50
|
|
135
|
-
## check for time zone
|
136
|
-
tz_name = TIMEZONES[ league.downcase ]
|
137
|
-
if tz_name.nil?
|
138
|
-
puts "!! ERROR - sorry no timezone configured for league #{league}"
|
139
|
-
exit 1
|
140
|
-
end
|
141
51
|
|
142
|
-
|
52
|
+
## check for time zone
|
53
|
+
tz = find_zone!( league: league,
|
54
|
+
season: season )
|
143
55
|
pp tz
|
144
56
|
|
145
57
|
## build a (reverse) team lookup by name
|
@@ -275,35 +187,35 @@ matches.each do |m|
|
|
275
187
|
end
|
276
188
|
|
277
189
|
|
278
|
-
##
|
279
|
-
## add time, timezone(tz)
|
280
|
-
## 2023-08-18T18:30:00Z
|
281
|
-
## e.g. "utcDate": "2020-05-09T00:00:00Z",
|
282
|
-
## "utcDate": "2023-08-18T18:30:00Z",
|
283
|
-
|
284
|
-
## -- todo - make sure / assert it's always utc - how???
|
285
|
-
## utc = ## tz_utc.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
286
|
-
## note: DateTime.strptime is supposed to be unaware of timezones!!!
|
287
|
-
## use to parse utc
|
288
|
-
utc = DateTime.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' ).to_time.utc
|
289
|
-
assert( utc.strftime( '%Y-%m-%dT%H:%M:%SZ' ) == m['utcDate'], 'utc time mismatch' )
|
290
190
|
|
291
|
-
|
191
|
+
utc = UTC.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
192
|
+
assert( utc.strftime( '%Y-%m-%dT%H:%M:%SZ' ) == m['utcDate'], 'utc time mismatch' )
|
292
193
|
|
293
194
|
|
294
195
|
## do NOT add time if status is SCHEDULED
|
295
196
|
## or POSTPONED for now
|
296
197
|
## otherwise assume time always present - why? why not?
|
198
|
+
##
|
199
|
+
## assume NOT valid utc time if 00:00
|
200
|
+
if utc.hour == 0 && utc.min == 0 &&
|
201
|
+
['SCHEDULED','POSTPONED'].include?( m['status'] )
|
202
|
+
date = utc.strftime( '%Y-%m-%d' )
|
203
|
+
time = ''
|
204
|
+
timezone = ''
|
205
|
+
else
|
206
|
+
local = tz.to_local( utc )
|
207
|
+
date = local.strftime( '%Y-%m-%d' )
|
208
|
+
time = local.strftime( '%H:%M' )
|
209
|
+
timezone = local.strftime( '%Z/%z' )
|
210
|
+
end
|
297
211
|
|
298
212
|
|
299
|
-
|
300
|
-
## todo/fix: assert matchday is a number e.g. 1,2,3, etc.!!!
|
301
213
|
recs << [stage,
|
302
214
|
group,
|
303
215
|
matchday,
|
304
|
-
|
305
|
-
|
306
|
-
|
216
|
+
date,
|
217
|
+
time,
|
218
|
+
timezone,
|
307
219
|
team1,
|
308
220
|
ft,
|
309
221
|
ht,
|
@@ -6,7 +6,7 @@ module Footballdata
|
|
6
6
|
def self.schedule( league:, season: )
|
7
7
|
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
8
8
|
|
9
|
-
league_code =
|
9
|
+
league_code = find_league!( league )
|
10
10
|
puts " mapping league >#{league}< to >#{league_code}<"
|
11
11
|
|
12
12
|
Metal.teams( league_code, season.start_year )
|
@@ -17,7 +17,7 @@ end
|
|
17
17
|
def self.matches( league:, season: )
|
18
18
|
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
19
19
|
|
20
|
-
league_code =
|
20
|
+
league_code = find_league!( league )
|
21
21
|
puts " mapping league >#{league}< to >#{league_code}<"
|
22
22
|
Metal.matches( league_code, season.start_year )
|
23
23
|
end
|
@@ -26,7 +26,7 @@ end
|
|
26
26
|
def self.teams( league:, season: )
|
27
27
|
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
28
28
|
|
29
|
-
league_code =
|
29
|
+
league_code = find_league!( league )
|
30
30
|
puts " mapping league >#{league}< to >#{league_code}<"
|
31
31
|
Metal.teams( league_code, season.start_year )
|
32
32
|
end
|
@@ -38,7 +38,7 @@ end
|
|
38
38
|
|
39
39
|
class Metal
|
40
40
|
|
41
|
-
def self.get( url,
|
41
|
+
def self.get( url,
|
42
42
|
auth: true,
|
43
43
|
headers: {} )
|
44
44
|
|
@@ -84,19 +84,19 @@ class Metal
|
|
84
84
|
def self.competition_teams_url( code, year ) "#{BASE_URL}/competitions/#{code}/teams?season=#{year}"; end
|
85
85
|
def self.competition_standings_url( code, year ) "#{BASE_URL}/competitions/#{code}/standings?season=#{year}"; end
|
86
86
|
def self.competition_scorers_url( code, year ) "#{BASE_URL}/competitions/#{code}/scorers?season=#{year}"; end
|
87
|
-
|
87
|
+
|
88
88
|
def self.matches( code, year,
|
89
|
-
headers: {} )
|
90
|
-
get( competition_matches_url( code, year ),
|
91
|
-
headers: headers )
|
89
|
+
headers: {} )
|
90
|
+
get( competition_matches_url( code, year ),
|
91
|
+
headers: headers )
|
92
92
|
end
|
93
93
|
|
94
|
-
def self.todays_matches_url( date=Date.today )
|
94
|
+
def self.todays_matches_url( date=Date.today )
|
95
95
|
"#{BASE_URL}/matches?"+
|
96
96
|
"dateFrom=#{date.strftime('%Y-%m-%d')}&"+
|
97
|
-
"dateTo=#{(date+1).strftime('%Y-%m-%d')}"
|
97
|
+
"dateTo=#{(date+1).strftime('%Y-%m-%d')}"
|
98
98
|
end
|
99
|
-
def self.todays_matches( date=Date.today ) ## use/rename to matches_today or such - why? why not?
|
99
|
+
def self.todays_matches( date=Date.today ) ## use/rename to matches_today or such - why? why not?
|
100
100
|
get( todays_matches_url( date ) )
|
101
101
|
end
|
102
102
|
|
data/lib/footballdata/leagues.rb
CHANGED
@@ -1,59 +1,24 @@
|
|
1
1
|
module Footballdata
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# DED - Eredivisie , Netherlands 10 seasons | 2019-08-09 - 2020-03-08 / matchday 34
|
24
|
-
|
25
|
-
'fr.1' => 'FL1', # incl. team(s) monaco
|
26
|
-
# FL1 - Ligue 1, France
|
27
|
-
# 9 seasons | 2019-08-09 - 2020-05-31 / matchday 38
|
28
|
-
#
|
29
|
-
# 2019 => 2019/20
|
30
|
-
# 2018 => 2018/19
|
31
|
-
# 2017 => xxx 2017-18 - requires subscription !!!
|
32
|
-
|
33
|
-
'it.1' => 'SA',
|
34
|
-
# SA - Serie A , Italy 15 seasons | 2019-08-24 - 2020-08-02 / matchday 27
|
35
|
-
|
36
|
-
'br.1' => 'BSA',
|
37
|
-
# BSA - Série A, Brazil
|
38
|
-
# 4 seasons | 2020-05-03 - 2020-12-06 / matchday 10
|
39
|
-
#
|
40
|
-
# 2020 => 2020
|
41
|
-
# 2019 => 2019
|
42
|
-
# 2018 => 2018
|
43
|
-
# 2017 => xxx 2017 - requires subscription !!!
|
44
|
-
|
45
|
-
## todo/check: use champs and NOT cl - why? why not?
|
46
|
-
'uefa.cl' => 'CL', ## note: cl is country code for chile!! - use champs - why? why not?
|
47
|
-
## was europe.cl / cl
|
48
|
-
|
49
|
-
## Copa Libertadores
|
50
|
-
'copa.l' => 'CLI',
|
51
|
-
|
52
|
-
############
|
53
|
-
## national teams
|
54
|
-
'euro' => 'EC',
|
55
|
-
'world' => 'WC',
|
56
|
-
|
57
|
-
}
|
3
|
+
def self.find_league!( league )
|
4
|
+
@leagues ||= begin
|
5
|
+
recs = read_csv( "#{FootballdataApi.root}/config/leagues.csv" )
|
6
|
+
leagues = {}
|
7
|
+
recs.each do |rec|
|
8
|
+
leagues[ rec['key'] ] = rec['code']
|
9
|
+
end
|
10
|
+
leagues
|
11
|
+
end
|
12
|
+
|
13
|
+
key = league.downcase
|
14
|
+
code = @leagues[ key ]
|
15
|
+
if code.nil?
|
16
|
+
puts "!! ERROR - no code/mapping found for league >#{league}<"
|
17
|
+
puts " mappings include:"
|
18
|
+
pp @leagues
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
code
|
22
|
+
end
|
58
23
|
end # module Footballdata
|
59
24
|
|
data/lib/footballdata/teams.rb
CHANGED
@@ -8,9 +8,9 @@ module Footballdata
|
|
8
8
|
def self.export_teams( league:, season: )
|
9
9
|
|
10
10
|
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
11
|
-
league_code =
|
11
|
+
league_code = find_league!( league )
|
12
12
|
|
13
|
-
teams_url = Metal.competition_teams_url( league_code,
|
13
|
+
teams_url = Metal.competition_teams_url( league_code,
|
14
14
|
season.start_year )
|
15
15
|
data_teams = Webcache.read_json( teams_url )
|
16
16
|
|
@@ -22,12 +22,12 @@ def self.export_teams( league:, season: )
|
|
22
22
|
clubs = {} ## by country
|
23
23
|
|
24
24
|
data_teams['teams'].each do |rec|
|
25
|
-
|
26
|
-
buf = String.new ### use for string buffer (or String.new('') - why? why not?
|
25
|
+
|
26
|
+
buf = String.new ### use for string buffer (or String.new('') - why? why not?
|
27
27
|
buf << "#{rec['name']}"
|
28
28
|
buf << ", #{rec['founded']}" if rec['founded']
|
29
|
-
if rec['venue']
|
30
|
-
buf << ", @ #{rec['venue']}"
|
29
|
+
if rec['venue']
|
30
|
+
buf << ", @ #{rec['venue']}"
|
31
31
|
# buf << " # #{rec['area']['name']}"
|
32
32
|
end
|
33
33
|
buf << "\n"
|
@@ -39,7 +39,7 @@ def self.export_teams( league:, season: )
|
|
39
39
|
|
40
40
|
alt_names << " | #{rec['tla']}" if rec['tla'] &&
|
41
41
|
rec['tla'] != rec['name']
|
42
|
-
|
42
|
+
|
43
43
|
if alt_names.size > 0
|
44
44
|
buf << " "
|
45
45
|
buf << alt_names
|
@@ -48,7 +48,7 @@ def self.export_teams( league:, season: )
|
|
48
48
|
|
49
49
|
## clean null in address (or keep nulls) - why? why not?
|
50
50
|
## e.g. null Rionegro null
|
51
|
-
## Calle 104 No. 13a - 32 Bogotá null
|
51
|
+
## Calle 104 No. 13a - 32 Bogotá null
|
52
52
|
|
53
53
|
buf << " address: #{rec['address'].gsub( /\bnull\b/, '')}"
|
54
54
|
buf << "\n"
|
@@ -57,21 +57,21 @@ def self.export_teams( league:, season: )
|
|
57
57
|
buf << " colors: #{rec['clubColors']}"
|
58
58
|
buf << "\n"
|
59
59
|
|
60
|
-
country = rec['area']['name']
|
60
|
+
country = rec['area']['name']
|
61
61
|
ary = clubs[ country] ||= []
|
62
62
|
ary << buf
|
63
63
|
end
|
64
64
|
# puts buf
|
65
|
-
|
65
|
+
|
66
66
|
## pp clubs
|
67
67
|
|
68
|
-
|
68
|
+
|
69
69
|
buf = String.new
|
70
70
|
|
71
71
|
if clubs.size > 1
|
72
72
|
clubs.each do |country, ary|
|
73
73
|
buf << "# #{country} - #{ary.size} clubs\n"
|
74
|
-
end
|
74
|
+
end
|
75
75
|
buf << "\n"
|
76
76
|
end
|
77
77
|
|
@@ -82,9 +82,8 @@ def self.export_teams( league:, season: )
|
|
82
82
|
end
|
83
83
|
|
84
84
|
path = "#{config.convert.out_dir}/#{season.to_path}/#{league.downcase}.clubs.txt"
|
85
|
-
write_text( path, buf )
|
85
|
+
write_text( path, buf )
|
86
86
|
end
|
87
87
|
|
88
88
|
|
89
89
|
end # module Footballdata
|
90
|
-
|
data/lib/footballdata/version.rb
CHANGED
data/lib/footballdata.rb
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
## 3rd party (our own)
|
2
|
-
require '
|
2
|
+
require 'football/timezones' # note - pulls in season/formats, cocos & tzinfo
|
3
3
|
require 'webget' ## incl. webget, webcache, webclient, etc.
|
4
4
|
|
5
5
|
|
6
|
-
require 'cocos' ## check if webget incl. cocos ??
|
7
|
-
|
8
|
-
|
9
|
-
require 'tzinfo'
|
10
|
-
|
11
|
-
|
12
6
|
module Footballdata
|
13
7
|
class Configuration
|
14
8
|
#########
|
@@ -36,11 +30,13 @@ end # module Footballdata
|
|
36
30
|
# our own code
|
37
31
|
require_relative 'footballdata/version'
|
38
32
|
require_relative 'footballdata/leagues'
|
33
|
+
|
39
34
|
require_relative 'footballdata/download'
|
40
35
|
require_relative 'footballdata/prettyprint'
|
41
36
|
|
42
37
|
require_relative 'footballdata/mods'
|
43
38
|
require_relative 'footballdata/convert'
|
39
|
+
require_relative 'footballdata/convert-score'
|
44
40
|
require_relative 'footballdata/teams'
|
45
41
|
|
46
42
|
|
metadata
CHANGED
@@ -1,31 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: footballdata-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
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-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: season-formats
|
14
|
+
name: football-timezones
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
30
16
|
requirements:
|
31
17
|
- - ">="
|
@@ -52,20 +38,6 @@ dependencies:
|
|
52
38
|
- - ">="
|
53
39
|
- !ruby/object:Gem::Version
|
54
40
|
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: cocos
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
41
|
- !ruby/object:Gem::Dependency
|
70
42
|
name: rdoc
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,7 +88,9 @@ files:
|
|
116
88
|
- README.md
|
117
89
|
- Rakefile
|
118
90
|
- bin/fbdat
|
91
|
+
- config/leagues.csv
|
119
92
|
- lib/footballdata.rb
|
93
|
+
- lib/footballdata/convert-score.rb
|
120
94
|
- lib/footballdata/convert.rb
|
121
95
|
- lib/footballdata/download.rb
|
122
96
|
- lib/footballdata/leagues.rb
|