football-sources 0.0.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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +4 -0
  3. data/Manifest.txt +36 -0
  4. data/README.md +28 -0
  5. data/Rakefile +31 -0
  6. data/lib/football-sources.rb +46 -0
  7. data/lib/football-sources/apis.rb +86 -0
  8. data/lib/football-sources/apis/config.rb +17 -0
  9. data/lib/football-sources/apis/convert.rb +239 -0
  10. data/lib/football-sources/apis/convert_cl.rb +267 -0
  11. data/lib/football-sources/apis/download.rb +11 -0
  12. data/lib/football-sources/apis/stat.rb +59 -0
  13. data/lib/football-sources/version.rb +19 -0
  14. data/lib/football-sources/worldfootball.rb +24 -0
  15. data/lib/football-sources/worldfootball/build.rb +245 -0
  16. data/lib/football-sources/worldfootball/config.rb +16 -0
  17. data/lib/football-sources/worldfootball/convert.rb +100 -0
  18. data/lib/football-sources/worldfootball/convert_reports.rb +107 -0
  19. data/lib/football-sources/worldfootball/download.rb +61 -0
  20. data/lib/football-sources/worldfootball/leagues.rb +200 -0
  21. data/lib/football-sources/worldfootball/leagues/asia.rb +53 -0
  22. data/lib/football-sources/worldfootball/leagues/europe--british_isles.rb +59 -0
  23. data/lib/football-sources/worldfootball/leagues/europe--central.rb +127 -0
  24. data/lib/football-sources/worldfootball/leagues/europe--eastern.rb +82 -0
  25. data/lib/football-sources/worldfootball/leagues/europe--northern.rb +57 -0
  26. data/lib/football-sources/worldfootball/leagues/europe--southern.rb +86 -0
  27. data/lib/football-sources/worldfootball/leagues/europe--western.rb +38 -0
  28. data/lib/football-sources/worldfootball/leagues/europe.rb +13 -0
  29. data/lib/football-sources/worldfootball/leagues/north_america.rb +44 -0
  30. data/lib/football-sources/worldfootball/leagues/pacific.rb +21 -0
  31. data/lib/football-sources/worldfootball/leagues/south_america.rb +11 -0
  32. data/lib/football-sources/worldfootball/mods.rb +72 -0
  33. data/lib/football-sources/worldfootball/tool.rb +100 -0
  34. data/lib/football-sources/worldfootball/vacuum.rb +66 -0
  35. data/lib/football/sources.rb +6 -0
  36. data/test/helper.rb +8 -0
  37. data/test/test_version.rb +16 -0
  38. metadata +147 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0d80d7220f2414773d0547c6aa69d15722d414bb
4
+ data.tar.gz: eae20eaed5e9fd9efdb33602cc2f3125b1334797
5
+ SHA512:
6
+ metadata.gz: cd4a9b5dbd4c86bd9ec20bebda0b56979bb6c5ce3d4fddf6fdfb947188b08f7dca68a931baf4bd199ff66f5518f326bc10bde273d43cd2c957c9e40c9f4b4cec
7
+ data.tar.gz: d8be6c1a8246cd61f77aa4b63f0b382d9cde0da408c83e0e7626ad34ed9daf567b5735702f05dbbf9a0dd8035baea51f9ff83e67a0cb14dc02e261659781e121
@@ -0,0 +1,4 @@
1
+ ### 0.0.1 / 2020-11-09
2
+
3
+ * Everything is new. First release.
4
+
@@ -0,0 +1,36 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/football-sources.rb
6
+ lib/football-sources/apis.rb
7
+ lib/football-sources/apis/config.rb
8
+ lib/football-sources/apis/convert.rb
9
+ lib/football-sources/apis/convert_cl.rb
10
+ lib/football-sources/apis/download.rb
11
+ lib/football-sources/apis/stat.rb
12
+ lib/football-sources/version.rb
13
+ lib/football-sources/worldfootball.rb
14
+ lib/football-sources/worldfootball/build.rb
15
+ lib/football-sources/worldfootball/config.rb
16
+ lib/football-sources/worldfootball/convert.rb
17
+ lib/football-sources/worldfootball/convert_reports.rb
18
+ lib/football-sources/worldfootball/download.rb
19
+ lib/football-sources/worldfootball/leagues.rb
20
+ lib/football-sources/worldfootball/leagues/asia.rb
21
+ lib/football-sources/worldfootball/leagues/europe--british_isles.rb
22
+ lib/football-sources/worldfootball/leagues/europe--central.rb
23
+ lib/football-sources/worldfootball/leagues/europe--eastern.rb
24
+ lib/football-sources/worldfootball/leagues/europe--northern.rb
25
+ lib/football-sources/worldfootball/leagues/europe--southern.rb
26
+ lib/football-sources/worldfootball/leagues/europe--western.rb
27
+ lib/football-sources/worldfootball/leagues/europe.rb
28
+ lib/football-sources/worldfootball/leagues/north_america.rb
29
+ lib/football-sources/worldfootball/leagues/pacific.rb
30
+ lib/football-sources/worldfootball/leagues/south_america.rb
31
+ lib/football-sources/worldfootball/mods.rb
32
+ lib/football-sources/worldfootball/tool.rb
33
+ lib/football-sources/worldfootball/vacuum.rb
34
+ lib/football/sources.rb
35
+ test/helper.rb
36
+ test/test_version.rb
@@ -0,0 +1,28 @@
1
+ # football-sources - get football data via web pages or web api (json) calls
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/football-sources](https://rubygems.org/gems/football-sources)
7
+ * rdoc :: [rubydoc.info/gems/football-sources](http://rubydoc.info/gems/football-sources)
8
+ * forum :: [groups.google.com/group/opensport](https://groups.google.com/group/opensport)
9
+
10
+
11
+ ## Usage
12
+
13
+ TBD
14
+
15
+
16
+ ## License
17
+
18
+ ![](https://publicdomainworks.github.io/buttons/zero88x31.png)
19
+
20
+ The `football-sources` scripts are dedicated to the public domain.
21
+ Use it as you please with no restrictions whatsoever.
22
+
23
+
24
+ ## Questions? Comments?
25
+
26
+ Send them along to the
27
+ [Open Sports & Friends Forum/Mailing List](http://groups.google.com/group/opensport).
28
+ Thanks!
@@ -0,0 +1,31 @@
1
+ require 'hoe'
2
+ require './lib/football-sources/version.rb'
3
+
4
+ Hoe.spec 'football-sources' do
5
+
6
+ self.version = FootballSources::VERSION
7
+
8
+ self.summary = 'football-sources - get football data via web pages or web api (json) calls'
9
+ self.description = summary
10
+
11
+ self.urls = { home: 'https://github.com/sportdb/sport.db' }
12
+
13
+ self.author = 'Gerald Bauer'
14
+ self.email = 'opensport@googlegroups.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
+ ['webget-football', '>= 0.0.1'],
22
+ ['sportdb-catalogs', '>= 1.0.0'],
23
+ ]
24
+
25
+ self.licenses = ['Public Domain']
26
+
27
+ self.spec_extras = {
28
+ required_ruby_version: '>= 2.2.2'
29
+ }
30
+
31
+ end
@@ -0,0 +1,46 @@
1
+ require 'webget/football'
2
+
3
+
4
+ # require 'sportdb/formats' ## for Season etc.
5
+ require 'sportdb/catalogs' ## note: incl. deps csvreader etc.
6
+
7
+
8
+
9
+ #############
10
+ ## todo/fix: reuse a "original" CsvMatchWriter
11
+ ## how? why? why not?
12
+ ###############
13
+ module Cache
14
+ class CsvMatchWriter
15
+
16
+ def self.write( path, recs, headers: )
17
+
18
+ ## for convenience - make sure parent folders/directories exist
19
+ FileUtils.mkdir_p( File.dirname( path )) unless Dir.exist?( File.dirname( path ))
20
+
21
+ File.open( path, 'w:utf-8' ) do |f|
22
+ f.write headers.join(',') ## e.g. Date,Team 1,FT,HT,Team 2
23
+ f.write "\n"
24
+ recs.each do |rec|
25
+ f.write rec.join(',')
26
+ f.write "\n"
27
+ end
28
+ end
29
+ end
30
+
31
+ end # class CsvMatchWriter
32
+ end # module Cache
33
+
34
+
35
+
36
+
37
+ ###
38
+ # our own code
39
+ require 'football-sources/version' # let version always go first
40
+
41
+ require 'football-sources/apis'
42
+ require 'football-sources/worldfootball'
43
+
44
+
45
+
46
+ puts FootballSources.banner # say hello
@@ -0,0 +1,86 @@
1
+ ###########################
2
+ # note: split code in two parts
3
+ # metal - "bare" basics - no ref to sportdb
4
+ # and rest / convert with sportdb references / goodies
5
+
6
+
7
+ module Footballdata
8
+
9
+ LEAGUES = {
10
+ 'eng.1' => 'PL', # incl. team(s) from wales
11
+ 'eng.2' => 'ELC',
12
+ # PL - Premier League , England 27 seasons | 2019-08-09 - 2020-07-25 / matchday 31
13
+ # ELC - Championship , England 3 seasons | 2019-08-02 - 2020-07-22 / matchday 38
14
+ #
15
+ # 2019 => 2019/20
16
+ # 2018 => 2018/19
17
+ # 2017 => xxx 2017-18 - requires subscription !!!
18
+
19
+ 'es.1' => 'PD',
20
+ # PD - Primera Division , Spain 27 seasons | 2019-08-16 - 2020-07-19 / matchday 31
21
+
22
+ 'pt.1' => 'PPL',
23
+ # PPL - Primeira Liga , Portugal 9 seasons | 2019-08-10 - 2020-07-26 / matchday 28
24
+
25
+ 'de.1' => 'BL1',
26
+ # BL1 - Bundesliga , Germany 24 seasons | 2019-08-16 - 2020-06-27 / matchday 34
27
+
28
+ 'nl.1' => 'DED',
29
+ # DED - Eredivisie , Netherlands 10 seasons | 2019-08-09 - 2020-03-08 / matchday 34
30
+
31
+ 'fr.1' => 'FL1', # incl. team(s) monaco
32
+ # FL1 - Ligue 1, France
33
+ # 9 seasons | 2019-08-09 - 2020-05-31 / matchday 38
34
+ #
35
+ # 2019 => 2019/20
36
+ # 2018 => 2018/19
37
+ # 2017 => xxx 2017-18 - requires subscription !!!
38
+
39
+ 'it.1' => 'SA',
40
+ # SA - Serie A , Italy 15 seasons | 2019-08-24 - 2020-08-02 / matchday 27
41
+
42
+ 'br.1' => 'BSA',
43
+ # BSA - Série A, Brazil
44
+ # 4 seasons | 2020-05-03 - 2020-12-06 / matchday 10
45
+ #
46
+ # 2020 => 2020
47
+ # 2019 => 2019
48
+ # 2018 => 2018
49
+ # 2017 => xxx 2017 - requires subscription !!!
50
+
51
+ ## todo/check: use champs and NOT cl - why? why not?
52
+ 'cl' => 'CL', ## note: cl is country code for chile!! - use champs - why? why not?
53
+ 'europe.cl' => 'CL', ## note: cl is country code for chile!! - use champs - why? why not?
54
+ # CL - UEFA Champions League , Europe 19 seasons | 2019-06-25 - 2020-05-30 / matchday 6
55
+ }
56
+
57
+
58
+ #########
59
+ ## Mods
60
+ # e.g.
61
+ # Cardiff City FC | Cardiff › Wales - Cardiff City Stadium, Leckwith Road Cardiff CF11 8AZ
62
+ # AS Monaco FC | Monaco › Monaco - Avenue des Castellans Monaco 98000
63
+
64
+
65
+ MODS = {
66
+ 'br.1' => {
67
+ 'América FC' => 'América MG', # in year 2018
68
+ },
69
+ 'pt.1' => {
70
+ 'Vitória SC' => 'Vitória Guimarães', ## avoid easy confusion with Vitória SC <=> Vitória FC
71
+ 'Vitória FC' => 'Vitória Setúbal',
72
+ },
73
+ }
74
+
75
+ end # module Footballdata
76
+
77
+
78
+ ###########################
79
+ ## our own code
80
+ require_relative 'apis/config'
81
+ require_relative 'apis/stat'
82
+ require_relative 'apis/download'
83
+
84
+ require_relative 'apis/convert'
85
+ require_relative 'apis/convert_cl'
86
+
@@ -0,0 +1,17 @@
1
+
2
+ module Footballdata
3
+
4
+ ### add some more config options / settings
5
+ class Configuration
6
+ #########
7
+ ## nested configuration classes - use - why? why not?
8
+ class Convert
9
+ def out_dir() @out_dir || './o'; end
10
+ def out_dir=(value) @out_dir = value; end
11
+ end
12
+
13
+ def convert() @convert ||= Convert.new; end
14
+ end # class Configuration
15
+
16
+
17
+ end # module Footballdata
@@ -0,0 +1,239 @@
1
+
2
+
3
+ module Footballdata
4
+
5
+
6
+ def self.convert( league:, season: )
7
+
8
+ ### note/fix: cl (champions league for now is a "special" case)
9
+ if league.downcase == 'cl'
10
+ convert_cl( league: league,
11
+ season: season )
12
+ return
13
+ end
14
+
15
+
16
+
17
+ season = Season( season ) ## cast (ensure) season class (NOT string, integer, etc.)
18
+
19
+ data = Webcache.read_json( Metal.competition_matches_url( LEAGUES[league.downcase], season.start_year ))
20
+ data_teams = Webcache.read_json( Metal.competition_teams_url( LEAGUES[league.downcase], season.start_year ))
21
+
22
+
23
+ ## build a (reverse) team lookup by name
24
+ puts "#{data_teams['teams'].size} teams"
25
+
26
+ teams_by_name = data_teams['teams'].reduce( {} ) do |h,rec|
27
+ h[ rec['name'] ] = rec
28
+ h
29
+ end
30
+
31
+ pp teams_by_name.keys
32
+
33
+
34
+
35
+ mods = MODS[ league.downcase ] || {}
36
+
37
+
38
+ recs = []
39
+
40
+ teams = Hash.new( 0 )
41
+
42
+ stat = Stat.new
43
+
44
+ matches = data[ 'matches']
45
+ matches.each do |m|
46
+ stat.update( m )
47
+
48
+ team1 = m['homeTeam']['name']
49
+ team2 = m['awayTeam']['name']
50
+
51
+ score = m['score']
52
+
53
+
54
+
55
+ if m['stage'] == 'REGULAR_SEASON'
56
+ teams[ team1 ] += 1
57
+ teams[ team2 ] += 1
58
+
59
+ ### mods - rename club names
60
+ unless mods.nil? || mods.empty?
61
+ team1 = mods[ team1 ] if mods[ team1 ]
62
+ team2 = mods[ team2 ] if mods[ team2 ]
63
+ end
64
+
65
+
66
+ ## e.g. "utcDate": "2020-05-09T00:00:00Z",
67
+ date_str = m['utcDate']
68
+ date = DateTime.strptime( date_str, '%Y-%m-%dT%H:%M:%SZ' )
69
+
70
+
71
+ comments = ''
72
+ ft = ''
73
+ ht = ''
74
+
75
+ case m['status']
76
+ when 'SCHEDULED', 'IN_PLAY'
77
+ ft = ''
78
+ ht = ''
79
+ when 'FINISHED'
80
+ ## todo/fix: assert duration == "REGULAR"
81
+ ft = "#{score['fullTime']['homeTeam']}-#{score['fullTime']['awayTeam']}"
82
+ ht = "#{score['halfTime']['homeTeam']}-#{score['halfTime']['awayTeam']}"
83
+ when 'AWARDED'
84
+ ## todo/fix: assert duration == "REGULAR"
85
+ ft = "#{score['fullTime']['homeTeam']}-#{score['fullTime']['awayTeam']}"
86
+ ft << ' (*)'
87
+ ht = ''
88
+ comments = 'awarded'
89
+ when 'CANCELLED'
90
+ ft = '(*)'
91
+ ht = ''
92
+ comments = 'canceled' ## us eng ? -> canceled, british eng. cancelled ?
93
+ when 'POSTPONED'
94
+ ft = '(*)'
95
+ ht = ''
96
+ comments = 'postponed'
97
+ else
98
+ puts "!! ERROR: unsupported match status >#{m['status']}< - sorry:"
99
+ pp m
100
+ exit 1
101
+ end
102
+
103
+
104
+ ## todo/fix: assert matchday is a number e.g. 1,2,3, etc.!!!
105
+ recs << [m['matchday'],
106
+ date.to_date.strftime( '%Y-%m-%d' ),
107
+ team1,
108
+ ft,
109
+ ht,
110
+ team2,
111
+ comments
112
+ ]
113
+
114
+
115
+ print '%2s' % m['matchday']
116
+ print ' - '
117
+ print '%-24s' % team1
118
+ print ' '
119
+ print ft
120
+ print ' '
121
+ print "(#{ht})" unless ht.empty?
122
+ print ' '
123
+ print '%-24s' % team2
124
+ print ' '
125
+ print comments
126
+ print ' | '
127
+ ## print date.to_date ## strip time
128
+ print date.to_date.strftime( '%a %b %-d %Y' )
129
+ print ' -- '
130
+ print date
131
+ print "\n"
132
+ else
133
+ puts "-- skipping #{m['stage']}"
134
+ end
135
+ end # each match
136
+
137
+
138
+
139
+ ## note: get season from first match
140
+ ## assert - all other matches include the same season
141
+ ## e.g.
142
+ # "season": {
143
+ # "id": 154,
144
+ # "startDate": "2018-08-03",
145
+ # "endDate": "2019-05-05",
146
+ # "currentMatchday": 46
147
+ # }
148
+
149
+ start_date = Date.strptime( matches[0]['season']['startDate'], '%Y-%m-%d' )
150
+ end_date = Date.strptime( matches[0]['season']['endDate'], '%Y-%m-%d' )
151
+
152
+ dates = "#{start_date.strftime('%b %-d')} - #{end_date.strftime('%b %-d')}"
153
+
154
+ buf = ''
155
+ buf << "#{season.key} (#{dates}) - "
156
+ buf << "#{teams.keys.size} clubs, "
157
+ buf << "#{stat[:regular_season][:matches]} matches, "
158
+ buf << "#{stat[:regular_season][:goals]} goals"
159
+ buf << "\n"
160
+
161
+ puts buf
162
+
163
+
164
+
165
+ ## note: warn if stage is greater one and not regular season!!
166
+ File.open( './errors.txt' , 'a:utf-8' ) do |f|
167
+ if stat[:all][:stage].keys != ['REGULAR_SEASON']
168
+ f.write "!! WARN - league: #{league}, season: #{season.key} includes non-regular stage(s):\n"
169
+ f.write " #{stat[:all][:stage].keys.inspect}\n"
170
+ end
171
+ end
172
+
173
+
174
+ File.open( './logs.txt', 'a:utf-8' ) do |f|
175
+ f.write "\n================================\n"
176
+ f.write "==== #{league} =============\n"
177
+ f.write buf
178
+ f.write " match status: #{stat[:regular_season][:status].inspect}\n"
179
+ f.write " match duration: #{stat[:regular_season][:duration].inspect}\n"
180
+
181
+ f.write "#{teams.keys.size} teams:\n"
182
+ teams.each do |name, count|
183
+ rec = teams_by_name[ name ]
184
+ f.write " #{count}x #{name}"
185
+ if rec
186
+ f.write " | #{rec['shortName']} " if name != rec['shortName']
187
+ f.write " › #{rec['area']['name']}"
188
+ f.write " - #{rec['address']}"
189
+ else
190
+ puts "!! ERROR - no team record found in teams.json for >#{name}<"
191
+ exit 1
192
+ end
193
+ f.write "\n"
194
+ end
195
+ end
196
+
197
+
198
+
199
+
200
+ # recs = recs.sort { |l,r| l[1] <=> r[1] }
201
+ ## reformat date / beautify e.g. Sat Aug 7 1993
202
+ recs.each { |rec| rec[1] = Date.strptime( rec[1], '%Y-%m-%d' ).strftime( '%a %b %-d %Y' ) }
203
+
204
+ headers = [
205
+ 'Matchday',
206
+ 'Date',
207
+ 'Team 1',
208
+ 'FT',
209
+ 'HT',
210
+ 'Team 2',
211
+ 'Comments'
212
+ ]
213
+
214
+ ## note: change season_key from 2019/20 to 2019-20 (for path/directory!!!!)
215
+ Cache::CsvMatchWriter.write( "#{config.convert.out_dir}/#{season.to_path}/#{league.downcase}.csv",
216
+ recs,
217
+ headers: headers )
218
+
219
+
220
+ teams.each do |name, count|
221
+ rec = teams_by_name[ name ]
222
+ print " #{count}x "
223
+ print name
224
+ if rec
225
+ print " | #{rec['shortName']} " if name != rec['shortName']
226
+ print " › #{rec['area']['name']}"
227
+ print " - #{rec['address']}"
228
+ else
229
+ puts "!! ERROR - no team record found in teams.json for #{name}"
230
+ exit 1
231
+ end
232
+ print "\n"
233
+ end
234
+
235
+ pp stat
236
+ end # method convert
237
+ end # module Footballdata
238
+
239
+