footballdata-api 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +6 -0
- data/Manifest.txt +15 -0
- data/README.md +165 -0
- data/Rakefile +33 -0
- data/bin/fbdat +200 -0
- data/lib/footballdata/convert.rb +332 -0
- data/lib/footballdata/download.rb +131 -0
- data/lib/footballdata/generator.rb +33 -0
- data/lib/footballdata/leagues.rb +59 -0
- data/lib/footballdata/mods.rb +22 -0
- data/lib/footballdata/prettyprint.rb +189 -0
- data/lib/footballdata/stat.rb +59 -0
- data/lib/footballdata/teams.rb +90 -0
- data/lib/footballdata/version.rb +20 -0
- data/lib/footballdata.rb +56 -0
- metadata +155 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
module Footballdata
|
2
|
+
|
3
|
+
|
4
|
+
def self.assert( cond, msg )
|
5
|
+
if cond
|
6
|
+
# do nothing
|
7
|
+
else
|
8
|
+
puts "!!! assert failed - #{msg}"
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.fmt_competition( rec )
|
14
|
+
buf = String.new
|
15
|
+
|
16
|
+
buf << "==> "
|
17
|
+
buf << "#{rec['competition']['name']} (#{rec['competition']['code']}) -- "
|
18
|
+
buf << "#{rec['area']['name']} (#{rec['area']['code']}) "
|
19
|
+
buf << "#{rec['competition']['type']} "
|
20
|
+
buf << "#{rec['season']['startDate']} - #{rec['season']['endDate']} "
|
21
|
+
buf << "@ #{rec['season']['currentMatchday']}"
|
22
|
+
buf << "\n"
|
23
|
+
|
24
|
+
buf
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.fmt_match( rec )
|
28
|
+
buf = String.new
|
29
|
+
|
30
|
+
## -- todo - make sure / assert it's always utc - how???
|
31
|
+
## utc = ## tz_utc.strptime( m['utcDate'], '%Y-%m-%dT%H:%M:%SZ' )
|
32
|
+
## note: DateTime.strptime is supposed to be unaware of timezones!!!
|
33
|
+
## use to parse utc
|
34
|
+
utc = DateTime.strptime( rec['utcDate'], '%Y-%m-%dT%H:%M:%SZ' ).to_time.utc
|
35
|
+
assert( utc.strftime( '%Y-%m-%dT%H:%M:%SZ' ) == rec['utcDate'], 'utc time mismatch' )
|
36
|
+
|
37
|
+
status = rec['status']
|
38
|
+
assert( %w[SCHEDULED
|
39
|
+
TIMED
|
40
|
+
FINISHED
|
41
|
+
POSTPONED
|
42
|
+
IN_PLAY
|
43
|
+
].include?( status ), "unknown status - #{status}" )
|
44
|
+
|
45
|
+
buf << '%-10s' % status
|
46
|
+
buf << utc.strftime( '%a %b %d %Y %H:%M')
|
47
|
+
buf << ' '
|
48
|
+
# pp rec['utcDate']
|
49
|
+
|
50
|
+
team1 = rec['homeTeam']['name'] ?
|
51
|
+
"#{rec['homeTeam']['name']} (#{rec['homeTeam']['tla']})" : '?'
|
52
|
+
team2 = rec['awayTeam']['name'] ?
|
53
|
+
"#{rec['awayTeam']['name']} (#{rec['awayTeam']['tla']})" : '?'
|
54
|
+
buf << '%22s' % team1
|
55
|
+
buf << " - "
|
56
|
+
buf << '%-22s' % team2
|
57
|
+
buf << " "
|
58
|
+
|
59
|
+
stage = rec['stage']
|
60
|
+
group = rec['group']
|
61
|
+
|
62
|
+
buf << "#{rec['matchday']} - #{stage} "
|
63
|
+
buf << "/ #{group} " if group
|
64
|
+
buf << "\n"
|
65
|
+
|
66
|
+
buf << " "
|
67
|
+
buf << '%-20s' % rec['score']['duration']
|
68
|
+
buf << ' '*24
|
69
|
+
|
70
|
+
duration = rec['score']['duration']
|
71
|
+
assert( %w[REGULAR
|
72
|
+
EXTRA_TIME
|
73
|
+
PENALTY_SHOOTOUT
|
74
|
+
].include?( duration ), "unknown duration - #{duration}" )
|
75
|
+
|
76
|
+
score = String.new
|
77
|
+
|
78
|
+
if duration == 'PENALTY_SHOOTOUT'
|
79
|
+
if rec['score']['extraTime']
|
80
|
+
## quick & dirty hack - calc et via regulartime+extratime
|
81
|
+
score << "#{rec['score']['penalties']['home']}-#{rec['score']['penalties']['away']} pen. "
|
82
|
+
score << "#{rec['score']['regularTime']['home']+rec['score']['extraTime']['home']}"
|
83
|
+
score << "-"
|
84
|
+
score << "#{rec['score']['regularTime']['away']+rec['score']['extraTime']['away']}"
|
85
|
+
score << " a.e.t. "
|
86
|
+
score << "(#{rec['score']['regularTime']['home']}-#{rec['score']['regularTime']['away']},"
|
87
|
+
score << "#{rec['score']['halfTime']['home']}-#{rec['score']['halfTime']['away']})"
|
88
|
+
else ### south american-style (no extra time)
|
89
|
+
## quick & dirty hacke - calc ft via fullTime-penalties
|
90
|
+
score << "#{rec['score']['penalties']['home']}-#{rec['score']['penalties']['away']} pen. "
|
91
|
+
score << "(#{rec['score']['fullTime']['home']-rec['score']['penalties']['home']}"
|
92
|
+
score << "-"
|
93
|
+
score << "#{rec['score']['fullTime']['away']-rec['score']['penalties']['away']},"
|
94
|
+
score << "#{rec['score']['halfTime']['home']}-#{rec['score']['halfTime']['away']})"
|
95
|
+
end
|
96
|
+
elsif duration == 'EXTRA_TIME'
|
97
|
+
score << "#{rec['score']['regularTime']['home']+rec['score']['extraTime']['home']}"
|
98
|
+
score << "-"
|
99
|
+
score << "#{rec['score']['regularTime']['away']+rec['score']['extraTime']['away']}"
|
100
|
+
score << " a.e.t. "
|
101
|
+
score << "(#{rec['score']['regularTime']['home']}-#{rec['score']['regularTime']['away']},"
|
102
|
+
score << "#{rec['score']['halfTime']['home']}-#{rec['score']['halfTime']['away']})"
|
103
|
+
elsif duration == 'REGULAR'
|
104
|
+
if rec['score']['fullTime']['home'] && rec['score']['fullTime']['away']
|
105
|
+
score << "#{rec['score']['fullTime']['home']}-#{rec['score']['fullTime']['away']} "
|
106
|
+
score << "(#{rec['score']['halfTime']['home']}-#{rec['score']['halfTime']['away']})"
|
107
|
+
end
|
108
|
+
else
|
109
|
+
raise ArgumentError, "unexpected/unknown score duration #{rec['score']['duration']}"
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
buf << score
|
114
|
+
buf << "\n"
|
115
|
+
buf
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
def self.pp_matches( data )
|
120
|
+
|
121
|
+
## track match status and score duration
|
122
|
+
stats = { 'status' => Hash.new(0),
|
123
|
+
'duration' => Hash.new(0),
|
124
|
+
'stage' => Hash.new(0),
|
125
|
+
'group' => Hash.new(0),
|
126
|
+
}
|
127
|
+
|
128
|
+
first = Date.strptime( data['resultSet']['first'], '%Y-%m-%d' )
|
129
|
+
last = Date.strptime( data['resultSet']['last'], '%Y-%m-%d' )
|
130
|
+
|
131
|
+
diff = (last - first).to_i # note - returns rational number (e.g. 30/1)
|
132
|
+
|
133
|
+
|
134
|
+
print "==> #{data['competition']['name']}, "
|
135
|
+
print "#{first.strftime('%a %b %d %Y')} - #{last.strftime('%a %b %d %Y')}"
|
136
|
+
print " (#{diff}d)"
|
137
|
+
print "\n"
|
138
|
+
|
139
|
+
data['matches'].each do |rec|
|
140
|
+
|
141
|
+
print fmt_match( rec )
|
142
|
+
|
143
|
+
## track stats
|
144
|
+
status = rec['status']
|
145
|
+
stats['status'][status] += 1
|
146
|
+
|
147
|
+
stage = rec['stage']
|
148
|
+
stats['stage'][stage] += 1
|
149
|
+
|
150
|
+
group = rec['group']
|
151
|
+
stats['group'][group] += 1 if group
|
152
|
+
|
153
|
+
duration = rec['score']['duration']
|
154
|
+
stats['duration'][duration] += 1
|
155
|
+
end
|
156
|
+
|
157
|
+
print " #{data['resultSet']['played']}/#{data['resultSet']['count']} matches"
|
158
|
+
print "\n"
|
159
|
+
|
160
|
+
print " status (#{stats['status'].size}): "
|
161
|
+
print fmt_count( stats['status'], sort: true )
|
162
|
+
print "\n"
|
163
|
+
print " duration (#{stats['duration'].size}): "
|
164
|
+
print fmt_count( stats['duration'], sort: true )
|
165
|
+
print "\n"
|
166
|
+
print " stage (#{stats['stage'].size}): "
|
167
|
+
print fmt_count( stats['stage'] )
|
168
|
+
print "\n"
|
169
|
+
print " group (#{stats['group'].size}): "
|
170
|
+
print fmt_count( stats['group'] )
|
171
|
+
print "\n"
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
def self.fmt_count( h, sort: false )
|
176
|
+
pairs = h.to_a
|
177
|
+
if sort
|
178
|
+
pairs = pairs.sort do |l,r|
|
179
|
+
res = r[1] <=> l[1] ## bigger number first
|
180
|
+
res = l[0] <=> r[0] if res == 0
|
181
|
+
res
|
182
|
+
end
|
183
|
+
end
|
184
|
+
pairs = pairs.map { |name,count| "#{name} (#{count})" }
|
185
|
+
pairs.join( ' · ' )
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
end # module Footballdata
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Footballdata
|
2
|
+
|
3
|
+
class Stat ## rename to match stat or something why? why not?
|
4
|
+
def initialize
|
5
|
+
@data = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](key) @data[ key ]; end
|
9
|
+
|
10
|
+
def update( match )
|
11
|
+
## keep track of some statistics
|
12
|
+
stat = @data[:all] ||= { stage: Hash.new( 0 ),
|
13
|
+
duration: Hash.new( 0 ),
|
14
|
+
status: Hash.new( 0 ),
|
15
|
+
group: Hash.new( 0 ),
|
16
|
+
matchday: Hash.new( 0 ),
|
17
|
+
|
18
|
+
matches: 0,
|
19
|
+
goals: 0,
|
20
|
+
}
|
21
|
+
|
22
|
+
stat[:stage][ match['stage'] ] += 1
|
23
|
+
stat[:group][ match['group'] ] += 1
|
24
|
+
stat[:status][ match['status'] ] += 1
|
25
|
+
stat[:matchday][ match['matchday'] ] += 1
|
26
|
+
|
27
|
+
score = match['score']
|
28
|
+
|
29
|
+
stat[:duration][ score['duration'] ] += 1 ## track - assert always REGULAR
|
30
|
+
|
31
|
+
stat[:matches] += 1
|
32
|
+
stat[:goals] += score['fullTime']['homeTeam'].to_i if score['fullTime']['homeTeam']
|
33
|
+
stat[:goals] += score['fullTime']['awayTeam'].to_i if score['fullTime']['awayTeam']
|
34
|
+
|
35
|
+
|
36
|
+
stage_key = match['stage'].downcase.to_sym # e.g. :regular_season
|
37
|
+
stat = @data[ stage_key ] ||= { duration: Hash.new( 0 ),
|
38
|
+
status: Hash.new( 0 ),
|
39
|
+
group: Hash.new( 0 ),
|
40
|
+
matchday: Hash.new( 0 ),
|
41
|
+
|
42
|
+
matches: 0,
|
43
|
+
goals: 0,
|
44
|
+
}
|
45
|
+
stat[:group][ match['group'] ] += 1
|
46
|
+
stat[:status][ match['status'] ] += 1
|
47
|
+
stat[:matchday][ match['matchday'] ] += 1
|
48
|
+
|
49
|
+
stat[:duration][ score['duration'] ] += 1 ## track - assert always REGULAR
|
50
|
+
|
51
|
+
stat[:matches] += 1
|
52
|
+
stat[:goals] += score['fullTime']['homeTeam'].to_i if score['fullTime']['homeTeam']
|
53
|
+
stat[:goals] += score['fullTime']['awayTeam'].to_i if score['fullTime']['awayTeam']
|
54
|
+
end
|
55
|
+
end # class Stat
|
56
|
+
end # module Footballdata
|
57
|
+
|
58
|
+
|
59
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
|
2
|
+
###########
|
3
|
+
### export teams
|
4
|
+
|
5
|
+
|
6
|
+
module Footballdata
|
7
|
+
|
8
|
+
def self.export_teams( league:, season: )
|
9
|
+
|
10
|
+
season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
|
11
|
+
league_code = LEAGUES[league.downcase]
|
12
|
+
|
13
|
+
teams_url = Metal.competition_teams_url( league_code,
|
14
|
+
season.start_year )
|
15
|
+
data_teams = Webcache.read_json( teams_url )
|
16
|
+
|
17
|
+
## build a (reverse) team lookup by name
|
18
|
+
puts "#{data_teams['teams'].size} teams"
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
clubs = {} ## by country
|
23
|
+
|
24
|
+
data_teams['teams'].each do |rec|
|
25
|
+
|
26
|
+
buf = String.new ### use for string buffer (or String.new('') - why? why not?
|
27
|
+
buf << "#{rec['name']}"
|
28
|
+
buf << ", #{rec['founded']}" if rec['founded']
|
29
|
+
if rec['venue']
|
30
|
+
buf << ", @ #{rec['venue']}"
|
31
|
+
# buf << " # #{rec['area']['name']}"
|
32
|
+
end
|
33
|
+
buf << "\n"
|
34
|
+
|
35
|
+
alt_names = String.new
|
36
|
+
alt_names << " | #{rec['shortName']}" if rec['shortName'] &&
|
37
|
+
rec['shortName'] != rec['name'] &&
|
38
|
+
rec['shortName'] != rec['tla']
|
39
|
+
|
40
|
+
alt_names << " | #{rec['tla']}" if rec['tla'] &&
|
41
|
+
rec['tla'] != rec['name']
|
42
|
+
|
43
|
+
if alt_names.size > 0
|
44
|
+
buf << " "
|
45
|
+
buf << alt_names
|
46
|
+
buf << "\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
## clean null in address (or keep nulls) - why? why not?
|
50
|
+
## e.g. null Rionegro null
|
51
|
+
## Calle 104 No. 13a - 32 Bogotá null
|
52
|
+
|
53
|
+
buf << " address: #{rec['address'].gsub( /\bnull\b/, '')}"
|
54
|
+
buf << "\n"
|
55
|
+
buf << " web: #{rec['website']}"
|
56
|
+
buf << "\n"
|
57
|
+
buf << " colors: #{rec['clubColors']}"
|
58
|
+
buf << "\n"
|
59
|
+
|
60
|
+
country = rec['area']['name']
|
61
|
+
ary = clubs[ country] ||= []
|
62
|
+
ary << buf
|
63
|
+
end
|
64
|
+
# puts buf
|
65
|
+
|
66
|
+
## pp clubs
|
67
|
+
|
68
|
+
|
69
|
+
buf = String.new
|
70
|
+
|
71
|
+
if clubs.size > 1
|
72
|
+
clubs.each do |country, ary|
|
73
|
+
buf << "# #{country} - #{ary.size} clubs\n"
|
74
|
+
end
|
75
|
+
buf << "\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
clubs.each do |country, ary|
|
79
|
+
buf << "= #{country} # #{ary.size} clubs\n\n"
|
80
|
+
buf << ary.join( "\n" )
|
81
|
+
buf << "\n\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
path = "#{config.convert.out_dir}/#{season.to_path}/#{league.downcase}.clubs.txt"
|
85
|
+
write_text( path, buf )
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end # module Footballdata
|
90
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module FootballdataApi
|
3
|
+
MAJOR = 0 ## todo: namespace inside version or something - why? why not??
|
4
|
+
MINOR = 2
|
5
|
+
PATCH = 0
|
6
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
7
|
+
|
8
|
+
def self.version
|
9
|
+
VERSION
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.banner
|
13
|
+
"footballdata-api/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.root
|
17
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
18
|
+
end
|
19
|
+
end # module FootballdataApi
|
20
|
+
|
data/lib/footballdata.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
## 3rd party (our own)
|
2
|
+
require 'season/formats' ## add season support
|
3
|
+
require 'webget' ## incl. webget, webcache, webclient, etc.
|
4
|
+
|
5
|
+
|
6
|
+
require 'cocos' ## check if webget incl. cocos ??
|
7
|
+
|
8
|
+
|
9
|
+
require 'tzinfo'
|
10
|
+
|
11
|
+
|
12
|
+
module Footballdata
|
13
|
+
class Configuration
|
14
|
+
#########
|
15
|
+
## nested configuration classes - use - why? why not?
|
16
|
+
class Convert
|
17
|
+
def out_dir() @out_dir || './o'; end
|
18
|
+
def out_dir=(value) @out_dir = value; end
|
19
|
+
end
|
20
|
+
|
21
|
+
def convert() @convert ||= Convert.new; end
|
22
|
+
end # class Configuration
|
23
|
+
|
24
|
+
## lets you use
|
25
|
+
## Footballdata.configure do |config|
|
26
|
+
## config.convert.out_dir = './o'
|
27
|
+
## end
|
28
|
+
def self.configure() yield( config ); end
|
29
|
+
def self.config() @config ||= Configuration.new; end
|
30
|
+
end # module Footballdata
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
###
|
36
|
+
# our own code
|
37
|
+
require_relative 'footballdata/version'
|
38
|
+
require_relative 'footballdata/leagues'
|
39
|
+
require_relative 'footballdata/download'
|
40
|
+
require_relative 'footballdata/prettyprint'
|
41
|
+
|
42
|
+
require_relative 'footballdata/mods'
|
43
|
+
require_relative 'footballdata/convert'
|
44
|
+
require_relative 'footballdata/teams'
|
45
|
+
|
46
|
+
|
47
|
+
require_relative 'footballdata/generator'
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
### for processing tool
|
52
|
+
## (auto-)add sportdb/writer (pulls in sportdb/catalogs and gitti)
|
53
|
+
## require 'sportdb/writers'
|
54
|
+
|
55
|
+
|
56
|
+
puts FootballdataApi.banner ## say hello
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: footballdata-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gerald Bauer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tzinfo
|
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
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: webget
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
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
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rdoc
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.0'
|
76
|
+
- - "<"
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '7'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '4.0'
|
86
|
+
- - "<"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '7'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: hoe
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '4.1'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '4.1'
|
103
|
+
description: footballdata-api - get football data via Daniel Freitag's football-data.org
|
104
|
+
api v4
|
105
|
+
email: gerald.bauer@gmail.com
|
106
|
+
executables:
|
107
|
+
- fbdat
|
108
|
+
extensions: []
|
109
|
+
extra_rdoc_files:
|
110
|
+
- CHANGELOG.md
|
111
|
+
- Manifest.txt
|
112
|
+
- README.md
|
113
|
+
files:
|
114
|
+
- CHANGELOG.md
|
115
|
+
- Manifest.txt
|
116
|
+
- README.md
|
117
|
+
- Rakefile
|
118
|
+
- bin/fbdat
|
119
|
+
- lib/footballdata.rb
|
120
|
+
- lib/footballdata/convert.rb
|
121
|
+
- lib/footballdata/download.rb
|
122
|
+
- lib/footballdata/generator.rb
|
123
|
+
- lib/footballdata/leagues.rb
|
124
|
+
- lib/footballdata/mods.rb
|
125
|
+
- lib/footballdata/prettyprint.rb
|
126
|
+
- lib/footballdata/stat.rb
|
127
|
+
- lib/footballdata/teams.rb
|
128
|
+
- lib/footballdata/version.rb
|
129
|
+
homepage: https://github.com/sportdb/sport.db
|
130
|
+
licenses:
|
131
|
+
- Public Domain
|
132
|
+
metadata: {}
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options:
|
135
|
+
- "--main"
|
136
|
+
- README.md
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 2.2.2
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubygems_version: 3.4.10
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: footballdata-api - get football data via Daniel Freitag's football-data.org
|
154
|
+
api v4
|
155
|
+
test_files: []
|