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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d24c209b9b7c40d0f042062a41edf15ebc99a9d6536b06456eb09b365ddc3d11
4
- data.tar.gz: d6d4c961906539774027860d4c29a306186f5fba96b049a3a7b9720a9c87498d
3
+ metadata.gz: 71f76e171de23b5062c30f432d5fece7bcb2cb0e7283d658dcf8ff79aefb6aa3
4
+ data.tar.gz: 74fc864d5c4b9ca42270abd3fdb941cebdb9857c072c7515e7e422829c018891
5
5
  SHA512:
6
- metadata.gz: bde8f1b34c6be7c3c68b5c051dcb21c257d721719ea1e1c648b911c504535832c885395492427ca985de7b2b35e2c2b92590cd5e41b5f5f6c7344dcee8e3904a
7
- data.tar.gz: a46daab3b1d77e498badaca558c237ad43e81c129641efa88450eabaa05d4b71499b6f2d7af0101a46b976e1ab6b0a152a9b3a6c3d0183faae53b56648814e51
6
+ metadata.gz: 83fa67d7c4bbd0952ad9e02f93be65c488bd728b52f8a9a1159ab42bd299b6b9b37ff5e75573582ef4a7f20ebef1d97ff7da111334dd5f6b4b71bf4793ea84af
7
+ data.tar.gz: 9f832375e9d03fe1de7d83d14083428d0f3eda704645cf585449d13cf7929030552075549d68e0d91892be0d66c4bf92fbc41a2403cecee362025ed2b2058513
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 0.3.1
1
+ ### 0.5.1
2
2
  ### 0.0.1 / 2024-08-27
3
3
 
4
4
  * Everything is new. First release.
data/Rakefile CHANGED
@@ -21,7 +21,7 @@ Hoe.spec 'sportdb-quick' do
21
21
  self.licenses = ['Public Domain']
22
22
 
23
23
  self.extra_deps = [
24
- ['sportdb-parser', '>= 0.4.0'],
24
+ ['sportdb-parser', '>= 0.5.4'],
25
25
  ['sportdb-structs', '>= 0.5.0'],
26
26
  ['logutils', '>= 0.6.1'],
27
27
  ]
@@ -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
- ## note: colon (:) MUST be followed by one (or more) spaces
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
- puts "line >#{line}<"
102
+ puts "lines:"
103
+ pp txt
113
104
  end
114
105
 
115
- ## skip new (experimental attrib syntax)
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
- end # each lines
124
+ =end
155
125
 
156
- ## pp @tree
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 |nodes|
163
-
164
- node_type = nodes[0][0] ## get node type of first/head node
134
+ @tree.each do |node|
165
135
 
166
- if node_type == :round_def
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
- parse_round_def( nodes )
171
- elsif node_type == :group_def ## NB: group goes after round (round may contain group marker too)
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
- parse_group_def( nodes )
174
-
175
- elsif node_type == :player ||
176
- node_type == :none # e.g [[:none], [:";"], [:player, "Xhaka"],...]
177
- ## note - for now goals line MUST start with player!!
178
- parse_goals( nodes )
179
- else
180
- ## try to be liberal/flexible
181
- ## eat-up nodes as we go
182
- ## assume match with group / round header
183
- ## etc. on its own line or not
184
-
185
- ## preprocess possible before match nodes
186
-
187
- while !nodes.empty? do
188
- node_type = nodes[0][0] ## get node type of first/head node
189
- if node_type == :round
190
- node = nodes.shift ## eat-up
191
- parse_round_header( node )
192
- elsif node_type == :leg
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 parse_group_header( node )
228
- logger.debug "parsing group header: >#{node}<"
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[1]
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 parse_group_def( nodes )
252
- logger.debug "parsing group def: >#{nodes}<"
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 = nodes[0]
262
- name = node[1] ## group name
263
-
264
- teams = nodes[1..-1].map do |node|
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
- def parse_round_def( nodes )
311
- logger.debug "parsing round def: >#{nodes}<"
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
- node = nodes[0]
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 = nodes[1]
323
- node_type = node[0]
324
- if node_type == :date
325
- start_date = end_date = _build_date( m: node[2][:m],
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 node_type == :duration
330
- start_date = _build_date( m: node[2][:start][:m],
331
- d: node[2][:start][:d],
332
- y: node[2][:start][:y],
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[2][:end][:m],
335
- d: node[2][:end][:d],
336
- y: node[2][:end][:y],
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 nodes
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 parse_round_header( node )
379
- logger.debug "parsing round header: >#{node}<"
311
+ def on_round_header( node )
312
+ logger.debug "on round header: >#{node}<"
380
313
 
381
- name = node[1]
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 parse_date_header( node )
336
+ def on_date_header( node )
403
337
  logger.debug( "date header: >#{node}<")
404
338
 
405
- date = _build_date( m: node[2][:m],
406
- d: node[2][:d],
407
- y: node[2][:y],
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
- ## Kane 39', 62', 67'
479
- ## consume/eat-up (optional?) commas
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
- goals
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
- goal = Import::Goal.new(
536
- player: rec[:name],
393
+ rec.minutes.each do |minute|
394
+ goal = Import::Goal.new(
395
+ player: rec.player,
537
396
  team: 1,
538
- minute: rec[:minute],
539
- offset: rec[:offset],
540
- penalty: rec[:pen] || false, # note: pass along/use false NOT nil
541
- owngoal: rec[:og] || false
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
- goals << goal
402
+ goals << goal
403
+ end
544
404
  end
545
405
  goals2.each do |rec|
546
- goal = Import::Goal.new(
547
- player: rec[:name],
406
+ rec.minutes.each do |minute|
407
+ goal = Import::Goal.new(
408
+ player: rec.player,
548
409
  team: 2,
549
- minute: rec[:minute],
550
- offset: rec[:offset],
551
- penalty: rec[:pen] || false, # note: pass along/use false NOT nil
552
- owngoal: rec[:og] || false
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 parse_match( nodes )
573
- logger.debug( "parse match: >#{nodes}<" )
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
- time = nil
579
- teams = []
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
- more = []
582
- status = nil
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
- while !nodes.empty?
585
- node = nodes.shift
586
- node_type = node[0]
587
-
588
- if node_type == :num
589
- num = node[1]
590
- elsif node_type == :date
591
- ## note: date wipes out/clear time
592
- ## time MUST always come after date
593
- time = nil
594
- date = _build_date( m: node[2][:m],
595
- d: node[2][:d],
596
- y: node[2][:y],
597
- start: @start )
598
- elsif node_type == :time
599
- ## note - there's no time (-only) type in ruby
600
- ## use string (e.g. '14:56', '1:44')
601
- ## use 01:44 or 1:44 ?
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
- else
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
- if teams.size != 2
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)
@@ -3,7 +3,7 @@ module SportDb
3
3
  module Module
4
4
  module Quick
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
- MINOR = 3
6
+ MINOR = 5
7
7
  PATCH = 1
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
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.3.1
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-02 00:00:00.000000000 Z
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.0
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.0
26
+ version: 0.5.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sportdb-structs
29
29
  requirement: !ruby/object:Gem::Requirement