sportdb-formats 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,446 @@
1
+ # encoding: utf-8
2
+
3
+ #### fix: move to textutils for reuse !!!!!!!!!! - why?? why not ??
4
+
5
+
6
+ module SportDb
7
+
8
+
9
+ class DateFinderBase
10
+
11
+ MONTH_EN_TO_MM = {
12
+ 'Jan' => '1', 'January' => '1',
13
+ 'Feb' => '2', 'February' => '2',
14
+ 'Mar' => '3', 'March' => '3',
15
+ 'Apr' => '4', 'April' => '4',
16
+ 'May' => '5',
17
+ 'Jun' => '6', 'June' => '6',
18
+ 'Jul' => '7', 'July' => '7',
19
+ 'Aug' => '8', 'August' => '8',
20
+ 'Sep' => '9', 'Sept' => '9', 'September' => '9',
21
+ 'Oct' => '10', 'October' => '10',
22
+ 'Nov' => '11', 'November' => '11',
23
+ 'Dec' => '12', 'December' =>'12' }
24
+
25
+ MONTH_FR_TO_MM = {
26
+ 'Janvier' => '1', 'Janv' => '1', 'Jan' => '1', ## check janv in use??
27
+ 'Février' => '2', 'Févr' => '2', 'Fév' => '2', ## check fevr in use???
28
+ 'Mars' => '3', 'Mar' => '3',
29
+ 'Avril' => '4', 'Avri' => '4', 'Avr' => '4', ## check avri in use??? if not remove
30
+ 'Mai' => '5',
31
+ 'Juin' => '6',
32
+ 'Juillet' => '7', 'Juil' => '7',
33
+ 'Août' => '8',
34
+ 'Septembre' => '9', 'Sept' => '9',
35
+ 'Octobre' => '10', 'Octo' => '10', 'Oct' => '10', ### check octo in use??
36
+ 'Novembre' => '11', 'Nove' => '11', 'Nov' => '11', ## check nove in use??
37
+ 'Décembre' => '12', 'Déce' => '12', 'Déc' => '12' } ## check dece in use??
38
+
39
+ MONTH_ES_TO_MM = {
40
+ 'Ene' => '1', 'Enero' => '1',
41
+ 'Feb' => '2',
42
+ 'Mar' => '3', 'Marzo' => '3',
43
+ 'Abr' => '4', 'Abril' => '4',
44
+ 'May' => '5', 'Mayo' => '5',
45
+ 'Jun' => '6', 'Junio' => '6',
46
+ 'Jul' => '7', 'Julio' => '7',
47
+ 'Ago' => '8', 'Agosto' => '8',
48
+ 'Sep' => '9', 'Set' => '9', 'Sept' => '9',
49
+ 'Oct' => '10',
50
+ 'Nov' => '11',
51
+ 'Dic' => '12' }
52
+
53
+ private
54
+ def calc_year( month, day, start_at: ) ## note: start_at required param for now on!!!
55
+
56
+ logger.debug " [calc_year] ????-#{month}-#{day} -- start_at: #{start_at}"
57
+
58
+ if month >= start_at.month
59
+ # assume same year as start_at event (e.g. 2013 for 2013/14 season)
60
+ start_at.year
61
+ else
62
+ # assume year+1 as start_at event (e.g. 2014 for 2013/14 season)
63
+ start_at.year+1
64
+ end
65
+ end
66
+
67
+
68
+ def parse_date_time( match_data, opts={} )
69
+
70
+ # convert regex match_data captures to hash
71
+ # - note: cannont use match_data like a hash (e.g. raises exception if key/name not present/found)
72
+ h = {}
73
+ # - note: do NOT forget to turn name into symbol for lookup in new hash (name.to_sym)
74
+ match_data.names.each { |name| h[name.to_sym] = match_data[name] } # or use match_data.names.zip( match_data.captures ) - more cryptic but "elegant"??
75
+
76
+ ## puts "[parse_date_time] match_data:"
77
+ ## pp h
78
+ logger.debug " [parse_date_time] hash: >#{h.inspect}<"
79
+
80
+ h[ :month ] = MONTH_EN_TO_MM[ h[:month_en] ] if h[:month_en]
81
+ h[ :month ] = MONTH_ES_TO_MM[ h[:month_es] ] if h[:month_es]
82
+ h[ :month ] = MONTH_FR_TO_MM[ h[:month_fr] ] if h[:month_fr]
83
+
84
+ month = h[:month]
85
+ day = h[:day]
86
+ year = h[:year] || calc_year( month.to_i, day.to_i, opts ).to_s
87
+
88
+ hours = h[:hours] || '12' # default to 12:00 for HH:MM (hours:minutes)
89
+ minutes = h[:minutes] || '00'
90
+
91
+ value = '%d-%02d-%02d %02d:%02d' % [year.to_i, month.to_i, day.to_i, hours.to_i, minutes.to_i]
92
+ logger.debug " date: >#{value}<"
93
+
94
+ DateTime.strptime( value, '%Y-%m-%d %H:%M' )
95
+ end
96
+
97
+ end # class DateFinderBase
98
+
99
+
100
+ class DateFinder < DateFinderBase
101
+
102
+ include LogUtils::Logging
103
+
104
+ # todo: make more generic for reuse
105
+ ### fix:
106
+ ### move to textutils
107
+ ## date/fr.yml en.yml etc. ???
108
+ ## why? why not?
109
+
110
+ MONTH_FR = 'Janvier|Janv|Jan|' +
111
+ 'Février|Févr|Fév|' +
112
+ 'Mars|Mar|' +
113
+ 'Avril|Avri|Avr|' +
114
+ 'Mai|' +
115
+ 'Juin|' +
116
+ 'Juillet|Juil|' +
117
+ 'Août|' +
118
+ 'Septembre|Sept|' +
119
+ 'Octobre|Octo|Oct|' +
120
+ 'Novembre|Nove|Nov|' +
121
+ 'Décembre|Déce|Déc'
122
+
123
+ WEEKDAY_FR = 'Lundi|Lun|L|' +
124
+ 'Mardi|Mar|Ma|' +
125
+ 'Mercredi|Mer|Me|' +
126
+ 'Jeudi|Jeu|J|' +
127
+ 'Vendredi|Ven|V|' +
128
+ 'Samedi|Sam|S|' +
129
+ 'Dimanche|Dim|D|'
130
+
131
+
132
+ MONTH_EN = 'January|Jan|'+
133
+ 'February|Feb|'+
134
+ 'March|Mar|'+
135
+ 'April|Apr|'+
136
+ 'May|'+
137
+ 'June|Jun|'+
138
+ 'July|Jul|'+
139
+ 'August|Aug|'+
140
+ 'September|Sept|Sep|'+
141
+ 'October|Oct|'+
142
+ 'November|Nov|'+
143
+ 'December|Dec'
144
+
145
+ ###
146
+ ## todo: add days
147
+ ## 1. Sunday - Sun. 2. Monday - Mon.
148
+ ## 3. Tuesday - Tu., Tue., or Tues. 4. Wednesday - Wed.
149
+ ## 5. Thursday - Th., Thu., Thur., or Thurs. 6. Friday - Fri.
150
+ ## 7. Saturday - Sat.
151
+
152
+
153
+ MONTH_ES = 'Enero|Ene|'+
154
+ 'Feb|'+
155
+ 'Marzo|Mar|'+
156
+ 'Abril|Abr|'+
157
+ 'Mayo|May|'+
158
+ 'Junio|Jun|'+
159
+ 'Julio|Jul|'+
160
+ 'Agosto|Ago|'+
161
+ 'Sept|Set|Sep|'+
162
+ 'Oct|'+
163
+ 'Nov|'+
164
+ 'Dic'
165
+
166
+ # todo/fix - add de and es too!!
167
+ # note: in Austria - Jänner - in Deutschland Januar allow both ??
168
+ # MONTH_DE = 'J[aä]n|Feb|Mär|Apr|Mai|Jun|Jul|Aug|Sep|Okt|Nov|Dez'
169
+
170
+
171
+ # e.g. 2012-09-14 20:30 => YYYY-MM-DD HH:MM
172
+ # nb: allow 2012-9-3 7:30 e.g. no leading zero required
173
+ # regex_db
174
+ DB__DATE_TIME_REGEX = /\b
175
+ (?<year>\d{4})
176
+ -
177
+ (?<month>\d{1,2})
178
+ -
179
+ (?<day>\d{1,2})
180
+ \s+
181
+ (?<hours>\d{1,2})
182
+ :
183
+ (?<minutes>\d{2})
184
+ \b/x
185
+
186
+ # e.g. 2012-09-14 w/ implied hours (set to 12:00)
187
+ # nb: allow 2012-9-3 e.g. no leading zero required
188
+ # regex_db2
189
+ DB__DATE_REGEX = /\b
190
+ (?<year>\d{4})
191
+ -
192
+ (?<month>\d{1,2})
193
+ -
194
+ (?<day>\d{1,2})
195
+ \b/x
196
+
197
+ # e.g. 14.09.2012 20:30 => DD.MM.YYYY HH:MM
198
+ # nb: allow 2.3.2012 e.g. no leading zero required
199
+ # nb: allow hour as 20.30
200
+ # regex_de
201
+ DD_MM_YYYY__DATE_TIME_REGEX = /\b
202
+ (?<day>\d{1,2})
203
+ \.
204
+ (?<month>\d{1,2})
205
+ \.
206
+ (?<year>\d{4})
207
+ \s+
208
+ (?<hours>\d{1,2})
209
+ [:.]
210
+ (?<minutes>\d{2})
211
+ \b/x
212
+
213
+ # e.g. 14.09. 20:30 => DD.MM. HH:MM
214
+ # nb: allow 2.3.2012 e.g. no leading zero required
215
+ # nb: allow hour as 20.30 or 3.30 instead of 03.30
216
+ # regex_de2
217
+ DD_MM__DATE_TIME_REGEX = /\b
218
+ (?<day>\d{1,2})
219
+ \.
220
+ (?<month>\d{1,2})
221
+ \.
222
+ \s+
223
+ (?<hours>\d{1,2})
224
+ [:.]
225
+ (?<minutes>\d{2})
226
+ \b/x
227
+
228
+ # e.g. 14.09.2012 => DD.MM.YYYY w/ implied hours (set to 12:00)
229
+ # regex_de3
230
+ DD_MM_YYYY__DATE_REGEX = /\b
231
+ (?<day>\d{1,2})
232
+ \.
233
+ (?<month>\d{1,2})
234
+ \.
235
+ (?<year>\d{4})
236
+ \b/x
237
+
238
+ # e.g. 14.09. => DD.MM. w/ implied year and implied hours (set to 12:00)
239
+ # note: allow end delimiter ] e.g. [Sa 12.01.] or end-of-string ($) too
240
+ # note: we use a lookahead for last part e.g. (?:\s+|$|[\]]) - do NOT cosume
241
+ # regex_de4 (use lookahead assert)
242
+ DD_MM__DATE_REGEX = /\b
243
+ (?<day>\d{1,2})
244
+ \.
245
+ (?<month>\d{1,2})
246
+ \.
247
+ (?=\s+|$|[\]])/x ## note: allow end-of-string/line too
248
+
249
+
250
+ # e.g. 12 May 2013 14:00 => D|DD.MMM.YYYY H|HH:MM
251
+ EN__DD_MONTH_YYYY__DATE_TIME_REGEX = /\b
252
+ (?<day>\d{1,2})
253
+ \s
254
+ (?<month_en>#{MONTH_EN})
255
+ \s
256
+ (?<year>\d{4})
257
+ \s+
258
+ (?<hours>\d{1,2})
259
+ :
260
+ (?<minutes>\d{2})
261
+ \b/x
262
+
263
+ ###
264
+ # fix: pass in lang (e.g. en or es)
265
+ # only process format for lang plus fallback to en?
266
+ # e.g. EN__DD_MONTH and ES__DD_MONTH depend on order for match (first listed will match)
267
+
268
+ # e.g. 12 May => D|DD.MMM w/ implied year and implied hours
269
+ EN__DD_MONTH__DATE_REGEX = /\b
270
+ (?<day>\d{1,2})
271
+ \s
272
+ (?<month_en>#{MONTH_EN})
273
+ \b/x
274
+
275
+
276
+ # e.g. Jun/12 2011 14:00
277
+ EN__MONTH_DD_YYYY__DATE_TIME_REGEX = /\b
278
+ (?<month_en>#{MONTH_EN})
279
+ \/
280
+ (?<day>\d{1,2})
281
+ \s
282
+ (?<year>\d{4})
283
+ \s+
284
+ (?<hours>\d{1,2})
285
+ :
286
+ (?<minutes>\d{2})
287
+ \b/x
288
+
289
+ # e.g. Jun/12 14:00 w/ implied year H|HH:MM
290
+ EN__MONTH_DD__DATE_TIME_REGEX = /\b
291
+ (?<month_en>#{MONTH_EN})
292
+ \/
293
+ (?<day>\d{1,2})
294
+ \s+
295
+ (?<hours>\d{1,2})
296
+ :
297
+ (?<minutes>\d{2})
298
+ \b/x
299
+
300
+ # e.g. Jun/12 2013 w/ implied hours (set to 12:00)
301
+ EN__MONTH_DD_YYYY__DATE_REGEX = /\b
302
+ (?<month_en>#{MONTH_EN})
303
+ \/
304
+ (?<day>\d{1,2})
305
+ \s
306
+ (?<year>\d{4})
307
+ \b/x
308
+
309
+ # e.g. Jun/12 w/ implied year and implied hours (set to 12:00)
310
+ # note: allow space too e.g Jun 12 -- check if conflicts w/ other formats??? (added for rsssf reader)
311
+ # -- fix: might eat french weekday mar 12 is mardi (mar) !!! see FR__ pattern
312
+ # fix: remove space again for now - and use simple en date reader or something!!!
313
+ ## was [\/ ] changed back to \/
314
+ EN__MONTH_DD__DATE_REGEX = /\b
315
+ (?<month_en>#{MONTH_EN})
316
+ \/
317
+ (?<day>\d{1,2})
318
+ \b/x
319
+
320
+
321
+ # e.g. 12 Ene w/ implied year and implied hours (set to 12:00)
322
+ ES__DD_MONTH__DATE_REGEX = /\b
323
+ (?<day>\d{1,2})
324
+ \s
325
+ (?<month_es>#{MONTH_ES})
326
+ \b/x
327
+
328
+ # e.g. Ven 8 Août or [Ven 8 Août] or Ven 8. Août or [Ven 8. Août]
329
+ ### note: do NOT consume [] in regex (use lookahead assert)
330
+ FR__WEEKDAY_DD_MONTH__DATE_REGEX = /\b
331
+ (?:#{WEEKDAY_FR}) # note: skip weekday for now; do NOT capture
332
+ \s+
333
+ (?<day>\d{1,2})
334
+ \.? # note: make dot optional
335
+ \s+
336
+ (?<month_fr>#{MONTH_FR})
337
+ (?=\s+|$|[\]])/x ## note: allow end-of-string/line too
338
+
339
+
340
+
341
+
342
+ # map table - 1) tag, 2) regex - note: order matters; first come-first matched/served
343
+ FORMATS = [
344
+ [ '[YYYY_MM_DD_hh_mm]', DB__DATE_TIME_REGEX ],
345
+ [ '[YYYY_MM_DD]', DB__DATE_REGEX ],
346
+ [ '[DD_MM_YYYY_hh_mm]', DD_MM_YYYY__DATE_TIME_REGEX ],
347
+ [ '[DD_MM_hh_mm]', DD_MM__DATE_TIME_REGEX ],
348
+ [ '[DD_MM_YYYY]', DD_MM_YYYY__DATE_REGEX ],
349
+ [ '[DD_MM]', DD_MM__DATE_REGEX ],
350
+ [ '[FR_WEEKDAY_DD_MONTH]', FR__WEEKDAY_DD_MONTH__DATE_REGEX ],
351
+ [ '[EN_DD_MONTH_YYYY_hh_mm]', EN__DD_MONTH_YYYY__DATE_TIME_REGEX ],
352
+ [ '[EN_MONTH_DD_YYYY_hh_mm]', EN__MONTH_DD_YYYY__DATE_TIME_REGEX ],
353
+ [ '[EN_MONTH_DD_hh_mm]', EN__MONTH_DD__DATE_TIME_REGEX ],
354
+ [ '[EN_MONTH_DD_YYYY]', EN__MONTH_DD_YYYY__DATE_REGEX ],
355
+ [ '[EN_MONTH_DD]', EN__MONTH_DD__DATE_REGEX ],
356
+ [ '[EN_DD_MONTH]', EN__DD_MONTH__DATE_REGEX ],
357
+ [ '[ES_DD_MONTH]', ES__DD_MONTH__DATE_REGEX ]
358
+ ]
359
+
360
+
361
+
362
+ def initialize
363
+ # nothing here for now
364
+ end
365
+
366
+ def find!( line, opts={} )
367
+ # fix: use more lookahead for all required trailing spaces!!!!!
368
+ # fix: use <name capturing group> for month,day,year etc.!!!
369
+
370
+ #
371
+ # fix: !!!!
372
+ # date in [] will become [[DATE.DE4]] - when getting removed will keep ]!!!!
373
+ # fix: change regex to \[[A-Z0-9.]\] !!!!!! plus add unit test too!!!
374
+ #
375
+
376
+ md = nil
377
+ FORMATS.each do |format|
378
+ tag = format[0]
379
+ pattern = format[1]
380
+ md=pattern.match( line )
381
+ if md
382
+ date = parse_date_time( md, opts )
383
+ ## fix: use md[0] e.g. match for sub! instead of using regex again - why? why not???
384
+ ## fix: use md.begin(0), md.end(0)
385
+ line.sub!( md[0], tag )
386
+ ## todo/fix: make sure match data will not get changed (e.g. using sub! before parse_date_time)
387
+ return date
388
+ end
389
+ # no match; continue; try next pattern
390
+ end
391
+
392
+ return nil # no match found
393
+ end
394
+
395
+ end # class DateFinder
396
+
397
+
398
+ class RsssfDateFinder < DateFinderBase
399
+
400
+ include LogUtils::Logging
401
+
402
+ MONTH_EN = 'Jan|'+
403
+ 'Feb|'+
404
+ 'March|Mar|'+
405
+ 'April|Apr|'+
406
+ 'May|'+
407
+ 'June|Jun|'+
408
+ 'July|Jul|'+
409
+ 'Aug|'+
410
+ 'Sept|Sep|'+
411
+ 'Oct|'+
412
+ 'Nov|'+
413
+ 'Dec'
414
+
415
+ ## e.g.
416
+ ## [Jun 7] or [Aug 12] etc. - not MUST include brackets e.g. []
417
+ ##
418
+ ## check add \b at the beginning and end - why?? why not?? working??
419
+ EN__MONTH_DD__DATE_REGEX = /\[
420
+ (?<month_en>#{MONTH_EN})
421
+ \s
422
+ (?<day>\d{1,2})
423
+ \]/x
424
+
425
+ def find!( line, opts={} )
426
+ # fix: use more lookahead for all required trailing spaces!!!!!
427
+ # fix: use <name capturing group> for month,day,year etc.!!!
428
+
429
+ tag = '[EN_MONTH_DD]'
430
+ pattern = EN__MONTH_DD__DATE_REGEX
431
+ md = pattern.match( line )
432
+ if md
433
+ date = parse_date_time( md, opts )
434
+ ## fix: use md[0] e.g. match for sub! instead of using regex again - why? why not???
435
+ ## fix: use md.begin(0), md.end(0)
436
+ line.sub!( md[0], tag )
437
+ ## todo/fix: make sure match data will not get changed (e.g. using sub! before parse_date_time)
438
+ return date
439
+ end
440
+ return nil # no match found
441
+ end
442
+
443
+
444
+ end ## class RsssfDateFinder
445
+
446
+ end # module SportDb
@@ -0,0 +1,216 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+ class Lang
6
+
7
+ include LogUtils::Logging
8
+
9
+ attr_reader :lang
10
+
11
+ def initialize
12
+ # fix/todo: load on demand; only if no fixtures loaded/configured use builtin
13
+ load_builtin_words
14
+ end
15
+
16
+
17
+ def load_builtin_words
18
+ builtin_words = {
19
+ 'en' => 'fixtures/en',
20
+ 'de' => 'fixtures/de',
21
+ 'es' => 'fixtures/es',
22
+ 'fr' => 'fixtures/fr',
23
+ 'it' => 'fixtures/it',
24
+ 'pt' => 'fixtures/pt',
25
+ 'ro' => 'fixtures/ro'
26
+ }
27
+
28
+ load_words( builtin_words, SportDb::Formats.config_path )
29
+ end
30
+
31
+
32
+ def load_words( h, include_path )
33
+ @lang = 'en' # make default lang english/en
34
+ @words = {} # resets fixtures
35
+ @cache = {} # reset cached values
36
+
37
+ h.each_with_index do |(key,value),i|
38
+ name = value
39
+ path = "#{include_path}/#{name}.yml"
40
+ logger.debug( "loading words #{key} (#{i+1}/#{h.size}) in '#{name}' (#{path})..." )
41
+ @words[ key ] = YAML.load( File.read_utf8( path ))
42
+ end
43
+
44
+ @classifier = TextUtils::Classifier.new
45
+ @words.each_with_index do |(key,value),i|
46
+ logger.debug "train classifier for #{key} (#{i+1}/#{@words.size})"
47
+ @classifier.train( key, value )
48
+ end
49
+
50
+ @classifier.dump # for debugging dump all words
51
+ end
52
+
53
+ def classify( text )
54
+ @classifier.classify( text )
55
+ end
56
+
57
+ def classify_file( path )
58
+ @classifier.classify_file( path )
59
+ end
60
+
61
+ def lang=(value)
62
+ logger.debug "setting lang to #{value}"
63
+
64
+ if @lang != value
65
+
66
+ ### todo: make reset cached values into method/function for reuse (see load_words)
67
+ # reset cached values on language change
68
+ logger.debug "reseting cached lang values (lang changed from #{@lang} to #{value})"
69
+
70
+ @cache = {}
71
+ end
72
+
73
+ @lang = value
74
+
75
+ end
76
+
77
+
78
+ def group
79
+ @cache[ :group ] ||= group_getter
80
+ end
81
+
82
+ def round
83
+ @cache[ :round ] ||= round_getter
84
+ end
85
+
86
+ def knockout_round
87
+ @cache[ :knockout_round ] ||= knockout_round_getter
88
+ end
89
+
90
+ def leg1
91
+ @cache[ :leg1 ] ||= leg1_getter
92
+ end
93
+
94
+ def leg2
95
+ @cache[ :leg2 ] ||= leg2_getter
96
+ end
97
+
98
+
99
+
100
+ def regex_group
101
+ @cache [ :regex_group ] ||= regex_group_getter
102
+ end
103
+
104
+ def regex_round
105
+ @cache[ :regex_round ] ||= regex_round_getter
106
+ end
107
+
108
+ def regex_knockout_round
109
+ @cache[ :regex_knockout_round ] ||= regex_knockout_round_getter
110
+ end
111
+
112
+ def regex_leg1
113
+ @cache[ :regex_leg1 ] ||= regex_leg1_getter
114
+ end
115
+
116
+ def regex_leg2
117
+ @cache[ :regex_leg2 ] ||= regex_leg2_getter
118
+ end
119
+
120
+ private
121
+ def group_getter
122
+ h = @words[ lang ]
123
+ values = "" # NB: always construct a new string (do NOT use a reference to hash value)
124
+ values << h['group']
125
+ values
126
+ end
127
+
128
+ def round_getter
129
+ # e.g. Spieltag|Runde|Achtelfinale|Viertelfinale|Halbfinale|Finale
130
+
131
+ ## fix/todo:
132
+ ## sort by length first - to allow best match e.g.
133
+ ## 3rd place play-off instead of Play-off ?? etc. - why? why not?
134
+
135
+ h = @words[ lang ]
136
+ values = "" # NB: always construct a new string (do NOT use a reference to hash value)
137
+ values << h['round']
138
+
139
+ ### add knockout rounds values too
140
+ values << "|" << h['round32']
141
+ values << "|" << h['round16']
142
+ values << "|" << h['quarterfinals']
143
+ values << "|" << h['semifinals']
144
+ values << "|" << h['fifthplace'] if h['fifthplace'] # nb: allow empty/is optional!!
145
+ values << "|" << h['thirdplace']
146
+ values << "|" << h['final']
147
+ values << "|" << h['playoffs'] if h['playoffs'] # nb: allow empty/is optional!!
148
+ values
149
+ end
150
+
151
+ def leg1_getter
152
+ h = @words[ lang ]
153
+ values = "" # NB: always construct a new string (do NOT use a reference to hash value)
154
+ values << h['leg1']
155
+ values
156
+ end
157
+
158
+ def leg2_getter
159
+ h = @words[ lang ]
160
+ values = "" # NB: always construct a new string (do NOT use a reference to hash value)
161
+ values << h['leg2']
162
+ values
163
+ end
164
+
165
+ def knockout_round_getter
166
+ h = @words[ lang ]
167
+ values = "" # NB: always construct a new string (do NOT use a reference to hash value)
168
+ values << h['round32']
169
+ values << "|" << h['round16']
170
+ values << "|" << h['quarterfinals']
171
+ values << "|" << h['semifinals']
172
+ values << "|" << h['fifthplace'] if h['fifthplace'] # nb: allow empty/is optional!!
173
+ values << "|" << h['thirdplace']
174
+ values << "|" << h['final']
175
+ values << "|" << h['playoffs'] if h['playoffs'] # nb: allow empty/is optional!!
176
+ values
177
+ end
178
+
179
+ def regex_group_getter
180
+ ## todo: escape for regex?
181
+ ## NB: let's ignore case (that is, UPCASE,downcase); always use /i flag
182
+ /#{group}/i
183
+ end
184
+
185
+ def regex_round_getter
186
+ ## todo: escape for regex?
187
+ ## todo: sort by length - biggest words go first? does regex match biggest word automatically?? - check
188
+ ## todo/fix: make - optional e.g. convert to ( |-) or better [ \-] ??
189
+ ## NB: let's ignore case (that is, UPCASE,downcase); always use /i flag
190
+ /#{round}/i
191
+ end
192
+
193
+ def regex_knockout_round_getter
194
+ ## todo: escape for regex?
195
+ ## todo: sort by length - biggest words go first? does regex match biggest word automatically?? - check
196
+ ## todo/fix: make - optional e.g. convert to ( |-) or better [ \-] ??
197
+ ## NB: let's ignore case (that is, UPCASE,downcase); always use /i flag
198
+ /#{knockout_round}/i
199
+ end
200
+
201
+ def regex_leg1_getter
202
+ ## todo: escape for regex?
203
+ ## NB: let's ignore case (that is, UPCASE,downcase); always use /i flag
204
+ /#{leg1}/i
205
+ end
206
+
207
+ def regex_leg2_getter
208
+ ## todo: escape for regex?
209
+ ## NB: let's ignore case (that is, UPCASE,downcase); always use /i flag
210
+ /#{leg2}/i
211
+ end
212
+
213
+ end # class Lang
214
+
215
+
216
+ end # module SportDb
@@ -6,7 +6,7 @@ module Formats
6
6
 
7
7
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
8
8
  MINOR = 1
9
- PATCH = 1
9
+ PATCH = 2
10
10
  VERSION = [MAJOR,MINOR,PATCH].join('.')
11
11
 
12
12
  def self.version
@@ -21,5 +21,10 @@ module Formats
21
21
  File.expand_path( File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) )
22
22
  end
23
23
 
24
+
25
+ def self.config_path
26
+ "#{root}/config"
27
+ end
28
+
24
29
  end # module Formats
25
30
  end # module SportDb