sportdb-formats 1.0.5 → 1.1.3

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 (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' )