sportdb-formats 1.0.6 → 1.1.4
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.
- checksums.yaml +4 -4
- data/Manifest.txt +6 -33
- data/Rakefile +2 -5
- data/lib/sportdb/formats.rb +54 -70
- data/lib/sportdb/formats/country/country_index.rb +2 -2
- data/lib/sportdb/formats/event/event_index.rb +141 -0
- data/lib/sportdb/formats/event/event_reader.rb +183 -0
- data/lib/sportdb/formats/league/league_index.rb +22 -18
- data/lib/sportdb/formats/league/league_outline_reader.rb +45 -13
- data/lib/sportdb/formats/league/league_reader.rb +7 -1
- data/lib/sportdb/formats/match/match_parser.rb +101 -111
- data/lib/sportdb/formats/package.rb +59 -11
- data/lib/sportdb/formats/parser_helper.rb +11 -2
- data/lib/sportdb/formats/team/club_index.rb +13 -11
- data/lib/sportdb/formats/team/club_index_history.rb +134 -0
- data/lib/sportdb/formats/team/club_reader_history.rb +203 -0
- data/lib/sportdb/formats/team/club_reader_props.rb +20 -5
- data/lib/sportdb/formats/version.rb +2 -2
- data/test/helper.rb +51 -81
- data/test/test_club_index_history.rb +107 -0
- data/test/test_club_reader_history.rb +212 -0
- data/test/test_datafile_package.rb +1 -1
- data/test/test_regex.rb +25 -7
- metadata +9 -78
- data/lib/sportdb/formats/config.rb +0 -40
- data/lib/sportdb/formats/match/match_parser_csv.rb +0 -314
- data/lib/sportdb/formats/name_helper.rb +0 -84
- data/lib/sportdb/formats/score/score_formats.rb +0 -220
- data/lib/sportdb/formats/score/score_parser.rb +0 -202
- data/lib/sportdb/formats/season_utils.rb +0 -27
- data/lib/sportdb/formats/structs/country.rb +0 -31
- data/lib/sportdb/formats/structs/group.rb +0 -18
- data/lib/sportdb/formats/structs/league.rb +0 -37
- data/lib/sportdb/formats/structs/match.rb +0 -151
- data/lib/sportdb/formats/structs/matchlist.rb +0 -220
- data/lib/sportdb/formats/structs/round.rb +0 -25
- data/lib/sportdb/formats/structs/season.rb +0 -123
- data/lib/sportdb/formats/structs/standings.rb +0 -247
- data/lib/sportdb/formats/structs/team.rb +0 -150
- data/lib/sportdb/formats/structs/team_usage.rb +0 -88
- data/test/test_clubs.rb +0 -40
- data/test/test_conf.rb +0 -65
- data/test/test_csv_match_parser.rb +0 -114
- data/test/test_csv_match_parser_utils.rb +0 -20
- data/test/test_csv_reader.rb +0 -31
- data/test/test_match.rb +0 -30
- data/test/test_match_auto.rb +0 -72
- data/test/test_match_auto_champs.rb +0 -45
- data/test/test_match_auto_euro.rb +0 -37
- data/test/test_match_auto_worldcup.rb +0 -61
- data/test/test_match_champs.rb +0 -27
- data/test/test_match_eng.rb +0 -26
- data/test/test_match_euro.rb +0 -27
- data/test/test_match_worldcup.rb +0 -27
- data/test/test_name_helper.rb +0 -67
- data/test/test_scores.rb +0 -122
- data/test/test_season.rb +0 -62
@@ -95,36 +95,40 @@ class LeagueIndex
|
|
95
95
|
end # method add
|
96
96
|
|
97
97
|
|
98
|
+
## helper to always convert (possible) country key to existing country record
|
99
|
+
## todo: make private - why? why not?
|
100
|
+
def country( country )
|
101
|
+
if country.is_a?( String ) || country.is_a?( Symbol )
|
102
|
+
## note: use own "global" countries index setting for ClubIndex - why? why not?
|
103
|
+
rec = catalog.countries.find( country.to_s )
|
104
|
+
if rec.nil?
|
105
|
+
puts "** !!! ERROR !!! - unknown country >#{country}< - no match found, sorry - add to world/countries.txt in config"
|
106
|
+
exit 1
|
107
|
+
end
|
108
|
+
rec
|
109
|
+
else
|
110
|
+
country ## (re)use country struct - no need to run lookup again
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
98
115
|
def match( name )
|
99
|
-
##
|
116
|
+
## note: returns empty array if no match and NOT nil
|
100
117
|
name = normalize( name )
|
101
|
-
@leagues_by_name[ name ]
|
118
|
+
@leagues_by_name[ name ] || []
|
102
119
|
end
|
103
120
|
|
104
|
-
|
105
121
|
def match_by( name:, country: )
|
106
122
|
## note: match must for now always include name
|
107
123
|
m = match( name )
|
108
|
-
if
|
124
|
+
if country ## filter by country
|
109
125
|
## note: country assumes / allows the country key or fifa code for now
|
110
|
-
|
111
126
|
## note: allow passing in of country struct too
|
112
|
-
country_rec =
|
113
|
-
country ## (re)use country struct - no need to run lookup again
|
114
|
-
else
|
115
|
-
## note: use own "global" countries index setting for ClubIndex - why? why not?
|
116
|
-
rec = catalog.countries.find( country )
|
117
|
-
if rec.nil?
|
118
|
-
puts "** !!! ERROR !!! - unknown country >#{country}< - no match found, sorry - add to world/countries.txt in config"
|
119
|
-
exit 1
|
120
|
-
end
|
121
|
-
rec
|
122
|
-
end
|
127
|
+
country_rec = country( country )
|
123
128
|
|
124
129
|
## note: also skip international leagues & cups (e.g. champions league etc.) for now - why? why not?
|
125
130
|
m = m.select { |league| league.country &&
|
126
131
|
league.country.key == country_rec.key }
|
127
|
-
m = nil if m.empty? ## note: reset to nil if no more matches
|
128
132
|
end
|
129
133
|
m
|
130
134
|
end
|
@@ -144,7 +148,7 @@ class LeagueIndex
|
|
144
148
|
m = match( name )
|
145
149
|
# pp m
|
146
150
|
|
147
|
-
if m.
|
151
|
+
if m.empty?
|
148
152
|
## fall through/do nothing
|
149
153
|
elsif m.size > 1
|
150
154
|
puts "** !!! ERROR - ambigious league name; too many leagues (#{m.size}) found:"
|
@@ -65,7 +65,7 @@ class LeagueOutlineReader ## todo/check - rename to LeaguePageReader / LeagueP
|
|
65
65
|
filtered_secs = []
|
66
66
|
filter = norm_seasons( season )
|
67
67
|
secs.each do |sec|
|
68
|
-
if filter.include?(
|
68
|
+
if filter.include?( Season.parse( sec[:season] ).key )
|
69
69
|
filtered_secs << sec
|
70
70
|
else
|
71
71
|
puts " skipping season >#{sec[:season]}< NOT matched by filter"
|
@@ -76,7 +76,7 @@ class LeagueOutlineReader ## todo/check - rename to LeaguePageReader / LeagueP
|
|
76
76
|
|
77
77
|
## pass 3 - check & map; replace inline (string with data struct record)
|
78
78
|
secs.each do |sec|
|
79
|
-
sec[:season] =
|
79
|
+
sec[:season] = Season.parse( sec[:season ] )
|
80
80
|
sec[:league] = catalog.leagues.find!( sec[:league] )
|
81
81
|
|
82
82
|
check_stage( sec[:stage] ) if sec[:stage] ## note: only check for now (no remapping etc.)
|
@@ -100,14 +100,18 @@ class LeagueOutlineReader ## todo/check - rename to LeaguePageReader / LeagueP
|
|
100
100
|
)
|
101
101
|
$}x
|
102
102
|
|
103
|
+
|
103
104
|
def norm_seasons( season_or_seasons ) ## todo/check: add alias norm_seasons - why? why not?
|
104
|
-
|
105
|
+
|
106
|
+
seasons = if season_or_seasons.is_a?( Array ) # is it an array already
|
107
|
+
season_or_seasons
|
108
|
+
elsif season_or_seasons.is_a?( Range ) # e.g. Season(1999)..Season(2001) or such
|
109
|
+
season_or_seasons.to_a
|
110
|
+
else ## assume - single entry - wrap in array
|
105
111
|
[season_or_seasons]
|
106
|
-
else ## assume it's an array already
|
107
|
-
season_or_seasons
|
108
112
|
end
|
109
113
|
|
110
|
-
seasons.map { |season|
|
114
|
+
seasons.map { |season| Season( season ).key }
|
111
115
|
end
|
112
116
|
|
113
117
|
|
@@ -121,14 +125,42 @@ class LeagueOutlineReader ## todo/check - rename to LeaguePageReader / LeagueP
|
|
121
125
|
values
|
122
126
|
end
|
123
127
|
|
124
|
-
def check_stage( name )
|
125
|
-
known_stages = ['regular season',
|
126
|
-
'championship round',
|
127
|
-
'relegation round',
|
128
|
-
'play-offs'
|
129
|
-
]
|
130
128
|
|
131
|
-
|
129
|
+
# note: normalize names e.g. downcase and remove all non a-z chars (e.g. space, dash, etc.)
|
130
|
+
KNOWN_STAGES = [
|
131
|
+
'Regular Season',
|
132
|
+
'Regular Stage',
|
133
|
+
'Championship Round',
|
134
|
+
'Championship Playoff', # or Championship play-off
|
135
|
+
'Relegation Round',
|
136
|
+
'Relegation Playoff',
|
137
|
+
'Play-offs',
|
138
|
+
'Playoff Stage',
|
139
|
+
'Grunddurchgang',
|
140
|
+
'Finaldurchgang - Qualifikationsgruppe',
|
141
|
+
'Finaldurchgang - Qualifikation',
|
142
|
+
'Finaldurchgang - Meistergruppe',
|
143
|
+
'Finaldurchgang - Meister',
|
144
|
+
'EL Play-off',
|
145
|
+
'Europa League Play-off',
|
146
|
+
'Europa-League-Play-offs',
|
147
|
+
'Playoffs - Championship',
|
148
|
+
'Playoffs - Europa League',
|
149
|
+
'Playoffs - Europa League - Finals',
|
150
|
+
'Playoffs - Relegation',
|
151
|
+
'Finals',
|
152
|
+
|
153
|
+
'Apertura',
|
154
|
+
'Apertura - Liguilla',
|
155
|
+
'Clausura',
|
156
|
+
'Clausura - Liguilla',
|
157
|
+
|
158
|
+
].map {|name| name.downcase.gsub( /[^a-z]/, '' ) }
|
159
|
+
|
160
|
+
|
161
|
+
def check_stage( name )
|
162
|
+
# note: normalize names e.g. downcase and remove all non a-z chars (e.g. space, dash, etc.)
|
163
|
+
if KNOWN_STAGES.include?( name.downcase.gsub( /[^a-z]/, '' ) )
|
132
164
|
## everything ok
|
133
165
|
else
|
134
166
|
puts "** !!! ERROR - no (league) stage match found for >#{name}<, add to (builtin) stages table; sorry"
|
@@ -118,12 +118,18 @@ def parse
|
|
118
118
|
alt_names_auto << "#{country.code}" if league_key == '1' ## add shortcut for top level 1 (just country key)
|
119
119
|
end
|
120
120
|
alt_names_auto << "#{country.name} #{league_key}" if league_key =~ /^[0-9]+$/ ## if all numeric e.g. add Austria 1 etc.
|
121
|
+
|
122
|
+
## auto-add with country prepended
|
123
|
+
## e.g. England Premier League, Austria Bundesliga etc.
|
124
|
+
## todo/check: also add variants with country alt name if present!!!
|
125
|
+
## todo/check: exclude cups or such from country + league name auto-add - why? why not?
|
126
|
+
alt_names_auto << "#{country.name} #{league_name}"
|
121
127
|
else ## assume int'l (no country) e.g. champions league, etc.
|
122
128
|
## only auto-add key (e.g. CL, EL, etc.)
|
123
129
|
alt_names_auto << league_key.upcase.gsub('.', ' ') ## note: no country code (prefix/leading) used
|
124
130
|
end
|
125
131
|
|
126
|
-
pp alt_names_auto
|
132
|
+
## pp alt_names_auto
|
127
133
|
|
128
134
|
## prepend country key/code if country present
|
129
135
|
## todo/fix: only auto-prepend country if key/code start with a number (level) or incl. cup
|
@@ -82,10 +82,9 @@ class MatchParser ## simple match parser for team match schedules
|
|
82
82
|
# team1 team2 - match (will get new auto-matchday! not last round)
|
83
83
|
@last_round = nil
|
84
84
|
|
85
|
-
name
|
85
|
+
name = find_group_name!( line )
|
86
86
|
|
87
87
|
logger.debug " name: >#{name}<"
|
88
|
-
logger.debug " pos: >#{pos}<"
|
89
88
|
logger.debug " line: >#{line}<"
|
90
89
|
|
91
90
|
group = @groups[ name ]
|
@@ -104,7 +103,7 @@ class MatchParser ## simple match parser for team match schedules
|
|
104
103
|
@mapper_teams.map_teams!( line )
|
105
104
|
teams = @mapper_teams.find_teams!( line )
|
106
105
|
|
107
|
-
name
|
106
|
+
name = find_group_name!( line )
|
108
107
|
|
109
108
|
logger.debug " line: >#{line}<"
|
110
109
|
|
@@ -116,7 +115,7 @@ class MatchParser ## simple match parser for team match schedules
|
|
116
115
|
end
|
117
116
|
|
118
117
|
|
119
|
-
def
|
118
|
+
def find_group_name!( line )
|
120
119
|
## group pos - for now support single digit e.g 1,2,3 or letter e.g. A,B,C or HEX
|
121
120
|
## nb: (?:) = is for non-capturing group(ing)
|
122
121
|
|
@@ -125,37 +124,25 @@ class MatchParser ## simple match parser for team match schedules
|
|
125
124
|
|
126
125
|
## todo:
|
127
126
|
## check if Group A: or [Group A] works e.g. : or ] get matched by \b ???
|
128
|
-
regex =
|
127
|
+
regex = /\b
|
128
|
+
(?:
|
129
|
+
(Group | Gruppe | Grupo)
|
130
|
+
[ ]+
|
131
|
+
(\d+ | [A-Z]+)
|
132
|
+
)
|
133
|
+
\b/x
|
129
134
|
|
130
135
|
m = regex.match( line )
|
131
136
|
|
132
|
-
return
|
133
|
-
|
134
|
-
pos = case m[1]
|
135
|
-
when 'A' then 1
|
136
|
-
when 'B' then 2
|
137
|
-
when 'C' then 3
|
138
|
-
when 'D' then 4
|
139
|
-
when 'E' then 5
|
140
|
-
when 'F' then 6
|
141
|
-
when 'G' then 7
|
142
|
-
when 'H' then 8
|
143
|
-
when 'I' then 9
|
144
|
-
when 'J' then 10
|
145
|
-
when 'K' then 11
|
146
|
-
when 'L' then 12
|
147
|
-
when 'HEX' then 666 # HEX for Hexagonal - todo/check: map to something else ??
|
148
|
-
else m[1].to_i
|
149
|
-
end
|
137
|
+
return nil if m.nil?
|
150
138
|
|
151
139
|
name = m[0]
|
152
140
|
|
153
141
|
logger.debug " name: >#{name}<"
|
154
|
-
logger.debug " pos: >#{pos}<"
|
155
142
|
|
156
|
-
line.sub!(
|
143
|
+
line.sub!( name, '[GROUP.NAME]' )
|
157
144
|
|
158
|
-
|
145
|
+
name
|
159
146
|
end
|
160
147
|
|
161
148
|
|
@@ -180,7 +167,6 @@ class MatchParser ## simple match parser for team match schedules
|
|
180
167
|
end_date = end_date.to_date
|
181
168
|
|
182
169
|
|
183
|
-
pos = find_round_pos!( line )
|
184
170
|
name = find_round_def_name!( line )
|
185
171
|
# NB: use extracted round name for knockout check
|
186
172
|
knockout_flag = is_knockout_round?( name )
|
@@ -188,15 +174,11 @@ class MatchParser ## simple match parser for team match schedules
|
|
188
174
|
|
189
175
|
logger.debug " start_date: #{start_date}"
|
190
176
|
logger.debug " end_date: #{end_date}"
|
191
|
-
logger.debug " pos: #{pos}"
|
192
177
|
logger.debug " name: >#{name}<"
|
193
178
|
logger.debug " knockout_flag: #{knockout_flag}"
|
194
179
|
|
195
180
|
logger.debug " line: >#{line}<"
|
196
181
|
|
197
|
-
#######################################
|
198
|
-
# todo/fix: add auto flag is false !!!! - why? why not?
|
199
|
-
# todo/fix/check: add num if present!!!!
|
200
182
|
round = Import::Round.new( name: name,
|
201
183
|
start_date: start_date,
|
202
184
|
end_date: end_date,
|
@@ -208,52 +190,6 @@ class MatchParser ## simple match parser for team match schedules
|
|
208
190
|
|
209
191
|
|
210
192
|
|
211
|
-
def find_round_pos!( line )
|
212
|
-
# pass #1) extract optional round pos from line
|
213
|
-
# e.g. (1) - must start line
|
214
|
-
regex_pos = /^[ \t]*\((\d{1,3})\)[ \t]+/
|
215
|
-
|
216
|
-
# pass #2) find free standing number e.g. Matchday 3 or Round 5 or 3. Spieltag etc.
|
217
|
-
# note: /\b(\d{1,3})\b/
|
218
|
-
# will match -12
|
219
|
-
# thus, use space required - will NOT match -2 e.g. Group-2 Play-off
|
220
|
-
# note: allow 1. Runde n
|
221
|
-
# 1^ Giornata
|
222
|
-
regex_num = /(?:^|\s)(\d{1,3})(?:[.\^\s]|$)/
|
223
|
-
|
224
|
-
if line =~ regex_pos
|
225
|
-
logger.debug " pos: >#{$1}<"
|
226
|
-
|
227
|
-
line.sub!( regex_pos, '[ROUND.POS] ' ) ## NB: add back trailing space that got swallowed w/ regex -> [ \t]+
|
228
|
-
return $1.to_i
|
229
|
-
elsif line =~ regex_num
|
230
|
-
## assume number in name is pos (e.g. Jornada 3, 3 Runde etc.)
|
231
|
-
## NB: do NOT remove pos from string (will get removed by round name)
|
232
|
-
|
233
|
-
num = $1.to_i # note: clone capture; keep a copy (another regex follows; will redefine $1)
|
234
|
-
|
235
|
-
#### fix:
|
236
|
-
# use/make keywords required
|
237
|
-
# e.g. Round of 16 -> should NOT match 16!
|
238
|
-
# Spiel um Platz 3 (or 5) etc -> should NOT match 3!
|
239
|
-
# Round 16 - ok
|
240
|
-
# thus, check for required keywords
|
241
|
-
|
242
|
-
## quick hack for round of 16
|
243
|
-
# todo: mask match e.g. Round of xxx ... and try again - might include something
|
244
|
-
# reuse pattern for Group XX Replays for example
|
245
|
-
if line =~ /^\s*Round of \d{1,3}\b/
|
246
|
-
return nil
|
247
|
-
end
|
248
|
-
|
249
|
-
logger.debug " pos: >#{num}<"
|
250
|
-
return num
|
251
|
-
else
|
252
|
-
## fix: add logger.warn no round pos found in line
|
253
|
-
return nil
|
254
|
-
end
|
255
|
-
end # method find_round_pos!
|
256
|
-
|
257
193
|
def find_round_def_name!( line )
|
258
194
|
# assume everything before pipe (\) is the round name
|
259
195
|
# strip [ROUND.POS], todo:?? [ROUND.NAME2]
|
@@ -266,10 +202,6 @@ class MatchParser ## simple match parser for team match schedules
|
|
266
202
|
|
267
203
|
## cut-off everything after (including) pipe (|)
|
268
204
|
buf = buf[ 0...buf.index('|') ]
|
269
|
-
|
270
|
-
# e.g. remove [ROUND.POS], [ROUND.NAME2], [GROUP.NAME+POS] etc.
|
271
|
-
buf.gsub!( /\[[^\]]+\]/, '' ) ## fix: use helper for (re)use e.g. remove_match_placeholder/marker or similar?
|
272
|
-
# remove leading and trailing whitespace
|
273
205
|
buf.strip!
|
274
206
|
|
275
207
|
logger.debug " find_round_def_name! line-after: >>#{buf}<<"
|
@@ -280,20 +212,38 @@ class MatchParser ## simple match parser for team match schedules
|
|
280
212
|
buf
|
281
213
|
end
|
282
214
|
|
215
|
+
|
216
|
+
## split by or || or |||
|
217
|
+
## or ++ or +++
|
218
|
+
## or -- or ---
|
219
|
+
## or // or ///
|
220
|
+
## note: allow Final | First Leg as ONE name same as
|
221
|
+
## Final - First Leg or
|
222
|
+
## Final, First Leg
|
223
|
+
## for cut-off always MUST be more than two chars
|
224
|
+
##
|
225
|
+
## todo/check: find a better name than HEADER_SEP(ARATOR) - why? why not?
|
226
|
+
## todo/fix: move to parser utils and add a method split_name or such?
|
227
|
+
HEADER_SEP_RE = / [ ]* ## allow (strip) leading spaces
|
228
|
+
(?:\|{2,} |
|
229
|
+
\+{2,} |
|
230
|
+
-{2,} |
|
231
|
+
\/{2,}
|
232
|
+
)
|
233
|
+
[ ]* ## allow (strip) trailing spaces
|
234
|
+
/x
|
235
|
+
|
283
236
|
def find_round_header_name!( line )
|
284
237
|
# assume everything left is the round name
|
285
238
|
# extract all other items first (round name2, round pos, group name n pos, etc.)
|
286
239
|
|
287
|
-
## todo/fix:
|
288
|
-
## cleanup method
|
289
|
-
## use buf.index( '//' ) to split string (see found_round_def)
|
290
|
-
## why? simpler why not?
|
291
|
-
## - do we currently allow groups if name2 present? add example if it works?
|
292
|
-
|
293
240
|
buf = line.dup
|
294
241
|
logger.debug " find_round_header_name! line-before: >>#{buf}<<"
|
295
242
|
|
296
|
-
|
243
|
+
|
244
|
+
parts = buf.split( HEADER_SEP_RE )
|
245
|
+
buf = parts[0]
|
246
|
+
|
297
247
|
buf.strip! # remove leading and trailing whitespace
|
298
248
|
|
299
249
|
logger.debug " find_round_name! line-after: >>#{buf}<<"
|
@@ -306,19 +256,30 @@ class MatchParser ## simple match parser for team match schedules
|
|
306
256
|
buf
|
307
257
|
end
|
308
258
|
|
259
|
+
## quick hack- collect all "fillwords" by language!!!!
|
260
|
+
## change later and add to sportdb-langs!!!!
|
261
|
+
##
|
262
|
+
## strip all "fillwords" e.g.:
|
263
|
+
## Nachtrag/Postponed/Addition/Supplemento names
|
264
|
+
##
|
265
|
+
## todo/change: find a better name for ROUND_EXTRA_WORDS - why? why not?
|
266
|
+
ROUND_EXTRA_WORDS_RE = /\b(?:
|
267
|
+
Nachtrag | ## de
|
268
|
+
Postponed | ## en
|
269
|
+
Addition | ## en
|
270
|
+
Supplemento ## es
|
271
|
+
)
|
272
|
+
\b/ix
|
309
273
|
|
310
274
|
def parse_round_header( line )
|
311
275
|
logger.debug "parsing round header line: >#{line}<"
|
312
276
|
|
313
|
-
## todo/check/fix:
|
314
|
-
# make sure Round of 16 will not return pos 16 -- how? possible?
|
315
|
-
# add unit test too to verify
|
316
|
-
pos = find_round_pos!( line )
|
317
|
-
|
318
277
|
name = find_round_header_name!( line )
|
319
278
|
|
320
279
|
logger.debug " line: >#{line}<"
|
321
280
|
|
281
|
+
name = name.sub( ROUND_EXTRA_WORDS_RE, '' )
|
282
|
+
name = name.strip
|
322
283
|
|
323
284
|
round = @rounds[ name ]
|
324
285
|
if round.nil? ## auto-add / create if missing
|
@@ -341,6 +302,11 @@ class MatchParser ## simple match parser for team match schedules
|
|
341
302
|
ScoreFormats.find!( line )
|
342
303
|
end
|
343
304
|
|
305
|
+
def find_status!( line )
|
306
|
+
StatusParser.find!( line )
|
307
|
+
end
|
308
|
+
|
309
|
+
|
344
310
|
def try_parse_game( line )
|
345
311
|
# note: clone line; for possible test do NOT modify in place for now
|
346
312
|
# note: returns true if parsed, false if no match
|
@@ -368,6 +334,10 @@ class MatchParser ## simple match parser for team match schedules
|
|
368
334
|
return false
|
369
335
|
end
|
370
336
|
|
337
|
+
## find (optional) match status e.g. [abandoned] or [replay] or [awarded]
|
338
|
+
## or [cancelled] or [postponed] etc.
|
339
|
+
status = find_status!( line ) ## todo/check: allow match status also in geo part (e.g. after @) - why? why not?
|
340
|
+
|
371
341
|
## pos = find_game_pos!( line )
|
372
342
|
|
373
343
|
date = find_date!( line, start: @start )
|
@@ -392,20 +362,23 @@ class MatchParser ## simple match parser for team match schedules
|
|
392
362
|
if @last_round
|
393
363
|
round = @last_round
|
394
364
|
else
|
395
|
-
## find (first) matching round by date
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
365
|
+
## find (first) matching round by date if rounds / matchdays defined
|
366
|
+
## if not rounds / matchdays defined - YES, allow matches WITHOUT rounds!!!
|
367
|
+
if @rounds.size > 0
|
368
|
+
@rounds.values.each do |round_rec|
|
369
|
+
## note: convert date to date only (no time) with to_date!!!
|
370
|
+
if (round_rec.start_date && round_rec.end_date) &&
|
371
|
+
(date.to_date >= round_rec.start_date &&
|
372
|
+
date.to_date <= round_rec.end_date)
|
373
|
+
round = round_rec
|
374
|
+
break
|
375
|
+
end
|
376
|
+
end
|
377
|
+
if round.nil?
|
378
|
+
puts "!! ERROR - no matching round found for match date:"
|
379
|
+
pp date
|
380
|
+
exit 1
|
403
381
|
end
|
404
|
-
end
|
405
|
-
if round.nil?
|
406
|
-
puts "!! ERROR - no matching round found for match date:"
|
407
|
-
pp date
|
408
|
-
exit 1
|
409
382
|
end
|
410
383
|
end
|
411
384
|
|
@@ -419,8 +392,8 @@ class MatchParser ## simple match parser for team match schedules
|
|
419
392
|
team2: team2, ## note: for now always use mapping value e.g. rec (NOT string e.g. team2.name)
|
420
393
|
score: score,
|
421
394
|
round: round ? round.name : nil, ## note: for now always use string (assume unique canonical name for event)
|
422
|
-
group: @last_group ? @last_group.name : nil
|
423
|
-
|
395
|
+
group: @last_group ? @last_group.name : nil, ## note: for now always use string (assume unique canonical name for event)
|
396
|
+
status: status )
|
424
397
|
### todo: cache team lookups in hash?
|
425
398
|
|
426
399
|
=begin
|
@@ -602,12 +575,29 @@ class MatchParser ## simple match parser for team match schedules
|
|
602
575
|
|
603
576
|
if date && team1.nil? && team2.nil?
|
604
577
|
logger.debug( "date header line found: >#{line}<")
|
605
|
-
logger.debug( " date: #{date}")
|
578
|
+
logger.debug( " date: #{date} with start: #{@start}")
|
606
579
|
|
607
580
|
@last_date = date # keep a reference for later use
|
608
|
-
|
581
|
+
|
582
|
+
### quick "corona" hack - support seasons going beyond 12 month (see swiss league 2019/20 and others!!)
|
583
|
+
## find a better way??
|
584
|
+
## set @start date to full year (e.g. 1.1.) if date.year is @start.year+1
|
585
|
+
## todo/fix: add to linter to check for chronological dates!! - warn if NOT chronological
|
586
|
+
### todo/check: just turn on for 2019/20 season or always? why? why not?
|
587
|
+
|
588
|
+
## todo/fix: add switch back to old @start_org
|
589
|
+
## if year is date.year == @start.year-1 -- possible when full date with year set!!!
|
590
|
+
if @start.month != 1
|
591
|
+
if date.year == @start.year+1
|
592
|
+
logger.debug( "!! hack - extending start date to full (next/end) year; assumes all dates are chronologigal - always moving forward" )
|
593
|
+
@start_org = @start ## keep a copy of the original (old) start date - why? why not? - not used for now
|
594
|
+
@start = Date.new( @start.year+1, 1, 1 )
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
true
|
609
599
|
else
|
610
|
-
|
600
|
+
false
|
611
601
|
end
|
612
602
|
end
|
613
603
|
|