footballdata-api 0.3.1 → 0.4.1
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 -2
- data/Rakefile +1 -3
- data/bin/fbdat +8 -3
- data/lib/footballdata/convert-score.rb +44 -0
- data/lib/footballdata/convert.rb +5 -68
- data/lib/footballdata/version.rb +1 -1
- data/lib/footballdata.rb +2 -8
- metadata +4 -33
- data/config/timezones.csv +0 -27
- data/lib/footballdata/timezones.rb +0 -97
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
@@ -4,8 +4,8 @@ README.md
|
|
4
4
|
Rakefile
|
5
5
|
bin/fbdat
|
6
6
|
config/leagues.csv
|
7
|
-
config/timezones.csv
|
8
7
|
lib/footballdata.rb
|
8
|
+
lib/footballdata/convert-score.rb
|
9
9
|
lib/footballdata/convert.rb
|
10
10
|
lib/footballdata/download.rb
|
11
11
|
lib/footballdata/leagues.rb
|
@@ -13,5 +13,4 @@ lib/footballdata/mods.rb
|
|
13
13
|
lib/footballdata/prettyprint.rb
|
14
14
|
lib/footballdata/stat.rb
|
15
15
|
lib/footballdata/teams.rb
|
16
|
-
lib/footballdata/timezones.rb
|
17
16
|
lib/footballdata/version.rb
|
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'
|
@@ -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,49 +1,6 @@
|
|
1
1
|
|
2
2
|
module Footballdata
|
3
3
|
|
4
|
-
|
5
|
-
def self.convert_score( score )
|
6
|
-
## duration: REGULAR · PENALTY_SHOOTOUT · EXTRA_TIME
|
7
|
-
ft, ht, et, pen = ["","","",""]
|
8
|
-
|
9
|
-
if score['duration'] == 'REGULAR'
|
10
|
-
ft = "#{score['fullTime']['home']}-#{score['fullTime']['away']}"
|
11
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
12
|
-
elsif score['duration'] == 'EXTRA_TIME'
|
13
|
-
et = "#{score['regularTime']['home']+score['extraTime']['home']}"
|
14
|
-
et << "-"
|
15
|
-
et << "#{score['regularTime']['away']+score['extraTime']['away']}"
|
16
|
-
|
17
|
-
ft = "#{score['regularTime']['home']}-#{score['regularTime']['away']}"
|
18
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
19
|
-
elsif score['duration'] == 'PENALTY_SHOOTOUT'
|
20
|
-
if score['extraTime']
|
21
|
-
## quick & dirty hack - calc et via regulartime+extratime
|
22
|
-
pen = "#{score['penalties']['home']}-#{score['penalties']['away']}"
|
23
|
-
et = "#{score['regularTime']['home']+score['extraTime']['home']}"
|
24
|
-
et << "-"
|
25
|
-
et << "#{score['regularTime']['away']+score['extraTime']['away']}"
|
26
|
-
|
27
|
-
ft = "#{score['regularTime']['home']}-#{score['regularTime']['away']}"
|
28
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
29
|
-
else ### south american-style (no extra time)
|
30
|
-
## quick & dirty hacke - calc ft via fullTime-penalties
|
31
|
-
pen = "#{score['penalties']['home']}-#{score['penalties']['away']}"
|
32
|
-
ft = "#{score['fullTime']['home']-score['penalties']['home']}"
|
33
|
-
ft << "-"
|
34
|
-
ft << "#{score['fullTime']['away']-score['penalties']['away']}"
|
35
|
-
ht = "#{score['halfTime']['home']}-#{score['halfTime']['away']}"
|
36
|
-
end
|
37
|
-
else
|
38
|
-
puts "!! unknown score duration:"
|
39
|
-
pp score
|
40
|
-
exit 1
|
41
|
-
end
|
42
|
-
|
43
|
-
[ft,ht,et,pen]
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
4
|
#######
|
48
5
|
## map round-like to higher-level stages
|
49
6
|
STAGES = {
|
@@ -80,13 +37,6 @@ STAGES = {
|
|
80
37
|
|
81
38
|
def self.convert( league:, season: )
|
82
39
|
|
83
|
-
### note/fix: cl (champions league for now is a "special" case)
|
84
|
-
# if league.downcase == 'cl'
|
85
|
-
# convert_cl( league: league,
|
86
|
-
# season: season )
|
87
|
-
# return
|
88
|
-
# end
|
89
|
-
|
90
40
|
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
91
41
|
|
92
42
|
league_code = find_league!( league )
|
@@ -237,22 +187,16 @@ matches.each do |m|
|
|
237
187
|
end
|
238
188
|
|
239
189
|
|
240
|
-
|
241
|
-
## add time, timezone(tz)
|
242
|
-
## 2023-08-18T18:30:00Z
|
243
|
-
## e.g. "utcDate": "2020-05-09T00:00:00Z",
|
244
|
-
## "utcDate": "2023-08-18T18:30:00Z",
|
245
|
-
|
246
|
-
## -- todo - make sure / assert it's always utc - how???
|
247
|
-
## utc = ## tz_utc.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
248
|
-
## note: DateTime.strptime is supposed to be unaware of timezones!!!
|
249
|
-
## use to parse utc
|
190
|
+
|
250
191
|
utc = UTC.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
251
192
|
assert( utc.strftime( '%Y-%m-%dT%H:%M:%SZ' ) == m['utcDate'], 'utc time mismatch' )
|
252
193
|
|
253
194
|
|
195
|
+
## do NOT add time if status is SCHEDULED
|
196
|
+
## or POSTPONED for now
|
197
|
+
## otherwise assume time always present - why? why not?
|
198
|
+
##
|
254
199
|
## assume NOT valid utc time if 00:00
|
255
|
-
## do
|
256
200
|
if utc.hour == 0 && utc.min == 0 &&
|
257
201
|
['SCHEDULED','POSTPONED'].include?( m['status'] )
|
258
202
|
date = utc.strftime( '%Y-%m-%d' )
|
@@ -266,13 +210,6 @@ matches.each do |m|
|
|
266
210
|
end
|
267
211
|
|
268
212
|
|
269
|
-
## do NOT add time if status is SCHEDULED
|
270
|
-
## or POSTPONED for now
|
271
|
-
## otherwise assume time always present - why? why not?
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
## todo/fix: assert matchday is a number e.g. 1,2,3, etc.!!!
|
276
213
|
recs << [stage,
|
277
214
|
group,
|
278
215
|
matchday,
|
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,13 +30,13 @@ end # module Footballdata
|
|
36
30
|
# our own code
|
37
31
|
require_relative 'footballdata/version'
|
38
32
|
require_relative 'footballdata/leagues'
|
39
|
-
require_relative 'footballdata/timezones'
|
40
33
|
|
41
34
|
require_relative 'footballdata/download'
|
42
35
|
require_relative 'footballdata/prettyprint'
|
43
36
|
|
44
37
|
require_relative 'footballdata/mods'
|
45
38
|
require_relative 'footballdata/convert'
|
39
|
+
require_relative 'footballdata/convert-score'
|
46
40
|
require_relative 'footballdata/teams'
|
47
41
|
|
48
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
|
@@ -117,8 +89,8 @@ files:
|
|
117
89
|
- Rakefile
|
118
90
|
- bin/fbdat
|
119
91
|
- config/leagues.csv
|
120
|
-
- config/timezones.csv
|
121
92
|
- lib/footballdata.rb
|
93
|
+
- lib/footballdata/convert-score.rb
|
122
94
|
- lib/footballdata/convert.rb
|
123
95
|
- lib/footballdata/download.rb
|
124
96
|
- lib/footballdata/leagues.rb
|
@@ -126,7 +98,6 @@ files:
|
|
126
98
|
- lib/footballdata/prettyprint.rb
|
127
99
|
- lib/footballdata/stat.rb
|
128
100
|
- lib/footballdata/teams.rb
|
129
|
-
- lib/footballdata/timezones.rb
|
130
101
|
- lib/footballdata/version.rb
|
131
102
|
homepage: https://github.com/sportdb/sport.db
|
132
103
|
licenses:
|
data/config/timezones.csv
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
key, zone
|
2
|
-
eng, Europe/London
|
3
|
-
es, Europe/Madrid
|
4
|
-
de, Europe/Berlin
|
5
|
-
fr, Europe/Paris
|
6
|
-
it, Europe/Rome
|
7
|
-
|
8
|
-
nl, Europe/Amsterdam
|
9
|
-
pt, Europe/Lisbon
|
10
|
-
|
11
|
-
## for champs default for not to cet (central european time) - why? why not?
|
12
|
-
uefa.cl, Europe/Paris
|
13
|
-
euro, Europe/Paris
|
14
|
-
|
15
|
-
## todo/fix - pt.1
|
16
|
-
## one team in madeira!!! check for different timezone??
|
17
|
-
## CD Nacional da Madeira
|
18
|
-
|
19
|
-
br, America/Sao_Paulo
|
20
|
-
## todo/fix - brazil has 4 timezones
|
21
|
-
## really only two in use for clubs
|
22
|
-
## west and east (amazonas et al)
|
23
|
-
## for now use west for all - why? why not?
|
24
|
-
copa.l, America/Sao_Paulo
|
25
|
-
|
26
|
-
|
27
|
-
## world+2022, add quatar here
|
@@ -1,97 +0,0 @@
|
|
1
|
-
|
2
|
-
class UTC
|
3
|
-
def self.now() Time.now.utc; end
|
4
|
-
def self.today() now.to_date; end
|
5
|
-
|
6
|
-
## -- todo - make sure / assert it's always utc - how???
|
7
|
-
## utc = ## tz_utc.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
8
|
-
## note: DateTime.strptime is supposed to be unaware of timezones!!!
|
9
|
-
## use to parse utc
|
10
|
-
## quick hack -
|
11
|
-
## use to_time.getutc instead of utc ???
|
12
|
-
def self.strptime( str, format )
|
13
|
-
DateTime.strptime( str, format ).to_time.utc
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.find_zone( name )
|
17
|
-
zone = TZInfo::Timezone.get( name )
|
18
|
-
## wrap tzinfo timezone in our own - for adding more (auto)checks etc.
|
19
|
-
zone ? Timezone.new( zone ) : nil
|
20
|
-
end
|
21
|
-
|
22
|
-
class Timezone ## nested inside UTC
|
23
|
-
## todo/fix
|
24
|
-
## cache timezone - why? why not?
|
25
|
-
def initialize( zone )
|
26
|
-
@zone = zone
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_local( time )
|
30
|
-
## assert time is Time (not Date or DateTIme)
|
31
|
-
## and assert utc!!!
|
32
|
-
assert( time.is_a?( Time ), "time #{time} is NOT of class Time; got #{time.class.name}" )
|
33
|
-
assert( time.utc?, "time #{time} is NOT utc; utc? returns #{time.utc?}" )
|
34
|
-
local = @zone.to_local( time )
|
35
|
-
local
|
36
|
-
end
|
37
|
-
|
38
|
-
def assert( cond, msg )
|
39
|
-
if cond
|
40
|
-
# do nothing
|
41
|
-
else
|
42
|
-
puts "!!! assert failed - #{msg}"
|
43
|
-
exit 1
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end # class Timezone
|
47
|
-
end # class UTC
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
module Footballdata
|
52
|
-
def self.find_zone!( league:, season: )
|
53
|
-
@zones ||= begin
|
54
|
-
recs = read_csv( "#{FootballdataApi.root}/config/timezones.csv" )
|
55
|
-
zones = {}
|
56
|
-
recs.each do |rec|
|
57
|
-
zone = UTC.find_zone( rec['zone'] )
|
58
|
-
if zone.nil?
|
59
|
-
## raise ArgumentError - invalid zone
|
60
|
-
puts "!! ERROR - cannot find timezone in timezone db:"
|
61
|
-
pp rec
|
62
|
-
exit 1
|
63
|
-
end
|
64
|
-
zones[ rec['key']] = zone
|
65
|
-
end
|
66
|
-
zones
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
## lookup first try by league+season
|
71
|
-
league_code = league.downcase
|
72
|
-
season = Season( season )
|
73
|
-
|
74
|
-
## e.g. world+2022, etc.
|
75
|
-
key = "#{league_code}+#{season}"
|
76
|
-
zone = @zones[key]
|
77
|
-
|
78
|
-
## try league e.g. eng.1 etc.
|
79
|
-
zone = @zones[league_code] if zone.nil?
|
80
|
-
|
81
|
-
## try first code only (country code )
|
82
|
-
if zone.nil?
|
83
|
-
code, _ = league_code.split( '.', 2 )
|
84
|
-
zone = @zones[code]
|
85
|
-
end
|
86
|
-
|
87
|
-
if zone.nil? ## still not found; report error
|
88
|
-
puts "!! ERROR: no timezone found for #{league} #{season}"
|
89
|
-
exit 1
|
90
|
-
end
|
91
|
-
|
92
|
-
zone
|
93
|
-
end
|
94
|
-
end # module Footballdata
|
95
|
-
|
96
|
-
|
97
|
-
|