footballdata-api 0.2.0
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 +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: []
|