sportdb-formats 0.1.6 → 0.1.7

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: 2a60a673f546001d9e4314f6e958428f0f1bec3e
4
- data.tar.gz: 453cfbf74d9afaebd2e06a51d2ac68b698f09559
3
+ metadata.gz: 421d04b4b20f49a37bb1a31161bb4ab7b5df3113
4
+ data.tar.gz: e533ef2bb8dbb3c1053416c98ede4c9d20c42546
5
5
  SHA512:
6
- metadata.gz: 73282d87f64ec9c625dc6b0c3cce958b1a6b64fdb0f07fdb8bde5b13e5f7b1e00c932936c9c16094d0de722ce754e6cb1bc0ecb84469125d587892505b1d600e
7
- data.tar.gz: 9d2575ea54a05c38582fe1354b520042be013747dc21db283cf5d5930e67976aadec9901be090fa89024917fdc6f3caaeb3b2819a807a7bb1015f118a48468e5
6
+ metadata.gz: 6256ca94b85f87865a44b4f892273cb4c2c9f17e7847e765cd3c73f408a005907181e202ec201498fd3214a603aed6af33b4ecbcf4e2af43cca851f7b1ac9a09
7
+ data.tar.gz: 750122be629a4b902356d845658cfcccbb0403e75e3f713e1ff4bd0da4aefb6b2355bc828aecb8e21d20addb5bfb9c1924df58830eb85e4743aa340c560924df
data/Manifest.txt CHANGED
@@ -4,12 +4,16 @@ README.md
4
4
  Rakefile
5
5
  lib/sportdb/formats.rb
6
6
  lib/sportdb/formats/datafile.rb
7
+ lib/sportdb/formats/goals.rb
7
8
  lib/sportdb/formats/outline_reader.rb
9
+ lib/sportdb/formats/scores.rb
8
10
  lib/sportdb/formats/season_utils.rb
9
11
  lib/sportdb/formats/version.rb
10
12
  test/helper.rb
11
13
  test/test_csv_reader.rb
12
14
  test/test_datafile.rb
13
15
  test/test_datafile_match.rb
16
+ test/test_goals.rb
14
17
  test/test_outline_reader.rb
18
+ test/test_scores.rb
15
19
  test/test_season_utils.rb
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ Hoe.spec 'sportdb-formats' do
21
21
 
22
22
  self.extra_deps = [
23
23
  ['alphabets', '>= 0.1.0'],
24
- ['date-formats', '>= 0.2.1'],
24
+ ['date-formats', '>= 0.2.4'],
25
25
  ['csvreader', '>= 1.2.4'],
26
26
  ['sportdb-langs', '>= 0.0.1'],
27
27
  ]
@@ -0,0 +1,277 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+
6
+
7
+ class GoalsPlayerStruct
8
+ ##
9
+ # note: player with own goal (o.g) gets listed on other team
10
+ # (thus, player might have two entries if also scored for its own team)
11
+ #
12
+ attr_accessor :name
13
+ attr_accessor :minutes # ary of minutes e.g. 30', 45+2', 72'
14
+
15
+ def initialize
16
+ @minutes = []
17
+ end
18
+ end
19
+
20
+
21
+ class GoalsMinuteStruct
22
+ attr_accessor :minute, :offset
23
+ attr_accessor :penalty, :owngoal # flags
24
+
25
+ def initialize
26
+ @offset = 0
27
+ @penalty = false
28
+ @owngoal = false
29
+ end
30
+ end
31
+
32
+
33
+ class GoalStruct
34
+ ######
35
+ # flat struct for goals - one entry per goals
36
+ attr_accessor :name
37
+ attr_accessor :team # 1 or 2 ? check/todo: add team1 or team2 flag?
38
+ attr_accessor :minute, :offset
39
+ attr_accessor :penalty, :owngoal
40
+ attr_accessor :score1, :score2 # gets calculated
41
+
42
+ ## add pos for sequence number? e.g. 1,2,3,4 (1st goald, 2nd goal, etc.) ???
43
+
44
+
45
+ def initialize( **kwargs ) ## add/allow quick and dirty quick init with keywords
46
+ if kwargs.empty?
47
+ # do nothing
48
+ else
49
+ kwargs.each do |key,value|
50
+ send( "#{key}=", value )
51
+ end
52
+ end
53
+ end
54
+
55
+ def ==(o)
56
+ o.class == self.class && o.state == state
57
+ end
58
+
59
+ def state
60
+ [@name, @team, @minute, @offset, @penalty, @owngoal, @score1, @score2]
61
+ end
62
+ end
63
+
64
+
65
+
66
+ # todo: find a better name? to avoid confusing w/ GoalsParser? use MatchGoalsParser or similar?
67
+ class GoalsFinder
68
+ include LogUtils::Logging
69
+
70
+
71
+ def initialize
72
+ # nothing here for now
73
+ end
74
+
75
+ def find!( line, opts={} )
76
+ # remove end-of-line comments
77
+ line = line.sub( /#.*$/ ) do |_|
78
+ logger.debug " cutting off end of line comment - >>#{$&}<<"
79
+ ''
80
+ end
81
+
82
+ # remove [] if presents e.g. [Neymar 12']
83
+ line = line.gsub( /[\[\]]/, '' )
84
+ # remove (single match) if line starts w/ - (allow spaces) e.g. [-;Neymar 12'] or [ - ;Neymar 12']
85
+ line = line.sub( /^[ ]*-[ ]*/, '' )
86
+
87
+ # split into left hand side (lhs) for team1 and
88
+ # right hand side (rhs) for team2
89
+
90
+ values = line.split( ';' )
91
+
92
+ # note: allow empty right hand side (e.g. team2 did NOT score any goals e.g. 3-0 etc.)
93
+ lhs = values[0]
94
+ rhs = values[1]
95
+
96
+ lhs = lhs.strip unless lhs.nil?
97
+ rhs = rhs.strip unless rhs.nil?
98
+
99
+ parser = GoalsParser.new
100
+ ## todo/check: only call if not nil?
101
+
102
+ logger.debug " lhs (team1): >#{lhs}<"
103
+ lhs_data = parser.parse!( lhs )
104
+ pp lhs_data
105
+
106
+ logger.debug " rhs (team2): >#{rhs}<"
107
+ rhs_data = parser.parse!( rhs )
108
+ pp rhs_data
109
+
110
+ ### merge into flat goal structs
111
+ goals = []
112
+ lhs_data.each do |player|
113
+ player.minutes.each do |minute|
114
+ goal = GoalStruct.new
115
+ goal.name = player.name
116
+ goal.team = 1
117
+ goal.minute = minute.minute
118
+ goal.offset = minute.offset
119
+ goal.penalty = minute.penalty
120
+ goal.owngoal = minute.owngoal
121
+ goals << goal
122
+ end
123
+ end
124
+
125
+ rhs_data.each do |player|
126
+ player.minutes.each do |minute|
127
+ goal = GoalStruct.new
128
+ goal.name = player.name
129
+ goal.team = 2
130
+ goal.minute = minute.minute
131
+ goal.offset = minute.offset
132
+ goal.penalty = minute.penalty
133
+ goal.owngoal = minute.owngoal
134
+ goals << goal
135
+ end
136
+ end
137
+
138
+
139
+ # sort by minute + offset
140
+ goals = goals.sort do |l,r|
141
+ res = l.minute <=> r.minute
142
+ if res == 0
143
+ res = l.offset <=> r.offset # pass 2: sort by offset
144
+ end
145
+ res
146
+ end
147
+
148
+ ## calc score1,score2
149
+ score1 = 0
150
+ score2 = 0
151
+ goals.each do |goal|
152
+ if goal.team == 1
153
+ score1 += 1
154
+ elsif goal.team == 2
155
+ score2 += 1
156
+ else
157
+ # todo: should not happen: issue warning
158
+ end
159
+ goal.score1 = score1
160
+ goal.score2 = score2
161
+ end
162
+
163
+ logger.debug " #{goals.size} goals:"
164
+ pp goals
165
+
166
+ goals
167
+ end
168
+
169
+ end # class GoalsFinder
170
+
171
+
172
+ class GoalsParser
173
+ include LogUtils::Logging
174
+
175
+
176
+ # note: use ^ for start of string only!!!
177
+ # - for now slurp everything up to digits (inlc. spaces - use strip to remove)
178
+ # todo/check: use/rename to NAME_UNTIL_REGEX ??? ( add lookahead for spaces?)
179
+ NAME_REGEX = /^
180
+ [^0-9]+
181
+ /x
182
+
183
+
184
+ # todo/check: change to MINUTE_REGEX ??
185
+ # add MINUTE_SKIP_REGEX or MINUTE_SEP_REGEX /^[ ,]+/
186
+ # todo/fix: split out penalty and owngoal flag in PATTERN constant for reuse
187
+ MINUTES_REGEX = /^ # note: use ^ for start of string only!!!
188
+ (?<minute>[0-9]{1,3})
189
+ (?:\+
190
+ (?<offset>[1-9]{1})
191
+ )?
192
+ '
193
+ (?:[ ]*
194
+ \(
195
+ (?<type>P|pen\.|o\.g\.)
196
+ \)
197
+ )?
198
+ /x
199
+
200
+
201
+
202
+ def initialize
203
+ # nothing here for now
204
+ end
205
+
206
+ def parse!( line, opts={} )
207
+
208
+ ## for now assume
209
+ ## everything up-to 0-9 and , and () is part of player name
210
+
211
+ ## try parsing lhs
212
+ ## todo: check for empty - remove (make it same as empty string)
213
+
214
+ players = []
215
+
216
+ name = get_player_name!( line )
217
+ while name
218
+ logger.debug " found player name >#{name}< - remaining >#{line}<"
219
+
220
+ player = GoalsPlayerStruct.new
221
+ player.name = name
222
+
223
+ minute_hash = get_minute_hash!( line )
224
+ while minute_hash
225
+ logger.debug " found minutes >#{minute_hash.inspect}< - remaining >#{line}<"
226
+
227
+ minute = GoalsMinuteStruct.new
228
+ minute.minute = minute_hash[:minute].to_i
229
+ minute.offset = minute_hash[:offset].to_i if minute_hash[:offset]
230
+ if minute_hash[:type]
231
+ minute.owngoal = true if minute_hash[:type] =~ /o\.g\./
232
+ minute.penalty = true if minute_hash[:type] =~ /P|pen\./
233
+ end
234
+ player.minutes << minute
235
+
236
+ # remove commas and spaces (note: use ^ for start of string only!!!)
237
+ line.sub!( /^[ ,]+/, '' )
238
+ minute_hash = get_minute_hash!( line )
239
+ end
240
+
241
+ players << player
242
+ name = get_player_name!( line )
243
+ end
244
+
245
+ players
246
+ end # method parse!
247
+
248
+ private
249
+ def get_player_name!( line )
250
+ m = NAME_REGEX.match( line )
251
+ if m
252
+ ## remove from line
253
+ line.slice!( 0...m[0].length )
254
+ m[0].strip # remove leading and trailing spaces
255
+ else
256
+ nil
257
+ end
258
+ end
259
+
260
+ def get_minute_hash!( line )
261
+ m = MINUTES_REGEX.match( line ) # note: use ^ for start of string only!!!
262
+ if m
263
+ h = {}
264
+ # - note: do NOT forget to turn name into symbol for lookup in new hash (name.to_sym)
265
+ m.names.each { |n| h[n.to_sym] = m[n] } # or use match_data.names.zip( match_data.captures ) - more cryptic but "elegant"??
266
+
267
+ ## remove matched string from line
268
+ line.slice!( 0...m[0].length )
269
+ h
270
+ else
271
+ nil
272
+ end
273
+ end
274
+
275
+ end # class GoalsParser
276
+
277
+ end # module SportDb
@@ -0,0 +1,241 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+ class ScoresFinder
6
+
7
+ include LogUtils::Logging
8
+
9
+
10
+ ## e.g. 3-4 pen. 2-2 a.e.t. (1-1, 1-1)
11
+ EN__P_ET_FT_HT__REGEX = /\b
12
+ (?<score1p>\d{1,2})
13
+ -
14
+ (?<score2p>\d{1,2})
15
+ \s* # allow optional spaces
16
+ (?:p|pen\.?|pso) # e.g. pen, pen., PSO, p etc.
17
+ \s* # allow optional spaces
18
+ (?<score1et>\d{1,2})
19
+ -
20
+ (?<score2et>\d{1,2})
21
+ \s* # allow optional spaces
22
+ (?:aet|a\.e\.t\.)
23
+ \s* # allow optional spaces
24
+ \(
25
+ (?<score1>\d{1,2})
26
+ -
27
+ (?<score2>\d{1,2})
28
+ \s*
29
+ ,
30
+ \s*
31
+ (?<score1i>\d{1,2})
32
+ -
33
+ (?<score2i>\d{1,2})
34
+ \)
35
+ (?=[\s\]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
36
+ ## note: \b works only after non-alphanum e.g. )
37
+
38
+
39
+ ## e.g. 2-1 a.e.t. (1-1, 0-0)
40
+ EN__ET_FT_HT__REGEX = /\b
41
+ (?<score1et>\d{1,2})
42
+ -
43
+ (?<score2et>\d{1,2})
44
+ \s* # allow optional spaces
45
+ (?:aet|a\.e\.t\.)
46
+ \s* # allow optional spaces
47
+ \(
48
+ (?<score1>\d{1,2})
49
+ -
50
+ (?<score2>\d{1,2})
51
+ \s*
52
+ ,
53
+ \s*
54
+ (?<score1i>\d{1,2})
55
+ -
56
+ (?<score2i>\d{1,2})
57
+ \)
58
+ (?=[\s\]]|$)/xi ## todo/check: remove loakahead assertion here - why require space?
59
+ ## note: \b works only after non-alphanum e.g. )
60
+
61
+
62
+ ## e.g. 2-1 (1-1)
63
+ EN__FT_HT__REGEX = /\b
64
+ (?<score1>\d{1,2})
65
+ -
66
+ (?<score2>\d{1,2})
67
+ \s*
68
+ \(
69
+ (?<score1i>\d{1,2})
70
+ -
71
+ (?<score2i>\d{1,2})
72
+ \)
73
+ (?=[\s\]]|$)/x ## todo/check: remove loakahead assertion here - why require space?
74
+ ## note: \b works only after non-alphanum e.g. )
75
+
76
+
77
+
78
+ ###################
79
+ # more
80
+
81
+ # e.g. 1:2 or 0:2 or 3:3 or
82
+ # 1-1 or 0-2 or 3-3 or
83
+ # 1x1 or 1X1 or 0x2 or 3x3 -- used in Brazil / Portugal
84
+ FT_REGEX = /\b
85
+ (?<score1>\d{1,2})
86
+ [:\-xX]
87
+ (?<score2>\d{1,2})
88
+ \b/x
89
+
90
+
91
+ # e.g. 1:2nV => after extra time a.e.t
92
+
93
+ # note: possible ending w/ . -> thus cannot use /b will not work w/ .; use zero look-ahead
94
+ ET_REGEX = /\b
95
+ (?<score1>\d{1,2})
96
+ [:\-xX]
97
+ (?<score2>\d{1,2})
98
+ \s? # allow optional space
99
+ (?:nv|n\.v\.|aet|a\.e\.t\.) # allow optional . e.g. nV or n.V.
100
+ (?=[\s\)\]]|$)/xi
101
+
102
+ ## todo: add/allow english markers e.g. pen or p ??
103
+
104
+ # e.g. 5:4iE => penalty / after penalty a.p
105
+
106
+
107
+ # note: possible ending w/ . -> thus cannot use /b will not work w/ .; use zero look-ahead
108
+ P_REGEX = /\b
109
+ (?<score1>\d{1,2})
110
+ [:\-xX]
111
+ (?<score2>\d{1,2})
112
+ \s? # allow optional space
113
+ (?:iE|i\.E\.|p|pen|PSO) # allow optional . e.g. iE or i.E.
114
+ (?=[\s\)\]]|$)/xi
115
+
116
+
117
+ ## todo: allow all-in-one "literal form a la kicker" e.g.
118
+ # 2:2 (1:1, 1:0) n.V. 5:1 i.E.
119
+
120
+ def initialize
121
+ # nothing here for now
122
+ end
123
+
124
+ def find!( line, opts={} )
125
+
126
+ ### fix: add and match all-in-one literal first, followed by
127
+
128
+ # note: always call after find_dates !!!
129
+ # scores match date-like patterns!! e.g. 10-11 or 10:00 etc.
130
+ # -- note: score might have two digits too
131
+
132
+ ### fix: depending on language allow 1:1 or 1-1
133
+ ## do NOT allow mix and match
134
+ ## e.g. default to en is 1-1
135
+ ## de is 1:1 etc.
136
+
137
+
138
+ # extract score from line
139
+ # and return it
140
+ # note: side effect - removes date from line string
141
+
142
+
143
+ score1i = nil # half time (ht) scores
144
+ score2i = nil
145
+
146
+ score1 = nil # full time (ft) scores
147
+ score2 = nil
148
+
149
+ score1et = nil # extra time (et) scores
150
+ score2et = nil
151
+
152
+ score1p = nil # penalty (p) scores
153
+ score2p = nil
154
+
155
+
156
+ if (md = EN__P_ET_FT_HT__REGEX.match( line ))
157
+ score1i = md[:score1i].to_i
158
+ score2i = md[:score2i].to_i
159
+ score1 = md[:score1].to_i
160
+ score2 = md[:score2].to_i
161
+ score1et = md[:score1et].to_i
162
+ score2et = md[:score2et].to_i
163
+ score1p = md[:score1p].to_i
164
+ score2p = md[:score2p].to_i
165
+
166
+ logger.debug " score.en__p_et_ft_ht: >#{score1p}-#{score2p} pen. #{score1et}-#{score2et} a.e.t. (#{score1}-#{score2}, #{score1i}-#{score2i})<"
167
+
168
+ line.sub!( md[0], '[SCORES.EN__P_ET_FT_HT]' )
169
+
170
+ elsif (md = EN__ET_FT_HT__REGEX.match( line ))
171
+ score1i = md[:score1i].to_i
172
+ score2i = md[:score2i].to_i
173
+ score1 = md[:score1].to_i
174
+ score2 = md[:score2].to_i
175
+ score1et = md[:score1et].to_i
176
+ score2et = md[:score2et].to_i
177
+
178
+ logger.debug " score.en__et_ft_ht: >#{score1et}-#{score2et} a.e.t. (#{score1}-#{score2}, #{score1i}-#{score2i})<"
179
+
180
+ line.sub!( md[0], '[SCORES.EN__ET_FT_HT]' )
181
+
182
+ elsif (md = EN__FT_HT__REGEX.match( line ))
183
+ score1i = md[:score1i].to_i
184
+ score2i = md[:score2i].to_i
185
+ score1 = md[:score1].to_i
186
+ score2 = md[:score2].to_i
187
+
188
+ logger.debug " score.en__ft_ht: >#{score1}-#{score2} (#{score1i}-#{score2i})<"
189
+
190
+ line.sub!( md[0], '[SCORES.EN__FT_HT]' )
191
+ else
192
+ #######################################################
193
+ ## try "standard" generic patterns for fallbacks
194
+
195
+ if (md = ET_REGEX.match( line ))
196
+ score1et = md[:score1].to_i
197
+ score2et = md[:score2].to_i
198
+
199
+ logger.debug " score.et: >#{score1et}-#{score2et}<"
200
+
201
+ line.sub!( md[0], '[SCORE.ET]' )
202
+ end
203
+
204
+ if (md = P_REGEX.match( line ))
205
+ score1p = md[:score1].to_i
206
+ score2p = md[:score2].to_i
207
+
208
+ logger.debug " score.p: >#{score1p}-#{score2p}<"
209
+
210
+ line.sub!( md[0], '[SCORE.P]' )
211
+ end
212
+
213
+ ## let full time (ft) standard regex go last - has no marker
214
+
215
+ if (md = FT_REGEX.match( line ))
216
+ score1 = md[:score1].to_i
217
+ score2 = md[:score2].to_i
218
+
219
+ logger.debug " score: >#{score1}-#{score2}<"
220
+
221
+ line.sub!( md[0], '[SCORE]' )
222
+ end
223
+ end
224
+
225
+ ## todo: how to handle game w/o extra time
226
+ # but w/ optional penalty ??? e.g. used in copa liberatores, for example
227
+ # retrun 0,0 or nil,nil for extra time score ?? or -1, -1 ??
228
+ # for now use nil,nil
229
+
230
+ scores = []
231
+ scores += [score1i, score2i] if score1p || score2p || score1et || score2et || score1 || score2 || score1i || score2i
232
+ scores += [score1, score2] if score1p || score2p || score1et || score2et || score1 || score2
233
+ scores += [score1et, score2et] if score1p || score2p || score1et || score2et
234
+ scores += [score1p, score2p] if score1p || score2p
235
+
236
+ scores
237
+ end
238
+
239
+ end # class ScoresFinder
240
+
241
+ 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 = 6
9
+ PATCH = 7
10
10
  VERSION = [MAJOR,MINOR,PATCH].join('.')
11
11
 
12
12
  def self.version
@@ -27,6 +27,10 @@ require 'sportdb/formats/datafile'
27
27
  require 'sportdb/formats/season_utils'
28
28
 
29
29
 
30
+ require 'sportdb/formats/scores'
31
+ require 'sportdb/formats/goals'
32
+
33
+
30
34
  ## let's put test configuration in its own namespace / module
31
35
  module SportDb
32
36
  class Test ## todo/check: works with module too? use a module - why? why not?
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_goals.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestGoals < MiniTest::Test
11
+
12
+
13
+ def test_world_cup_1930
14
+ line = " [L. Laurent 19' Langiller 40' Maschinot 43', 87'; Carreño 70']"
15
+
16
+ assert_equal [
17
+ SportDb::GoalStruct.new(
18
+ name: 'L. Laurent',
19
+ minute: 19,
20
+ offset: 0,
21
+ owngoal: false,
22
+ penalty: false,
23
+ score1: 1,
24
+ score2: 0,
25
+ team: 1),
26
+ SportDb::GoalStruct.new(
27
+ name: 'Langiller',
28
+ minute: 40,
29
+ offset: 0,
30
+ owngoal: false,
31
+ penalty: false,
32
+ score1: 2,
33
+ score2: 0,
34
+ team: 1),
35
+ SportDb::GoalStruct.new(
36
+ name: 'Maschinot',
37
+ minute: 43,
38
+ offset: 0,
39
+ owngoal: false,
40
+ penalty: false,
41
+ score1: 3,
42
+ score2: 0,
43
+ team: 1),
44
+ SportDb::GoalStruct.new(
45
+ name: 'Carreño',
46
+ minute: 70,
47
+ offset: 0,
48
+ owngoal: false,
49
+ penalty: false,
50
+ score1: 3,
51
+ score2: 1,
52
+ team: 2),
53
+ SportDb::GoalStruct.new(
54
+ name: 'Maschinot',
55
+ minute: 87,
56
+ offset: 0,
57
+ owngoal: false,
58
+ penalty: false,
59
+ score1: 4,
60
+ score2: 1,
61
+ team: 1)], parse_goals( line )
62
+
63
+
64
+ line = " [Monti 81'] "
65
+ assert_equal [
66
+ SportDb::GoalStruct.new(
67
+ name: 'Monti',
68
+ minute: 81,
69
+ offset: 0,
70
+ owngoal: false,
71
+ penalty: false,
72
+ score1: 1,
73
+ score2: 0,
74
+ team: 1)], parse_goals( line )
75
+
76
+
77
+ line = " [Vidal 3', 65' M. Rosas 51' (o.g.)]"
78
+ assert_equal [
79
+ SportDb::GoalStruct.new(
80
+ name: 'Vidal',
81
+ minute: 3,
82
+ offset: 0,
83
+ owngoal: false,
84
+ penalty: false,
85
+ score1: 1,
86
+ score2: 0,
87
+ team: 1),
88
+ SportDb::GoalStruct.new(
89
+ name: 'M. Rosas',
90
+ minute: 51,
91
+ offset: 0,
92
+ owngoal: true,
93
+ penalty: false,
94
+ score1: 2,
95
+ score2: 0,
96
+ team: 1),
97
+ SportDb::GoalStruct.new(
98
+ name: 'Vidal',
99
+ minute: 65,
100
+ offset: 0,
101
+ owngoal: false,
102
+ penalty: false,
103
+ score1: 3,
104
+ score2: 0,
105
+ team: 1)], parse_goals( line )
106
+ end
107
+
108
+ private
109
+ def parse_goals( line )
110
+ SportDb::GoalsFinder.new.find!( line )
111
+ end
112
+
113
+ end # class TestGoals
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_scores.rb
6
+
7
+
8
+ require 'helper'
9
+
10
+ class TestScores < MiniTest::Test
11
+
12
+
13
+ def test_scores
14
+ data = [
15
+ [ '10:0', [nil,nil,10,0]],
16
+ [ '1:22', [nil,nil,1,22]],
17
+ [ '1-22', [nil,nil,1,22]],
18
+ [ '1x22', [nil,nil,1,22]],
19
+ [ '1X22', [nil,nil,1,22]],
20
+
21
+
22
+ ## do not support three digits
23
+ [ '1-222', []],
24
+ [ '111-0', []],
25
+ [ '1:222', []],
26
+ [ '111:0', []],
27
+ [ '111x0', []],
28
+ [ '111X0', []],
29
+
30
+ ## penality only
31
+ [ '3-4iE', [nil,nil,nil,nil,nil,nil,3,4]],
32
+ [ '3:4iE', [nil,nil,nil,nil,nil,nil,3,4]],
33
+ [ '3:4 iE', [nil,nil,nil,nil,nil,nil,3,4]],
34
+ [ '3:4 i.E.', [nil,nil,nil,nil,nil,nil,3,4]],
35
+ [ '3-4 pen', [nil,nil,nil,nil,nil,nil,3,4]],
36
+ [ '3-4 PSO', [nil,nil,nil,nil,nil,nil,3,4]], # PSO => penalty shotout
37
+ [ '3-4p', [nil,nil,nil,nil,nil,nil,3,4]],
38
+ [ '3-4 p', [nil,nil,nil,nil,nil,nil,3,4]],
39
+
40
+ ## extra time only - allow ?? why not ?? only allow penalty w/ missing extra time?
41
+ ## todo/fix: issue warning or error in parser!!!
42
+ [ '3-4nV', [nil,nil,nil,nil,3,4]],
43
+ [ '3:4nV', [nil,nil,nil,nil,3,4]],
44
+ [ '3-4 aet', [nil,nil,nil,nil,3,4]],
45
+ [ '3-4 a.e.t.', [nil,nil,nil,nil,3,4]],
46
+
47
+ [ '3:4nV 1:1', [nil,nil,1,1,3,4]],
48
+ [ '1:1 3:4nV', [nil,nil,1,1,3,4]],
49
+ [ '3:4 nV 1:1', [nil,nil,1,1,3,4]],
50
+ [ '3:4 n.V. 1:1', [nil,nil,1,1,3,4]],
51
+
52
+ [ '3:4iE 1:1', [nil,nil,1,1,nil,nil,3,4]],
53
+ [ '1:1 3:4iE', [nil,nil,1,1,nil,nil,3,4]],
54
+
55
+ [ '1:1 2:2nV 3:4iE', [nil,nil,1,1,2,2,3,4]],
56
+ [ '3:4iE 2:2nV 1:1', [nil,nil,1,1,2,2,3,4]],
57
+ [ '3:4 i.E. 2:2 n.V. 1:1', [nil,nil,1,1,2,2,3,4]],
58
+ [ '3-4p 2-2aet 1-1', [nil,nil,1,1,2,2,3,4]],
59
+ [ '3-4 pen 2-2 aet 1-1', [nil,nil,1,1,2,2,3,4]],
60
+
61
+ #####################################################
62
+ ## check new all-in-one english (en) formats / patterns
63
+ [ '2-1 (1-1)', [1,1,2,1]],
64
+ [ '2-1 a.e.t. (1-1, 0-0)', [0,0,1,1,2,1]],
65
+ [ '2-1aet (1-1, 0-0)', [0,0,1,1,2,1]],
66
+ [ '2-1 A.E.T. (1-1, 0-0)', [0,0,1,1,2,1]],
67
+ [ '2-1AET (1-1, 0-0)', [0,0,1,1,2,1]],
68
+ [ '3-4 pen. 2-2 a.e.t. (1-1, 1-1)', [1,1,1,1,2,2,3,4]],
69
+ [ '3-4 pen 2-2 a.e.t. (1-1, 1-1)', [1,1,1,1,2,2,3,4]],
70
+ [ '3-4 pen 2-2 a.e.t. (1-1, 1-1)', [1,1,1,1,2,2,3,4]],
71
+ [ '3-4p 2-2aet (1-1, 1-1)', [1,1,1,1,2,2,3,4]],
72
+ [ '3-4PSO 2-2AET (1-1, 1-1)', [1,1,1,1,2,2,3,4]],
73
+ ]
74
+
75
+ assert_scores( data )
76
+ end
77
+
78
+ private
79
+ def assert_scores( data )
80
+ data.each do |rec|
81
+ line = rec[0]
82
+ exp = rec[1]
83
+
84
+ assert_equal exp, parse_scores( line )
85
+ end
86
+ end
87
+
88
+ def parse_scores( line )
89
+ finder = SportDb::ScoresFinder.new
90
+ finder.find!( line )
91
+ end
92
+
93
+ end # class TestScores
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: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-01 00:00:00.000000000 Z
11
+ date: 2019-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: alphabets
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.1
33
+ version: 0.2.4
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.1
40
+ version: 0.2.4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: csvreader
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -109,14 +109,18 @@ files:
109
109
  - Rakefile
110
110
  - lib/sportdb/formats.rb
111
111
  - lib/sportdb/formats/datafile.rb
112
+ - lib/sportdb/formats/goals.rb
112
113
  - lib/sportdb/formats/outline_reader.rb
114
+ - lib/sportdb/formats/scores.rb
113
115
  - lib/sportdb/formats/season_utils.rb
114
116
  - lib/sportdb/formats/version.rb
115
117
  - test/helper.rb
116
118
  - test/test_csv_reader.rb
117
119
  - test/test_datafile.rb
118
120
  - test/test_datafile_match.rb
121
+ - test/test_goals.rb
119
122
  - test/test_outline_reader.rb
123
+ - test/test_scores.rb
120
124
  - test/test_season_utils.rb
121
125
  homepage: https://github.com/sportdb/sport.db
122
126
  licenses: