sportdb-formats 0.1.6 → 0.1.7

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 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: