sportdb-quick 0.5.1 → 0.5.2

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
  SHA256:
3
- metadata.gz: 71f76e171de23b5062c30f432d5fece7bcb2cb0e7283d658dcf8ff79aefb6aa3
4
- data.tar.gz: 74fc864d5c4b9ca42270abd3fdb941cebdb9857c072c7515e7e422829c018891
3
+ metadata.gz: d7f373cf63aa06b60bfe3f654df254e3e04d5a47c499a6be1dc4f9d90c061f84
4
+ data.tar.gz: ec5b8ea56ef5785b4133cd814254a0a4290873b453e806ad27f974dac4ac8594
5
5
  SHA512:
6
- metadata.gz: 83fa67d7c4bbd0952ad9e02f93be65c488bd728b52f8a9a1159ab42bd299b6b9b37ff5e75573582ef4a7f20ebef1d97ff7da111334dd5f6b4b71bf4793ea84af
7
- data.tar.gz: 9f832375e9d03fe1de7d83d14083428d0f3eda704645cf585449d13cf7929030552075549d68e0d91892be0d66c4bf92fbc41a2403cecee362025ed2b2058513
6
+ metadata.gz: 19dd7b607f4c3288f176f941a570c1f316956ee2867f1cfebaebcf180506a3d640a797ea723ee889406f8f6682c326a95ab89a0877250b4709fa8bb5b6eb8aef
7
+ data.tar.gz: b6a76be55c06acb1f4487794a9097d2f6e1d5ea4414b2f1fabbf32d3f18df2a90cc8024d1c51b8f42d7be1e610ba7543dc9c6b41e3eea4822e16e8b689ca7687
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 0.5.1
1
+ ### 0.5.2
2
2
  ### 0.0.1 / 2024-08-27
3
3
 
4
4
  * Everything is new. First release.
data/Manifest.txt CHANGED
@@ -4,6 +4,8 @@ README.md
4
4
  Rakefile
5
5
  lib/sportdb/quick.rb
6
6
  lib/sportdb/quick/match_parser.rb
7
- lib/sportdb/quick/quick_league_outline_reader.rb
7
+ lib/sportdb/quick/outline.rb
8
+ lib/sportdb/quick/outline_reader.rb
9
+ lib/sportdb/quick/quick_league_outline.rb
8
10
  lib/sportdb/quick/quick_match_reader.rb
9
11
  lib/sportdb/quick/version.rb
@@ -32,22 +32,36 @@ class MatchParser ## simple match parser for team match schedules
32
32
 
33
33
 
34
34
 
35
-
36
- def _read_lines( txt ) ## todo/check: add alias preproc_lines or build_lines or prep_lines etc. - why? why not?
37
- ## returns an array of lines with comments and empty lines striped / removed
38
- lines = []
35
+ def _prep_lines( lines ) ## todo/check: add alias preproc_lines or build_lines or prep_lines etc. - why? why not?
36
+
37
+ ## todo/fix - rework and make simpler
38
+ ## no need to double join array of string to txt etc.
39
+
40
+ txt = if lines.is_a?( Array )
41
+ ## join together with newline
42
+ lines.reduce( String.new ) do |mem,line|
43
+ mem << line; mem << "\n"; mem
44
+ end
45
+ else ## assume single-all-in-one txt
46
+ lines
47
+ end
48
+
49
+ ## preprocess automagically - why? why not?
50
+ ## strip lines with comments and empty lines striped / removed
51
+ txt_new = String.new
39
52
  txt.each_line do |line| ## preprocess
40
53
  line = line.strip
41
54
  next if line.empty? || line.start_with?('#') ### skip empty lines and comments
42
55
 
43
56
  line = line.sub( /#.*/, '' ).strip ### cut-off end-of line comments too
44
- lines << line
57
+
58
+ txt_new << line
59
+ txt_new << "\n"
45
60
  end
46
- lines
61
+ txt_new
47
62
  end
48
63
 
49
64
 
50
-
51
65
  #
52
66
  # todo/fix: change start to start: too!!!
53
67
  # might be optional in the future!! - why? why not?
@@ -58,9 +72,10 @@ class MatchParser ## simple match parser for team match schedules
58
72
  ## todo/check: change to text instead of array of lines - why? why not?
59
73
 
60
74
  ## note - wrap in enumerator/iterator a.k.a lines reader
61
- @lines = lines.is_a?( String ) ?
62
- _read_lines( lines ) : lines
75
+ ## @lines = lines.is_a?( String ) ?
76
+ ## _read_lines( lines ) : lines
63
77
 
78
+ @txt = _prep_lines( lines )
64
79
  @start = start
65
80
  @errors = []
66
81
  end
@@ -90,17 +105,9 @@ class MatchParser ## simple match parser for team match schedules
90
105
  @tree = []
91
106
 
92
107
 
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
-
101
108
  if debug?
102
109
  puts "lines:"
103
- pp txt
110
+ pp @txt
104
111
  end
105
112
 
106
113
  =begin
@@ -123,7 +130,7 @@ class MatchParser ## simple match parser for team match schedules
123
130
  @tree << t
124
131
  =end
125
132
 
126
- parser = RaccMatchParser.new( txt ) ## use own parser instance (not shared) - why? why not?
133
+ parser = RaccMatchParser.new( @txt ) ## use own parser instance (not shared) - why? why not?
127
134
  @tree = parser.parse
128
135
  ## pp @tree
129
136
 
@@ -151,6 +158,8 @@ class MatchParser ## simple match parser for team match schedules
151
158
  on_match_line( node )
152
159
  elsif node.is_a? RaccMatchParser::GoalLine
153
160
  on_goal_line( node )
161
+ elsif node.is_a? RaccMatchParser::LineupLine
162
+ ## skip lineup for now
154
163
  else
155
164
  ## report error
156
165
  msg = "!! WARN - unknown node (parse tree type) - #{node.class.name}"
@@ -159,7 +168,6 @@ class MatchParser ## simple match parser for team match schedules
159
168
 
160
169
  log( msg )
161
170
  log( node.pretty_inspect )
162
- ## exit 1
163
171
  end
164
172
  end # tree.each
165
173
 
@@ -566,18 +574,26 @@ class GoalStruct
566
574
  time_str = time if date && time
567
575
 
568
576
 
569
- ground = nil
577
+ ground = nil
578
+ timezone = nil
579
+ if node.geo
580
+ ground = node.geo
581
+ ## note: only add/check for timezone if geo (aka ground) is present - why? why not?
582
+ timezone = node.timezone if node.timezone
583
+ end
584
+
570
585
 
571
- @matches << Import::Match.new( num: num,
572
- date: date_str,
573
- time: time_str,
574
- team1: team1, ## note: for now always use mapping value e.g. rec (NOT string e.g. team1.name)
575
- team2: team2, ## note: for now always use mapping value e.g. rec (NOT string e.g. team2.name)
576
- score: score,
577
- round: round ? round.name : nil, ## note: for now always use string (assume unique canonical name for event)
578
- group: @last_group ? @last_group.name : nil, ## note: for now always use string (assume unique canonical name for event)
579
- status: status,
580
- ground: ground )
586
+ @matches << Import::Match.new( num: num,
587
+ date: date_str,
588
+ time: time_str,
589
+ team1: team1, ## note: for now always use mapping value e.g. rec (NOT string e.g. team1.name)
590
+ team2: team2, ## note: for now always use mapping value e.g. rec (NOT string e.g. team2.name)
591
+ score: score,
592
+ round: round ? round.name : nil, ## note: for now always use string (assume unique canonical name for event)
593
+ group: @last_group ? @last_group.name : nil, ## note: for now always use string (assume unique canonical name for event)
594
+ status: status,
595
+ ground: ground,
596
+ timezone: timezone )
581
597
  ### todo: cache team lookups in hash?
582
598
  end
583
599
  end # class MatchParser
@@ -0,0 +1,96 @@
1
+
2
+ module SportDb
3
+
4
+ ###
5
+ # add a simple Outline convenience class
6
+ # for processing OUtlines with OUtlineReader
7
+ # rename to simply Outline - why? why not?
8
+ # todo - add more processing options - why? why not?
9
+
10
+ class Outline
11
+ def self.read( path )
12
+ nodes = OutlineReader.read( path )
13
+ new( nodes )
14
+ end
15
+
16
+ def self.parse( txt )
17
+ nodes = OutlineReader.parse( txt )
18
+ new( nodes )
19
+ end
20
+
21
+
22
+ def initialize( nodes )
23
+ @nodes = nodes
24
+ end
25
+
26
+ def each_para( &blk )
27
+ ## note: every (new) read call - resets errors list to empty
28
+ ### @errors = []
29
+
30
+ ## process nodes
31
+ h1 = nil
32
+ h2 = nil
33
+ orphans = 0 ## track paragraphs's with no heading
34
+
35
+ @nodes.each do |node|
36
+ type = node[0]
37
+
38
+ if type == :h1
39
+ h1 = node[1] ## get heading text
40
+ puts " = Heading 1 >#{node[1]}<"
41
+ elsif type == :h2
42
+ if h1.nil?
43
+ puts "!! WARN - no heading for subheading; skipping processing"
44
+ next
45
+ end
46
+ h2 = node[1] ## get heading text
47
+ puts " == Heading 2 >#{node[1]}<"
48
+ elsif type == :p
49
+ if h1.nil?
50
+ orphans += 1 ## only warn once
51
+ puts "!! WARN - no heading for #{orphans} text paragraph(s); skipping parse"
52
+ next
53
+ end
54
+
55
+ lines = node[1]
56
+ blk.call( lines )
57
+ else
58
+ pp node
59
+ raise ArgumentError, "unsupported (node) type >#{type}<"
60
+ end
61
+ end # each node
62
+ end # each_para
63
+ alias_method :each_paragraph, :each_para
64
+
65
+
66
+ ## get all para(graphs) as text (not array of lines)
67
+ ## make default - why? why not?
68
+ #
69
+ # design - or wrap lines into a Para class
70
+ # with properties lines and text
71
+ # and such - why? why not?
72
+ # downside - might be overkill/overengineered
73
+ # just use simple txt as string (buffer) for all - why? why not?
74
+ ##
75
+ ## hacky alternative - add a to_text or text method to string and array - why? why not?
76
+
77
+
78
+ def each_para_text( &blk ) ## or use each_text or ? - why? why not=
79
+ each_para do |lines|
80
+ txt = lines.reduce( String.new ) do |mem,line|
81
+ mem << line; mem << "\n"; mem
82
+ end
83
+ blk.call( txt )
84
+ end
85
+ end
86
+ end # class Outline
87
+
88
+
89
+
90
+ ###
91
+ # add alternate alias - why? why not?
92
+ QuickMatchOutline = Outline
93
+
94
+
95
+ end ## module SportDb
96
+
@@ -0,0 +1,98 @@
1
+
2
+
3
+ module SportDb
4
+
5
+
6
+ class OutlineReader
7
+
8
+ def self.debug=(value) @@debug = value; end
9
+ def self.debug?() @@debug ||= false; end
10
+ def debug?() self.class.debug?; end
11
+
12
+
13
+
14
+ def self.read( path ) ## use - rename to read_file or from_file etc. - why? why not?
15
+ txt = File.open( path, 'r:utf-8' ) {|f| f.read }
16
+ parse( txt )
17
+ end
18
+
19
+ def self.parse( txt )
20
+ new( txt ).parse
21
+ end
22
+
23
+ def initialize( txt )
24
+ @txt = txt
25
+ end
26
+
27
+ ## note: skip "decorative" only heading e.g. ========
28
+ ## todo/check: find a better name e.g. HEADING_EMPTY_RE or HEADING_LINE_RE or ???
29
+ HEADING_BLANK_RE = %r{\A
30
+ ={1,}
31
+ \z}x
32
+
33
+ ## note: like in wikimedia markup (and markdown) all optional trailing ==== too
34
+ HEADING_RE = %r{\A
35
+ (?<marker>={1,}) ## 1. leading ======
36
+ [ ]*
37
+ (?<text>[^=]+) ## 2. text (note: for now no "inline" = allowed)
38
+ [ ]*
39
+ =* ## 3. (optional) trailing ====
40
+ \z}x
41
+
42
+ def parse
43
+ outline=[] ## outline structure
44
+ start_para = true ## start new para(graph) on new text line?
45
+
46
+ @txt.each_line do |line|
47
+ line = line.strip ## todo/fix: keep leading and trailing spaces - why? why not?
48
+
49
+ if line.empty? ## todo/fix: keep blank line nodes?? and just remove comments and process headings?! - why? why not?
50
+ start_para = true
51
+ next
52
+ end
53
+
54
+ break if line == '__END__'
55
+
56
+ next if line.start_with?( '#' ) ## skip comments too
57
+ ## strip inline (until end-of-line) comments too
58
+ ## e.g Eupen | KAS Eupen ## [de]
59
+ ## => Eupen | KAS Eupen
60
+ ## e.g bq Bonaire, BOE # CONCACAF
61
+ ## => bq Bonaire, BOE
62
+ line = line.sub( /#.*/, '' ).strip
63
+ pp line if debug?
64
+
65
+ ## todo/check: also use heading blank as paragraph "breaker" or treat it like a comment ?? - why? why not?
66
+ next if HEADING_BLANK_RE.match( line ) # skip "decorative" only heading e.g. ========
67
+
68
+ ## note: like in wikimedia markup (and markdown) all optional trailing ==== too
69
+ if m=HEADING_RE.match( line )
70
+ start_para = true
71
+
72
+ heading_marker = m[:marker]
73
+ heading_level = heading_marker.length ## count number of = for heading level
74
+ heading = m[:text].strip
75
+
76
+ puts "heading #{heading_level} >#{heading}<" if debug?
77
+ outline << [:"h#{heading_level}", heading]
78
+ else ## assume it's a (plain/regular) text line
79
+ if start_para
80
+ outline << [:p, [line]]
81
+ start_para = false
82
+ else
83
+ node = outline[-1] ## get last entry
84
+ if node[0] == :p ## assert it's a p(aragraph) node!!!
85
+ node[1] << line ## add line to p(aragraph)
86
+ else
87
+ puts "!! ERROR - invalid outline state / format - expected p(aragraph) node; got:"
88
+ pp node
89
+ exit 1
90
+ end
91
+ end
92
+ end
93
+ end
94
+ outline
95
+ end # method read
96
+ end # class OutlineReader
97
+
98
+ end # module SportDb
@@ -3,39 +3,66 @@
3
3
  module SportDb
4
4
 
5
5
  ## shared "higher-level" outline reader
6
- ### quick version WITHOUT any validation/mapping !!!
6
+ ### quick version WITHOUT any (database) validation/mapping/normalization !!!
7
7
 
8
- class QuickLeagueOutlineReader
8
+
9
+ class QuickLeagueOutline
9
10
 
10
11
  def self.read( path )
11
- txt = File.open( path, 'r:utf-8' ) {|f| f.read }
12
- parse( txt )
13
- end
12
+ nodes = OutlineReader.read( path )
13
+ new( nodes )
14
+ end
14
15
 
15
16
  def self.parse( txt )
16
- new( txt ).parse
17
+ nodes = OutlineReader.parse( txt )
18
+ new( nodes )
17
19
  end
18
20
 
19
21
 
20
- def initialize( txt )
21
- @txt = txt
22
+
23
+ def initialize( nodes )
24
+ @nodes = nodes
22
25
  end
23
26
 
24
- def parse
27
+
28
+ ###
29
+ # use Section struct for easier access - why? why not?
30
+ ## e.g. sec.league instead of sec[:league] etc.
31
+
32
+ Section = Struct.new( :league, :season, :stage, :lines ) do
33
+ def text ## for alternate line access (all-in-text string)
34
+ txt = lines.reduce( String.new ) do |mem,line|
35
+ mem << line; mem << "\n"; mem
36
+ end
37
+ txt
38
+ end
39
+ end
40
+
41
+ def each_sec( &blk )
42
+ @secs ||= _parse
43
+
44
+ @secs.each do |sec|
45
+ blk.call( sec )
46
+ end
47
+ end
48
+ alias_method :each_section, :each_sec
49
+
50
+
51
+ def _parse
25
52
  secs=[] # sec(tion)s
26
- OutlineReader.parse( @txt ).each do |node|
53
+ @nodes.each do |node|
27
54
  if node[0] == :h1
28
55
  ## check for league (and stage) and season
29
56
  heading = node[1]
30
- values = split_league( heading )
57
+ values = _split_league( heading )
31
58
  if m=values[0].match( LEAGUE_SEASON_HEADING_RE )
32
59
  puts "league >#{m[:league]}<, season >#{m[:season]}<"
33
60
 
34
- secs << { league: m[:league],
35
- season: m[:season],
36
- stage: values[1], ## note: defaults to nil if not present
37
- lines: []
38
- }
61
+ secs << Section.new( league: m[:league],
62
+ season: m[:season],
63
+ stage: values[1], ## note: defaults to nil if not present
64
+ lines: []
65
+ )
39
66
  else
40
67
  puts "** !!! ERROR - cannot match league and season in heading; season missing?"
41
68
  pp heading
@@ -44,12 +71,12 @@ class QuickLeagueOutlineReader
44
71
  elsif node[0] == :h2
45
72
  ## todo/check - make sure parsed h1 first
46
73
  heading = node[1]
47
- ## reuse league, season from h1
48
- secs << { league: secs[-1][:league],
49
- season: secs[-1][:season],
50
- stage: heading,
51
- lines: []
52
- }
74
+ ## note - reuse league, season from h1
75
+ secs << Section.new( league: secs[-1].league,
76
+ season: secs[-1].season,
77
+ stage: heading,
78
+ lines: []
79
+ )
53
80
  elsif node[0] == :p ## paragraph with (text) lines
54
81
  lines = node[1]
55
82
  ## note: skip lines if no heading seen
@@ -58,7 +85,8 @@ class QuickLeagueOutlineReader
58
85
  pp lines
59
86
  else
60
87
  ## todo/check: unroll paragraphs into lines or pass along paragraphs - why? why not?
61
- secs[-1][:lines] += lines
88
+ ## add paragraphs not unrolled lines - why? why not?
89
+ secs[-1].lines += lines
62
90
  end
63
91
  else
64
92
  puts "** !!! ERROR - unknown line type; for now only heading 1 for leagues supported; sorry:"
@@ -67,7 +95,7 @@ class QuickLeagueOutlineReader
67
95
  end
68
96
  end
69
97
  secs
70
- end # method parse
98
+ end # method _parse
71
99
 
72
100
 
73
101
  ## split into league + season
@@ -81,7 +109,7 @@ class QuickLeagueOutlineReader
81
109
  )
82
110
  $}x
83
111
 
84
- def split_league( str ) ## todo/check: rename to parse_league(s) - why? why not?
112
+ def _split_league( str ) ## todo/check: rename to parse_league(s) - why? why not?
85
113
  ## split into league / stage / ... e.g.
86
114
  ## => Österr. Bundesliga 2018/19, Regular Season
87
115
  ## => Österr. Bundesliga 2018/19, Championship Round
@@ -91,5 +119,5 @@ class QuickLeagueOutlineReader
91
119
  values = values.map { |value| value.strip } ## remove all whitespaces
92
120
  values
93
121
  end
94
- end # class QuickLeagueOutlineReader
122
+ end # class QuickLeagueOutline
95
123
  end # module SportDb
@@ -24,7 +24,7 @@ class QuickMatchReader
24
24
 
25
25
  def initialize( txt )
26
26
  @errors = []
27
- @txt = txt
27
+ @outline = QuickLeagueOutline.parse( txt )
28
28
  end
29
29
 
30
30
  attr_reader :errors
@@ -55,17 +55,15 @@ class QuickMatchReader
55
55
  @errors = []
56
56
 
57
57
  @data = {} # return data hash with leagues
58
- # and seasons
59
- # for now merge stage into matches
60
-
61
- secs = QuickLeagueOutlineReader.parse( @txt )
62
- pp secs if debug?
63
-
64
- secs.each do |sec| ## sec(tion)s
65
- season = Season.parse( sec[:season] ) ## convert (str) to season obj!!!
66
- league = sec[:league]
67
- stage = sec[:stage]
68
- lines = sec[:lines]
58
+ # and seasons
59
+ # for now merge stage into matches
60
+
61
+ @outline.each_sec do |sec| ## sec(tion)s
62
+ ### move season parse into outline upstream - why? why not?
63
+ season = Season.parse( sec.season ) ## convert (str) to season obj!!!
64
+ league = sec.league
65
+ stage = sec.stage
66
+ lines = sec.lines
69
67
 
70
68
  start = if season.year?
71
69
  Date.new( season.start_year, 1, 1 )
@@ -4,7 +4,7 @@ module SportDb
4
4
  module Quick
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
6
  MINOR = 5
7
- PATCH = 1
7
+ PATCH = 2
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
data/lib/sportdb/quick.rb CHANGED
@@ -17,10 +17,17 @@ end
17
17
  ## our own code
18
18
  require_relative 'quick/version'
19
19
 
20
-
20
+ ## "generic" outline readers, documents & more
21
+ ##
22
+ ## todo/check - move outline reader upstream to cocos - why? why not?
23
+ ## use read_outline(), parse_outline() - why? why not?
24
+ require_relative 'quick/outline_reader'
25
+ require_relative 'quick/outline'
26
+
27
+ ## match & league machinery
21
28
  require_relative 'quick/match_parser'
22
29
 
23
- require_relative 'quick/quick_league_outline_reader'
30
+ require_relative 'quick/quick_league_outline'
24
31
  require_relative 'quick/quick_match_reader'
25
32
 
26
33
 
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.5.1
4
+ version: 0.5.2
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-18 00:00:00.000000000 Z
11
+ date: 2025-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sportdb-parser
@@ -101,7 +101,9 @@ files:
101
101
  - Rakefile
102
102
  - lib/sportdb/quick.rb
103
103
  - lib/sportdb/quick/match_parser.rb
104
- - lib/sportdb/quick/quick_league_outline_reader.rb
104
+ - lib/sportdb/quick/outline.rb
105
+ - lib/sportdb/quick/outline_reader.rb
106
+ - lib/sportdb/quick/quick_league_outline.rb
105
107
  - lib/sportdb/quick/quick_match_reader.rb
106
108
  - lib/sportdb/quick/version.rb
107
109
  homepage: https://github.com/sportdb/sport.db