sportdb-formats 1.0.5 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +8 -11
  3. data/Rakefile +1 -1
  4. data/lib/sportdb/formats.rb +19 -0
  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 +27 -7
  10. data/lib/sportdb/formats/league/league_reader.rb +7 -1
  11. data/lib/sportdb/formats/match/mapper.rb +63 -63
  12. data/lib/sportdb/formats/match/mapper_teams.rb +1 -1
  13. data/lib/sportdb/formats/match/match_parser.rb +141 -193
  14. data/lib/sportdb/formats/match/match_parser_csv.rb +169 -25
  15. data/lib/sportdb/formats/match/match_status_parser.rb +86 -0
  16. data/lib/sportdb/formats/name_helper.rb +4 -1
  17. data/lib/sportdb/formats/package.rb +57 -9
  18. data/lib/sportdb/formats/parser_helper.rb +11 -2
  19. data/lib/sportdb/formats/score/score_formats.rb +19 -0
  20. data/lib/sportdb/formats/score/score_parser.rb +10 -2
  21. data/lib/sportdb/formats/season_utils.rb +0 -11
  22. data/lib/sportdb/formats/structs/group.rb +5 -12
  23. data/lib/sportdb/formats/structs/match.rb +7 -1
  24. data/lib/sportdb/formats/structs/round.rb +6 -13
  25. data/lib/sportdb/formats/structs/season.rb +114 -45
  26. data/lib/sportdb/formats/structs/standings.rb +30 -9
  27. data/lib/sportdb/formats/structs/team.rb +8 -2
  28. data/lib/sportdb/formats/team/club_index.rb +13 -11
  29. data/lib/sportdb/formats/team/club_index_history.rb +138 -0
  30. data/lib/sportdb/formats/team/club_reader_history.rb +203 -0
  31. data/lib/sportdb/formats/team/club_reader_props.rb +2 -3
  32. data/lib/sportdb/formats/version.rb +2 -2
  33. data/test/helper.rb +48 -81
  34. data/test/test_club_index_history.rb +107 -0
  35. data/test/test_club_reader_history.rb +212 -0
  36. data/test/test_country_reader.rb +2 -2
  37. data/test/test_datafile_package.rb +1 -1
  38. data/test/test_match_status_parser.rb +49 -0
  39. data/test/test_regex.rb +25 -7
  40. data/test/test_scores.rb +2 -0
  41. data/test/test_season.rb +68 -19
  42. metadata +12 -15
  43. data/test/test_conf.rb +0 -65
  44. data/test/test_csv_match_parser.rb +0 -114
  45. data/test/test_csv_match_parser_utils.rb +0 -20
  46. data/test/test_match_auto.rb +0 -72
  47. data/test/test_match_auto_champs.rb +0 -45
  48. data/test/test_match_auto_euro.rb +0 -37
  49. data/test/test_match_auto_worldcup.rb +0 -61
  50. data/test/test_match_champs.rb +0 -27
  51. data/test/test_match_eng.rb +0 -26
  52. data/test/test_match_euro.rb +0 -27
  53. data/test/test_match_worldcup.rb +0 -27
@@ -95,12 +95,29 @@ module SportDb
95
95
  headers_mapping[:score] = find_header( headers, ['FT'] )
96
96
  headers_mapping[:scorei] = find_header( headers, ['HT'] )
97
97
 
98
- headers_mapping[:round] = find_header( headers, ['Round'] )
98
+ headers_mapping[:round] = find_header( headers, ['Round', 'Matchday'] )
99
99
 
100
100
  ## optional headers - note: find_header returns nil if header NOT found
101
101
  header_stage = find_header( headers, ['Stage'] )
102
102
  headers_mapping[:stage] = header_stage if header_stage
103
- else
103
+
104
+ header_group = find_header( headers, ['Group'] )
105
+ headers_mapping[:group] = header_group if header_group
106
+
107
+
108
+ header_et = find_header( headers, ['ET', 'AET'] ) ## (after) extra time
109
+ headers_mapping[:score_et] = header_et if header_et
110
+
111
+ header_p = find_header( headers, ['P', 'PEN'] ) ## penalties
112
+ headers_mapping[:score_p] = header_p if header_p
113
+
114
+ header_notes = find_header( headers, ['Notes', 'Comments'] )
115
+ headers_mapping[:notes] = header_notes if header_notes
116
+
117
+
118
+ header_league = find_header( headers, ['League'] )
119
+ headers_mapping[:league] = header_league if header_league
120
+ else
104
121
  ## else try footballdata.uk and others
105
122
  headers_mapping[:team1] = find_header( headers, ['HomeTeam', 'HT', 'Home'] )
106
123
  headers_mapping[:team2] = find_header( headers, ['AwayTeam', 'AT', 'Away'] )
@@ -167,7 +184,10 @@ module SportDb
167
184
 
168
185
 
169
186
  ## check if data present - if not skip (might be empty row)
170
- if team1.nil? && team2.nil?
187
+ ## note: (old classic) csv reader returns nil for empty fields
188
+ ## new modern csv reader ALWAYS returns strings (and empty strings for data not available (n/a))
189
+ if (team1.nil? || team1.empty?) &&
190
+ (team2.nil? || team2.empty?)
171
191
  puts "*** WARN: skipping empty? row[#{i}] - no teams found:"
172
192
  pp row
173
193
  next
@@ -182,9 +202,11 @@ module SportDb
182
202
  col = row[ headers_mapping[ :date ]]
183
203
  col = col.strip # make sure not leading or trailing spaces left over
184
204
 
185
- if col.empty? || col == '-' || col == '?'
186
- ## note: allow missing / unknown date for match
187
- date = nil
205
+ if col.empty? ||
206
+ col =~ /^-{1,}$/ || # e.g. - or ---
207
+ col =~ /^\?{1,}$/ # e.g. ? or ???
208
+ ## note: allow missing / unknown date for match
209
+ date = nil
188
210
  else
189
211
  ## remove possible weekday or weeknumber e.g. (Fri) (4) etc.
190
212
  col = col.sub( /\(W?\d{1,2}\)/, '' ) ## e.g. (W11), (4), (21) etc.
@@ -199,6 +221,8 @@ module SportDb
199
221
  date_fmt = '%Y-%m-%d' # e.g. 1995-08-04
200
222
  elsif col =~ /^\d{1,2} \w{3} \d{4}$/
201
223
  date_fmt = '%d %b %Y' # e.g. 8 Jul 2017
224
+ elsif col =~ /^\w{3} \w{3} \d{1,2} \d{4}$/
225
+ date_fmt = '%a %b %d %Y' # e.g. Sat Aug 7 1993
202
226
  else
203
227
  puts "*** !!! wrong (unknown) date format >>#{col}<<; cannot continue; fix it; sorry"
204
228
  ## todo/fix: add to errors/warns list - why? why not?
@@ -211,12 +235,23 @@ module SportDb
211
235
  end
212
236
 
213
237
 
238
+ ##
239
+ ## todo/fix: round might not always be just a simple integer number!!!
240
+ ## might be text such as Final | Leg 1 or such!!!!
214
241
  round = nil
215
242
  ## check for (optional) round / matchday
216
243
  if headers_mapping[ :round ]
217
244
  col = row[ headers_mapping[ :round ]]
218
245
  ## todo: issue warning if not ? or - (and just empty string) why? why not
219
- round = col.to_i if col =~ /^\d{1,2}$/ # check format - e.g. ignore ? or - or such non-numbers for now
246
+ ## (old attic) was: round = col.to_i if col =~ /^\d{1,2}$/ # check format - e.g. ignore ? or - or such non-numbers for now
247
+
248
+ ## note: make round always a string for now!!!! e.g. "1", "2" too!!
249
+ round = if col.nil? || col.empty? || col == '-' || col == 'n/a'
250
+ ## note: allow missing round for match / defaults to nil
251
+ nil
252
+ else
253
+ col
254
+ end
220
255
  end
221
256
 
222
257
 
@@ -245,25 +280,65 @@ module SportDb
245
280
  score2i = ht[1].to_i if ht[1] =~ /^\d{1,2}$/
246
281
  end
247
282
 
283
+
248
284
  ## check for all-in-one full time scores?
249
285
  if headers_mapping[ :score ]
250
- ft = row[ headers_mapping[ :score ] ]
251
- if ft =~ /^\d{1,2}[\-:]\d{1,2}$/ ## sanity check scores format
252
- scores = ft.split( /[\-:]/ )
253
- score1 = scores[0].to_i
254
- score2 = scores[1].to_i
286
+ col = row[ headers_mapping[ :score ]]
287
+ score = parse_score( col )
288
+ if score
289
+ score1 = score[0]
290
+ score2 = score[1]
291
+ else
292
+ puts "!! ERROR - invalid score (ft) format >#{col}<:"
293
+ pp row
294
+ exit 1
255
295
  end
256
- ## todo/fix: issue warning if non-empty!!! and not matching format!!!!
257
296
  end
258
297
 
259
298
  if headers_mapping[ :scorei ]
260
- ht = row[ headers_mapping[ :scorei ] ]
261
- if ht =~ /^\d{1,2}[\-:]\d{1,2}$/ ## sanity check scores format
262
- scores = ht.split( /[\-:]/) ## allow 1-1 and 1:1
263
- score1i = scores[0].to_i
264
- score2i = scores[1].to_i
299
+ col = row[ headers_mapping[ :scorei ]]
300
+ score = parse_score( col )
301
+ if score
302
+ score1i = score[0]
303
+ score2i = score[1]
304
+ else
305
+ puts "!! ERROR - invalid score (ht) format >#{col}<:"
306
+ pp row
307
+ exit 1
308
+ end
309
+ end
310
+
311
+ ####
312
+ ## try optional score - extra time (et) and penalities (p/pen)
313
+ score1et = nil
314
+ score2et = nil
315
+ score1p = nil
316
+ score2p = nil
317
+
318
+ if headers_mapping[ :score_et ]
319
+ col = row[ headers_mapping[ :score_et ]]
320
+ score = parse_score( col )
321
+ if score
322
+ score1et = score[0]
323
+ score2et = score[1]
324
+ else
325
+ puts "!! ERROR - invalid score (et) format >#{col}<:"
326
+ pp row
327
+ exit 1
328
+ end
329
+ end
330
+
331
+ if headers_mapping[ :score_p ]
332
+ col = row[ headers_mapping[ :score_p ]]
333
+ score = parse_score( col )
334
+ if score
335
+ score1p = score[0]
336
+ score2p = score[1]
337
+ else
338
+ puts "!! ERROR - invalid score (p) format >#{col}<:"
339
+ pp row
340
+ exit 1
265
341
  end
266
- ## todo/fix: issue warning if non-empty!!! and not matching format!!!!
267
342
  end
268
343
 
269
344
 
@@ -283,13 +358,51 @@ module SportDb
283
358
  end
284
359
  end
285
360
 
361
+ group = nil
362
+ if headers_mapping[ :group ]
363
+ col = row[ headers_mapping[ :group ]]
364
+ ## todo/fix: check can col be nil e.g. col.nil? possible?
365
+ group = if col.nil? || col.empty? || col == '-' || col == 'n/a'
366
+ ## note: allow missing stage for match / defaults to "regular"
367
+ nil
368
+ else
369
+ col
370
+ end
371
+ end
372
+
373
+ status = nil ## e.g. AWARDED, CANCELLED, POSTPONED, etc.
374
+ if headers_mapping[ :notes ]
375
+ col = row[ headers_mapping[ :notes ]]
376
+ ## check for optional (match) status in notes / comments
377
+ status = if col.nil? || col.empty? || col == '-' || col == 'n/a'
378
+ nil
379
+ else
380
+ StatusParser.parse( col ) # note: returns nil if no (match) status found
381
+ end
382
+ end
383
+
384
+
385
+ league = nil
386
+ league = row[ headers_mapping[ :league ]] if headers_mapping[ :league ]
286
387
 
287
- match = Import::Match.new( date: date,
288
- team1: team1, team2: team2,
289
- score1: score1, score2: score2,
290
- score1i: score1i, score2i: score2i,
291
- round: round,
292
- stage: stage )
388
+
389
+ ## puts 'match attributes:'
390
+ attributes = {
391
+ date: date,
392
+ team1: team1, team2: team2,
393
+ score1: score1, score2: score2,
394
+ score1i: score1i, score2i: score2i,
395
+ score1et: score1et, score2et: score2et,
396
+ score1p: score1p, score2p: score2p,
397
+ round: round,
398
+ stage: stage,
399
+ group: group,
400
+ status: status,
401
+ league: league
402
+ }
403
+ ## pp attributes
404
+
405
+ match = Import::Match.new( **attributes )
293
406
  matches << match
294
407
  end
295
408
 
@@ -309,6 +422,37 @@ module SportDb
309
422
  nil ## no matching header found!!!
310
423
  end
311
424
 
425
+ ########
426
+ # more helpers
427
+ #
428
+
429
+ def parse_score( str )
430
+ if str.nil? ## todo/check: remove nil case - possible? - why? why not?
431
+ [nil,nil]
432
+ else
433
+ ## remove (optional single) note/footnote/endnote markers
434
+ ## e.g. (*) or (a), (b),
435
+ ## or [*], [A], [1], etc.
436
+ ## - allow (1) or maybe (*1) in the future - why? why not?
437
+ str = str.sub( /\( [a-z*] \)
438
+ |
439
+ \[ [1-9a-z*] \]
440
+ /ix, '' ).strip
441
+
442
+ if str.empty? || str == '?' || str == '-' || str == 'n/a'
443
+ [nil,nil]
444
+ ### todo/check: use regex with named capture groups here - why? why not?
445
+ elsif str =~ /^\d{1,2}[:-]\d{1,2}$/ ## sanity check scores format
446
+ score = str.split( /[:-]/ )
447
+ [score[0].to_i, score[1].to_i]
448
+ else
449
+ nil ## note: returns nil if invalid / unparseable format!!!
450
+ end
451
+ end
452
+ end # method parse_score
453
+
454
+
455
+
312
456
  end # class CsvMatchParser
313
457
  end # module SportDb
314
458
 
@@ -0,0 +1,86 @@
1
+ #####################
2
+ # helpers for parsing & finding match status e.g.
3
+ # - cancelled / canceled
4
+ # - awarded
5
+ # - abandoned
6
+ # - replay
7
+ # etc.
8
+
9
+
10
+ module SportDb
11
+
12
+ class Status
13
+ # note: use a class as an "enum"-like namespace for now - why? why not?
14
+ # move class into Match e.g. Match::Status - why? why not?
15
+ CANCELLED = 'CANCELLED' # canceled (US spelling), cancelled (UK spelling) - what to use?
16
+ AWARDED = 'AWARDED'
17
+ POSTPONED = 'POSTPONED'
18
+ ABANDONED = 'ABANDONED'
19
+ REPLAY = 'REPLAY'
20
+ end # class Status
21
+
22
+
23
+
24
+ class StatusParser
25
+
26
+ def self.parse( str )
27
+ ## note: returns nil if no match found
28
+ ## note: english usage - cancelled (in UK), canceled (in US)
29
+ if str =~ /^(cancelled|
30
+ canceled|
31
+ can\.
32
+ )/xi
33
+ Status::CANCELLED
34
+ elsif str =~ /^(awarded|
35
+ awd\.
36
+ )/xi
37
+ Status::AWARDED
38
+ elsif str =~ /^(postponed
39
+ )/xi
40
+ Status::POSTPONED
41
+ elsif str =~ /^(abandoned|
42
+ abd\.
43
+ )/xi
44
+ Status::ABANDONED
45
+ elsif str =~ /^(replay
46
+ )/xi
47
+ Status::REPLAY
48
+ else
49
+ # no match
50
+ nil
51
+ end
52
+ end
53
+
54
+
55
+ RUN_RE = /\[
56
+ (?<text>[^\]]+)
57
+ \]
58
+ /x
59
+ def self.find!( line )
60
+ ## for now check all "protected" text run blocks e.g. []
61
+ ## puts "line: >#{line}<"
62
+
63
+ status = nil
64
+
65
+ str = line
66
+ while m = str.match( RUN_RE )
67
+ str = m.post_match ## keep on processing rest of line/str (a.k.a. post match string)
68
+
69
+ ## check for status match
70
+ match_str = m[0] ## keep a copy of the match string (for later sub)
71
+ text = m[:text].strip
72
+ ## puts " text: >#{text}<"
73
+
74
+ status = parse( text )
75
+
76
+ if status
77
+ line.sub!( match_str, "[STATUS.#{status}]" )
78
+ break
79
+ end
80
+ end # while match
81
+
82
+ status
83
+ end # method find!
84
+ end # class StatusParser
85
+
86
+ end # module SportDb
@@ -46,9 +46,12 @@ module SportDb
46
46
  ## Estudiantes (LP) => Estudiantes LP
47
47
  ## Saint Patrick’s Athletic FC => Saint Patricks Athletic FC
48
48
  ## Myllykosken Pallo −47 => Myllykosken Pallo 47
49
+ ##
50
+ ## add & too!!
51
+ ## e.g. Brighton & Hove Albion => Brighton Hove Albion -- and others in England
49
52
 
50
53
  NORM_RE = %r{
51
- [.'’º/()_−-]
54
+ [.'’º/()&_−-]
52
55
  }x # note: in [] dash (-) if last doesn't need to get escaped
53
56
  ## note: remove all dots (.), dash (-), ', º, /, etc.
54
57
  # . U+002E (46) - FULL STOP
@@ -13,12 +13,22 @@ module SportDb
13
13
  ## leagues.txt or leagues_en.txt
14
14
  ## remove support for en.leagues.txt - why? why not?
15
15
  LEAGUES_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
16
- (?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.clubs.wiki.txt
16
+ (?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.leagues.txt
17
17
  leagues
18
18
  (?:_[a-z0-9_-]+)?
19
19
  \.txt$
20
20
  }x
21
21
 
22
+ ## seasons.txt or seasons_en.txt
23
+ ## remove support for br.seasons.txt - why? why not?
24
+ SEASONS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
25
+ (?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.seasons.txt
26
+ seasons
27
+ (?:_[a-z0-9_-]+)?
28
+ \.txt$
29
+ }x
30
+
31
+
22
32
  ## clubs.txt or clubs_en.txt
23
33
  ## remove support for en.clubs.txt - why? why not?
24
34
  CLUBS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
@@ -35,12 +45,22 @@ module SportDb
35
45
  \.wiki\.txt$
36
46
  }x
37
47
 
38
- CLUB_PROPS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
48
+ ## todo/fix: rename to CLUBS too e.g. CLUBS_PROPS to reflect filename - why? why not?
49
+ CLUBS_PROPS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
39
50
  (?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.clubs.props.txt
40
51
  clubs
41
52
  (?:_[a-z0-9_-]+)?
42
53
  \.props\.txt$
43
54
  }x
55
+ CLUB_PROPS_RE = CLUBS_PROPS_RE ## add alias for now (fix later - why? why not?)
56
+
57
+
58
+ CLUBS_HISTORY_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
59
+ (?: [a-z]{1,4}\. )? # optional country code/key e.g. eng.clubs.history.txt
60
+ clubs
61
+ (?:_[a-z0-9_-]+)?
62
+ \.history\.txt$
63
+ }x
44
64
 
45
65
  ## teams.txt or teams_history.txt
46
66
  TEAMS_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
@@ -49,6 +69,8 @@ module SportDb
49
69
  \.txt$
50
70
  }x
51
71
 
72
+
73
+ ### todo/fix: change SEASON_RE to SEASON_KEY_RE (avoid confusion w/ SEASONS_RE for datafile?) - why? why not? !!!!!!!
52
74
  ### season folder:
53
75
  ## e.g. /2019-20 or
54
76
  ## year-only e.g. /2019 or
@@ -73,6 +95,10 @@ module SportDb
73
95
  /[a-z0-9_.-]+\.csv$ ## note: allow dot (.) too e.g /eng.1.csv
74
96
  }x
75
97
 
98
+ ### add "generic" pattern to find all csv datafiles
99
+ CSV_RE = %r{ (?: ^|/ )
100
+ [a-z0-9_.-]+\.csv$ ## note: allow dot (.) too e.g /eng.1.csv
101
+ }x
76
102
 
77
103
 
78
104
  ## move class-level "static" finders to DirPackage (do NOT work for now for zip packages) - why? why not?
@@ -96,16 +122,22 @@ module SportDb
96
122
  def self.find_teams( path, pattern: TEAMS_RE ) find( path, pattern ); end
97
123
  def self.match_teams( path ) TEAMS_RE.match( path ); end
98
124
 
99
- def self.find_clubs( path, pattern: CLUBS_RE ) find( path, pattern ); end
100
- def self.find_clubs_wiki( path, pattern: CLUBS_WIKI_RE ) find( path, pattern ); end
125
+ def self.find_clubs( path, pattern: CLUBS_RE ) find( path, pattern ); end
126
+ def self.find_clubs_wiki( path, pattern: CLUBS_WIKI_RE ) find( path, pattern ); end
127
+ def self.find_clubs_history( path, pattern: CLUBS_HISTORY_RE ) find( path, pattern ); end
101
128
 
102
- def self.match_clubs( path ) CLUBS_RE.match( path ); end
103
- def self.match_clubs_wiki( path ) CLUBS_WIKI_RE.match( path ); end
104
- def self.match_club_props( path, pattern: CLUB_PROPS_RE ) pattern.match( path ); end
129
+ def self.match_clubs( path ) CLUBS_RE.match( path ); end
130
+ def self.match_clubs_wiki( path ) CLUBS_WIKI_RE.match( path ); end
131
+ def self.match_clubs_history( path ) CLUBS_HISTORY_RE.match( path); end
132
+ def self.match_clubs_props( path, pattern: CLUBS_PROPS_RE ) pattern.match( path ); end
105
133
 
106
134
  def self.find_leagues( path, pattern: LEAGUES_RE ) find( path, pattern ); end
107
135
  def self.match_leagues( path ) LEAGUES_RE.match( path ); end
108
136
 
137
+ def self.find_seasons( path, pattern: SEASONS_RE ) find( path, pattern ); end
138
+ def self.match_seasons( path ) SEASONS_RE.match( path ); end
139
+
140
+
109
141
  def self.find_conf( path, pattern: CONF_RE ) find( path, pattern ); end
110
142
  def self.match_conf( path ) CONF_RE.match( path ); end
111
143
 
@@ -118,6 +150,7 @@ module SportDb
118
150
  end
119
151
  ## add match_match and match_match_csv - why? why not?
120
152
 
153
+
121
154
  class << self
122
155
  alias_method :match_teams?, :match_teams
123
156
  alias_method :teams?, :match_teams
@@ -128,12 +161,21 @@ module SportDb
128
161
  alias_method :match_clubs_wiki?, :match_clubs_wiki
129
162
  alias_method :clubs_wiki?, :match_clubs_wiki
130
163
 
131
- alias_method :match_club_props?, :match_club_props
132
- alias_method :club_props?, :match_club_props
164
+ alias_method :match_clubs_history?, :match_clubs_history
165
+ alias_method :clubs_history?, :match_clubs_history
166
+
167
+ alias_method :match_club_props, :match_clubs_props
168
+ alias_method :match_club_props?, :match_clubs_props
169
+ alias_method :club_props?, :match_clubs_props
170
+ alias_method :match_clubs_props?, :match_clubs_props
171
+ alias_method :clubs_props?, :match_clubs_props
133
172
 
134
173
  alias_method :match_leagues?, :match_leagues
135
174
  alias_method :leagues?, :match_leagues
136
175
 
176
+ alias_method :match_seasons?, :match_seasons
177
+ alias_method :seasons?, :match_seasons
178
+
137
179
  alias_method :match_conf?, :match_conf
138
180
  alias_method :conf?, :match_conf
139
181
  end
@@ -212,11 +254,17 @@ module SportDb
212
254
  end
213
255
  end
214
256
  def each_match_csv( &blk ) each( pattern: MATCH_CSV_RE, &blk ); end
257
+ def each_csv( &blk ) each( pattern: CSV_RE, &blk ); end
258
+
215
259
  def each_club_props( &blk ) each( pattern: CLUB_PROPS_RE, &blk ); end
216
260
 
217
261
  def each_leagues( &blk ) each( pattern: LEAGUES_RE, &blk ); end
218
262
  def each_clubs( &blk ) each( pattern: CLUBS_RE, &blk ); end
219
263
  def each_clubs_wiki( &blk ) each( pattern: CLUBS_WIKI_RE, &blk ); end
264
+ def each_clubs_history( &blk ) each( pattern: CLUBS_HISTORY_RE, &blk ); end
265
+
266
+ def each_seasons( &blk ) each( pattern: SEASONS_RE, &blk ); end
267
+
220
268
 
221
269
  ## return all match datafile entries
222
270
  def match( format: 'txt' )