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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c1645b8fed586be03207b65e25866473f3124c3d
4
- data.tar.gz: c50d164b1cf1fe79e5dc5c8ac9e946fc6ba96f31
3
+ metadata.gz: 666fc1f16808dddbc988aa073c0d3b47c08a5934
4
+ data.tar.gz: 97437435e1f37341c9f2cc15c8b4e67adf0efe61
5
5
  SHA512:
6
- metadata.gz: bed9e662901b25660899f1b3df3f6a9f506f88422a50db23d119d7f55a4e94ac84e82474879926b5f6db079a13600ebe093ae3ea39d351e758b25e3904789edf
7
- data.tar.gz: c2aff73cf2ba9ea04fddde788076bd72b983681ba2e492a665f3e104f76712ce1708d32abc1eb64e0dece966f34d30bda3724acaf53598d487b51307f735cc4e
6
+ metadata.gz: 9498c5e378feab9fa1e80a8287f33ab608e606ecde6ae914997483850faffbbbc7695ef07d2cea1e04a529e724b01612e8231fe8625c19d0af34f3fabffd0a14
7
+ data.tar.gz: 28146d5c35a061f6c128a001c190681eb76de5471cde8124435e77d93ccca090bf0a84a7a6a09ccb67372f8edef0198e8f09390126629d14072901ff5fcb7743
@@ -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
@@ -18,6 +20,7 @@ lib/sportdb/formats/match/mapper_teams.rb
18
20
  lib/sportdb/formats/match/match_parser.rb
19
21
  lib/sportdb/formats/match/match_parser_auto_conf.rb
20
22
  lib/sportdb/formats/match/match_parser_csv.rb
23
+ lib/sportdb/formats/match/match_status_parser.rb
21
24
  lib/sportdb/formats/name_helper.rb
22
25
  lib/sportdb/formats/outline_reader.rb
23
26
  lib/sportdb/formats/package.rb
@@ -36,7 +39,9 @@ lib/sportdb/formats/structs/standings.rb
36
39
  lib/sportdb/formats/structs/team.rb
37
40
  lib/sportdb/formats/structs/team_usage.rb
38
41
  lib/sportdb/formats/team/club_index.rb
42
+ lib/sportdb/formats/team/club_index_history.rb
39
43
  lib/sportdb/formats/team/club_reader.rb
44
+ lib/sportdb/formats/team/club_reader_history.rb
40
45
  lib/sportdb/formats/team/club_reader_props.rb
41
46
  lib/sportdb/formats/team/national_team_index.rb
42
47
  lib/sportdb/formats/team/team_index.rb
@@ -44,14 +49,13 @@ lib/sportdb/formats/team/wiki_reader.rb
44
49
  lib/sportdb/formats/version.rb
45
50
  test/helper.rb
46
51
  test/test_club_index.rb
52
+ test/test_club_index_history.rb
47
53
  test/test_club_reader.rb
54
+ test/test_club_reader_history.rb
48
55
  test/test_club_reader_props.rb
49
56
  test/test_clubs.rb
50
- test/test_conf.rb
51
57
  test/test_country_index.rb
52
58
  test/test_country_reader.rb
53
- test/test_csv_match_parser.rb
54
- test/test_csv_match_parser_utils.rb
55
59
  test/test_csv_reader.rb
56
60
  test/test_datafile.rb
57
61
  test/test_datafile_package.rb
@@ -60,14 +64,7 @@ test/test_league_index.rb
60
64
  test/test_league_outline_reader.rb
61
65
  test/test_league_reader.rb
62
66
  test/test_match.rb
63
- test/test_match_auto.rb
64
- test/test_match_auto_champs.rb
65
- test/test_match_auto_euro.rb
66
- test/test_match_auto_worldcup.rb
67
- test/test_match_champs.rb
68
- test/test_match_eng.rb
69
- test/test_match_euro.rb
70
- test/test_match_worldcup.rb
67
+ test/test_match_status_parser.rb
71
68
  test/test_name_helper.rb
72
69
  test/test_outline_reader.rb
73
70
  test/test_package.rb
data/Rakefile CHANGED
@@ -23,7 +23,7 @@ Hoe.spec 'sportdb-formats' do
23
23
  ['alphabets', '>= 1.0.0'],
24
24
  ['date-formats', '>= 1.0.1'],
25
25
  ['csvreader', '>= 1.2.4'],
26
- ['sportdb-langs', '>= 0.1.0'],
26
+ ['sportdb-langs', '>= 0.1.1'],
27
27
 
28
28
  ['rubyzip', '>= 1.2.4' ],
29
29
  ]
@@ -75,10 +75,12 @@ require 'sportdb/formats/goals'
75
75
 
76
76
  require 'sportdb/formats/match/mapper'
77
77
  require 'sportdb/formats/match/mapper_teams'
78
+ require 'sportdb/formats/match/match_status_parser'
78
79
  require 'sportdb/formats/match/match_parser'
79
80
  require 'sportdb/formats/match/match_parser_auto_conf'
80
81
  require 'sportdb/formats/match/conf_parser'
81
82
 
83
+
82
84
  require 'sportdb/formats/match/match_parser_csv'
83
85
 
84
86
  require 'sportdb/formats/country/country_reader'
@@ -119,6 +121,9 @@ require 'sportdb/formats/team/wiki_reader'
119
121
  require 'sportdb/formats/team/national_team_index'
120
122
  require 'sportdb/formats/team/team_index'
121
123
 
124
+ require 'sportdb/formats/team/club_reader_history'
125
+ require 'sportdb/formats/team/club_index_history'
126
+
122
127
 
123
128
  ###
124
129
  # add convenience helpers / shortcuts
@@ -136,6 +141,20 @@ end # module Import
136
141
  end # module SportDb
137
142
 
138
143
 
144
+ require 'sportdb/formats/event/event_reader'
145
+ require 'sportdb/formats/event/event_index'
146
+
147
+ ## add convenience helper
148
+ module SportDb
149
+ module Import
150
+ class EventInfo
151
+ def self.read( path ) EventInfoReader.read( path ); end
152
+ def self.parse( txt ) EventInfoReader.parse( txt ); end
153
+ end # class EventInfo
154
+ end # module Import
155
+ end # module SportDb
156
+
157
+
139
158
 
140
159
 
141
160
 
@@ -109,12 +109,12 @@ class CountryIndex
109
109
  @countries_by_name[ name ]
110
110
  end
111
111
 
112
- def []( key )
112
+ def find( key )
113
113
  country = find_by_code( key )
114
114
  country = find_by_name( key ) if country.nil? ## try lookup / find by (normalized) name
115
115
  country
116
116
  end
117
- alias_method :find, :[]
117
+ alias_method :[], :find
118
118
 
119
119
 
120
120
  ###
@@ -0,0 +1,141 @@
1
+ module SportDb
2
+ module Import
3
+
4
+
5
+
6
+ class EventIndex
7
+
8
+ def self.build( path )
9
+ pack = Package.new( path ) ## lets us use direcotry or zip archive
10
+
11
+ recs = []
12
+ pack.each_seasons do |entry|
13
+ recs += EventInfoReader.parse( entry.read )
14
+ end
15
+ recs
16
+
17
+ index = new
18
+ index.add( recs )
19
+ index
20
+ end
21
+
22
+
23
+
24
+ attr_reader :events
25
+ def initialize
26
+ @events = []
27
+ @leagues = {}
28
+ end
29
+
30
+ def add( recs )
31
+ @events += recs ## add to "linear" records
32
+
33
+ recs.each do |rec|
34
+ league = rec.league
35
+ season = rec.season
36
+
37
+ seasons = @leagues[ league.key ] ||= {}
38
+ seasons[season.key] = rec
39
+ end
40
+ ## build search index by leagues (and season)
41
+ end
42
+
43
+ def find_by( league:, season: )
44
+ league_key = league.is_a?( String ) ? league : league.key
45
+ season_key = season.is_a?( String ) ? season : season.key
46
+
47
+ seasons = @leagues[ league_key ]
48
+ if seasons
49
+ seasons[ season_key ]
50
+ else
51
+ nil
52
+ end
53
+ end # method find_by
54
+ end ## class EventIndex
55
+
56
+
57
+
58
+ class SeasonIndex
59
+ def initialize( *args )
60
+ @leagues = {} ## use a league hash by years for now; change later
61
+
62
+ if args.size == 1 && args[0].is_a?( EventIndex )
63
+ ## convenience setup/hookup
64
+ ## (auto-)add all events from event index
65
+ add( args[0].events )
66
+ else
67
+ pp args
68
+ raise ArgumentError.new( 'unsupported arguments' )
69
+ end
70
+ end
71
+
72
+ def add( recs )
73
+ ## use a lookup index by year for now
74
+ ## todo - find something better/more generic for searching/matching date periods!!!
75
+ recs.each do |rec|
76
+ league = rec.league
77
+ season = rec.season
78
+
79
+ years = @leagues[ league.key ] ||= {}
80
+ if season.year?
81
+ years[season.start_year] ||= []
82
+ years[season.start_year] << rec
83
+ else
84
+ years[season.start_year] ||= []
85
+ years[season.end_year] ||= []
86
+ years[season.start_year] << rec
87
+ years[season.end_year] << rec
88
+ end
89
+ end
90
+ end # method add
91
+
92
+ def find_by( date:, league: )
93
+ date = Date.strptime( date, '%Y-%m-%d' ) if date.is_a?( String )
94
+ league_key = league.is_a?( String ) ? league : league.key
95
+
96
+ years = @leagues[ league_key ]
97
+ if years
98
+ year = years[ date.year ]
99
+ if year
100
+ season_key = nil
101
+ year.each do |event|
102
+ ## todo/check: rename/use between? instead of include? - why? why not?
103
+ if event.include?( date )
104
+ season_key = event.season.key
105
+ break
106
+ end
107
+ end
108
+ if season_key.nil?
109
+ puts "!! WARN: date >#{date}< out-of-seasons for year #{date.year} in league #{league_key}:"
110
+ year.each do |event|
111
+ puts " #{event.season.key} | #{event.start_date} - #{event.end_date}"
112
+ end
113
+ ## retry again and pick season with "overflow" at the end (date is great end_date)
114
+ year.each do |event|
115
+ if date > event.end_date
116
+ diff_in_days = date.to_date.jd - event.end_date.to_date.jd
117
+ puts " +#{diff_in_days} days - adding overflow to #{event.season.key} ending on #{event.end_date} ++ #{date}"
118
+ season_key = event.season.key
119
+ break
120
+ end
121
+ end
122
+ ## exit now for sure - if still empty!!!!
123
+ if season_key.nil?
124
+ puts "!! ERROR: CANNOT auto-fix / (auto-)append date at the end of an event; check season setup - sorry"
125
+ exit 1
126
+ end
127
+ end
128
+ season_key
129
+ else
130
+ nil ## no year defined / found for league
131
+ end
132
+ else
133
+ nil ## no league defined / found
134
+ end
135
+ end # method find
136
+
137
+ end # class SeasonIndex
138
+
139
+
140
+ end # module Import
141
+ 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
+