footballdata-api 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 16f099d030a007993b7289956e920fd89baff6abc506feeca3dad792453efe76
4
+ data.tar.gz: 8f3d2df27a3dc12cc15fa2a8ee0dcd42a51ed793261a2ab2795020147596e7f6
5
+ SHA512:
6
+ metadata.gz: cca1d63da2e1823a3c9cc2636953da2f691101c32b63f5004c5349338d9dd75099ac993786e038cf3e2ea8a41f3ac1ce7510cdf148f1f13a98d360203613cf99
7
+ data.tar.gz: 6030f680eb2e5dadd269ee78bd778c1b465914702e20fe98e55e0967346feb67a6b74d8a965dea73ce62b9c8f457ba1de811d02e26a603b90ff4d3a160b8ee99
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ### 0.2.0
2
+
3
+ ### 0.0.1 / 2024-07-03
4
+
5
+ * Everything is new. First release.
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,15 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ bin/fbdat
6
+ lib/footballdata.rb
7
+ lib/footballdata/convert.rb
8
+ lib/footballdata/download.rb
9
+ lib/footballdata/generator.rb
10
+ lib/footballdata/leagues.rb
11
+ lib/footballdata/mods.rb
12
+ lib/footballdata/prettyprint.rb
13
+ lib/footballdata/stat.rb
14
+ lib/footballdata/teams.rb
15
+ lib/footballdata/version.rb
data/README.md ADDED
@@ -0,0 +1,165 @@
1
+ # footballdata-api - get football data via Daniel Freitag's football-data.org api v4
2
+
3
+
4
+ * home :: [github.com/sportdb/sport.db](https://github.com/sportdb/sport.db)
5
+ * bugs :: [github.com/sportdb/sport.db/issues](https://github.com/sportdb/sport.db/issues)
6
+ * gem :: [rubygems.org/gems/footballdata-api](https://rubygems.org/gems/footballdata-api)
7
+ * rdoc :: [rubydoc.info/gems/footballdata-api](http://rubydoc.info/gems/footballdata-api)
8
+
9
+
10
+
11
+ ## Usage
12
+
13
+
14
+ [Daniel Freitag](https://www.football-data.org/about)'s dev-friendly football API
15
+ offers a free to use plan
16
+ for 12 leagues (API key sign-up and use required).
17
+ See [`football-data.org` »](https://www.football-data.org)
18
+
19
+
20
+ **Step 0 - Setup Secrets**
21
+
22
+ Set the API key / token in the env(ironement).
23
+ Example:
24
+
25
+ ```
26
+ set FOOTBALLDATA=1234567890abcdef1234567890abcdef
27
+ ```
28
+
29
+
30
+ **Step 1 - Download Match Schedules**
31
+
32
+ Download the match schedules (in json) via api calls
33
+ to your (local) web cache (in `~/.cache`).
34
+ Note: The free trier has a 10 request/minute limit,
35
+ thus, sleep/wait 10 secs after every request
36
+ (should result in ~6 requests/minute).
37
+
38
+
39
+ ``` ruby
40
+ require 'footballdata'
41
+
42
+
43
+ # download up (ongoing) 2020 or 2020/21 seasons
44
+ Webget.config.sleep = 10
45
+
46
+ Footballdata.schedule( league: 'eng.1', season: '2020/21' )
47
+ Footballdata.schedule( league: 'eng.2', season: '2020/21' )
48
+
49
+ Footballdata.schedule( league: 'de.1', season: '2020/21' )
50
+ Footballdata.schedule( league: 'es.1', season: '2020/21' )
51
+
52
+ Footballdata.schedule( league: 'fr.1', season: '2020/21' )
53
+ Footballdata.schedule( league: 'it.1', season: '2020/21' )
54
+
55
+ Footballdata.schedule( league: 'nl.1', season: '2020/21' )
56
+ Footballdata.schedule( league: 'pt.1', season: '2020/21' )
57
+
58
+ Footballdata.schedule( league: 'cl', season: '2020/21' )
59
+
60
+ # note: Brasileirão - season is a calendar year (NOT an academic year)
61
+ Footballdata.schedule( league: 'br.1', season: '2020' )
62
+ ```
63
+
64
+ Note: You can find all downloaded match schedules
65
+ in your (local) web cache (in `~/.cache/api.football-data.org`) as pretty printed json documents.
66
+
67
+
68
+
69
+
70
+ **Step 2 - Convert (Cached) Match Schedules to Records**
71
+
72
+ Convert the (cached) match schedules
73
+ in JSON to the one-line, one-match & one-file, one-season
74
+ "standard" [Football.CSV format](https://github.com/footballcsv). Example:
75
+
76
+ ``` ruby
77
+ require 'footballdata'
78
+
79
+ ['eng.1', 'eng.2',
80
+ 'de.1',
81
+ 'es.1',
82
+ 'fr.1',
83
+ 'it.1',
84
+ 'nl.1',
85
+ 'pt.1',
86
+ 'cl',
87
+ ].each do |league|
88
+ Footballdata.convert( league: league, season: '2020/21' )
89
+ end
90
+
91
+ Footballdata.convert( league: 'br.1', season: '2020' )
92
+ ```
93
+
94
+ Note: By default all datasets get written into the `./o`
95
+ directory. Use `Footballdata.config.convert.out_dir`
96
+ to change the output directory.
97
+
98
+ The English Premier League (`eng.1`) results in `./o/2020-21/eng.1.csv`:
99
+
100
+ ```
101
+ Matchday,Date,Team 1,FT,HT,Team 2,Comments
102
+ 1,Sun Sep 13 2020,Manchester City FC,(*),,Aston Villa FC,postponed
103
+ 1,Sun Sep 13 2020,Burnley FC,(*),,Manchester United FC,postponed
104
+ 1,Sat Sep 12 2020,Fulham FC,0-3,0-1,Arsenal FC,
105
+ 1,Sat Sep 12 2020,Crystal Palace FC,1-0,1-0,Southampton FC,
106
+ 1,Sat Sep 12 2020,Liverpool FC,4-3,3-2,Leeds United FC,
107
+ 1,Sat Sep 12 2020,West Ham United FC,0-2,0-0,Newcastle United FC,
108
+ 1,Sun Sep 13 2020,West Bromwich Albion FC,0-3,0-0,Leicester City FC,
109
+ 1,Sun Sep 13 2020,Tottenham Hotspur FC,0-1,0-0,Everton FC,
110
+ 1,Mon Sep 14 2020,Sheffield United FC,0-2,0-2,Wolverhampton Wanderers FC,
111
+ 1,Mon Sep 14 2020,Brighton & Hove Albion FC,1-3,0-1,Chelsea FC,
112
+ 2,Sat Sep 19 2020,Everton FC,5-2,2-1,West Bromwich Albion FC,
113
+ 2,Sat Sep 19 2020,Leeds United FC,4-3,2-1,Fulham FC,
114
+ 2,Sat Sep 19 2020,Manchester United FC,1-3,0-1,Crystal Palace FC,
115
+ 2,Sat Sep 19 2020,Arsenal FC,2-1,1-1,West Ham United FC,
116
+ 2,Sun Sep 20 2020,Southampton FC,2-5,1-1,Tottenham Hotspur FC,
117
+ 2,Sun Sep 20 2020,Newcastle United FC,0-3,0-2,Brighton & Hove Albion FC,
118
+ 2,Sun Sep 20 2020,Chelsea FC,0-2,0-0,Liverpool FC,
119
+ 2,Sun Sep 20 2020,Leicester City FC,4-2,1-1,Burnley FC,
120
+ 2,Mon Sep 21 2020,Aston Villa FC,1-0,0-0,Sheffield United FC,
121
+ 2,Mon Sep 21 2020,Wolverhampton Wanderers FC,1-3,0-2,Manchester City FC,
122
+ ...
123
+ ```
124
+
125
+ Or the Brasileirão (`br.1`) in `./o/2020/br.1.csv`:
126
+
127
+ ```
128
+ Matchday,Date,Team 1,FT,HT,Team 2,Comments
129
+ 1,Sat Aug 8 2020,Fortaleza EC,0-2,0-2,CA Paranaense,
130
+ 1,Sat Aug 8 2020,Coritiba FBC,0-1,0-0,SC Internacional,
131
+ 1,Sun Aug 9 2020,SC Recife,3-2,3-1,Ceará SC,
132
+ 1,Sun Aug 9 2020,Santos FC,1-1,0-0,RB Bragantino,
133
+ 1,Sun Aug 9 2020,CR Flamengo,0-1,0-1,CA Mineiro,
134
+ 1,Sun Aug 9 2020,Goiás EC,(*),,São Paulo FC,postponed
135
+ 1,Sun Aug 9 2020,Grêmio FBPA,1-0,1-0,Fluminense FC,
136
+ 1,Sun Aug 9 2020,SE Palmeiras,(*),,CR Vasco da Gama,postponed
137
+ 2,Wed Aug 12 2020,CA Mineiro,3-2,0-2,SC Corinthians Paulista,
138
+ 2,Wed Aug 12 2020,CA Paranaense,2-1,1-1,Goiás EC,
139
+ 2,Wed Aug 12 2020,RB Bragantino,1-1,1-0,Botafogo FR,
140
+ 2,Wed Aug 12 2020,AC Goianiense,3-0,2-0,CR Flamengo,
141
+ 2,Wed Aug 12 2020,EC Bahia,1-0,1-0,Coritiba FBC,
142
+ 2,Thu Aug 13 2020,Fluminense FC,1-1,1-1,SE Palmeiras,
143
+ 2,Thu Aug 13 2020,Ceará SC,1-1,1-0,Grêmio FBPA,
144
+ 2,Thu Aug 13 2020,São Paulo FC,1-0,1-0,Fortaleza EC,
145
+ 2,Thu Aug 13 2020,SC Internacional,2-0,0-0,Santos FC,
146
+ 2,Thu Aug 13 2020,CR Vasco da Gama,2-0,2-0,SC Recife,
147
+ ...
148
+ ```
149
+
150
+
151
+
152
+ That's it for now.
153
+
154
+
155
+
156
+ ## License
157
+
158
+ The `footballdata` scripts are dedicated to the public domain.
159
+ Use it as you please with no restrictions whatsoever.
160
+
161
+
162
+ ## Questions? Comments?
163
+
164
+ Yes, you can. More than welcome.
165
+ See [Help & Support »](https://github.com/openfootball/help)
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require 'hoe'
2
+ require './lib/footballdata/version.rb'
3
+
4
+ Hoe.spec 'footballdata-api' do
5
+
6
+ self.version = FootballdataApi::VERSION
7
+
8
+ self.summary = "footballdata-api - get football data via Daniel Freitag's football-data.org api v4"
9
+ self.description = summary
10
+
11
+ self.urls = { home: 'https://github.com/sportdb/sport.db' }
12
+
13
+ self.author = 'Gerald Bauer'
14
+ self.email = 'gerald.bauer@gmail.com'
15
+
16
+ # switch extension to .markdown for gihub formatting
17
+ self.readme_file = 'README.md'
18
+ self.history_file = 'CHANGELOG.md'
19
+
20
+ self.extra_deps = [
21
+ ['tzinfo'],
22
+ ['season-formats'],
23
+ ['webget'],
24
+ ['cocos'], ## later pull in with sportsdb-writers
25
+ ]
26
+
27
+ self.licenses = ['Public Domain']
28
+
29
+ self.spec_extras = {
30
+ required_ruby_version: '>= 2.2.2'
31
+ }
32
+
33
+ end
data/bin/fbdat ADDED
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## tip: to test run:
4
+ ## ruby -I ./lib bin/fbdat
5
+
6
+ require 'footballdata'
7
+
8
+
9
+ load_env ## use dotenv (.env)
10
+
11
+
12
+ Webcache.root = if File.exist?( '/sports/cache' )
13
+ puts " setting web cache to >/sports/cache<"
14
+ '/sports/cache'
15
+ else
16
+ './cache'
17
+ end
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
+ Webget.config.sleep = 10
24
+
25
+
26
+
27
+
28
+ require 'optparse'
29
+
30
+
31
+
32
+ module Footballdata
33
+ def self.main( args=ARGV )
34
+
35
+ opts = {}
36
+ parser = OptionParser.new do |parser|
37
+ parser.banner = "Usage: #{$PROGRAM_NAME} [options]"
38
+
39
+ parser.on( "--cache", "--cached", "--offline",
40
+ "use cached data in #{Webcache.root}" ) do |cached|
41
+ opts[:cached] = cached
42
+ end
43
+ end
44
+ parser.parse!( args )
45
+
46
+ puts "OPTS:"
47
+ p opts
48
+ puts "ARGV:"
49
+ p args
50
+
51
+
52
+ ## try special args
53
+
54
+ if ['plan', 'plans',
55
+ 'comp', 'comps'].include?(args[0])
56
+
57
+ if opts[:cached]
58
+ ## do nothing
59
+ else
60
+ Metal.competitions( auth: true ) ## get free tier (TIER_ONE) with auth (token)
61
+ end
62
+
63
+ url = Metal.competitions_url
64
+ pp url
65
+ #=> "http://api.football-data.org/v4/competitions"
66
+
67
+ data = Webcache.read_json( url )
68
+ pp data
69
+
70
+ comps = data['competitions']
71
+ comps.each do |rec|
72
+ print "==> "
73
+ print "#{rec['area']['name']} (#{rec['area']['code']}) - "
74
+ print "#{rec['name']} (#{rec['code']}) -- "
75
+ print "#{rec['plan']} #{rec['type']}, "
76
+ print "#{rec['numberOfAvailableSeasons']} season(s)"
77
+ print "\n"
78
+
79
+ print " #{rec['currentSeason']['startDate']} - #{rec['currentSeason']['endDate']} "
80
+ print "@ #{rec['currentSeason']['currentMatchday']}"
81
+ print "\n"
82
+ end
83
+
84
+ puts " #{comps.size} competition(s)"
85
+ exit 0
86
+ end
87
+
88
+
89
+ ###
90
+ # pretty print today's matches (tomorrow/yesterday/etc.)
91
+
92
+
93
+ ##
94
+ ## note - cannot use t for today (used for tomorrow)
95
+ ## find a different shortcode - why? why not?
96
+
97
+ ### note - today is default if no args passed in!!!
98
+
99
+ ##
100
+ ## todo - add more date offsets - t+2,t+3,t+4, etc.
101
+
102
+ date = if ['y', 'yesterday', 't-1', '-1'].include?( args[0] )
103
+ Date.today-1
104
+ elsif ['t', 'tomorrow', 't+1', '1', '+1'].include?( args[0] )
105
+ Date.today+1
106
+ elsif ['m', 'match', 'matches', 'today'].include?( args[0] || 'today' ) ## make default - why? why not?
107
+ Date.today
108
+ else
109
+ nil
110
+ end
111
+
112
+ if date
113
+ if opts[:cached]
114
+ ## do nothing
115
+ else
116
+ Metal.todays_matches( date )
117
+ end
118
+
119
+ data = Webcache.read_json( Metal.todays_matches_url( date ) )
120
+ pp data
121
+
122
+ last_comp = nil
123
+ data['matches'].each do |rec|
124
+ ## only print competition header if different from last match
125
+ comp = fmt_competition( rec )
126
+ puts comp if comp != last_comp
127
+
128
+ puts fmt_match( rec )
129
+
130
+ last_comp = comp
131
+ end
132
+ exit 0
133
+ end
134
+
135
+
136
+
137
+ ###
138
+ # league and season - pretty print matches
139
+ #
140
+ ## samples:
141
+ ## national teams
142
+ ## EC 2024 - euro
143
+ ## EC 2021
144
+ ## WC 2022 - world cup
145
+ ## club cups intl
146
+ ## CL 2023 - (uefa/european) champions league
147
+ ## CLI 2204 - (south american) copa libertadores
148
+ ## club leagues
149
+ ## PL 2024 - england premiere league
150
+
151
+
152
+ league_code = args[0] || 'PL'
153
+
154
+ ### convenience helpers - lets you use eng.1, euro, etc.
155
+ ## check if mapping for league_code
156
+ if LEAGUES.has_key?( league_code.downcase )
157
+ league_code = LEAGUES[ league_code.downcase ]
158
+ else
159
+ ## assume "native" code
160
+ ## always upcase e.g. pl => PL etc.
161
+ league_code = league_code.upcase
162
+ end
163
+
164
+
165
+ season = Season( args[1] ||
166
+ (league_code == 'EC' ? '2024' : '2024/25'))
167
+
168
+ season_start_year = season.start_year ## use year - why? why not?
169
+
170
+ pp league_code, season_start_year
171
+
172
+ if opts[:cached]
173
+ ## do nothing
174
+ else
175
+ ## download dataset(s)
176
+ ## try download
177
+ Metal.matches( league_code,
178
+ season_start_year )
179
+ end
180
+
181
+ url = Metal.competition_matches_url( league_code,
182
+ season_start_year )
183
+ pp url
184
+ #=> "http://api.football-data.org/v4/competitions/EC/matches?season=2024"
185
+
186
+ data = Webcache.read_json( url )
187
+ ## pp data
188
+
189
+ pp_matches( data )
190
+
191
+ end # def self.main
192
+ end # module Footballdata
193
+
194
+
195
+
196
+ Footballdata.main( ARGV )
197
+
198
+
199
+ puts "bye"
200
+