sportdb-quick 0.3.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Rakefile +1 -1
- data/lib/sportdb/quick/match_parser.rb +166 -329
- data/lib/sportdb/quick/quick_match_reader.rb +8 -0
- data/lib/sportdb/quick/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71f76e171de23b5062c30f432d5fece7bcb2cb0e7283d658dcf8ff79aefb6aa3
|
4
|
+
data.tar.gz: 74fc864d5c4b9ca42270abd3fdb941cebdb9857c072c7515e7e422829c018891
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83fa67d7c4bbd0952ad9e02f93be65c488bd728b52f8a9a1159ab42bd299b6b9b37ff5e75573582ef4a7f20ebef1d97ff7da111334dd5f6b4b71bf4793ea84af
|
7
|
+
data.tar.gz: 9f832375e9d03fe1de7d83d14083428d0f3eda704645cf585449d13cf7929030552075549d68e0d91892be0d66c4bf92fbc41a2403cecee362025ed2b2058513
|
data/CHANGELOG.md
CHANGED
data/Rakefile
CHANGED
@@ -9,7 +9,19 @@ class MatchParser ## simple match parser for team match schedules
|
|
9
9
|
|
10
10
|
include Logging ## e.g. logger#debug, logger#info, etc.
|
11
11
|
|
12
|
+
def log( msg )
|
13
|
+
## append msg to ./logs.txt
|
14
|
+
## use ./errors.txt - why? why not?
|
15
|
+
File.open( './logs.txt', 'a:utf-8' ) do |f|
|
16
|
+
f.write( msg )
|
17
|
+
f.write( "\n" )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
12
23
|
|
24
|
+
|
13
25
|
def self.parse( lines, start: )
|
14
26
|
## todo/fix: add support for txt and lines
|
15
27
|
## check if lines_or_txt is an array or just a string
|
@@ -26,8 +38,8 @@ class MatchParser ## simple match parser for team match schedules
|
|
26
38
|
lines = []
|
27
39
|
txt.each_line do |line| ## preprocess
|
28
40
|
line = line.strip
|
29
|
-
|
30
41
|
next if line.empty? || line.start_with?('#') ### skip empty lines and comments
|
42
|
+
|
31
43
|
line = line.sub( /#.*/, '' ).strip ### cut-off end-of line comments too
|
32
44
|
lines << line
|
33
45
|
end
|
@@ -35,29 +47,7 @@ class MatchParser ## simple match parser for team match schedules
|
|
35
47
|
end
|
36
48
|
|
37
49
|
|
38
|
-
|
39
|
-
## make sure mon feb 12 18:10 will not match
|
40
|
-
## allow 1. FC Köln etc.
|
41
|
-
## Mainz 05:
|
42
|
-
## limit to 30 chars max
|
43
|
-
## only allow chars incl. intl buut (NOT ()[]/;)
|
44
|
-
##
|
45
|
-
## Group A:
|
46
|
-
## Group B: - remove colon
|
47
|
-
## or lookup first
|
48
|
-
|
49
|
-
ATTRIB_RE = %r{^
|
50
|
-
[ ]*? # slurp leading spaces
|
51
|
-
(?<key>[^:|\]\[()\/; -]
|
52
|
-
[^:|\]\[()\/;]{0,30}
|
53
|
-
)
|
54
|
-
[ ]*? # slurp trailing spaces
|
55
|
-
:[ ]+
|
56
|
-
(?<value>.+)
|
57
|
-
[ ]*? # slurp trailing spaces
|
58
|
-
$
|
59
|
-
}ix
|
60
|
-
|
50
|
+
|
61
51
|
#
|
62
52
|
# todo/fix: change start to start: too!!!
|
63
53
|
# might be optional in the future!! - why? why not?
|
@@ -88,8 +78,6 @@ class MatchParser ## simple match parser for team match schedules
|
|
88
78
|
@last_round = nil
|
89
79
|
@last_group = nil
|
90
80
|
|
91
|
-
## last_goals - rename to (longer) @last_team_goals or such - why? why not?
|
92
|
-
@last_goals = 1 ## toggle between 1|2 - hacky (quick & dirty) support for multi-line goals, fix soon!
|
93
81
|
|
94
82
|
@teams = Hash.new(0) ## track counts (only) for now for (interal) team stats - why? why not?
|
95
83
|
@rounds = {}
|
@@ -99,41 +87,23 @@ class MatchParser ## simple match parser for team match schedules
|
|
99
87
|
@warns = [] ## track list of warnings (unmatched lines) too - why? why not?
|
100
88
|
|
101
89
|
|
102
|
-
|
103
|
-
@parser = Parser.new
|
104
90
|
@tree = []
|
105
91
|
|
106
|
-
attrib_found = false
|
107
|
-
|
108
|
-
@lines.each_with_index do |line,i|
|
109
92
|
|
93
|
+
## flatten lines
|
94
|
+
txt = []
|
95
|
+
@lines.each_with_index do |line,i|
|
96
|
+
txt << line
|
97
|
+
txt << "\n"
|
98
|
+
end
|
99
|
+
txt = txt.join
|
100
|
+
|
110
101
|
if debug?
|
111
|
-
puts
|
112
|
-
|
102
|
+
puts "lines:"
|
103
|
+
pp txt
|
113
104
|
end
|
114
105
|
|
115
|
-
|
116
|
-
if attrib_found == false &&
|
117
|
-
ATTRIB_RE.match?( line )
|
118
|
-
## note: check attrib regex AFTER group def e.g.:
|
119
|
-
## Group A:
|
120
|
-
## Group B: etc.
|
121
|
-
## todo/fix - change Group A: to Group A etc.
|
122
|
-
## Group B: to Group B
|
123
|
-
attrib_found = true
|
124
|
-
## logger.debug "skipping key/value line - >#{line}<"
|
125
|
-
next
|
126
|
-
end
|
127
|
-
|
128
|
-
if attrib_found
|
129
|
-
## check if line ends with dot
|
130
|
-
## if not slurp up lines to the next do!!!
|
131
|
-
## logger.debug "skipping key/value line - >#{line}<"
|
132
|
-
attrib_found = false if line.end_with?( '.' )
|
133
|
-
# logger.debug "skipping key/value line (cont.) - >#{line}<"
|
134
|
-
next
|
135
|
-
end
|
136
|
-
|
106
|
+
=begin
|
137
107
|
t, error_messages = @parser.parse_with_errors( line )
|
138
108
|
|
139
109
|
|
@@ -151,71 +121,47 @@ class MatchParser ## simple match parser for team match schedules
|
|
151
121
|
pp t if debug?
|
152
122
|
|
153
123
|
@tree << t
|
154
|
-
|
124
|
+
=end
|
155
125
|
|
156
|
-
|
126
|
+
parser = RaccMatchParser.new( txt ) ## use own parser instance (not shared) - why? why not?
|
127
|
+
@tree = parser.parse
|
128
|
+
## pp @tree
|
157
129
|
|
158
130
|
## report parse errors here - why? why not?
|
159
131
|
|
160
132
|
|
161
133
|
|
162
|
-
@tree.each do |
|
163
|
-
|
164
|
-
node_type = nodes[0][0] ## get node type of first/head node
|
134
|
+
@tree.each do |node|
|
165
135
|
|
166
|
-
if
|
136
|
+
if node.is_a? RaccMatchParser::RoundDef
|
167
137
|
## todo/fix: add round definition (w begin n end date)
|
168
138
|
## todo: do not patch rounds with definition (already assume begin/end date is good)
|
169
139
|
## -- how to deal with matches that get rescheduled/postponed?
|
170
|
-
|
171
|
-
|
140
|
+
on_round_def( node )
|
141
|
+
elsif node.is_a? RaccMatchParser::GroupDef ## NB: group goes after round (round may contain group marker too)
|
172
142
|
### todo: add pipe (|) marker (required)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
##
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
node = nodes.shift ## eat-up
|
194
|
-
## ignore (round) leg for now - add later leg - 1|2|3 etc!!!
|
195
|
-
## needs to get added to db/schema too!!!!
|
196
|
-
## add @last_leg = nil or 1|2|3 etc.
|
197
|
-
elsif node_type == :group
|
198
|
-
## -- lets you set group e.g. Group A etc.
|
199
|
-
node = nodes.shift ## eat-up
|
200
|
-
parse_group_header( node )
|
201
|
-
elsif node_type == :date
|
202
|
-
node = nodes.shift ## eat-up
|
203
|
-
parse_date_header( node )
|
204
|
-
## add time here too - why? why not?
|
205
|
-
## add skip comma separator here too - why? why not?
|
206
|
-
## "slurp-up" in upstream parser?
|
207
|
-
## e.g. round, group or group, round ?
|
208
|
-
else
|
209
|
-
break
|
210
|
-
end
|
211
|
-
end
|
212
|
-
next if nodes.empty?
|
213
|
-
|
214
|
-
## rename to try_parse_match - why? why not?
|
215
|
-
parse_match( nodes )
|
143
|
+
on_group_def( node )
|
144
|
+
elsif node.is_a? RaccMatchParser::GroupHeader
|
145
|
+
on_group_header( node )
|
146
|
+
elsif node.is_a? RaccMatchParser::RoundHeader
|
147
|
+
on_round_header( node )
|
148
|
+
elsif node.is_a? RaccMatchParser::DateHeader
|
149
|
+
on_date_header( node )
|
150
|
+
elsif node.is_a? RaccMatchParser::MatchLine
|
151
|
+
on_match_line( node )
|
152
|
+
elsif node.is_a? RaccMatchParser::GoalLine
|
153
|
+
on_goal_line( node )
|
154
|
+
else
|
155
|
+
## report error
|
156
|
+
msg = "!! WARN - unknown node (parse tree type) - #{node.class.name}"
|
157
|
+
puts msg
|
158
|
+
pp node
|
159
|
+
|
160
|
+
log( msg )
|
161
|
+
log( node.pretty_inspect )
|
162
|
+
## exit 1
|
216
163
|
end
|
217
|
-
|
218
|
-
end # tree.each
|
164
|
+
end # tree.each
|
219
165
|
|
220
166
|
## note - team keys are names and values are "internal" stats!!
|
221
167
|
## and NOT team/club/nat_team structs!!
|
@@ -224,8 +170,8 @@ class MatchParser ## simple match parser for team match schedules
|
|
224
170
|
|
225
171
|
|
226
172
|
|
227
|
-
def
|
228
|
-
logger.debug "
|
173
|
+
def on_group_header( node )
|
174
|
+
logger.debug "on group header: >#{node}<"
|
229
175
|
|
230
176
|
# note: group header resets (last) round (allows, for example):
|
231
177
|
# e.g.
|
@@ -235,7 +181,7 @@ class MatchParser ## simple match parser for team match schedules
|
|
235
181
|
# team1 team2 - match (will get new auto-matchday! not last round)
|
236
182
|
@last_round = nil
|
237
183
|
|
238
|
-
name = node
|
184
|
+
name = node.name
|
239
185
|
|
240
186
|
group = @groups[ name ]
|
241
187
|
if group.nil?
|
@@ -248,8 +194,8 @@ class MatchParser ## simple match parser for team match schedules
|
|
248
194
|
end
|
249
195
|
|
250
196
|
|
251
|
-
def
|
252
|
-
logger.debug "
|
197
|
+
def on_group_def( node )
|
198
|
+
logger.debug "on group def: >#{node}<"
|
253
199
|
|
254
200
|
## e.g
|
255
201
|
## [:group_def, "Group A"],
|
@@ -258,26 +204,15 @@ class MatchParser ## simple match parser for team match schedules
|
|
258
204
|
## [:team, "Hungary"],
|
259
205
|
## [:team, "Switzerland"]
|
260
206
|
|
261
|
-
node
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
if node[0] == :team
|
266
|
-
team = node[1]
|
267
|
-
@teams[ team ] += 1
|
268
|
-
team
|
269
|
-
else
|
270
|
-
puts "!! PARSE ERROR - only teams expected in group def; got:"
|
271
|
-
pp nodes
|
272
|
-
exit 1
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
207
|
+
node.teams.each do |team|
|
208
|
+
@teams[ team ] += 1
|
209
|
+
end
|
210
|
+
|
276
211
|
## todo/check/fix: add back group key - why? why not?
|
277
|
-
group = Import::Group.new( name: name,
|
278
|
-
teams: teams )
|
212
|
+
group = Import::Group.new( name: node.name,
|
213
|
+
teams: node.teams )
|
279
214
|
|
280
|
-
@groups[ name ] = group
|
215
|
+
@groups[ node.name ] = group
|
281
216
|
end
|
282
217
|
|
283
218
|
|
@@ -307,37 +242,35 @@ class MatchParser ## simple match parser for team match schedules
|
|
307
242
|
Date.new( y,m,d ) ## y,m,d
|
308
243
|
end
|
309
244
|
|
310
|
-
|
311
|
-
|
245
|
+
|
246
|
+
def on_round_def( node )
|
247
|
+
logger.debug "on round def: >#{node}<"
|
312
248
|
|
313
249
|
## e.g. [[:round_def, "Matchday 1"], [:duration, "Fri Jun/14 - Tue Jun/18"]]
|
314
250
|
## [[:round_def, "Matchday 2"], [:duration, "Wed Jun/19 - Sat Jun/22"]]
|
315
251
|
## [[:round_def, "Matchday 3"], [:duration, "Sun Jun/23 - Wed Jun/26"]]
|
316
252
|
|
317
|
-
|
318
|
-
name = node[1]
|
253
|
+
name = node.name
|
319
254
|
# NB: use extracted round name for knockout check
|
320
255
|
# knockout_flag = is_knockout_round?( name )
|
321
256
|
|
322
|
-
node
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
d: node[2][:d],
|
327
|
-
y: node[2][:y],
|
257
|
+
if node.date
|
258
|
+
start_date = end_date = _build_date( m: node.date[:m],
|
259
|
+
d: node.date[:d],
|
260
|
+
y: node.date[:y],
|
328
261
|
start: @start)
|
329
|
-
elsif
|
330
|
-
start_date = _build_date( m: node[
|
331
|
-
d: node[
|
332
|
-
y: node[
|
262
|
+
elsif node.duration
|
263
|
+
start_date = _build_date( m: node.duration[:start][:m],
|
264
|
+
d: node.duration[:start][:d],
|
265
|
+
y: node.duration[:start][:y],
|
333
266
|
start: @start)
|
334
|
-
end_date = _build_date( m: node[
|
335
|
-
d: node[
|
336
|
-
y: node[
|
267
|
+
end_date = _build_date( m: node.duration[:end][:m],
|
268
|
+
d: node.duration[:end][:d],
|
269
|
+
y: node.duration[:end][:y],
|
337
270
|
start: @start)
|
338
271
|
else
|
339
272
|
puts "!! PARSE ERROR - expected date or duration for round def; got:"
|
340
|
-
pp
|
273
|
+
pp node
|
341
274
|
exit 1
|
342
275
|
end
|
343
276
|
|
@@ -375,10 +308,11 @@ class MatchParser ## simple match parser for team match schedules
|
|
375
308
|
end
|
376
309
|
|
377
310
|
|
378
|
-
def
|
379
|
-
logger.debug "
|
311
|
+
def on_round_header( node )
|
312
|
+
logger.debug "on round header: >#{node}<"
|
380
313
|
|
381
|
-
name = node[
|
314
|
+
name = node.names[0] ## ignore more names for now
|
315
|
+
## fix later - fix more names!!!
|
382
316
|
|
383
317
|
# name = name.sub( ROUND_EXTRA_WORDS_RE, '' )
|
384
318
|
# name = name.strip
|
@@ -399,12 +333,12 @@ class MatchParser ## simple match parser for team match schedules
|
|
399
333
|
## reset date/time e.g. @last_date = nil !!!!
|
400
334
|
end
|
401
335
|
|
402
|
-
def
|
336
|
+
def on_date_header( node )
|
403
337
|
logger.debug( "date header: >#{node}<")
|
404
338
|
|
405
|
-
date = _build_date( m: node[
|
406
|
-
d: node[
|
407
|
-
y: node[
|
339
|
+
date = _build_date( m: node.date[:m],
|
340
|
+
d: node.date[:d],
|
341
|
+
y: node.date[:y],
|
408
342
|
start: @start )
|
409
343
|
|
410
344
|
logger.debug( " date: #{date} with start: #{@start}")
|
@@ -431,93 +365,17 @@ class MatchParser ## simple match parser for team match schedules
|
|
431
365
|
=end
|
432
366
|
end
|
433
367
|
|
434
|
-
def parse_minutes( nodes )
|
435
|
-
## parse goals by player
|
436
|
-
## may have multiple minutes!!
|
437
|
-
goals = []
|
438
|
-
|
439
|
-
node = nodes.shift ## get player
|
440
|
-
name = node[1]
|
441
|
-
|
442
|
-
loop do
|
443
|
-
goal = {}
|
444
|
-
goal[:name] = name
|
445
|
-
|
446
|
-
node_type = nodes[0][0]
|
447
|
-
if node_type != :minute
|
448
|
-
puts "!! PARSE ERROR - minute expected to follow player (in goal); got #{node_type}:"
|
449
|
-
pp nodes
|
450
|
-
exit 1
|
451
|
-
end
|
452
|
-
|
453
|
-
node = nodes.shift
|
454
|
-
goal[:minute] = node[2][:m]
|
455
|
-
goal[:offset] = node[2][:offset] if node[2][:offset]
|
456
|
-
|
457
|
-
## check for own goal or penalty or such
|
458
|
-
if !nodes.empty?
|
459
|
-
node_type = nodes[0][0]
|
460
|
-
if node_type == :og
|
461
|
-
nodes.shift
|
462
|
-
goal[:og] = true
|
463
|
-
elsif node_type == :pen
|
464
|
-
nodes.shift
|
465
|
-
goal[:pen] = true
|
466
|
-
else
|
467
|
-
# do nothing
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
goals << goal
|
472
|
-
|
473
|
-
## check if another minute ahead; otherwise break
|
474
|
-
break if nodes.empty?
|
475
|
-
|
476
|
-
node_type = nodes[0][0]
|
477
368
|
|
478
|
-
|
479
|
-
|
480
|
-
if node_type == :','
|
481
|
-
nodes.shift
|
482
|
-
node_type = nodes[0][0]
|
483
|
-
end
|
484
|
-
|
485
|
-
break if node_type != :minute
|
486
|
-
end
|
369
|
+
def on_goal_line( node )
|
370
|
+
logger.debug "on goal line: >#{node}<"
|
487
371
|
|
372
|
+
goals1 = node.goals1
|
373
|
+
goals2 = node.goals2
|
488
374
|
|
489
|
-
|
490
|
-
end
|
491
|
-
|
492
|
-
|
493
|
-
def parse_goals( nodes )
|
494
|
-
logger.debug "parse goals: >#{nodes}<"
|
495
|
-
|
496
|
-
goals1 = []
|
497
|
-
goals2 = []
|
498
|
-
|
499
|
-
while !nodes.empty?
|
500
|
-
node_type = nodes[0][0]
|
501
|
-
if node_type == :player
|
502
|
-
more_goals = parse_minutes( nodes )
|
503
|
-
## hacky multi-line support for goals
|
504
|
-
## using last_goal (1|2)
|
505
|
-
@last_goals == 2 ? goals2 += more_goals :
|
506
|
-
goals1 += more_goals
|
507
|
-
elsif node_type == :';' ## team separator
|
508
|
-
nodes.shift # eat-up
|
509
|
-
@last_goals = 2
|
510
|
-
elsif node_type == :none
|
511
|
-
nodes.shift # eat-up
|
512
|
-
else
|
513
|
-
puts "!! PARSE ERROR - unexpected node type in goals;; got #{node_type}:"
|
514
|
-
pp nodes
|
515
|
-
exit 1
|
516
|
-
end
|
517
|
-
end
|
518
|
-
|
375
|
+
|
519
376
|
pp [goals1,goals2] if debug?
|
520
377
|
|
378
|
+
|
521
379
|
## wrap in struct andd add/append to match
|
522
380
|
=begin
|
523
381
|
class GoalStruct
|
@@ -532,26 +390,30 @@ class GoalStruct
|
|
532
390
|
|
533
391
|
goals = []
|
534
392
|
goals1.each do |rec|
|
535
|
-
|
536
|
-
|
393
|
+
rec.minutes.each do |minute|
|
394
|
+
goal = Import::Goal.new(
|
395
|
+
player: rec.player,
|
537
396
|
team: 1,
|
538
|
-
minute:
|
539
|
-
offset:
|
540
|
-
penalty:
|
541
|
-
owngoal:
|
397
|
+
minute: minute.m,
|
398
|
+
offset: minute.offset,
|
399
|
+
penalty: minute.pen || false, # note: pass along/use false NOT nil
|
400
|
+
owngoal: minute.og || false
|
542
401
|
)
|
543
|
-
|
402
|
+
goals << goal
|
403
|
+
end
|
544
404
|
end
|
545
405
|
goals2.each do |rec|
|
546
|
-
|
547
|
-
|
406
|
+
rec.minutes.each do |minute|
|
407
|
+
goal = Import::Goal.new(
|
408
|
+
player: rec.player,
|
548
409
|
team: 2,
|
549
|
-
minute:
|
550
|
-
offset:
|
551
|
-
penalty:
|
552
|
-
owngoal:
|
410
|
+
minute: minute.m,
|
411
|
+
offset: minute.offset,
|
412
|
+
penalty: minute.pen || false, # note: pass along/use false NOT nil
|
413
|
+
owngoal: minute.og || false
|
553
414
|
)
|
554
415
|
goals << goal
|
416
|
+
end
|
555
417
|
end
|
556
418
|
|
557
419
|
pp goals if debug?
|
@@ -569,90 +431,69 @@ class GoalStruct
|
|
569
431
|
end
|
570
432
|
|
571
433
|
|
572
|
-
def
|
573
|
-
logger.debug( "
|
434
|
+
def on_match_line( node )
|
435
|
+
logger.debug( "on match: >#{node}<" )
|
574
436
|
|
575
437
|
## collect (possible) nodes by type
|
576
438
|
num = nil
|
439
|
+
num = node.ord if node.ord
|
440
|
+
|
577
441
|
date = nil
|
578
|
-
|
579
|
-
|
442
|
+
date = _build_date( m: node.date[:m],
|
443
|
+
d: node.date[:d],
|
444
|
+
y: node.date[:y],
|
445
|
+
start: @start ) if node.date
|
446
|
+
|
447
|
+
## note - there's no time (-only) type in ruby
|
448
|
+
## use string (e.g. '14:56', '1:44')
|
449
|
+
## use 01:44 or 1:44 ?
|
450
|
+
## check for 0:00 or 24:00 possible?
|
451
|
+
time = nil
|
452
|
+
time = ('%d:%02d' % [node.time[:h], node.time[:m]]) if node.time
|
453
|
+
|
454
|
+
|
455
|
+
### todo/fix
|
456
|
+
## add keywords (e.g. ht, ft or such) to Score.new - why? why not?
|
457
|
+
## or use new Score.build( ht:, ft:, ) or such - why? why not?
|
458
|
+
## pp score
|
580
459
|
score = nil
|
581
|
-
|
582
|
-
|
460
|
+
if node.score
|
461
|
+
ht = node.score[:ht] || [nil,nil]
|
462
|
+
ft = node.score[:ft] || [nil,nil]
|
463
|
+
et = node.score[:et] || [nil,nil]
|
464
|
+
p = node.score[:p] || [nil,nil]
|
465
|
+
values = [*ht, *ft, *et, *p]
|
466
|
+
## pp values
|
467
|
+
score = Score.new( *values )
|
468
|
+
end
|
469
|
+
|
583
470
|
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
elsif node_type == :
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
## check for 0:00 or 24:00 possible?
|
603
|
-
time = '%d:%02d' % [node[2][:h], node[2][:m]]
|
604
|
-
elsif node_type == :team
|
605
|
-
teams << node[1]
|
606
|
-
elsif node_type == :score
|
607
|
-
### todo/fix
|
608
|
-
## add keywords (e.g. ht, ft or such) to Score.new - why? why not?
|
609
|
-
## or use new Score.build( ht:, ft:, ) or such - why? why not?
|
610
|
-
ht = node[2][:ht] || [nil,nil]
|
611
|
-
ft = node[2][:ft] || [nil,nil]
|
612
|
-
et = node[2][:et] || [nil,nil]
|
613
|
-
p = node[2][:p] || [nil,nil]
|
614
|
-
values = [*ht, *ft, *et, *p]
|
615
|
-
## pp values
|
616
|
-
|
617
|
-
score = Score.new( *values )
|
618
|
-
## pp score
|
619
|
-
elsif node_type == :status # e.g. awarded, canceled, postponed, etc.
|
620
|
-
status = node[1]
|
621
|
-
elsif node_type == :vs
|
622
|
-
## skip; do nothing
|
623
|
-
##
|
624
|
-
## todo - add ## find (optional) match status e.g. [abandoned] or [replay] or [awarded]
|
625
|
-
## or [cancelled] or [postponed] etc.
|
626
|
-
## status = find_status!( line ) ## todo/check: allow match status also in geo part (e.g. after @) - why? why not?
|
627
|
-
|
628
|
-
elsif node_type == :'@' ||
|
629
|
-
node_type == :',' ||
|
630
|
-
node_type == :geo ||
|
631
|
-
node_type == :timezone
|
471
|
+
status = nil
|
472
|
+
status = node.status if node.status ### assume text for now
|
473
|
+
## if node_type == :status # e.g. awarded, canceled, postponed, etc.
|
474
|
+
## status = node[1]
|
475
|
+
#
|
476
|
+
## todo - add ## find (optional) match status e.g. [abandoned] or [replay] or [awarded]
|
477
|
+
## or [cancelled] or [postponed] etc.
|
478
|
+
## status = find_status!( line ) ## todo/check: allow match status also in geo part (e.g. after @) - why? why not?
|
479
|
+
|
480
|
+
|
481
|
+
###############
|
482
|
+
# add more for ground (and timezone!!!)
|
483
|
+
more = []
|
484
|
+
#
|
485
|
+
# elsif node_type == :'@' ||
|
486
|
+
# node_type == :',' ||
|
487
|
+
# node_type == :geo ||
|
488
|
+
# node_type == :timezone
|
632
489
|
## e.g.
|
633
490
|
## [:"@"], [:geo, "Stade de France"], [:","], [:geo, "Saint-Denis"]]
|
634
491
|
## [:"@"], [:geo, "Arena de São Paulo"], [:","], [:geo, "São Paulo"], [:timezone, "(UTC-3)"]
|
635
|
-
more << node[1] if node_type == :geo
|
636
|
-
|
637
|
-
puts "!! PARSE ERROR - unexpected node type #{node_type} in match line; got:"
|
638
|
-
pp node
|
639
|
-
## exit 1
|
640
|
-
@errors << ["PARSE ERROR - unexpected node type #{node_type} in match line; got: #{node.inspect}"]
|
641
|
-
return
|
642
|
-
end
|
643
|
-
end
|
492
|
+
# more << node[1] if node_type == :geo
|
493
|
+
|
644
494
|
|
645
|
-
|
646
|
-
|
647
|
-
puts "!! PARSE ERROR - expected two teams; got #{teams.size}:"
|
648
|
-
pp teams
|
649
|
-
## exit 1
|
650
|
-
@errors << ["PARSE ERROR - expected two teams; got #{teams.size}: #{teams.inspect}"]
|
651
|
-
return
|
652
|
-
end
|
653
|
-
|
654
|
-
team1 = teams[0]
|
655
|
-
team2 = teams[1]
|
495
|
+
team1 = node.team1
|
496
|
+
team2 = node.team2
|
656
497
|
|
657
498
|
@teams[ team1 ] += 1
|
658
499
|
@teams[ team2 ] += 1
|
@@ -738,10 +579,6 @@ class GoalStruct
|
|
738
579
|
status: status,
|
739
580
|
ground: ground )
|
740
581
|
### todo: cache team lookups in hash?
|
741
|
-
|
742
|
-
## hacky goals support
|
743
|
-
### reset/toggle 1/2
|
744
|
-
@last_goals = 1
|
745
582
|
end
|
746
583
|
end # class MatchParser
|
747
584
|
end # module SportDb
|
@@ -73,6 +73,14 @@ class QuickMatchReader
|
|
73
73
|
Date.new( season.start_year, 7, 1 )
|
74
74
|
end
|
75
75
|
|
76
|
+
# if debug?
|
77
|
+
# puts " (sec) lines:"
|
78
|
+
# pp lines
|
79
|
+
# end
|
80
|
+
|
81
|
+
### note - skip section if no lines !!!!!
|
82
|
+
next if lines.empty? ## or use lines.size == 0
|
83
|
+
|
76
84
|
|
77
85
|
parser = MatchParser.new( lines,
|
78
86
|
start ) ## note: keep season start_at date for now (no need for more specific stage date need for now)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sportdb-quick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-01-
|
11
|
+
date: 2025-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sportdb-parser
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.4
|
19
|
+
version: 0.5.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.4
|
26
|
+
version: 0.5.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sportdb-structs
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|