sportdb 1.8.3 → 1.8.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +7 -1
- data/lib/sportdb.rb +7 -1
- data/lib/sportdb/models/team.rb +19 -5
- data/lib/sportdb/models/world/city.rb +6 -1
- data/lib/sportdb/models/world/continent.rb +7 -1
- data/lib/sportdb/models/world/country.rb +6 -3
- data/lib/sportdb/models/world/region.rb +6 -2
- data/lib/sportdb/stats.rb +0 -5
- data/lib/sportdb/utils.rb +9 -529
- data/lib/sportdb/utils_date.rb +222 -0
- data/lib/sportdb/utils_group.rb +50 -0
- data/lib/sportdb/utils_map.rb +37 -0
- data/lib/sportdb/utils_record.rb +91 -0
- data/lib/sportdb/utils_round.rb +94 -0
- data/lib/sportdb/utils_scores.rb +91 -0
- data/lib/sportdb/utils_teams.rb +49 -0
- data/lib/sportdb/version.rb +2 -1
- metadata +19 -13
- data/lib/sportdb/title.rb +0 -146
data/Manifest.txt
CHANGED
@@ -75,9 +75,15 @@ lib/sportdb/service/views/debug.erb
|
|
75
75
|
lib/sportdb/service/views/index.erb
|
76
76
|
lib/sportdb/service/views/layout.erb
|
77
77
|
lib/sportdb/stats.rb
|
78
|
-
lib/sportdb/title.rb
|
79
78
|
lib/sportdb/updater.rb
|
80
79
|
lib/sportdb/utils.rb
|
80
|
+
lib/sportdb/utils_date.rb
|
81
|
+
lib/sportdb/utils_group.rb
|
82
|
+
lib/sportdb/utils_map.rb
|
83
|
+
lib/sportdb/utils_record.rb
|
84
|
+
lib/sportdb/utils_round.rb
|
85
|
+
lib/sportdb/utils_scores.rb
|
86
|
+
lib/sportdb/utils_teams.rb
|
81
87
|
lib/sportdb/version.rb
|
82
88
|
test/helper.rb
|
83
89
|
test/test_changes.rb
|
data/lib/sportdb.rb
CHANGED
@@ -29,7 +29,6 @@ require 'fetcher' # for fetching/downloading fixtures via HTTP/HTTPS etc.
|
|
29
29
|
|
30
30
|
require 'sportdb/version'
|
31
31
|
|
32
|
-
require 'sportdb/title' ## fix - move to textutils gem
|
33
32
|
require 'sportdb/models/forward'
|
34
33
|
require 'sportdb/models/world/city'
|
35
34
|
require 'sportdb/models/world/country'
|
@@ -65,6 +64,13 @@ end
|
|
65
64
|
|
66
65
|
require 'sportdb/schema' # NB: requires sportdb/models (include SportDB::Models)
|
67
66
|
require 'sportdb/utils'
|
67
|
+
require 'sportdb/utils_date'
|
68
|
+
require 'sportdb/utils_group'
|
69
|
+
require 'sportdb/utils_map'
|
70
|
+
require 'sportdb/utils_record'
|
71
|
+
require 'sportdb/utils_round'
|
72
|
+
require 'sportdb/utils_scores'
|
73
|
+
require 'sportdb/utils_teams'
|
68
74
|
require 'sportdb/reader'
|
69
75
|
require 'sportdb/lang'
|
70
76
|
|
data/lib/sportdb/models/team.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
module SportDb::Model
|
2
2
|
|
3
|
+
##################
|
4
|
+
# FIX: add ?
|
5
|
+
#
|
6
|
+
# use single table inheritance STI ????
|
7
|
+
# - to mark two dervided classes e.g.
|
8
|
+
# - Club ??? - why? why not?
|
9
|
+
# - NationalTeam ??? - why? why not?
|
10
|
+
|
3
11
|
|
4
12
|
class Team < ActiveRecord::Base
|
5
13
|
|
6
|
-
has_many :home_games, :
|
7
|
-
has_many :away_games, :
|
14
|
+
has_many :home_games, class_name: 'Game', foreign_key: 'team1_id'
|
15
|
+
has_many :away_games, class_name: 'Game', foreign_key: 'team2_id'
|
8
16
|
|
9
17
|
REGEX_KEY = /^[a-z]{3,}$/
|
10
18
|
REGEX_CODE = /^[A-Z][A-Z0-9][A-Z0-9_]?$/ # must start w/ letter a-z (2 n 3 can be number or underscore _)
|
@@ -13,10 +21,16 @@ class Team < ActiveRecord::Base
|
|
13
21
|
validates :key, :format => { :with => REGEX_KEY, :message => 'expected three or more lowercase letters a-z' }
|
14
22
|
validates :code, :format => { :with => REGEX_CODE, :message => 'expected two or three uppercase letters A-Z (and 0-9_; must start with A-Z)' }, :allow_nil => true
|
15
23
|
|
16
|
-
has_many :event_teams, :
|
24
|
+
has_many :event_teams, class_name: 'EventTeam' # join table (events+teams)
|
17
25
|
has_many :events, :through => :event_teams
|
18
26
|
|
27
|
+
|
19
28
|
### fix!!! - how to do it with has_many macro? use finder_sql?
|
29
|
+
## finder_sql is depreciated in Rails 4!!!
|
30
|
+
## keep as is! best solution ??
|
31
|
+
## a discussion here -> https://github.com/rails/rails/issues/9726
|
32
|
+
## a discussion here (not really helpful) -> http://stackoverflow.com/questions/2125440/activerecord-has-many-where-two-columns-in-table-a-are-primary-keys-in-table-b
|
33
|
+
|
20
34
|
def games
|
21
35
|
Game.where( 'team1_id = ? or team2_id = ?', id, id ).order( 'play_at' )
|
22
36
|
end
|
@@ -32,8 +46,8 @@ class Team < ActiveRecord::Base
|
|
32
46
|
|
33
47
|
has_many :badges # Winner, 2nd, Cupsieger, Aufsteiger, Absteiger, etc.
|
34
48
|
|
35
|
-
belongs_to :country, :
|
36
|
-
belongs_to :city, :
|
49
|
+
belongs_to :country, class_name: 'WorldDb::Model::Country', foreign_key: 'country_id'
|
50
|
+
belongs_to :city, class_name: 'WorldDb::Model::City', foreign_key: 'city_id'
|
37
51
|
|
38
52
|
|
39
53
|
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
## todo: how to best extends city model?
|
4
3
|
|
5
4
|
module WorldDb::Model
|
6
5
|
|
7
6
|
class City
|
8
7
|
has_many :teams, class_name: 'SportDb::Model::Team', foreign_key: 'city_id'
|
8
|
+
|
9
|
+
# fix: require active record 4
|
10
|
+
# has_many :clubs, -> { where club: true }, class_name: 'SportDb::Model::Team', foreign_key: 'city_id'
|
11
|
+
# has_many :national_teams, -> { where club: false }, class_name: 'SportDb::Model::Team', foreign_key: 'city_id'
|
12
|
+
|
13
|
+
|
9
14
|
has_many :grounds, class_name: 'SportDb::Model::Ground', foreign_key: 'city_id'
|
10
15
|
has_many :games, :through => :grounds
|
11
16
|
end
|
@@ -3,7 +3,13 @@
|
|
3
3
|
module WorldDb::Model
|
4
4
|
|
5
5
|
class Continent
|
6
|
-
has_many :teams,
|
6
|
+
has_many :teams, :through => :countries
|
7
|
+
|
8
|
+
# fix: require active record 4
|
9
|
+
# has_many :clubs, :through => :countries
|
10
|
+
# has_many :national_teams, :through => :countries
|
11
|
+
|
12
|
+
|
7
13
|
has_many :leagues, :through => :countries
|
8
14
|
has_many :grounds, :through => :countries
|
9
15
|
end # class Continent
|
@@ -1,11 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
## todo: how to best extends country model?
|
4
|
-
|
5
3
|
module WorldDb::Model
|
6
4
|
|
7
5
|
class Country
|
8
|
-
has_many :teams,
|
6
|
+
has_many :teams, class_name: 'SportDb::Model::Team', foreign_key: 'country_id'
|
7
|
+
|
8
|
+
# fix: require active record 4
|
9
|
+
# has_many :clubs, -> { where club: true }, class_name: 'SportDb::Model::Team', foreign_key: 'country_id'
|
10
|
+
# has_many :national_teams, -> { where club: false }, class_name: 'SportDb::Model::Team', foreign_key: 'country_id'
|
11
|
+
|
9
12
|
has_many :leagues, class_name: 'SportDb::Model::League', foreign_key: 'country_id'
|
10
13
|
has_many :grounds, class_name: 'SportDb::Model::Ground', foreign_key: 'country_id'
|
11
14
|
end # class Country
|
@@ -1,11 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
## todo: how to best extends country model?
|
4
3
|
|
5
4
|
module WorldDb::Model
|
6
5
|
|
7
6
|
class Region
|
8
|
-
has_many :teams,
|
7
|
+
has_many :teams, class_name: 'SportDb::Model::Team', :through => :cities
|
8
|
+
|
9
|
+
# fix: require active record 4
|
10
|
+
# has_many :clubs, class_name: 'SportDb::Model::Team', :through => :cities
|
11
|
+
# has_many :national_teams, class_name: 'SportDb::Model::Team', :through => :cities
|
12
|
+
|
9
13
|
has_many :grounds, class_name: 'SportDb::Model::Ground', :through => :cities
|
10
14
|
end # class Region
|
11
15
|
|
data/lib/sportdb/stats.rb
CHANGED
@@ -5,7 +5,6 @@ module SportDb
|
|
5
5
|
include SportDb::Models
|
6
6
|
|
7
7
|
def tables
|
8
|
-
puts "Stats:"
|
9
8
|
puts " #{League.count} leagues / #{Season.count} seasons"
|
10
9
|
puts " #{Event.count} events (league+season recs) / #{Round.count} rounds / #{Group.count} groups"
|
11
10
|
puts " #{Team.count} teams"
|
@@ -18,10 +17,6 @@ module SportDb
|
|
18
17
|
puts " #{Goal.count} goals (person+game recs)"
|
19
18
|
|
20
19
|
puts " #{Ground.count} grounds|stadiums"
|
21
|
-
|
22
|
-
puts " #{Country.count} countries / #{Region.count} regions / #{City.count} cities"
|
23
|
-
|
24
|
-
## todo: add tags / taggings from worlddb
|
25
20
|
end
|
26
21
|
|
27
22
|
def props
|
data/lib/sportdb/utils.rb
CHANGED
@@ -3,76 +3,15 @@
|
|
3
3
|
### note: some utils moved to worldbdb/utils for reuse
|
4
4
|
|
5
5
|
|
6
|
-
|
6
|
+
####
|
7
|
+
## move to folder matcher(s)/finder(s)
|
8
|
+
# -- rename to FixtureFinder or FixtureFinders
|
9
|
+
# or just GeneralFinder
|
10
|
+
# TeamFinder etc. ???
|
7
11
|
|
8
|
-
def is_postponed?( line )
|
9
|
-
# check if line include postponed marker e.g. =>
|
10
|
-
line =~ /=>/
|
11
|
-
end
|
12
|
-
|
13
|
-
def is_round?( line )
|
14
|
-
line =~ SportDb.lang.regex_round
|
15
|
-
end
|
16
|
-
|
17
|
-
def is_group?( line )
|
18
|
-
# NB: check after is_round? (round may contain group reference!)
|
19
|
-
line =~ SportDb.lang.regex_group
|
20
|
-
end
|
21
|
-
|
22
|
-
def is_knockout_round?( line )
|
23
|
-
|
24
|
-
## todo: check for adding ignore case for regex (e.g. 1st leg/1st Leg)
|
25
|
-
|
26
|
-
if line =~ SportDb.lang.regex_leg1
|
27
|
-
logger.debug " two leg knockout; skip knockout flag on first leg"
|
28
|
-
false
|
29
|
-
elsif line =~ SportDb.lang.regex_knockout_round
|
30
|
-
logger.debug " setting knockout flag to true"
|
31
|
-
true
|
32
|
-
elsif line =~ /K\.O\.|K\.o\.|Knockout/
|
33
|
-
## NB: add two language independent markers, that is, K.O. and Knockout
|
34
|
-
logger.debug " setting knockout flag to true (lang independent marker)"
|
35
|
-
true
|
36
|
-
else
|
37
|
-
false
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def find_group_title_and_pos!( line )
|
42
|
-
## group pos - for now support single digit e.g 1,2,3 or letter e.g. A,B,C or HEX
|
43
|
-
## nb: (?:) = is for non-capturing group(ing)
|
44
|
-
regex = /(?:Group|Gruppe|Grupo)\s+((?:\d{1}|[A-Z]{1,3}))\b/
|
45
|
-
|
46
|
-
match = regex.match( line )
|
47
|
-
|
48
|
-
return [nil,nil] if match.nil?
|
49
|
-
|
50
|
-
pos = case match[1]
|
51
|
-
when 'A' then 1
|
52
|
-
when 'B' then 2
|
53
|
-
when 'C' then 3
|
54
|
-
when 'D' then 4
|
55
|
-
when 'E' then 5
|
56
|
-
when 'F' then 6
|
57
|
-
when 'G' then 7
|
58
|
-
when 'H' then 8
|
59
|
-
when 'I' then 9
|
60
|
-
when 'J' then 10
|
61
|
-
when 'K' then 11
|
62
|
-
when 'L' then 12
|
63
|
-
when 'HEX' then 666 # HEX for Hexagonal - todo/check: map to something else ??
|
64
|
-
else match[1].to_i
|
65
|
-
end
|
66
|
-
|
67
|
-
title = match[0]
|
68
12
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
line.sub!( regex, '[GROUP|TITLE+POS]' )
|
73
|
-
|
74
|
-
return [title,pos]
|
75
|
-
end
|
13
|
+
module SportDb
|
14
|
+
module FixtureHelpers
|
76
15
|
|
77
16
|
|
78
17
|
def cut_off_end_of_line_comment!( line )
|
@@ -86,315 +25,6 @@ module SportDb::FixtureHelpers
|
|
86
25
|
# NB: line = line.sub will NOT work - thus, lets use line.sub!
|
87
26
|
end
|
88
27
|
|
89
|
-
|
90
|
-
def find_round_title2!( line )
|
91
|
-
# assume everything after // is title2 - strip off leading n trailing whitespaces
|
92
|
-
regex = /\/{2,}\s*(.+)\s*$/
|
93
|
-
if line =~ regex
|
94
|
-
logger.debug " title2: >#{$1}<"
|
95
|
-
|
96
|
-
line.sub!( regex, '[ROUND|TITLE2]' )
|
97
|
-
return $1
|
98
|
-
else
|
99
|
-
return nil # no round title2 found (title2 is optional)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
def find_round_title!( line )
|
105
|
-
# assume everything left is the round title
|
106
|
-
# extract all other items first (round title2, round pos, group title n pos, etc.)
|
107
|
-
|
108
|
-
buf = line.dup
|
109
|
-
logger.debug " find_round_title! line-before: >>#{buf}<<"
|
110
|
-
|
111
|
-
buf.gsub!( /\[.+?\]/, '' ) # e.g. remove [ROUND|POS], [ROUND|TITLE2], [GROUP|TITLE+POS] etc.
|
112
|
-
buf.sub!( /\s+[\/\-]{1,}\s+$/, '' ) # remove optional trailing / or / chars (left over from group)
|
113
|
-
buf.strip! # remove leading and trailing whitespace
|
114
|
-
|
115
|
-
logger.debug " find_round_title! line-after: >>#{buf}<<"
|
116
|
-
|
117
|
-
### bingo - assume what's left is the round title
|
118
|
-
|
119
|
-
logger.debug " title: >>#{buf}<<"
|
120
|
-
line.sub!( buf, '[ROUND|TITLE]' )
|
121
|
-
|
122
|
-
buf
|
123
|
-
end
|
124
|
-
|
125
|
-
|
126
|
-
def find_round_pos!( line )
|
127
|
-
## fix/todo:
|
128
|
-
## if no round found assume last_pos+1 ??? why? why not?
|
129
|
-
|
130
|
-
# extract optional round pos from line
|
131
|
-
# e.g. (1) - must start line
|
132
|
-
regex_pos = /^[ \t]*\((\d{1,3})\)[ \t]+/
|
133
|
-
|
134
|
-
## find free standing number
|
135
|
-
regex_num = /\b(\d{1,3})\b/
|
136
|
-
|
137
|
-
if line =~ regex_pos
|
138
|
-
logger.debug " pos: >#{$1}<"
|
139
|
-
|
140
|
-
line.sub!( regex_pos, '[ROUND|POS] ' ) ## NB: add back trailing space that got swallowed w/ regex -> [ \t]+
|
141
|
-
return $1.to_i
|
142
|
-
elsif line =~ regex_num
|
143
|
-
## assume number in title is pos (e.g. Jornada 3, 3 Runde etc.)
|
144
|
-
## NB: do NOT remove pos from string (will get removed by round title)
|
145
|
-
logger.debug " pos: >#{$1}<"
|
146
|
-
return $1.to_i
|
147
|
-
else
|
148
|
-
## fix: add logger.warn no round pos found in line
|
149
|
-
return nil
|
150
|
-
end
|
151
|
-
end # method find_round_pos!
|
152
|
-
|
153
|
-
|
154
|
-
def calculate_year( day, month, start_at )
|
155
|
-
if month >= start_at.month
|
156
|
-
# assume same year as start_at event (e.g. 2013 for 2013/14 season)
|
157
|
-
start_at.year
|
158
|
-
else
|
159
|
-
# assume year+1 as start_at event (e.g. 2014 for 2013/14 season)
|
160
|
-
start_at.year+1
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def find_date!( line, opts={} )
|
165
|
-
|
166
|
-
## NB: lets us pass in start_at/end_at date (for event)
|
167
|
-
# for auto-complete year
|
168
|
-
|
169
|
-
# extract date from line
|
170
|
-
# and return it
|
171
|
-
# NB: side effect - removes date from line string
|
172
|
-
|
173
|
-
# e.g. 2012-09-14 20:30 => YYYY-MM-DD HH:MM
|
174
|
-
# nb: allow 2012-9-3 7:30 e.g. no leading zero required
|
175
|
-
regex_db = /\b(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{2})\b/
|
176
|
-
|
177
|
-
# e.g. 2012-09-14 w/ implied hours (set to 12:00)
|
178
|
-
# nb: allow 2012-9-3 e.g. no leading zero required
|
179
|
-
regex_db2 = /\b(\d{4})-(\d{1,2})-(\d{1,2})\b/
|
180
|
-
|
181
|
-
# e.g. 14.09. 20:30 => DD.MM. HH:MM
|
182
|
-
# nb: allow 2.3.2012 e.g. no leading zero required
|
183
|
-
# nb: allow hour as 20.30 or 3.30 instead of 03.30
|
184
|
-
regex_de = /\b(\d{1,2})\.(\d{1,2})\.\s+(\d{1,2})[:.](\d{2})\b/
|
185
|
-
|
186
|
-
# e.g. 14.09.2012 20:30 => DD.MM.YYYY HH:MM
|
187
|
-
# nb: allow 2.3.2012 e.g. no leading zero required
|
188
|
-
# nb: allow hour as 20.30
|
189
|
-
regex_de2 = /\b(\d{1,2})\.(\d{1,2})\.(\d{4})\s+(\d{1,2})[:.](\d{2})\b/
|
190
|
-
|
191
|
-
# e.g. 14.09.2012 => DD.MM.YYYY w/ implied hours (set to 12:00)
|
192
|
-
regex_de3 = /\b(\d{1,2})\.(\d{1,2})\.(\d{4})\b/
|
193
|
-
|
194
|
-
# e.g. 14.09. => DD.MM. w/ implied year and implied hours (set to 12:00)
|
195
|
-
regex_de4 = /\b(\d{1,2})\.(\d{1,2})\.\s+/
|
196
|
-
|
197
|
-
|
198
|
-
month_abbrev_en = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"
|
199
|
-
|
200
|
-
# e.g. 12 May 2013 14:00 => D|DD.MMM.YYYY H|HH:MM
|
201
|
-
regex_en = /\b(\d{1,2})\s(#{month_abbrev_en})\s(\d{4})\s+(\d{1,2}):(\d{2})\b/
|
202
|
-
|
203
|
-
## todo: add version w/ hours
|
204
|
-
# e.g. Jun/12 w/ implied year and implied hours (set to 12:00)
|
205
|
-
regex_en2 = /\b(#{month_abbrev_en})\/(\d{1,2})\b/
|
206
|
-
|
207
|
-
|
208
|
-
if line =~ regex_db
|
209
|
-
value = '%d-%02d-%02d %02d:%02d' % [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i]
|
210
|
-
logger.debug " date: >#{value}<"
|
211
|
-
|
212
|
-
## todo: lets you configure year
|
213
|
-
## and time zone (e.g. cet, eet, utc, etc.)
|
214
|
-
|
215
|
-
line.sub!( regex_db, '[DATE.DB]' )
|
216
|
-
|
217
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
218
|
-
elsif line =~ regex_db2
|
219
|
-
value = '%d-%02d-%02d 12:00' % [$1.to_i, $2.to_i, $3.to_i]
|
220
|
-
logger.debug " date: >#{value}<"
|
221
|
-
|
222
|
-
line.sub!( regex_db2, '[DATE.DB2]' )
|
223
|
-
|
224
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
225
|
-
elsif line =~ regex_de2
|
226
|
-
value = '%d-%02d-%02d %02d:%02d' % [$3.to_i, $2.to_i, $1.to_i, $4.to_i, $5.to_i]
|
227
|
-
logger.debug " date: >#{value}<"
|
228
|
-
|
229
|
-
## todo: lets you configure year
|
230
|
-
## and time zone (e.g. cet, eet, utc, etc.)
|
231
|
-
|
232
|
-
line.sub!( regex_de2, '[DATE.DE2]' )
|
233
|
-
|
234
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
235
|
-
elsif line =~ regex_de
|
236
|
-
|
237
|
-
year = calculate_year( $1.to_i, $2.to_i, opts[:start_at] )
|
238
|
-
|
239
|
-
value = '%d-%02d-%02d %02d:%02d' % [year, $2.to_i, $1.to_i, $3.to_i, $4.to_i]
|
240
|
-
logger.debug " date: >#{value}<"
|
241
|
-
|
242
|
-
## todo: lets you configure year
|
243
|
-
## and time zone (e.g. cet, eet, utc, etc.)
|
244
|
-
|
245
|
-
line.sub!( regex_de, '[DATE.DE]' )
|
246
|
-
|
247
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
248
|
-
elsif line =~ regex_de3
|
249
|
-
value = '%d-%02d-%02d 12:00' % [$3.to_i, $2.to_i, $1.to_i]
|
250
|
-
logger.debug " date: >#{value}<"
|
251
|
-
|
252
|
-
## todo: lets you configure year
|
253
|
-
## and time zone (e.g. cet, eet, utc, etc.)
|
254
|
-
|
255
|
-
line.sub!( regex_de3, '[DATE.DE3]' )
|
256
|
-
|
257
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
258
|
-
elsif line =~ regex_de4
|
259
|
-
|
260
|
-
year = calculate_year( $1.to_i, $2.to_i, opts[:start_at] )
|
261
|
-
|
262
|
-
value = '%d-%02d-%02d 12:00' % [year, $2.to_i, $1.to_i]
|
263
|
-
logger.debug " date: >#{value}<"
|
264
|
-
|
265
|
-
## todo: lets you configure year
|
266
|
-
## and time zone (e.g. cet, eet, utc, etc.)
|
267
|
-
|
268
|
-
### NOTE: needs a trailing space
|
269
|
-
# not if regex ends w/ whitespace e.g. /s+
|
270
|
-
# make sure sub! adds a space at the end
|
271
|
-
# e.g. '[DATE.DE4]' becomes '[DATE.DE4] '
|
272
|
-
|
273
|
-
line.sub!( regex_de4, '[DATE.DE4] ' )
|
274
|
-
|
275
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
276
|
-
elsif line =~ regex_en
|
277
|
-
value = '%d-%s-%02d %02d:%02d' % [$3.to_i, $2, $1.to_i, $4.to_i, $5.to_i]
|
278
|
-
logger.debug " date: >#{value}<"
|
279
|
-
|
280
|
-
line.sub!( regex_en, '[DATE.EN]' )
|
281
|
-
|
282
|
-
return DateTime.strptime( value, '%Y-%b-%d %H:%M' ) ## %b - abbreviated month name (e.g. Jan,Feb, etc.)
|
283
|
-
elsif line =~ regex_en2
|
284
|
-
# todo: make more generic for reuse
|
285
|
-
month_abbrev_en_to_i = {
|
286
|
-
'Jan' => 1,
|
287
|
-
'Feb' => 2,
|
288
|
-
'Mar' => 3,
|
289
|
-
'Apr' => 4,
|
290
|
-
'May' => 5,
|
291
|
-
'Jun' => 6,
|
292
|
-
'Jul' => 7,
|
293
|
-
'Aug' => 8,
|
294
|
-
'Sep' => 9,
|
295
|
-
'Oct' => 10,
|
296
|
-
'Nov' => 11,
|
297
|
-
'Dec' => 12 }
|
298
|
-
|
299
|
-
day = $2.to_i
|
300
|
-
month = month_abbrev_en_to_i[ $1 ]
|
301
|
-
year = calculate_year( day, month, opts[:start_at] )
|
302
|
-
|
303
|
-
value = '%d-%02d-%02d 12:00' % [year, month, day]
|
304
|
-
logger.debug " date: >#{value}<"
|
305
|
-
|
306
|
-
line.sub!( regex_en2, '[DATE.EN2] ' )
|
307
|
-
|
308
|
-
return DateTime.strptime( value, '%Y-%m-%d %H:%M' )
|
309
|
-
else
|
310
|
-
return nil
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
|
315
|
-
def find_record_comment!( line )
|
316
|
-
# assume everything left after the last record marker,that is, ] is a record comment
|
317
|
-
|
318
|
-
regex = /]([^\]]+?)$/ # NB: use non-greedy +?
|
319
|
-
|
320
|
-
if line =~ regex
|
321
|
-
value = $1.strip
|
322
|
-
return nil if value.blank? # skip whitespaces only
|
323
|
-
|
324
|
-
logger.debug " comment: >#{value}<"
|
325
|
-
|
326
|
-
line.sub!( value, '[REC.COMMENT] ' )
|
327
|
-
return value
|
328
|
-
else
|
329
|
-
return nil
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
|
334
|
-
def find_record_timeline!( line )
|
335
|
-
|
336
|
-
# +1 lap or +n laps
|
337
|
-
regex_laps = /\s+\+\d{1,2}\s(lap|laps)\b/
|
338
|
-
|
339
|
-
# 2:17:15.123
|
340
|
-
regex_time = /\b\d{1,2}:\d{2}:\d{2}\.\d{1,3}\b/
|
341
|
-
|
342
|
-
# +40.1 secs
|
343
|
-
regex_secs = /\s+\+\d{1,3}\.\d{1,3}\s(secs)\b/ # NB: before \+ - boundry (\b) will not work
|
344
|
-
|
345
|
-
# NB: $& contains the complete matched text
|
346
|
-
|
347
|
-
if line =~ regex_laps
|
348
|
-
value = $&.strip
|
349
|
-
logger.debug " timeline.laps: >#{value}<"
|
350
|
-
|
351
|
-
line.sub!( value, '[REC.TIMELINE.LAPS] ' ) # NB: add trailing space
|
352
|
-
return value
|
353
|
-
elsif line =~ regex_time
|
354
|
-
value = $&.strip
|
355
|
-
logger.debug " timeline.time: >#{value}<"
|
356
|
-
|
357
|
-
line.sub!( value, '[REC.TIMELINE.TIME] ' ) # NB: add trailing space
|
358
|
-
return value
|
359
|
-
elsif line =~ regex_secs
|
360
|
-
value = $&.strip
|
361
|
-
logger.debug " timeline.secs: >#{value}<"
|
362
|
-
|
363
|
-
line.sub!( value, '[REC.TIMELINE.SECS] ' ) # NB: add trailing space
|
364
|
-
return value
|
365
|
-
else
|
366
|
-
return nil
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
def find_record_laps!( line )
|
371
|
-
# e.g. first free-standing number w/ one or two digits e.g. 7 or 28 etc.
|
372
|
-
regex = /\b(\d{1,2})\b/
|
373
|
-
if line =~ regex
|
374
|
-
logger.debug " laps: >#{$1}<"
|
375
|
-
|
376
|
-
line.sub!( regex, '[REC.LAPS] ' ) # NB: add trailing space
|
377
|
-
return $1.to_i
|
378
|
-
else
|
379
|
-
return nil
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
def find_record_leading_state!( line )
|
384
|
-
# e.g. 1|2|3|etc or Ret - must start line
|
385
|
-
regex = /^[ \t]*(\d{1,3}|Ret)[ \t]+/
|
386
|
-
if line =~ regex
|
387
|
-
value = $1.dup
|
388
|
-
logger.debug " state: >#{value}<"
|
389
|
-
|
390
|
-
line.sub!( regex, '[REC.STATE] ' ) # NB: add trailing space
|
391
|
-
return value
|
392
|
-
else
|
393
|
-
return nil
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
|
398
28
|
def find_leading_pos!( line )
|
399
29
|
# extract optional game pos from line
|
400
30
|
# and return it
|
@@ -418,156 +48,6 @@ module SportDb::FixtureHelpers
|
|
418
48
|
end
|
419
49
|
|
420
50
|
|
421
|
-
def find_scores!( line )
|
422
|
-
|
423
|
-
# note: always call after find_dates !!!
|
424
|
-
# scores match date-like patterns!! e.g. 10-11 or 10:00 etc.
|
425
|
-
# -- note: score might have two digits too
|
426
|
-
|
427
|
-
### fix: depending on language allow 1:1 or 1-1
|
428
|
-
## do NOT allow mix and match
|
429
|
-
## e.g. default to en is 1-1
|
430
|
-
## de is 1:1 etc.
|
431
|
-
|
432
|
-
|
433
|
-
# extract score from line
|
434
|
-
# and return it
|
435
|
-
# NB: side effect - removes date from line string
|
436
|
-
|
437
|
-
# note: regex should NOT match regex extra time or penalty
|
438
|
-
# thus, we do NOT any longer allow spaces for now between
|
439
|
-
# score and marker (e.g. nV,iE, etc.)
|
440
|
-
|
441
|
-
# e.g. 1:2 or 0:2 or 3:3 // 1-1 or 0-2 or 3-3
|
442
|
-
regex = /\b(\d{1,2})[:\-](\d{1,2})\b/
|
443
|
-
|
444
|
-
## todo: add/allow english markers e.g. aet ??
|
445
|
-
|
446
|
-
## fix: use case insansitive flag instead e.g. /i
|
447
|
-
# instead of [nN] etc.
|
448
|
-
|
449
|
-
# e.g. 1:2nV => after extra time a.e.t
|
450
|
-
regex_et = /\b(\d{1,2})[:\-](\d{1,2})[nN][vV]\b/
|
451
|
-
|
452
|
-
# e.g. 5:4iE => penalty / after penalty a.p
|
453
|
-
regex_p = /\b(\d{1,2})[:\-](\d{1,2})[iI][eE]\b/
|
454
|
-
|
455
|
-
scores = []
|
456
|
-
|
457
|
-
## todo: how to handle game w/o extra time
|
458
|
-
# but w/ optional penalty ??? e.g. used in copa liberatores, for example
|
459
|
-
# retrun 0,0 or nil,nil for extra time score ?? or -1, -1 ??
|
460
|
-
# for now use nil,nil
|
461
|
-
|
462
|
-
if line =~ regex
|
463
|
-
logger.debug " score: >#{$1}-#{$2}<"
|
464
|
-
|
465
|
-
line.sub!( regex, '[SCORE]' )
|
466
|
-
|
467
|
-
scores << $1.to_i
|
468
|
-
scores << $2.to_i
|
469
|
-
end
|
470
|
-
|
471
|
-
## todo:
|
472
|
-
## reverse matching order ??? allows us to support spaces for nV and iE
|
473
|
-
## why? why not??
|
474
|
-
|
475
|
-
if line =~ regex_et
|
476
|
-
logger.debug " score.et: >#{$1}-#{$2}<"
|
477
|
-
|
478
|
-
line.sub!( regex_et, '[SCORE.ET]' )
|
479
|
-
|
480
|
-
## check scores empty? - fill with nil,nil
|
481
|
-
scores += [nil,nil] if scores.size == 0
|
482
|
-
|
483
|
-
scores << $1.to_i
|
484
|
-
scores << $2.to_i
|
485
|
-
end
|
486
|
-
|
487
|
-
if line =~ regex_p
|
488
|
-
logger.debug " score.p: >#{$1}-#{$2}<"
|
489
|
-
|
490
|
-
line.sub!( regex_p, '[SCORE.P]' )
|
491
|
-
|
492
|
-
## check scores empty? - fill with nil,nil
|
493
|
-
scores += [nil,nil] if scores.size == 0
|
494
|
-
scores += [nil,nil] if scores.size == 2
|
495
|
-
|
496
|
-
scores << $1.to_i
|
497
|
-
scores << $2.to_i
|
498
|
-
end
|
499
|
-
scores
|
500
|
-
end # methdod find_scores!
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
def find_teams!( line ) # NB: returns an array - note: plural! (teamsss)
|
505
|
-
TextUtils.find_keys_for!( 'team', line )
|
506
|
-
end
|
507
|
-
|
508
|
-
def find_team!( line ) # NB: returns key (string or nil)
|
509
|
-
TextUtils.find_key_for!( 'team', line )
|
510
|
-
end
|
511
|
-
|
512
|
-
## todo: check if find_team1 gets used? if not remove it!! use find_teams!
|
513
|
-
def find_team1!( line )
|
514
|
-
TextUtils.find_key_for!( 'team1', line )
|
515
|
-
end
|
516
|
-
|
517
|
-
def find_team2!( line )
|
518
|
-
TextUtils.find_key_for!( 'team2', line )
|
519
|
-
end
|
520
|
-
|
521
|
-
## todo/fix: pass in known_teams as a parameter? why? why not?
|
522
|
-
|
523
|
-
def map_teams!( line )
|
524
|
-
TextUtils.map_titles_for!( 'team', line, @known_teams )
|
525
|
-
end
|
526
|
-
|
527
|
-
def map_team!( line ) # alias map_teams!
|
528
|
-
map_teams!( line )
|
529
|
-
end
|
530
|
-
|
531
|
-
|
532
|
-
def find_ground!( line )
|
533
|
-
TextUtils.find_key_for!( 'ground', line )
|
534
|
-
end
|
535
|
-
|
536
|
-
## todo/fix: pass in known_grounds as a parameter? why? why not?
|
537
|
-
def map_ground!( line )
|
538
|
-
TextUtils.map_titles_for!( 'ground', line, @known_grounds )
|
539
|
-
end
|
540
|
-
|
541
|
-
|
542
|
-
def find_track!( line )
|
543
|
-
TextUtils.find_key_for!( 'track', line )
|
544
|
-
end
|
545
|
-
|
546
|
-
## todo/fix: pass in known_tracks as a parameter? why? why not?
|
547
|
-
def map_track!( line )
|
548
|
-
TextUtils.map_titles_for!( 'track', line, @known_tracks )
|
549
|
-
end
|
550
|
-
|
551
|
-
def find_person!( line )
|
552
|
-
TextUtils.find_key_for!( 'person', line )
|
553
|
-
end
|
554
|
-
|
555
|
-
def map_person!( line )
|
556
|
-
TextUtils.map_titles_for!( 'person', line, @known_persons)
|
557
|
-
end
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
## depreciated methods - use map_
|
562
|
-
def match_teams!( line ) ## fix: rename to map_teams!! - remove match_teams!
|
563
|
-
## todo: issue depreciated warning
|
564
|
-
map_teams!( line )
|
565
|
-
end # method match_teams!
|
566
|
-
|
567
|
-
def match_track!( line ) ## fix: rename to map_track!!!
|
568
|
-
## todo: issue depreciated warning
|
569
|
-
map_track!( line )
|
570
|
-
end # method match_tracks!
|
571
|
-
|
572
51
|
|
573
|
-
end # module
|
52
|
+
end # module FixtureHelpers
|
53
|
+
end # module SportDb
|