sportdb-formats 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4cdd2bc410771494ed506a24d384ca3c8b1c9684
4
- data.tar.gz: 066f5288da503a00efe280369f57d6cd65bf4bf7
3
+ metadata.gz: 89c3ae173bed0c7a68f30a897e4cf34da8d72d6e
4
+ data.tar.gz: f3898e8b03177b62075cced2a90be2502555bf63
5
5
  SHA512:
6
- metadata.gz: f61edee9495047fc49dfb5720c7afc1e0e316e5fab024d8fc0b1bd5fcdad70524f6e22d24d8fad0aa679380565e0a0c7e36fae79c170655f8a7a496dee170aca
7
- data.tar.gz: b378202d2c8152ac46386618d3c69c03d802b1439e74175f8d84fad304ce111edb0bb1cd848fc969848ce55e0cf8de15a46bec322351d5d199652ed16d41b164
6
+ metadata.gz: 4c938af88f6dd86f1736532c9d8271a3e56f1769b955a31ce6d84a0b1fcf5a6eec7cfa42e0c019bd7072351d777a1988d6637c4297bee0dad9592bb8ec7450e8
7
+ data.tar.gz: a80df68f64e13eeb9a85931e2d2dd4381f204f94a4ea9254c89b4b28346db4c1542321aed4fd123aef5ddedc7e4cd2c08731dd340326fae5dc94b57fa6797835
@@ -8,6 +8,8 @@ lib/sportdb/formats/country/country_index.rb
8
8
  lib/sportdb/formats/country/country_reader.rb
9
9
  lib/sportdb/formats/datafile.rb
10
10
  lib/sportdb/formats/datafile_package.rb
11
+ lib/sportdb/formats/event/event_index.rb
12
+ lib/sportdb/formats/event/event_reader.rb
11
13
  lib/sportdb/formats/goals.rb
12
14
  lib/sportdb/formats/league/league_index.rb
13
15
  lib/sportdb/formats/league/league_outline_reader.rb
@@ -68,6 +70,7 @@ test/test_match_auto_worldcup.rb
68
70
  test/test_match_champs.rb
69
71
  test/test_match_eng.rb
70
72
  test/test_match_euro.rb
73
+ test/test_match_start_date.rb
71
74
  test/test_match_worldcup.rb
72
75
  test/test_name_helper.rb
73
76
  test/test_outline_reader.rb
@@ -136,6 +136,20 @@ end # module Import
136
136
  end # module SportDb
137
137
 
138
138
 
139
+ require 'sportdb/formats/event/event_reader'
140
+ require 'sportdb/formats/event/event_index'
141
+
142
+ ## add convenience helper
143
+ module SportDb
144
+ module Import
145
+ class EventInfo
146
+ def self.read( path ) EventInfoReader.read( path ); end
147
+ def self.parse( txt ) EventInfoReader.parse( txt ); end
148
+ end # class EventInfo
149
+ end # module Import
150
+ end # module SportDb
151
+
152
+
139
153
 
140
154
 
141
155
 
@@ -0,0 +1,143 @@
1
+ module SportDb
2
+ module Import
3
+
4
+
5
+ class EventIndex
6
+
7
+ def self.build( path )
8
+ datafiles = Package.find_seasons( path )
9
+
10
+ puts
11
+ puts "#{datafiles.size} seasons datafile(s):"
12
+ pp datafiles
13
+
14
+ index = new
15
+ datafiles.each do |datafile|
16
+ recs = EventInfoReader.read( datafile )
17
+ # pp recs
18
+
19
+ index.add( recs )
20
+ end
21
+
22
+ index
23
+ end
24
+
25
+
26
+ attr_reader :events
27
+ def initialize
28
+ @events = []
29
+ @leagues = {}
30
+ end
31
+
32
+ def add( recs )
33
+ @events += recs ## add to "linear" records
34
+
35
+ recs.each do |rec|
36
+ league = rec.league
37
+ season = rec.season
38
+
39
+ seasons = @leagues[ league.key ] ||= {}
40
+ seasons[season.key] = rec
41
+ end
42
+ ## build search index by leagues (and season)
43
+ end
44
+
45
+ def find_by( league:, season: )
46
+ league_key = league.is_a?( String ) ? league : league.key
47
+ season_key = season.is_a?( String ) ? season : season.key
48
+
49
+ seasons = @leagues[ league_key ]
50
+ if seasons
51
+ seasons[ season_key ]
52
+ else
53
+ nil
54
+ end
55
+ end # method find_by
56
+ end ## class EventIndex
57
+
58
+
59
+
60
+ class SeasonIndex
61
+ def initialize( *args )
62
+ @leagues = {} ## use a league hash by years for now; change later
63
+
64
+ if args.size == 1 && args[0].is_a?( EventIndex )
65
+ ## convenience setup/hookup
66
+ ## (auto-)add all events from event index
67
+ add( args[0].events )
68
+ else
69
+ pp args
70
+ raise ArgumentError.new( 'unsupported arguments' )
71
+ end
72
+ end
73
+
74
+ def add( recs )
75
+ ## use a lookup index by year for now
76
+ ## todo - find something better/more generic for searching/matching date periods!!!
77
+ recs.each do |rec|
78
+ league = rec.league
79
+ season = rec.season
80
+
81
+ years = @leagues[ league.key ] ||= {}
82
+ if season.year?
83
+ years[season.start_year] ||= []
84
+ years[season.start_year] << rec
85
+ else
86
+ years[season.start_year] ||= []
87
+ years[season.end_year] ||= []
88
+ years[season.start_year] << rec
89
+ years[season.end_year] << rec
90
+ end
91
+ end
92
+ end # method add
93
+
94
+ def find_by( date:, league: )
95
+ date = Date.strptime( date, '%Y-%m-%d' ) if date.is_a?( String )
96
+ league_key = league.is_a?( String ) ? league : league.key
97
+
98
+ years = @leagues[ league_key ]
99
+ if years
100
+ year = years[ date.year ]
101
+ if year
102
+ season_key = nil
103
+ year.each do |event|
104
+ ## todo/check: rename/use between? instead of include? - why? why not?
105
+ if event.include?( date )
106
+ season_key = event.season.key
107
+ break
108
+ end
109
+ end
110
+ if season_key.nil?
111
+ puts "!! WARN: date >#{date}< out-of-seasons for year #{date.year} in league #{league_key}:"
112
+ year.each do |event|
113
+ puts " #{event.season.key} | #{event.start_date} - #{event.end_date}"
114
+ end
115
+ ## retry again and pick season with "overflow" at the end (date is great end_date)
116
+ year.each do |event|
117
+ if date > event.end_date
118
+ diff_in_days = date.to_date.jd - event.end_date.to_date.jd
119
+ puts " +#{diff_in_days} days - adding overflow to #{event.season.key} ending on #{event.end_date} ++ #{date}"
120
+ season_key = event.season.key
121
+ break
122
+ end
123
+ end
124
+ ## exit now for sure - if still empty!!!!
125
+ if season_key.nil?
126
+ puts "!! ERROR: CANNOT auto-fix / (auto-)append date at the end of an event; check season setup - sorry"
127
+ exit 1
128
+ end
129
+ end
130
+ season_key
131
+ else
132
+ nil ## no year defined / found for league
133
+ end
134
+ else
135
+ nil ## no league defined / found
136
+ end
137
+ end # method find
138
+
139
+ end # class SeasonIndex
140
+
141
+
142
+ end # module Import
143
+ end # module SportDb
@@ -0,0 +1,183 @@
1
+
2
+ module SportDb
3
+ module Import
4
+
5
+
6
+ class EventInfo
7
+ ## "high level" info (summary) about event (like a "wikipedia infobox")
8
+ ## use for checking dataset imports; lets you check e.g.
9
+ ## - dates within range
10
+ ## - number of teams e.g. 20
11
+ ## - matches played e.g. 380
12
+ ## - goals scored e.g. 937
13
+ ## etc.
14
+
15
+ attr_reader :league,
16
+ :season,
17
+ :teams,
18
+ :matches,
19
+ :goals,
20
+ :start_date,
21
+ :end_date
22
+
23
+ def initialize( league:, season:,
24
+ start_date: nil, end_date: nil,
25
+ teams: nil,
26
+ matches: nil,
27
+ goals: nil )
28
+
29
+ @league = league
30
+ @season = season
31
+
32
+ @start_date = start_date
33
+ @end_date = end_date
34
+
35
+ @teams = teams ## todo/check: rename/use teams_count ??
36
+ @matches = matches ## todo/check: rename/use match_count ??
37
+ @goals = goals
38
+ end
39
+
40
+ def include?( date )
41
+ ## todo/fix: add options e.g.
42
+ ## - add delta/off_by_one or such?
43
+ ## - add strict (for) only return true if date range (really) defined (no generic auto-rules)
44
+
45
+ ### note: for now allow off by one error (via timezone/local time errors)
46
+ ## todo/fix: issue warning if off by one!!!!
47
+ if @start_date && @end_date
48
+ date >= (@start_date-1) &&
49
+ date <= (@end_date+1)
50
+ else
51
+ if @season.year?
52
+ # assume generic rule
53
+ ## same year e.g. Jan 1 - Dec 31; always true for now
54
+ date.year == @season.start_year
55
+ else
56
+ # assume generic rule
57
+ ## July 1 - June 30 (Y+1)
58
+ ## - todo/check -start for some countries/leagues in June 1 or August 1 ????
59
+ date >= Date.new( @season.start_year, 7, 1 ) &&
60
+ date <= Date.new( @season.end_year, 6, 30 )
61
+ end
62
+ end
63
+ end # method include?
64
+ alias_method :between?, :include?
65
+ end # class EventInfo
66
+
67
+
68
+ class EventInfoReader
69
+ def catalog() Import.catalog; end
70
+
71
+
72
+ def self.read( path )
73
+ txt = File.open( path, 'r:utf-8') {|f| f.read }
74
+ new( txt ).parse
75
+ end
76
+
77
+ def self.parse( txt )
78
+ new( txt ).parse
79
+ end
80
+
81
+ def initialize( txt )
82
+ @txt = txt
83
+ end
84
+
85
+ def parse
86
+ recs = []
87
+
88
+ parse_csv( @txt ).each do |row|
89
+ league_col = row['League']
90
+ season_col = row['Season'] || row['Year']
91
+ dates_col = row['Dates']
92
+
93
+ season = Import::Season.new( season_col )
94
+ league = catalog.leagues.find!( league_col )
95
+
96
+
97
+ dates = []
98
+ if dates_col.nil? || dates_col.empty?
99
+ ## do nothing; no dates - keep dates array empty
100
+ else
101
+ ## squish spaces
102
+ dates_col = dates_col.gsub( /[ ]{2,}/, ' ' ) ## squish/fold spaces
103
+
104
+ puts "#{league.name} (#{league.key}) | #{season.key} | #{dates_col}"
105
+
106
+ ### todo/check: check what parts "Aug 15" return ???
107
+ ### short form for "Aug 15 -" - works?
108
+
109
+ ## todo/fix!!! - check EventInfo.include?
110
+ ## now allow dates with only start_date too!! (WITHOUT end_date)
111
+ parts = dates_col.split( /[ ]*[–-][ ]*/ )
112
+ if parts.size == 1
113
+ pp parts
114
+ dates << DateFormats.parse( parts[0], start: Date.new( season.start_year, 1, 1 ), lang: 'en' )
115
+ pp dates
116
+ elsif parts.size == 2
117
+ pp parts
118
+ dates << DateFormats.parse( parts[0], start: Date.new( season.start_year, 1, 1 ), lang: 'en' )
119
+ dates << DateFormats.parse( parts[1], start: Date.new( season.end_year ? season.end_year : season.start_year, 1, 1 ), lang: 'en' )
120
+ pp dates
121
+
122
+ ## assert/check if period is less than 365 days for now
123
+ diff = dates[1].to_date.jd - dates[0].to_date.jd
124
+ puts "#{diff}d"
125
+ if diff > 365
126
+ puts "!! ERROR - date range / period assertion failed; expected diff < 365 days"
127
+ exit 1
128
+ end
129
+ else
130
+ puts "!! ERRROR - expected data range / period - one or two dates; got #{parts.size}:"
131
+ pp dates_col
132
+ pp parts
133
+ exit 1
134
+ end
135
+ end
136
+
137
+
138
+ teams_col = row['Clubs'] || row['Teams']
139
+ goals_col = row['Goals']
140
+
141
+ ## note: remove (and allow) all non-digits e.g. 370 goals, 20 clubs, etc.
142
+ teams_col = teams_col.gsub( /[^0-9]/, '' ) if teams_col
143
+ goals_col = goals_col.gsub( /[^0-9]/, '' ) if goals_col
144
+
145
+ teams = (teams_col.nil? || teams_col.empty?) ? nil : teams_col.to_i
146
+ goals = (goals_col.nil? || goals_col.empty?) ? nil : goals_col.to_i
147
+
148
+ matches_col = row['Matches']
149
+ ## note: support additions in matches (played) e.g.
150
+ # 132 + 63 Play-off-Spiele
151
+ matches_col = matches_col.gsub( /[^0-9+]/, '' ) if matches_col
152
+
153
+ matches = if matches_col.nil? || matches_col.empty?
154
+ nil
155
+ else
156
+ if matches_col.index( '+' ) ### check for calculations
157
+ ## note: for now only supports additions
158
+ matches_col.split( '+' ).reduce( 0 ) do |sum,str|
159
+ sum + str.to_i
160
+ end
161
+ else ## assume single (integer) number
162
+ matches_col.to_i
163
+ end
164
+ end
165
+
166
+ rec = EventInfo.new( league: league,
167
+ season: season,
168
+ start_date: dates[0],
169
+ end_date: dates[1],
170
+ teams: teams,
171
+ matches: matches,
172
+ goals: goals
173
+ )
174
+ recs << rec
175
+ end # each row
176
+ recs
177
+ end # method parse
178
+ end # class EventInfoReader
179
+
180
+
181
+ end ## module Import
182
+ end ## module SportDb
183
+
@@ -563,12 +563,29 @@ class MatchParser ## simple match parser for team match schedules
563
563
 
564
564
  if date && team1.nil? && team2.nil?
565
565
  logger.debug( "date header line found: >#{line}<")
566
- logger.debug( " date: #{date}")
566
+ logger.debug( " date: #{date} with start: #{@start}")
567
567
 
568
568
  @last_date = date # keep a reference for later use
569
- return true
569
+
570
+ ### quick "corona" hack - support seasons going beyond 12 month (see swiss league 2019/20 and others!!)
571
+ ## find a better way??
572
+ ## set @start date to full year (e.g. 1.1.) if date.year is @start.year+1
573
+ ## todo/fix: add to linter to check for chronological dates!! - warn if NOT chronological
574
+ ### todo/check: just turn on for 2019/20 season or always? why? why not?
575
+
576
+ ## todo/fix: add switch back to old @start_org
577
+ ## if year is date.year == @start.year-1 -- possible when full date with year set!!!
578
+ if @start.month != 1
579
+ if date.year == @start.year+1
580
+ logger.debug( "!! hack - extending start date to full (next/end) year; assumes all dates are chronologigal - always moving forward" )
581
+ @start_org = @start ## keep a copy of the original (old) start date - why? why not? - not used for now
582
+ @start = Date.new( @start.year+1, 1, 1 )
583
+ end
584
+ end
585
+
586
+ true
570
587
  else
571
- return false
588
+ false
572
589
  end
573
590
  end
574
591
 
@@ -95,7 +95,7 @@ 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'] )
@@ -221,6 +221,9 @@ module SportDb
221
221
  end
222
222
 
223
223
 
224
+ ##
225
+ ## todo/fix: round might not always be just a simple integer number!!!
226
+ ## might be text such as Final | Leg 1 or such!!!!
224
227
  round = nil
225
228
  ## check for (optional) round / matchday
226
229
  if headers_mapping[ :round ]
@@ -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 (/)
@@ -49,6 +59,8 @@ module SportDb
49
59
  \.txt$
50
60
  }x
51
61
 
62
+
63
+ ### todo/fix: change SEASON_RE to SEASON_KEY_RE (avoid confusion w/ SEASONS_RE for datafile?) - why? why not? !!!!!!!
52
64
  ### season folder:
53
65
  ## e.g. /2019-20 or
54
66
  ## year-only e.g. /2019 or
@@ -110,6 +122,10 @@ module SportDb
110
122
  def self.find_leagues( path, pattern: LEAGUES_RE ) find( path, pattern ); end
111
123
  def self.match_leagues( path ) LEAGUES_RE.match( path ); end
112
124
 
125
+ def self.find_seasons( path, pattern: SEASONS_RE ) find( path, pattern ); end
126
+ def self.match_seasons( path ) SEASONS_RE.match( path ); end
127
+
128
+
113
129
  def self.find_conf( path, pattern: CONF_RE ) find( path, pattern ); end
114
130
  def self.match_conf( path ) CONF_RE.match( path ); end
115
131
 
@@ -139,6 +155,9 @@ module SportDb
139
155
  alias_method :match_leagues?, :match_leagues
140
156
  alias_method :leagues?, :match_leagues
141
157
 
158
+ alias_method :match_seasons?, :match_seasons
159
+ alias_method :seasons?, :match_seasons
160
+
142
161
  alias_method :match_conf?, :match_conf
143
162
  alias_method :conf?, :match_conf
144
163
  end
@@ -2,21 +2,10 @@
2
2
 
3
3
 
4
4
  module SeasonHelper ## use Helpers why? why not?
5
-
6
5
  ##############################################
7
6
  ### deprecated!!! use new Season class!!!
8
7
  ## this code will get removed!!!!
9
8
  ###################################################
10
-
11
- def prev( str ) SportDb::Import::Season.new( str ).prev; end
12
- def key( str ) SportDb::Import::Season.new( str ).key; end
13
- def directory( str, format: nil ) SportDb::Import::Season.new( str ).directory( format: format ); end
14
-
15
- ## note: new start_year now returns an integer number (no longer a string)!!!
16
- def start_year( str ) SportDb::Import::Season.new( str ).start_year; end
17
- ## note: new end_year now returns an integer number (no longer a string)!!!
18
- ## if now end_year (year? == true) than returns nil (no longer the start_year "as fallback")!!!
19
- def end_year( str ) SportDb::Import::Season.new( str ).end_year; end
20
9
  end # module SeasonHelper
21
10
 
22
11
 
@@ -1,26 +1,19 @@
1
1
  # encoding: utf-8
2
2
 
3
3
 
4
- module SportDb
5
- module Import
4
+ ### note: make Season like Date a "top-level" / "generic" class
5
+
6
6
 
7
7
 
8
8
  class Season
9
9
  ##
10
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
11
 
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
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?
23
15
 
16
+ ## todo: add unicode - too - why? why not? see wikipedia pages, for example
24
17
 
25
18
  YYYY_YYYY_RE = %r{^ ## e.g. 2011-2012 or 2011/2012
26
19
  (\d{4})
@@ -45,79 +38,155 @@ class Season
45
38
  $
46
39
  }x
47
40
 
48
- def parse( str )
41
+
42
+ def self.parse( str )
43
+ new( *_parse( str ))
44
+ end
45
+
46
+ def self._parse( str ) ## "internal" parse helper
49
47
  if str =~ YYYY_YYYY_RE ## e.g. 2011/2012
50
48
  [$1.to_i, $2.to_i]
51
49
  elsif str =~ YYYY_YY_RE ## e.g. 2011/12
52
50
  fst = $1.to_i
53
51
  snd = $2.to_i
54
52
  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
53
+ raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
56
54
  [fst, fst+1]
57
55
  elsif str =~ YYYY_Y_RE ## e.g. 2011/2
58
56
  fst = $1.to_i
59
57
  snd = $2.to_i
60
58
  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
59
+ raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
62
60
  [fst, fst+1]
63
61
  elsif str =~ YYYY_RE ## e.g. 2011
64
62
  [$1.to_i]
65
63
  else
66
- raise ArgumentError.new( "[Season#parse] unkown season format >>#{str}<<; sorry cannot parse")
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 )
67
99
  end
68
100
  end
69
101
 
70
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
71
105
 
72
106
  def prev
73
107
  if year?
74
- Season.new( "#{@start_year-1}" )
108
+ Season.new( @start_year-1 )
75
109
  else
76
- Season.new( "#{@start_year-1}/#{@start_year}" )
110
+ Season.new( @start_year-1, @start_year )
77
111
  end
78
112
  end
79
113
 
80
- def key
114
+ def next
81
115
  if year?
82
- '%d' % @start_year
116
+ Season.new( @start_year+1 )
83
117
  else
84
- '%d/%02d' % [@start_year, @end_year % 100]
118
+ Season.new( @end_year, @end_year+1 )
85
119
  end
86
120
  end
87
- alias_method :to_key, :key
88
- alias_method :to_s, :key
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 ??
89
127
 
90
- alias_method :name, :key
91
- alias_method :title, :key
128
+ res = @start_year <=> other.start_year
92
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
93
135
 
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, ...
136
+ res
137
+ end
98
138
 
99
- ## convert season name to "standard" season name for directory
100
139
 
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]
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}<"
112
152
  end
113
153
  end
114
- end # method path
115
- alias_method :directory, :path ## keep "legacy" directory alias - why? why not?
116
- alias_method :to_path, :path
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
117
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
118
182
 
119
183
  end # class Season
120
184
 
121
185
 
186
+
187
+
188
+ module SportDb
189
+ module Import
190
+ Season = ::Season ## add a convenience alias
122
191
  end # module Import
123
192
  end # module SportDb
@@ -7,7 +7,7 @@ module Formats
7
7
 
8
8
  MAJOR = 1 ## todo: namespace inside version or something - why? why not??
9
9
  MINOR = 1
10
- PATCH = 1
10
+ PATCH = 2
11
11
  VERSION = [MAJOR,MINOR,PATCH].join('.')
12
12
 
13
13
  def self.version
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_match_start_date.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+
11
+ class TestMatchStart < MiniTest::Test
12
+
13
+ def test_eng
14
+ txt =<<TXT
15
+ Matchday 1
16
+ [Aug 2]
17
+ A - B
18
+ Matchday 2
19
+ [Jan 3]
20
+ A - B
21
+ Matchday 3
22
+ [Aug 4]
23
+ A - B
24
+ TXT
25
+
26
+ teams =<<TXT
27
+ A
28
+ B
29
+ TXT
30
+ SportDb::Import.config.lang = 'en'
31
+
32
+ start = Date.new( 2017, 7, 1 )
33
+
34
+ parser = SportDb::MatchParser.new( txt, teams, start )
35
+ matches, rounds = parser.parse
36
+
37
+ pp rounds
38
+ pp matches ## only dump last record for now
39
+
40
+ assert_equal Date.new( 2017, 8, 2), matches[0].date
41
+ assert_equal Date.new( 2018, 1, 3), matches[1].date
42
+ assert_equal Date.new( 2018, 8, 4), matches[2].date
43
+ end # method test_end
44
+ end # class TestMatchStart
@@ -9,25 +9,35 @@ require 'helper'
9
9
 
10
10
  class TestSeason < MiniTest::Test
11
11
 
12
- Season = SportDb::Import::Season
13
-
14
- def test_path
15
- assert_equal '2010-11', Season.new( '2010-11' ).path
16
- assert_equal '2010-11', Season.new( '2010-2011' ).path
17
- assert_equal '2010-11', Season.new( '2010/11' ).path
18
- assert_equal '2010-11', Season.new( '2010/1' ).path
19
- assert_equal '2010-11', Season.new( '2010/2011' ).path
20
- assert_equal '2010', Season.new( '2010' ).path
21
-
22
- assert_equal '2010s/2010-11', Season.new( '2010-11' ).path( format: 'long' )
23
- assert_equal '2010s/2010-11', Season.new( '2010-2011' ).path( format: 'long' )
24
- assert_equal '2010s/2010', Season.new( '2010' ).path( format: 'long' )
25
-
26
- assert_equal '1999-00', Season.new( '1999-00' ).path
27
- assert_equal '1999-00', Season.new( '1999-2000' ).path
28
- assert_equal '1990s/1999-00', Season.new( '1999-00' ).path( format: 'long' )
29
- assert_equal '1990s/1999-00', Season.new( '1999-2000' ).path( format: 'long' )
30
- end # method test_path
12
+
13
+ def test_to_path
14
+ assert_equal '2010-11', Season.new( '2010-11' ).to_path
15
+ assert_equal '2010-11', Season.new( '2010-2011' ).to_path
16
+ assert_equal '2010-11', Season.new( '2010/11' ).to_path
17
+ assert_equal '2010-11', Season.new( '2010/1' ).to_path
18
+ assert_equal '2010-11', Season.new( '2010/2011' ).to_path
19
+ assert_equal '2010', Season.new( '2010' ).to_path
20
+
21
+ assert_equal '2010-11', Season.new( 2010, 2011 ).to_path
22
+ assert_equal '2010', Season.new( 2010 ).to_path
23
+
24
+ assert_equal '2010s/2010-11', Season.new( '2010-11' ).to_path( :decade )
25
+ assert_equal '2010s/2010-11', Season.new( '2010-2011' ).to_path( :decade )
26
+ assert_equal '2010s/2010', Season.new( '2010' ).to_path( :decade )
27
+
28
+ assert_equal '1999-00', Season.new( '1999-00' ).to_path
29
+ assert_equal '1999-00', Season.new( '1999-2000' ).to_path
30
+ assert_equal '1990s/1999-00', Season.new( '1999-00' ).to_path( :decade )
31
+ assert_equal '1990s/1999-00', Season.new( '1999-2000' ).to_path( :decade )
32
+
33
+ assert_equal '2000s/2010-11', Season.new( '2010-11' ).to_path( :century )
34
+ assert_equal '2000s/2010-11', Season.new( '2010-2011' ).to_path( :century )
35
+ assert_equal '2000s/2010', Season.new( '2010' ).to_path( :century )
36
+
37
+ assert_equal '1900s/1999-00', Season.new( '1999-00' ).to_path( :century )
38
+ assert_equal '1900s/1999-00', Season.new( '1999-2000' ).to_path( :century )
39
+ end # method test_to_path
40
+
31
41
 
32
42
  def test_key
33
43
  assert_equal '2010/11', Season.new( '2010-11' ).key
@@ -59,4 +69,43 @@ class TestSeason < MiniTest::Test
59
69
  assert_equal '1998/99', Season.new( '1999-00' ).prev.key
60
70
  assert_equal '1998/99', Season.new( '1999-2000' ).prev.key
61
71
  end
72
+
73
+ def test_next
74
+ assert_equal '2009/10', Season.new( '2008-09' ).next.key
75
+ assert_equal '2009/10', Season.new( '2008-2009' ).next.key
76
+ assert_equal '2009', Season.new( '2008' ).next.key
77
+
78
+ assert_equal '1998/99', Season.new( '1997-98' ).next.key
79
+ assert_equal '1998/99', Season.new( '1997-1998' ).next.key
80
+ end
81
+
82
+
83
+ def test_range
84
+ s2010 = Season.new( '2010' )..Season.new( '2019' )
85
+ pp s2010.to_a
86
+ # => [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
87
+
88
+ s2010 = Season.new( '2010-11')..Season.new( '2019-20')
89
+ pp s2010.to_a
90
+ # => [2010/11, 2011/12, 2012/13, 2013/14, 2014/15,
91
+ # 2015/16, 2016/17, 2017/18, 2018/19, 2019/20]
92
+
93
+ puts s2010 === Season.new( '2015-16' ) # true
94
+ puts s2010 === Season.new( '2015' ) # false - why? if using >= <=
95
+ puts s2010 === Season.new( '1999-00' ) # false
96
+ puts s2010 === Season.new( '2020-21' ) # false
97
+
98
+ puts Season.new( '2010-11' ) < Season.new( '2015' ) # true
99
+ puts Season.new( '2015' ) < Season.new( '2019-20') # true
100
+
101
+ puts Season.new( '2015' ) == Season.new( '2015-16') # false
102
+ puts Season.new( '2015' ) < Season.new( '2015-16') # true
103
+ puts Season.new( '2015' ) == Season.new( '2015') # true
104
+
105
+ puts
106
+ puts s2010.include? Season.new( '2015-16' ) # true
107
+ puts s2010.include? Season.new( '2015' ) # false
108
+ puts s2010.include? Season.new( '1999-00' ) # false
109
+ end
110
+
62
111
  end # class TestSeason
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb-formats
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-15 00:00:00.000000000 Z
11
+ date: 2020-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: alphabets
@@ -127,6 +127,8 @@ files:
127
127
  - lib/sportdb/formats/country/country_reader.rb
128
128
  - lib/sportdb/formats/datafile.rb
129
129
  - lib/sportdb/formats/datafile_package.rb
130
+ - lib/sportdb/formats/event/event_index.rb
131
+ - lib/sportdb/formats/event/event_reader.rb
130
132
  - lib/sportdb/formats/goals.rb
131
133
  - lib/sportdb/formats/league/league_index.rb
132
134
  - lib/sportdb/formats/league/league_outline_reader.rb
@@ -187,6 +189,7 @@ files:
187
189
  - test/test_match_champs.rb
188
190
  - test/test_match_eng.rb
189
191
  - test/test_match_euro.rb
192
+ - test/test_match_start_date.rb
190
193
  - test/test_match_worldcup.rb
191
194
  - test/test_name_helper.rb
192
195
  - test/test_outline_reader.rb