sportdb-formats 1.0.6 → 1.1.4

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +6 -33
  3. data/Rakefile +2 -5
  4. data/lib/sportdb/formats.rb +54 -70
  5. data/lib/sportdb/formats/country/country_index.rb +2 -2
  6. data/lib/sportdb/formats/event/event_index.rb +141 -0
  7. data/lib/sportdb/formats/event/event_reader.rb +183 -0
  8. data/lib/sportdb/formats/league/league_index.rb +22 -18
  9. data/lib/sportdb/formats/league/league_outline_reader.rb +45 -13
  10. data/lib/sportdb/formats/league/league_reader.rb +7 -1
  11. data/lib/sportdb/formats/match/match_parser.rb +101 -111
  12. data/lib/sportdb/formats/package.rb +59 -11
  13. data/lib/sportdb/formats/parser_helper.rb +11 -2
  14. data/lib/sportdb/formats/team/club_index.rb +13 -11
  15. data/lib/sportdb/formats/team/club_index_history.rb +134 -0
  16. data/lib/sportdb/formats/team/club_reader_history.rb +203 -0
  17. data/lib/sportdb/formats/team/club_reader_props.rb +20 -5
  18. data/lib/sportdb/formats/version.rb +2 -2
  19. data/test/helper.rb +51 -81
  20. data/test/test_club_index_history.rb +107 -0
  21. data/test/test_club_reader_history.rb +212 -0
  22. data/test/test_datafile_package.rb +1 -1
  23. data/test/test_regex.rb +25 -7
  24. metadata +9 -78
  25. data/lib/sportdb/formats/config.rb +0 -40
  26. data/lib/sportdb/formats/match/match_parser_csv.rb +0 -314
  27. data/lib/sportdb/formats/name_helper.rb +0 -84
  28. data/lib/sportdb/formats/score/score_formats.rb +0 -220
  29. data/lib/sportdb/formats/score/score_parser.rb +0 -202
  30. data/lib/sportdb/formats/season_utils.rb +0 -27
  31. data/lib/sportdb/formats/structs/country.rb +0 -31
  32. data/lib/sportdb/formats/structs/group.rb +0 -18
  33. data/lib/sportdb/formats/structs/league.rb +0 -37
  34. data/lib/sportdb/formats/structs/match.rb +0 -151
  35. data/lib/sportdb/formats/structs/matchlist.rb +0 -220
  36. data/lib/sportdb/formats/structs/round.rb +0 -25
  37. data/lib/sportdb/formats/structs/season.rb +0 -123
  38. data/lib/sportdb/formats/structs/standings.rb +0 -247
  39. data/lib/sportdb/formats/structs/team.rb +0 -150
  40. data/lib/sportdb/formats/structs/team_usage.rb +0 -88
  41. data/test/test_clubs.rb +0 -40
  42. data/test/test_conf.rb +0 -65
  43. data/test/test_csv_match_parser.rb +0 -114
  44. data/test/test_csv_match_parser_utils.rb +0 -20
  45. data/test/test_csv_reader.rb +0 -31
  46. data/test/test_match.rb +0 -30
  47. data/test/test_match_auto.rb +0 -72
  48. data/test/test_match_auto_champs.rb +0 -45
  49. data/test/test_match_auto_euro.rb +0 -37
  50. data/test/test_match_auto_worldcup.rb +0 -61
  51. data/test/test_match_champs.rb +0 -27
  52. data/test/test_match_eng.rb +0 -26
  53. data/test/test_match_euro.rb +0 -27
  54. data/test/test_match_worldcup.rb +0 -27
  55. data/test/test_name_helper.rb +0 -67
  56. data/test/test_scores.rb +0 -122
  57. data/test/test_season.rb +0 -62
@@ -1,25 +0,0 @@
1
- module SportDb
2
- module Import
3
-
4
- class Round
5
- attr_reader :name, :start_date, :end_date, :knockout
6
- attr_accessor :num # note: make read & writable - why? why not?
7
-
8
- def initialize( name:,
9
- num: nil,
10
- start_date: nil,
11
- end_date: nil,
12
- knockout: false,
13
- auto: true )
14
- @name = name
15
- @num = num
16
- @start_date = start_date
17
- @end_date = end_date
18
- @knockout = knockout
19
- @auto = auto # auto-created (inline reference/header without proper definition before)
20
- end
21
- end # class Round
22
-
23
- end # module Import
24
- end # module SportDb
25
-
@@ -1,123 +0,0 @@
1
- # encoding: utf-8
2
-
3
-
4
- module SportDb
5
- module Import
6
-
7
-
8
- class Season
9
- ##
10
- ## todo: add (optional) start_date and end_date - why? why not?
11
- ## add next
12
-
13
-
14
- attr_reader :start_year,
15
- :end_year
16
-
17
- def year?() @end_year.nil?; end ## single-year season e.g. 2011 if no end_year present
18
-
19
-
20
- def initialize( str ) ## assume only string / line gets passed in for now
21
- @start_year, @end_year = parse( str )
22
- end
23
-
24
-
25
- YYYY_YYYY_RE = %r{^ ## e.g. 2011-2012 or 2011/2012
26
- (\d{4})
27
- [/-]
28
- (\d{4})
29
- $
30
- }x
31
- YYYY_YY_RE = %r{^ ## e.g. 2011-12 or 2011/12
32
- (\d{4})
33
- [/-]
34
- (\d{2})
35
- $
36
- }x
37
- YYYY_Y_RE = %r{^ ## e.g. 2011-2 or 2011/2
38
- (\d{4})
39
- [/-]
40
- (\d{1})
41
- $
42
- }x
43
- YYYY_RE = %r{^ ## e.g. 2011
44
- (\d{4})
45
- $
46
- }x
47
-
48
- def parse( str )
49
- if str =~ YYYY_YYYY_RE ## e.g. 2011/2012
50
- [$1.to_i, $2.to_i]
51
- elsif str =~ YYYY_YY_RE ## e.g. 2011/12
52
- fst = $1.to_i
53
- snd = $2.to_i
54
- snd_exp = '%02d' % [(fst+1) % 100] ## double check: e.g 00 == 00, 01==01 etc.
55
- raise ArgumentError.new( "[Season#parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}") if snd_exp != $2
56
- [fst, fst+1]
57
- elsif str =~ YYYY_Y_RE ## e.g. 2011/2
58
- fst = $1.to_i
59
- snd = $2.to_i
60
- snd_exp = '%d' % [(fst+1) % 10] ## double check: e.g 0 == 0, 1==1 etc.
61
- raise ArgumentError.new( "[Season#parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}") if snd_exp != $2
62
- [fst, fst+1]
63
- elsif str =~ YYYY_RE ## e.g. 2011
64
- [$1.to_i]
65
- else
66
- raise ArgumentError.new( "[Season#parse] unkown season format >>#{str}<<; sorry cannot parse")
67
- end
68
- end
69
-
70
-
71
-
72
- def prev
73
- if year?
74
- Season.new( "#{@start_year-1}" )
75
- else
76
- Season.new( "#{@start_year-1}/#{@start_year}" )
77
- end
78
- end
79
-
80
- def key
81
- if year?
82
- '%d' % @start_year
83
- else
84
- '%d/%02d' % [@start_year, @end_year % 100]
85
- end
86
- end
87
- alias_method :to_key, :key
88
- alias_method :to_s, :key
89
-
90
- alias_method :name, :key
91
- alias_method :title, :key
92
-
93
-
94
- def path( format: nil )
95
- ## todo: find better names for formats - why? why not?:
96
- ## long | archive | decade(?) => 1980s/1988-89, 2010s/2017-18, ...
97
- ## short | std(?) => 1988-89, 2017-18, ...
98
-
99
- ## convert season name to "standard" season name for directory
100
-
101
- if ['l', 'long', 'archive' ].include?( format.to_s ) ## note: allow passing in of symbol to e.g. 'long' or :long
102
- if year? ## e.g. 2000s/2001
103
- "%3d0s/%4d" % [@start_year / 10, @start_year]
104
- else ## e.g. 2000s/2001-02
105
- "%3d0s/%4d-%02d" % [@start_year / 10, @start_year, @end_year % 100]
106
- end
107
- else ## default 'short' format / fallback
108
- if year? ## e.g. 2001
109
- "%4d" % @start_year
110
- else ## e.g. 2001-02
111
- "%4d-%02d" % [@start_year, @end_year % 100]
112
- end
113
- end
114
- end # method path
115
- alias_method :directory, :path ## keep "legacy" directory alias - why? why not?
116
- alias_method :to_path, :path
117
-
118
-
119
- end # class Season
120
-
121
-
122
- end # module Import
123
- end # module SportDb
@@ -1,247 +0,0 @@
1
- # encoding: utf-8
2
-
3
- ##########
4
- # todo/fix:
5
- ## reuse standings helper/calculator from sportdb
6
- ## do NOT duplicate
7
-
8
-
9
- module SportDb
10
- module Import
11
-
12
-
13
- class Standings
14
-
15
- class StandingsLine ## nested class StandinsLine
16
- attr_accessor :rank, :team,
17
- :played, :won, :lost, :drawn, ## -- total
18
- :goals_for, :goals_against, :pts,
19
- :home_played, :home_won, :home_lost, :home_drawn, ## -- home
20
- :home_goals_for, :home_goals_against, :home_pts,
21
- :away_played, :away_won, :away_lost, :away_drawn, ## -- away
22
- :away_goals_for, :away_goals_against, :away_pts
23
-
24
- def initialize( team )
25
- @rank = nil # use 0? why? why not?
26
- @team = team
27
- @played = @home_played = @away_played = 0
28
- @won = @home_won = @away_won = 0
29
- @lost = @home_lost = @away_lost = 0
30
- @drawn = @home_drawn = @away_drawn = 0
31
- @goals_for = @home_goals_for = @away_goals_for = 0
32
- @goals_against = @home_goals_against = @away_goals_against = 0
33
- @pts = @home_pts = @away_pts = 0
34
- end
35
- end # (nested) class StandingsLine
36
-
37
-
38
- def initialize( opts={} )
39
- ## fix:
40
- # passing in e.g. pts for win (3? 2? etc.)
41
- # default to 3 for now
42
-
43
- ## lets you pass in 2 as an alterantive, for example
44
- @pts_won = opts[:pts_won] || 3
45
-
46
- @lines = {} # StandingsLines cached by team name/key
47
- end
48
-
49
-
50
- def update( match_or_matches )
51
- ## convenience - update all matches at once
52
- matches = match_or_matches.is_a?(Array) ? match_or_matches : [match_or_matches]
53
-
54
- matches.each_with_index do |match,i| # note: index(i) starts w/ zero (0)
55
- update_match( match )
56
- end
57
- self # note: return self to allow chaining
58
- end
59
-
60
-
61
- def to_a
62
- ## return lines; sort and add rank
63
- ## note: will update rank!!!! (side effect)
64
-
65
- #############################
66
- ### calc ranking position (rank)
67
- ## fix/allow same rank e.g. all 1 or more than one team 3rd etc.
68
-
69
- # build array from hash
70
- ary = []
71
- @lines.each do |k,v|
72
- ary << v
73
- end
74
-
75
- ary.sort! do |l,r|
76
- ## note: reverse order (thus, change l,r to r,l)
77
- value = r.pts <=> l.pts
78
- if value == 0 # same pts try goal diff
79
- value = (r.goals_for-r.goals_against) <=> (l.goals_for-l.goals_against)
80
- if value == 0 # same goal diff too; try assume more goals better for now
81
- value = r.goals_for <=> l.goals_for
82
- end
83
- end
84
- value
85
- end
86
-
87
- ## update rank using ordered array
88
- ary.each_with_index do |line,i|
89
- line.rank = i+1 ## add ranking (e.g. 1,2,3 etc.) - note: i starts w/ zero (0)
90
- end
91
-
92
- ary
93
- end # to_a
94
-
95
-
96
-
97
- #####
98
- ###
99
- ## fix: move build to StandingsPart/Report !!!!
100
- def build( source: nil ) ## build / pretty print standings table in string buffer
101
- ## keep pretty printer in struct - why? why not?
102
-
103
-
104
- ## add standings table in markdown to buffer (buf)
105
-
106
- ## todo: use different styles/formats (simple/ etc ???)
107
-
108
- ## simple table (only totals - no home/away)
109
- ## standings.to_a.each do |l|
110
- ## buf << '%2d. ' % l.rank
111
- ## buf << '%-28s ' % l.team
112
- ## buf << '%2d ' % l.played
113
- ## buf << '%3d ' % l.won
114
- ## buf << '%3d ' % l.drawn
115
- ## buf << '%3d ' % l.lost
116
- ## buf << '%3d:%-3d ' % [l.goals_for,l.goals_against]
117
- ## buf << '%3d' % l.pts
118
- ## buf << "\n"
119
- ## end
120
-
121
- buf = ''
122
- buf << "\n"
123
- buf << "```\n"
124
- buf << " - Home - - Away - - Total -\n"
125
- buf << " Pld W D L F:A W D L F:A F:A +/- Pts\n"
126
-
127
- to_a.each do |l|
128
- buf << '%2d. ' % l.rank
129
- buf << '%-28s ' % l.team
130
- buf << '%2d ' % l.played
131
-
132
- buf << '%2d ' % l.home_won
133
- buf << '%2d ' % l.home_drawn
134
- buf << '%2d ' % l.home_lost
135
- buf << '%3d:%-3d ' % [l.home_goals_for,l.home_goals_against]
136
-
137
- buf << '%2d ' % l.away_won
138
- buf << '%2d ' % l.away_drawn
139
- buf << '%2d ' % l.away_lost
140
- buf << '%3d:%-3d ' % [l.away_goals_for,l.away_goals_against]
141
-
142
- buf << '%3d:%-3d ' % [l.goals_for,l.goals_against]
143
-
144
- goals_diff = l.goals_for-l.goals_against
145
- if goals_diff > 0
146
- buf << '%3s ' % "+#{goals_diff}"
147
- elsif goals_diff < 0
148
- buf << '%3s ' % "#{goals_diff}"
149
- else ## assume 0
150
- buf << ' '
151
- end
152
-
153
- buf << '%3d' % l.pts
154
- buf << "\n"
155
- end
156
-
157
- buf << "```\n"
158
- buf << "\n"
159
-
160
- ## optinal: add data source if known / present
161
- ## assume (relative) markdown link for now in README.md
162
- if source
163
- buf << "(Source: [`#{source}`](#{source}))\n"
164
- buf << "\n"
165
- end
166
-
167
- buf
168
- end
169
-
170
-
171
- private
172
- def update_match( m ) ## add a match
173
-
174
- ## puts " #{m.team1} - #{m.team2} #{m.score_str}"
175
- unless m.over?
176
- puts " !!!! skipping match - not yet over (play_at date in the future)"
177
- return
178
- end
179
-
180
- unless m.complete?
181
- puts "!!! [calc_standings] skipping match #{m.team1} - #{m.team2} - scores incomplete #{m.score_str}"
182
- return
183
- end
184
-
185
- line1 = @lines[ m.team1 ] || StandingsLine.new( m.team1 )
186
- line2 = @lines[ m.team2 ] || StandingsLine.new( m.team2 )
187
-
188
- line1.played += 1
189
- line1.home_played += 1
190
-
191
- line2.played += 1
192
- line2.away_played += 1
193
-
194
- if m.winner == 1
195
- line1.won += 1
196
- line1.home_won += 1
197
-
198
- line2.lost += 1
199
- line2.away_lost += 1
200
-
201
- line1.pts += @pts_won
202
- line1.home_pts += @pts_won
203
- elsif m.winner == 2
204
- line1.lost += 1
205
- line1.home_lost += 1
206
-
207
- line2.won += 1
208
- line2.away_won += 1
209
-
210
- line2.pts += @pts_won
211
- line2.away_pts += @pts_won
212
- else ## assume drawn/tie (that is, 0)
213
- line1.drawn += 1
214
- line1.home_drawn += 1
215
-
216
- line2.drawn += 1
217
- line2.away_drawn += 1
218
-
219
- line1.pts += 1
220
- line1.home_pts += 1
221
- line2.pts += 1
222
- line2.away_pts += 1
223
- end
224
-
225
- if m.score1 && m.score2
226
- line1.goals_for += m.score1
227
- line1.home_goals_for += m.score1
228
- line1.goals_against += m.score2
229
- line1.home_goals_against += m.score2
230
-
231
- line2.goals_for += m.score2
232
- line2.away_goals_for += m.score2
233
- line2.goals_against += m.score1
234
- line2.away_goals_against += m.score1
235
- else
236
- puts "*** warn: [standings] skipping match with missing scores: #{m.inspect}"
237
- end
238
-
239
- @lines[ m.team1 ] = line1
240
- @lines[ m.team2 ] = line2
241
- end # method update_match
242
-
243
- end # class Standings
244
-
245
-
246
- end # module Import
247
- end # module SportDb
@@ -1,150 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module SportDb
4
- module Import
5
-
6
-
7
- ##
8
- ## todo/fix: remove self.create in structs!!! use just new!!!
9
-
10
- class Team
11
- ## todo: use just names for alt_names - why? why not?
12
- attr_accessor :key, :name, :alt_names,
13
- :code, ## code == abbreviation e.g. ARS etc.
14
- :year, :year_end, ## todo/fix: change year to start_year and year_end to end_year (like in season)!!!
15
- :country
16
-
17
-
18
- def names
19
- ## todo/check: add alt_names_auto too? - why? why not?
20
- [@name] + @alt_names
21
- end ## all names
22
-
23
- def key
24
- ## note: auto-generate key "on-the-fly" if missing for now - why? why not?
25
- ## note: quick hack - auto-generate key, that is, remove all non-ascii chars and downcase
26
- @key || @name.downcase.gsub( /[^a-z]/, '' )
27
- end
28
-
29
-
30
- ## special import only attribs
31
- attr_accessor :alt_names_auto ## auto-generated alt names
32
- attr_accessor :wikipedia # wikipedia page name (for english (en))
33
-
34
-
35
- def historic?() @year_end ? true : false; end
36
- alias_method :past?, :historic?
37
-
38
- def wikipedia?() @wikipedia; end
39
- def wikipedia_url
40
- if @wikipedia
41
- ## note: replace spaces with underscore (-)
42
- ## e.g. Club Brugge KV => Club_Brugge_KV
43
- ## todo/check/fix:
44
- ## check if "plain" dash (-) needs to get replaced with typographic dash??
45
- "https://en.wikipedia.org/wiki/#{@wikipedia.gsub(' ','_')}"
46
- else
47
- nil
48
- end
49
- end
50
-
51
-
52
- def initialize( **kwargs )
53
- @alt_names = []
54
- @alt_names_auto = []
55
-
56
- update( kwargs ) unless kwargs.empty?
57
- end
58
-
59
- def update( **kwargs )
60
- @key = kwargs[:key] if kwargs.has_key? :key
61
- @name = kwargs[:name] if kwargs.has_key? :name
62
- @code = kwargs[:code] if kwargs.has_key? :code
63
- @alt_names = kwargs[:alt_names] if kwargs.has_key? :alt_names
64
- self ## note - MUST return self for chaining
65
- end
66
-
67
-
68
- ## helper methods for import only
69
- ## check for duplicates
70
- include NameHelper
71
-
72
- def duplicates?
73
- names = [name] + alt_names + alt_names_auto
74
- names = names.map { |name| normalize( sanitize(name) ) }
75
-
76
- names.size != names.uniq.size
77
- end
78
-
79
- def duplicates
80
- names = [name] + alt_names + alt_names_auto
81
-
82
- ## calculate (count) frequency and select if greater than one
83
- names.reduce( {} ) do |h,name|
84
- norm = normalize( sanitize(name) )
85
- h[norm] ||= []
86
- h[norm] << name; h
87
- end.select { |norm,names| names.size > 1 }
88
- end
89
-
90
-
91
- def add_variants( name_or_names )
92
- names = name_or_names.is_a?(Array) ? name_or_names : [name_or_names]
93
- names.each do |name|
94
- name = sanitize( name )
95
- self.alt_names_auto += variants( name )
96
- end
97
- end
98
- end # class Team
99
-
100
-
101
-
102
- class NationalTeam < Team
103
- def initialize( **kwargs )
104
- super
105
- end
106
-
107
- def update( **kwargs )
108
- super
109
- self ## note - MUST return self for chaining
110
- end
111
-
112
- end # class NationalTeam
113
-
114
-
115
- ########
116
- # more attribs - todo/fix - also add "upstream" to struct & model!!!!!
117
- # district, geos, year_end, country, etc.
118
-
119
- class Club < Team
120
- attr_accessor :ground
121
-
122
- attr_accessor :a, :b
123
- def a?() @a == nil; end ## is a (1st) team / club (i)? if a is NOT set
124
- def b?() @a != nil; end ## is b (2nd/reserve/jr) team / club (ii) if a is set
125
-
126
- ## note: delegate/forward all geo attributes for team b for now (to team a) - keep - why? why not?
127
- attr_writer :city, :district, :geos
128
- def city() @a == nil ? @city : @a.city; end
129
- def district() @a == nil ? @district : @a.district; end
130
- def country() @a == nil ? @country : @a.country; end
131
- def geos() @a == nil ? @geos : @a.geos; end
132
-
133
-
134
- def initialize( **kwargs )
135
- super
136
- end
137
-
138
- def update( **kwargs )
139
- super
140
- @city = kwargs[:city] if kwargs.has_key? :city
141
- ## todo/fix: use city struct - why? why not?
142
- ## todo/fix: add country too or report unused keywords / attributes - why? why not?
143
-
144
- self ## note - MUST return self for chaining
145
- end
146
- end # class Club
147
-
148
-
149
- end # module Import
150
- end # module SportDb