sportdb-exporters 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 192a963be138b0e03063615abbb95e84d2e2f492
4
+ data.tar.gz: a881a0a6845e6265b81c20411eaba1fe3a35fa31
5
+ SHA512:
6
+ metadata.gz: a947f48d8d2b14b360934c7dd2c8cf11b8a086a4dcc57aa7516ddf3e82192fc77dda3c36f28e46bba475e598ffada9abf826779142e30d1e10d25daa34315931
7
+ data.tar.gz: b22a856f3a193a9817c4b3f5d1def27d513a1c2ac3c93c10851693032308e27027cfcc96bd42069c762d4413b4b26c3ee87281c02ab350e9cee6f37edec6ac08
@@ -0,0 +1,4 @@
1
+ ### 0.0.1 / 2020-09-21
2
+
3
+ * Everything is new. First release.
4
+
@@ -0,0 +1,8 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/sportdb/exporters.rb
6
+ lib/sportdb/exporters/json_exporter.rb
7
+ lib/sportdb/exporters/json_exporter_more.rb
8
+ lib/sportdb/exporters/version.rb
@@ -0,0 +1,28 @@
1
+ # sportdb-exporters - export helpers for sport.db data in various formats incl. json, csv, and friends
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/sportdb-exporters](https://rubygems.org/gems/sportdb-exporters)
7
+ * rdoc :: [rubydoc.info/gems/sportdb-exporters](http://rubydoc.info/gems/sportdb-exporters)
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 `sportdb-exporters` 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,26 @@
1
+ require 'hoe'
2
+ require './lib/sportdb/exporters/version.rb'
3
+
4
+ Hoe.spec 'sportdb-exporters' do
5
+
6
+ self.version = SportDb::Module::Exporters::VERSION
7
+
8
+ self.summary = 'sportdb-exporters - export helpers for sport.db data in various formats incl. json, csv, and friends'
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.licenses = ['Public Domain']
21
+
22
+ self.spec_extras = {
23
+ required_ruby_version: '>= 2.2.2'
24
+ }
25
+
26
+ end
@@ -0,0 +1,14 @@
1
+ require 'sportdb/catalogs'
2
+ require 'sportdb/models'
3
+
4
+
5
+ ###
6
+ # our own code
7
+ require 'sportdb/exporters/version'
8
+ require 'sportdb/exporters/json_exporter'
9
+ require 'sportdb/exporters/json_exporter_more'
10
+
11
+
12
+
13
+ SportDb::Module::Exporters.banner # say hello
14
+
@@ -0,0 +1,237 @@
1
+ module SportDb
2
+ class JsonExporter
3
+
4
+
5
+ LEAGUE_TO_BASENAME = {
6
+ 'eng.1' => 'en.1',
7
+ 'eng.2' => 'en.2',
8
+ 'eng.3' => 'en.3',
9
+ 'eng.4' => 'en.4',
10
+
11
+ 'world' => 'worldcup',
12
+ ## 'cl' => 'cl', ## keep cl as is :-)
13
+ 'uefa.cl' => 'cl',
14
+ 'uefa.cl.quali' => 'cl.quali'
15
+ }
16
+
17
+
18
+ def self.export( league_key, out_root: )
19
+
20
+ puts "find league >#{league_key}<"
21
+ league = Model::League.find_by( key: league_key )
22
+
23
+ if league.nil?
24
+ puts "!! WARN: no league found for >#{league_key}<; skipping export json"
25
+ return
26
+ end
27
+
28
+
29
+ league.events.each do |event|
30
+ puts "** event:"
31
+ pp event.name
32
+ pp event.season
33
+ pp event.league
34
+ puts "teams.count: #{event.teams.count}"
35
+ puts "rounds.count: #{event.rounds.count}"
36
+ puts "groups.count: #{event.groups.count}"
37
+ puts "matches.count: #{event.matches.count}"
38
+
39
+
40
+ ## build path e.g.
41
+ ## 2014-15/at.1.clubs.json
42
+
43
+ ## -- check for remapping (e.g. add .1); if not found use league key as is
44
+ league_basename = LEAGUE_TO_BASENAME[ event.league.key ] || event.league.key
45
+
46
+ season_basename = event.season.name.sub('/', '-') ## e.g. change 2014/15 to 2014-15
47
+
48
+
49
+ out_dir = "#{out_root}/#{season_basename}"
50
+ ## make sure folders exist
51
+ FileUtils.mkdir_p( out_dir ) unless Dir.exists?( out_dir )
52
+
53
+ ### note:
54
+ ## skip teams for now if no teams on "top-level"
55
+ ## - what to do? use all unique teams from matches? yes, yes!!
56
+ ## - maybe add stages array to team - why? why not?
57
+ ## - or use teams by stage?
58
+
59
+ ## if empty - try regular season stage
60
+ ## or apertura stage?
61
+
62
+
63
+ unless event.teams.empty?
64
+ data_clubs = build_clubs( event )
65
+ ## pp data_clubs
66
+ File.open( "#{out_dir}/#{league_basename}.clubs.json", 'w:utf-8' ) do |f|
67
+ f.write JSON.pretty_generate( data_clubs )
68
+ end
69
+ end
70
+
71
+ # note: make groups export optional for now - why? why not?
72
+ unless event.groups.empty?
73
+ data_groups = build_groups( event )
74
+ ## pp data_groups
75
+ File.open( "#{out_dir}/#{league_basename}.groups.json", 'w' ) do |f|
76
+ f.write JSON.pretty_generate( data_groups )
77
+ end
78
+ end
79
+
80
+ data_matches = build_matches( event )
81
+ ## pp data_matches
82
+ File.open( "#{out_dir}/#{league_basename}.json", 'w:utf-8' ) do |f|
83
+ f.write JSON.pretty_generate( data_matches )
84
+ end
85
+ end
86
+ end
87
+
88
+
89
+ ###############
90
+ ## helpers
91
+
92
+ def self.build_clubs( event )
93
+ clubs = []
94
+ event.teams.each do |team|
95
+ clubs << { name: team.name,
96
+ code: team.code,
97
+ country: team.country.name, }
98
+ end
99
+
100
+ data = {
101
+ name: event.name,
102
+ clubs: clubs
103
+ }
104
+
105
+ data
106
+ end
107
+
108
+
109
+ def self.build_groups( event )
110
+ groups = []
111
+ event.groups.each do |group|
112
+ teams = []
113
+
114
+ if group.teams.empty?
115
+ puts "!! WARN - group #{group.name} has no teams/is empty"
116
+ end
117
+
118
+ group.teams.each do |team|
119
+ teams << team.name
120
+ end
121
+ groups << { name: group.name, teams: teams }
122
+ end
123
+
124
+ data = {
125
+ name: event.name,
126
+ groups: groups
127
+ }
128
+
129
+ data
130
+ end
131
+
132
+
133
+ def self.build_matches( event )
134
+ ## note: no longer list by rounds
135
+ ## now list by dates and add round as a "regular" field
136
+ ## note: make round optional too!!!
137
+
138
+ matches = []
139
+ event.matches.order( 'date ASC' ).each do |match|
140
+ h = {}
141
+
142
+ ## let stage and/or group go first if present/available
143
+ h[ :stage ] = match.stage.name if match.stage
144
+ h[ :round ] = match.round.name if match.round
145
+ h[ :group ] = match.group.name if match.group
146
+
147
+
148
+ h[ :date ] = match.date.strftime( '%Y-%m-%d')
149
+ h[ :team1 ] = match.team1.name
150
+ h[ :team2 ] = match.team2.name
151
+
152
+
153
+ score = {}
154
+ if match.score1 && match.score2
155
+ score[:ft] = [match.score1, match.score2]
156
+ end
157
+
158
+ if match.score1et && match.score2et
159
+ score[:et] = [match.score1et, match.score2et]
160
+ end
161
+
162
+ if match.score1p && match.score2p
163
+ score[:p] = [match.score1p, match.score2p]
164
+ end
165
+
166
+ h[ :score ] = score unless score.empty? ## note: only add if has some data
167
+
168
+
169
+ unless match.goals.empty?
170
+ goals1, goals2 = build_goals( match )
171
+ h[ :goals1 ] = goals1
172
+ h[ :goals2 ] = goals2
173
+ end
174
+
175
+
176
+ if match.status
177
+ case match.status
178
+ when Status::CANCELLED
179
+ h[ :status ] = 'CANCELLED'
180
+ when Status::AWARDED
181
+ h[ :status ] = 'AWARDED'
182
+ when Status::ABANDONED
183
+ h[ :status ] = 'ABANDONED'
184
+ when Status::REPLAY
185
+ h[ :status ] = 'REPLAY'
186
+ when Status::POSTPONED
187
+ ## note: add NOTHING for postponed for now
188
+ else
189
+ puts "!! WARN - unknown match status >#{match.status}<:"
190
+ pp match
191
+ h[ :status ] = match.status.downcase ## print "literal" downcased for now
192
+ end
193
+ end
194
+
195
+ matches << h
196
+ end
197
+
198
+ data = {
199
+ name: event.name,
200
+ matches: matches
201
+ }
202
+
203
+ data
204
+ end
205
+
206
+
207
+
208
+ def self.build_goals( match )
209
+ goals1 = []
210
+ goals2 = []
211
+
212
+ match.goals.each do |goal|
213
+ if goal.team_id == match.team1_id
214
+ goals = goals1
215
+ elsif goal.team_id == match.team2_id
216
+ goals = goals2
217
+ else
218
+ puts "*** team id NOT matching for goal; must be team1 or team2 id"
219
+ exit 1 ## exit - why? why not?
220
+ end
221
+
222
+ g = { name: goal.person.name,
223
+ minute: goal.minute,
224
+ }
225
+ g[:offset] = goal.offset if goal.offset != 0
226
+ g[:score1] = goal.score1
227
+ g[:score2] = goal.score2
228
+ g[:penalty] = goal.penalty if goal.penalty
229
+ g[:owngoal] = goal.owngoal if goal.owngoal
230
+ goals << g
231
+ end
232
+ [goals1, goals2]
233
+ end
234
+
235
+
236
+ end # class Json Exporter
237
+ end # module SportDb
@@ -0,0 +1,250 @@
1
+ module SportDb
2
+ class JsonExporter
3
+
4
+ ## hack: for timezone (add timezone to city - fix/fix/fix)
5
+
6
+ CITY_TO_TIMEZONE = {
7
+ ## brazil 2014
8
+ 'Rio de Janeiro' => 'UTC-3',
9
+ 'Brasília' => 'UTC-3',
10
+ 'São Paulo' => 'UTC-3',
11
+ 'Fortaleza' => 'UTC-3',
12
+ 'Belo Horizonte' => 'UTC-3',
13
+ 'Salvador' => 'UTC-3',
14
+ 'Natal' => 'UTC-3',
15
+ 'Porto Alegre' => 'UTC-3',
16
+ 'Recife' => 'UTC-3',
17
+ 'Curitiba' => 'UTC-3',
18
+ 'Cuiabá' => 'UTC-4',
19
+ 'Manaus' => 'UTC-4',
20
+ ## russia 2018
21
+ 'Kaliningrad' => 'UTC+2',
22
+ 'Nizhny Novgorod' => 'UTC+3',
23
+ 'Volgograd' => 'UTC+3',
24
+ 'Saransk' => 'UTC+3',
25
+ 'Rostov-on-Don' => 'UTC+3',
26
+ 'Kazan' => 'UTC+3',
27
+ 'Sochi' => 'UTC+3',
28
+ 'Saint Petersburg' => 'UTC+3',
29
+ 'Moscow' => 'UTC+3',
30
+ 'Samara' => 'UTC+4',
31
+ 'Ekaterinburg' => 'UTC+5',
32
+ }
33
+
34
+ def self.city_to_timezone( city )
35
+ CITY_TO_TIMEZONE[ city ] || '?'
36
+ end
37
+
38
+
39
+ def self.export_worldcup( league_key, out_root: )
40
+
41
+ league = Model::League.find_by_key!( league_key )
42
+
43
+ league.events.each do |event|
44
+ puts "** event:"
45
+ pp event.title
46
+ pp event.season
47
+ pp event.league
48
+ puts "teams.count: #{event.teams.count}"
49
+ puts "rounds.count: #{event.rounds.count}"
50
+ puts "groups.count: #{event.groups.count}"
51
+ puts "grounds.count: #{event.grounds.count}"
52
+
53
+
54
+ grounds = []
55
+ event.grounds.each do |ground|
56
+ grounds << { key: ground.key,
57
+ name: ground.title,
58
+ capacity: ground.capacity,
59
+ city: ground.city.name,
60
+ timezone: city_to_timezone( ground.city.name ) }
61
+ end
62
+
63
+ hash_grounds = {
64
+ name: event.title,
65
+ stadiums: grounds
66
+ }
67
+
68
+ pp hash_grounds
69
+
70
+
71
+ teams = []
72
+ event.teams.each do |team|
73
+ if team.country.assoc
74
+ continental = {}
75
+ team.country.assoc.parent_assocs.each do |parent|
76
+ ## next if parent.key == 'fifa' ## skip fifa
77
+ ## todo/fix: only include / use (single) continental (parent) org/assoc
78
+ ## find/use continental parent only for now
79
+ if ['caf', 'afc', 'concacaf', 'uefa', 'conmebol', 'ofc'].include? parent.key
80
+ continental = { name: parent.title,
81
+ code: parent.key.upcase }
82
+ end
83
+ end
84
+ assoc = { key: team.country.assoc.key,
85
+ name: team.country.assoc.title,
86
+ }
87
+ assoc[ :continental ] = continental unless continental.empty?
88
+ else
89
+ assoc = {}
90
+ end
91
+ t = { name: team.title,
92
+ code: team.code,
93
+ continent: team.country.continent.name }
94
+ t[ :assoc ] = assoc unless assoc.empty?
95
+ teams << t
96
+ end
97
+
98
+ hash_teams = {
99
+ name: event.title,
100
+ teams: teams
101
+ }
102
+
103
+ pp hash_teams
104
+
105
+
106
+ standings = []
107
+ event.groups.each do |group|
108
+ entries = []
109
+ group_standing = Model::GroupStanding.find_by( group_id: group.id )
110
+ if group_standing
111
+ group_standing.entries.each do |entry|
112
+ entries << { team: { name: entry.team.name, code: entry.team.code },
113
+ pos: entry.pos,
114
+ played: entry.played,
115
+ won: entry.won,
116
+ drawn: entry.drawn,
117
+ lost: entry.lost,
118
+ goals_for: entry.goals_for,
119
+ goals_against: entry.goals_against,
120
+ pts: entry.pts
121
+ }
122
+ end
123
+ end
124
+ standings << { name: group.title, standings: entries }
125
+ end
126
+
127
+ hash_standings = {
128
+ name: event.title,
129
+ groups: standings
130
+ }
131
+
132
+ pp hash_standings
133
+
134
+
135
+ groups = []
136
+ event.groups.each do |group|
137
+ teams = []
138
+ group.teams.each do |team|
139
+ teams << { name: team.title,
140
+ code: team.code
141
+ }
142
+ end
143
+ groups << { name: group.title, teams: teams }
144
+ end
145
+
146
+ hash_groups = {
147
+ name: event.title,
148
+ groups: groups
149
+ }
150
+
151
+ pp hash_groups
152
+
153
+
154
+ rounds = []
155
+ event.rounds.each do |round|
156
+ matches = []
157
+ round.games.each do |game|
158
+ m = { num: game.pos, ## use id - why? why not?
159
+ date: game.play_at.strftime( '%Y-%m-%d'),
160
+ time: game.play_at.strftime( '%H:%M'),
161
+ team1: {
162
+ name: game.team1.title,
163
+ code: game.team1.code
164
+ },
165
+ team2: {
166
+ name: game.team2.title,
167
+ code: game.team2.code
168
+ },
169
+ score1: game.score1,
170
+ score2: game.score2,
171
+ score1i: game.score1i, # half time / first third (opt)
172
+ score2i: game.score2i, # half time - team 2
173
+ }
174
+
175
+ if game.knockout
176
+ m[ :score1et ] = game.score1et # extratime - team 1 (opt)
177
+ m[ :score2et ] = game.score2et # extratime - team 2 (opt)
178
+ m[ :score1p ] = game.score1p # penalty - team 1 (opt)
179
+ m[ :score2p ] = game.score2p # penalty - team 2 (opt) elfmeter (opt)
180
+ m[ :knockout ] = game.knockout
181
+ end
182
+
183
+ unless game.goals.empty?
184
+ goals1, goals2 = build_goals( game )
185
+ m[ :goals1 ] = goals1
186
+ m[ :goals2 ] = goals2
187
+ end
188
+
189
+ if game.group
190
+ m[ :group ] = game.group.title
191
+ end
192
+
193
+ if game.ground
194
+ m[ :stadium ] = { key: game.ground.key, name: game.ground.title }
195
+ m[ :city ] = game.ground.city.name
196
+ m[ :timezone ] = city_to_timezone( game.ground.city.name )
197
+ end
198
+
199
+ matches << m
200
+ end
201
+
202
+ rounds << { name: round.title, matches: matches }
203
+ end
204
+
205
+ hash_matches = {
206
+ name: event.title,
207
+ rounds: rounds
208
+ }
209
+
210
+ pp hash_matches
211
+
212
+
213
+ ## build path e.g.
214
+ ## 2014-15/at.1.clubs.json
215
+ ## 2018/worldcup.teams.json
216
+
217
+ ## -- check for remapping (e.g. add .1); if not found use league key as is
218
+ league_basename = LEAGUE_TO_BASENAME[ event.league.key ] || event.league.key
219
+
220
+ season_basename = event.season.title.sub('/', '-') ## e.g. change 2014/15 to 2014-15
221
+
222
+
223
+ out_dir = "#{out_root}/#{season_basename}"
224
+ ## make sure folders exist
225
+ FileUtils.mkdir_p( out_dir ) unless Dir.exists?( out_dir )
226
+
227
+ File.open( "#{out_dir}/#{league_basename}.stadiums.json", 'w' ) do |f|
228
+ f.write JSON.pretty_generate( hash_grounds )
229
+ end
230
+
231
+ File.open( "#{out_dir}/#{league_basename}.teams.json", 'w' ) do |f|
232
+ f.write JSON.pretty_generate( hash_teams )
233
+ end
234
+
235
+ File.open( "#{out_dir}/#{league_basename}.groups.json", 'w' ) do |f|
236
+ f.write JSON.pretty_generate( hash_groups )
237
+ end
238
+
239
+ File.open( "#{out_dir}/#{league_basename}.standings.json", 'w' ) do |f|
240
+ f.write JSON.pretty_generate( hash_standings )
241
+ end
242
+
243
+ File.open( "#{out_dir}/#{league_basename}.json", 'w' ) do |f|
244
+ f.write JSON.pretty_generate( hash_matches )
245
+ end
246
+ end
247
+ end
248
+
249
+ end # class Json Exporter
250
+ end # module SportDb
@@ -0,0 +1,25 @@
1
+
2
+ module SportDb
3
+ module Module
4
+ module Exporters
5
+
6
+ MAJOR = 0 ## todo: namespace inside version or something - why? why not??
7
+ MINOR = 0
8
+ PATCH = 1
9
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
10
+
11
+ def self.version
12
+ VERSION
13
+ end
14
+
15
+ def self.banner
16
+ "sportdb-exporters/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
17
+ end
18
+
19
+ def self.root
20
+ File.expand_path( File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) )
21
+ end
22
+
23
+ end # module Exporters
24
+ end # module Module
25
+ end # module SportDb
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sportdb-exporters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gerald Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-09-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdoc
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hoe
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.16'
41
+ description: sportdb-exporters - export helpers for sport.db data in various formats
42
+ incl. json, csv, and friends
43
+ email: opensport@googlegroups.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files:
47
+ - CHANGELOG.md
48
+ - Manifest.txt
49
+ - README.md
50
+ files:
51
+ - CHANGELOG.md
52
+ - Manifest.txt
53
+ - README.md
54
+ - Rakefile
55
+ - lib/sportdb/exporters.rb
56
+ - lib/sportdb/exporters/json_exporter.rb
57
+ - lib/sportdb/exporters/json_exporter_more.rb
58
+ - lib/sportdb/exporters/version.rb
59
+ homepage: https://github.com/sportdb/sport.db
60
+ licenses:
61
+ - Public Domain
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options:
65
+ - "--main"
66
+ - README.md
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 2.2.2
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.5.2
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: sportdb-exporters - export helpers for sport.db data in various formats incl.
85
+ json, csv, and friends
86
+ test_files: []