sportdb-formats 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
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