sportdb-formats 1.1.3 → 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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +0 -24
  3. data/Rakefile +2 -5
  4. data/lib/sportdb/formats.rb +39 -74
  5. data/lib/sportdb/formats/event/event_reader.rb +1 -1
  6. data/lib/sportdb/formats/league/league_outline_reader.rb +18 -6
  7. data/lib/sportdb/formats/package.rb +2 -2
  8. data/lib/sportdb/formats/team/club_index_history.rb +2 -6
  9. data/lib/sportdb/formats/team/club_reader_history.rb +1 -1
  10. data/lib/sportdb/formats/team/club_reader_props.rb +18 -2
  11. data/lib/sportdb/formats/version.rb +1 -1
  12. data/test/helper.rb +3 -0
  13. metadata +5 -71
  14. data/lib/sportdb/formats/config.rb +0 -40
  15. data/lib/sportdb/formats/match/match_parser_csv.rb +0 -458
  16. data/lib/sportdb/formats/match/match_status_parser.rb +0 -86
  17. data/lib/sportdb/formats/name_helper.rb +0 -87
  18. data/lib/sportdb/formats/score/score_formats.rb +0 -239
  19. data/lib/sportdb/formats/score/score_parser.rb +0 -204
  20. data/lib/sportdb/formats/season_utils.rb +0 -16
  21. data/lib/sportdb/formats/structs/country.rb +0 -31
  22. data/lib/sportdb/formats/structs/group.rb +0 -18
  23. data/lib/sportdb/formats/structs/league.rb +0 -37
  24. data/lib/sportdb/formats/structs/match.rb +0 -157
  25. data/lib/sportdb/formats/structs/matchlist.rb +0 -220
  26. data/lib/sportdb/formats/structs/round.rb +0 -25
  27. data/lib/sportdb/formats/structs/season.rb +0 -192
  28. data/lib/sportdb/formats/structs/standings.rb +0 -268
  29. data/lib/sportdb/formats/structs/team.rb +0 -157
  30. data/lib/sportdb/formats/structs/team_usage.rb +0 -88
  31. data/test/test_clubs.rb +0 -40
  32. data/test/test_csv_reader.rb +0 -31
  33. data/test/test_match.rb +0 -30
  34. data/test/test_match_status_parser.rb +0 -49
  35. data/test/test_name_helper.rb +0 -67
  36. data/test/test_scores.rb +0 -124
  37. data/test/test_season.rb +0 -111
@@ -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,192 +0,0 @@
1
- # encoding: utf-8
2
-
3
-
4
- ### note: make Season like Date a "top-level" / "generic" class
5
-
6
-
7
-
8
- class Season
9
- ##
10
- ## todo: add (optional) start_date and end_date - why? why not?
11
-
12
- ## todo/todo/todo/check/check/check !!!
13
- ## todo: add a kernel Seaons e.g. Season('2011/12')
14
- ## forward to Season.convert( *args ) - why? why not?
15
-
16
- ## todo: add unicode - too - why? why not? see wikipedia pages, for example
17
-
18
- YYYY_YYYY_RE = %r{^ ## e.g. 2011-2012 or 2011/2012
19
- (\d{4})
20
- [/-]
21
- (\d{4})
22
- $
23
- }x
24
- YYYY_YY_RE = %r{^ ## e.g. 2011-12 or 2011/12
25
- (\d{4})
26
- [/-]
27
- (\d{2})
28
- $
29
- }x
30
- YYYY_Y_RE = %r{^ ## e.g. 2011-2 or 2011/2
31
- (\d{4})
32
- [/-]
33
- (\d{1})
34
- $
35
- }x
36
- YYYY_RE = %r{^ ## e.g. 2011
37
- (\d{4})
38
- $
39
- }x
40
-
41
-
42
- def self.parse( str )
43
- new( *_parse( str ))
44
- end
45
-
46
- def self._parse( str ) ## "internal" parse helper
47
- if str =~ YYYY_YYYY_RE ## e.g. 2011/2012
48
- [$1.to_i, $2.to_i]
49
- elsif str =~ YYYY_YY_RE ## e.g. 2011/12
50
- fst = $1.to_i
51
- snd = $2.to_i
52
- snd_exp = '%02d' % [(fst+1) % 100] ## double check: e.g 00 == 00, 01==01 etc.
53
- raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
54
- [fst, fst+1]
55
- elsif str =~ YYYY_Y_RE ## e.g. 2011/2
56
- fst = $1.to_i
57
- snd = $2.to_i
58
- snd_exp = '%d' % [(fst+1) % 10] ## double check: e.g 0 == 0, 1==1 etc.
59
- raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
60
- [fst, fst+1]
61
- elsif str =~ YYYY_RE ## e.g. 2011
62
- [$1.to_i]
63
- else
64
- raise ArgumentError, "[Season.parse] unkown season format >>#{str}<<; sorry cannot parse"
65
- end
66
- end
67
-
68
-
69
-
70
- attr_reader :start_year,
71
- :end_year
72
-
73
- def initialize( *args ) ## assume only string / line gets passed in for now
74
- if args.size == 1 && args[0].is_a?( String )
75
- @start_year, @end_year = self.class._parse( args[0] )
76
- elsif args.size == 1 && args[0].is_a?( Integer )
77
- @start_year = args[0]
78
- @end_year = nil
79
- elsif args.size == 2 && args[0].is_a?( Integer ) &&
80
- args[1].is_a?( Integer )
81
- @start_year = args[0]
82
- @end_year = args[1]
83
- end_year_exp = @start_year+1
84
- raise ArgumentError, "[Season] invalid year in season >>#{to_s}<<; expected #{end_year_exp} but got #{@end_year}" if end_year_exp != @end_year
85
- else
86
- pp args
87
- raise ArgumentError, "[Season] expected season string or season start year (integer) with opt. end year"
88
- end
89
- end
90
-
91
-
92
- ###
93
- ## convenience helper
94
- def start_date ## generate "generic / syntetic start date" - keep helper - why? why not?
95
- if year?
96
- Date.new( start_year, 1, 1 )
97
- else
98
- Date.new( start_year 1, 7 )
99
- end
100
- end
101
-
102
-
103
- ## single-year season e.g. 2011 if no end_year present - todo - find a better name?
104
- def year?() @end_year.nil?; end
105
-
106
- def prev
107
- if year?
108
- Season.new( @start_year-1 )
109
- else
110
- Season.new( @start_year-1, @start_year )
111
- end
112
- end
113
-
114
- def next
115
- if year?
116
- Season.new( @start_year+1 )
117
- else
118
- Season.new( @end_year, @end_year+1 )
119
- end
120
- end
121
- alias_method :succ, :next ## add support for ranges
122
-
123
- include Comparable
124
- def <=>(other)
125
- ## todo/fix/fix: check if other is_a?( Season )!!!
126
- ## what to return if other type/class ??
127
-
128
- res = @start_year <=> other.start_year
129
-
130
- ## check special edge case - year season and other e.g.
131
- ## 2010 <=> 2010/2011
132
- if res == 0 && @end_year != other.end_year
133
- res = @end_year ? 1 : -1 # the season with an end year is greater / wins for now
134
- end
135
-
136
- res
137
- end
138
-
139
-
140
-
141
- def to_formatted_s( format=:default, sep: '/' )
142
- if year?
143
- '%d' % @start_year
144
- else
145
- case format
146
- when :default, :short, :s ## e.g. 1999/00 or 2019/20
147
- "%d#{sep}%02d" % [@start_year, @end_year % 100]
148
- when :long, :l ## e.g. 1999/2000 or 2019/2020
149
- "%d#{sep}%d" % [@start_year, @end_year]
150
- else
151
- raise ArgumentError, "[Season.to_s] unsupported format >#{format}<"
152
- end
153
- end
154
- end
155
- alias_method :to_s, :to_formatted_s
156
-
157
- def key() to_s( :short ); end
158
- alias_method :to_key, :key
159
- alias_method :name, :key
160
- alias_method :title, :key
161
-
162
- alias_method :inspect, :key ## note: add inspect debug support change debug output to string!!
163
-
164
-
165
-
166
- def to_path( format=:default )
167
- case format
168
- when :default, :short, :s ## e.g. 1999-00 or 2019-20
169
- to_s( :short, sep: '-' )
170
- when :long, :l ## e.g. 1999-2000 or 2019-2000
171
- to_s( :long, sep: '-' )
172
- when :archive, :decade, :d ## e.g. 1990s/1999-00 or 2010s/2019-20
173
- "%3d0s/%s" % [@start_year / 10, to_s( :short, sep: '-' )]
174
- when :century, :c ## e.g. 1900s/1990-00 or 2000s/2019-20
175
- "%2d00s/%s" % [@start_year / 100, to_s( :short, sep: '-' )]
176
- else
177
- raise ArgumentError, "[Season.to_path] unsupported format >#{format}<"
178
- end
179
- end # method to_path
180
- alias_method :directory, :to_path ## keep "legacy" directory alias - why? why not?
181
- alias_method :path, :to_path
182
-
183
- end # class Season
184
-
185
-
186
-
187
-
188
- module SportDb
189
- module Import
190
- Season = ::Season ## add a convenience alias
191
- end # module Import
192
- end # module SportDb
@@ -1,268 +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 - todo/fix: change to Line - why? why not?
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
- alias_method :team_name, :team ## note: team for now always a string
25
- alias_method :pos, :rank ## rename back to use pos instead of rank - why? why not?
26
-
27
-
28
- def initialize( team )
29
- @rank = nil # use 0? why? why not?
30
- ## change rank back to pos - why? why not?
31
- @team = team
32
- @played = @home_played = @away_played = 0
33
- @won = @home_won = @away_won = 0
34
- @lost = @home_lost = @away_lost = 0
35
- @drawn = @home_drawn = @away_drawn = 0
36
- @goals_for = @home_goals_for = @away_goals_for = 0
37
- @goals_against = @home_goals_against = @away_goals_against = 0
38
- @pts = @home_pts = @away_pts = 0
39
- end
40
- end # (nested) class StandingsLine
41
-
42
-
43
- def initialize( opts={} )
44
- ## fix:
45
- # passing in e.g. pts for win (3? 2? etc.)
46
- # default to 3 for now
47
-
48
- ## lets you pass in 2 as an alterantive, for example
49
- @pts_won = opts[:pts_won] || 3
50
-
51
- @lines = {} # StandingsLines cached by team name/key
52
- end
53
-
54
-
55
- def update( match_or_matches )
56
- ## convenience - update all matches at once
57
- ## todo/check: check for ActiveRecord_Associations_CollectionProxy and than use to_a (to "force" array) - why? why not?
58
- matches = if match_or_matches.is_a?(Array)
59
- match_or_matches
60
- else
61
- [match_or_matches]
62
- end
63
-
64
- matches.each_with_index do |match,i| # note: index(i) starts w/ zero (0)
65
- update_match( match )
66
- end
67
- self # note: return self to allow chaining
68
- end
69
-
70
-
71
- def to_a
72
- ## return lines; sort and add rank
73
- ## note: will update rank!!!! (side effect)
74
-
75
- #############################
76
- ### calc ranking position (rank)
77
- ## fix/allow same rank e.g. all 1 or more than one team 3rd etc.
78
-
79
- # build array from hash
80
- ary = []
81
- @lines.each do |k,v|
82
- ary << v
83
- end
84
-
85
- ary.sort! do |l,r|
86
- ## note: reverse order (thus, change l,r to r,l)
87
- value = r.pts <=> l.pts
88
- if value == 0 # same pts try goal diff
89
- value = (r.goals_for-r.goals_against) <=> (l.goals_for-l.goals_against)
90
- if value == 0 # same goal diff too; try assume more goals better for now
91
- value = r.goals_for <=> l.goals_for
92
- end
93
- end
94
- value
95
- end
96
-
97
- ## update rank using ordered array
98
- ary.each_with_index do |line,i|
99
- line.rank = i+1 ## add ranking (e.g. 1,2,3 etc.) - note: i starts w/ zero (0)
100
- end
101
-
102
- ary
103
- end # to_a
104
-
105
-
106
-
107
- #####
108
- ###
109
- ## fix: move build to StandingsPart/Report !!!!
110
- def build( source: nil ) ## build / pretty print standings table in string buffer
111
- ## keep pretty printer in struct - why? why not?
112
-
113
-
114
- ## add standings table in markdown to buffer (buf)
115
-
116
- ## todo: use different styles/formats (simple/ etc ???)
117
-
118
- ## simple table (only totals - no home/away)
119
- ## standings.to_a.each do |l|
120
- ## buf << '%2d. ' % l.rank
121
- ## buf << '%-28s ' % l.team
122
- ## buf << '%2d ' % l.played
123
- ## buf << '%3d ' % l.won
124
- ## buf << '%3d ' % l.drawn
125
- ## buf << '%3d ' % l.lost
126
- ## buf << '%3d:%-3d ' % [l.goals_for,l.goals_against]
127
- ## buf << '%3d' % l.pts
128
- ## buf << "\n"
129
- ## end
130
-
131
- buf = ''
132
- buf << "\n"
133
- buf << "```\n"
134
- buf << " - Home - - Away - - Total -\n"
135
- buf << " Pld W D L F:A W D L F:A F:A +/- Pts\n"
136
-
137
- to_a.each do |l|
138
- buf << '%2d. ' % l.rank
139
- buf << '%-28s ' % l.team
140
- buf << '%2d ' % l.played
141
-
142
- buf << '%2d ' % l.home_won
143
- buf << '%2d ' % l.home_drawn
144
- buf << '%2d ' % l.home_lost
145
- buf << '%3d:%-3d ' % [l.home_goals_for,l.home_goals_against]
146
-
147
- buf << '%2d ' % l.away_won
148
- buf << '%2d ' % l.away_drawn
149
- buf << '%2d ' % l.away_lost
150
- buf << '%3d:%-3d ' % [l.away_goals_for,l.away_goals_against]
151
-
152
- buf << '%3d:%-3d ' % [l.goals_for,l.goals_against]
153
-
154
- goals_diff = l.goals_for-l.goals_against
155
- if goals_diff > 0
156
- buf << '%3s ' % "+#{goals_diff}"
157
- elsif goals_diff < 0
158
- buf << '%3s ' % "#{goals_diff}"
159
- else ## assume 0
160
- buf << ' '
161
- end
162
-
163
- buf << '%3d' % l.pts
164
- buf << "\n"
165
- end
166
-
167
- buf << "```\n"
168
- buf << "\n"
169
-
170
- ## optinal: add data source if known / present
171
- ## assume (relative) markdown link for now in README.md
172
- if source
173
- buf << "(Source: [`#{source}`](#{source}))\n"
174
- buf << "\n"
175
- end
176
-
177
- buf
178
- end
179
-
180
-
181
- private
182
- def update_match( m ) ## add a match
183
-
184
- ## note: always use team as string for now
185
- ## for now allow passing in of string OR struct - why? why not?
186
- ## todo/fix: change to m.team1_name and m.team2_name - why? why not?
187
- team1 = m.team1.is_a?( String ) ? m.team1 : m.team1.name
188
- team2 = m.team2.is_a?( String ) ? m.team2 : m.team2.name
189
-
190
- score = m.score_str
191
-
192
- ## puts " #{team1} - #{team2} #{score}"
193
-
194
- unless m.over?
195
- puts " !!!! skipping match - not yet over (date in the future) => #{m.date}"
196
- return
197
- end
198
-
199
- unless m.complete?
200
- puts "!!! [calc_standings] skipping match #{team1} - #{team2} w/ past date #{m.date} - scores incomplete => #{score}"
201
- return
202
- end
203
-
204
-
205
-
206
- line1 = @lines[ team1 ] || StandingsLine.new( team1 )
207
- line2 = @lines[ team2 ] || StandingsLine.new( team2 )
208
-
209
- line1.played += 1
210
- line1.home_played += 1
211
-
212
- line2.played += 1
213
- line2.away_played += 1
214
-
215
- if m.winner == 1
216
- line1.won += 1
217
- line1.home_won += 1
218
-
219
- line2.lost += 1
220
- line2.away_lost += 1
221
-
222
- line1.pts += @pts_won
223
- line1.home_pts += @pts_won
224
- elsif m.winner == 2
225
- line1.lost += 1
226
- line1.home_lost += 1
227
-
228
- line2.won += 1
229
- line2.away_won += 1
230
-
231
- line2.pts += @pts_won
232
- line2.away_pts += @pts_won
233
- else ## assume drawn/tie (that is, 0)
234
- line1.drawn += 1
235
- line1.home_drawn += 1
236
-
237
- line2.drawn += 1
238
- line2.away_drawn += 1
239
-
240
- line1.pts += 1
241
- line1.home_pts += 1
242
- line2.pts += 1
243
- line2.away_pts += 1
244
- end
245
-
246
- if m.score1 && m.score2
247
- line1.goals_for += m.score1
248
- line1.home_goals_for += m.score1
249
- line1.goals_against += m.score2
250
- line1.home_goals_against += m.score2
251
-
252
- line2.goals_for += m.score2
253
- line2.away_goals_for += m.score2
254
- line2.goals_against += m.score1
255
- line2.away_goals_against += m.score1
256
- else
257
- puts "*** warn: [standings] skipping match with missing scores: #{m.inspect}"
258
- end
259
-
260
- @lines[ team1 ] = line1
261
- @lines[ team2 ] = line2
262
- end # method update_match
263
-
264
- end # class Standings
265
-
266
-
267
- end # module Import
268
- end # module SportDb