sportdb-quick 0.1.2 → 0.2.1

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: 9a1f7a6531aba4ac7f0223ee696b347f90d422d6297ee04e03d4839f2e3a1ba0
4
- data.tar.gz: 3d2e7b520183f40149856467646af58a17d39232d3bb0f78c285e7c220af7ece
3
+ metadata.gz: 743ddb45d7379bdcb351178da359316544e663307b5d96c34f6ac90b9752fce3
4
+ data.tar.gz: 86960f084c612aec1e04f183ba1f3a89959518355e498527734b23a265090fa9
5
5
  SHA512:
6
- metadata.gz: 071ffe16ce450fccdeb4a6fcbcc4749a2ffec2e22a95ca0b9ae8d80d981741bd6f960b0715a61aee23452dd699bd5043e46ab197fcc9a070e379e13a073f4508
7
- data.tar.gz: c765504847f2240b14068805e3965e2f186d38f78674f631d95cacd286c64b08007b4316043951979538bf6c1a7f7e25cf14f48e96fcd33fafbae6d124216c14
6
+ metadata.gz: 6068e848f99a756b9de1d4012cda3d5c6750dc99c329f773cbd692ffa9004f2cfa5835ffdb329aae055eaa30f1ffafeab42adc1a627d05ca040261d71d5476a7
7
+ data.tar.gz: d143f15ecca6cc4bdf3c72e0d8883c94622198e9fd721ce14e93ebc882c127ef4300d865bb05d7c129e82e2f27d81ea25ca4894e0d254a0b80e6600911cd6ac5
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 0.1.2
1
+ ### 0.2.1
2
2
 
3
3
  ### 0.0.1 / 2024-08-27
4
4
 
data/Manifest.txt CHANGED
@@ -9,7 +9,6 @@ lib/sportdb/quick/csv/goal_parser_csv.rb
9
9
  lib/sportdb/quick/csv/match_parser_csv.rb
10
10
  lib/sportdb/quick/csv/match_status_parser.rb
11
11
  lib/sportdb/quick/match_parser.rb
12
- lib/sportdb/quick/opts.rb
13
12
  lib/sportdb/quick/quick_league_outline_reader.rb
14
13
  lib/sportdb/quick/quick_match_reader.rb
15
14
  lib/sportdb/quick/version.rb
data/bin/fbt CHANGED
@@ -26,8 +26,8 @@ require 'optparse'
26
26
 
27
27
  args = ARGV
28
28
  opts = { debug: false,
29
- metal: false,
30
- quick: true }
29
+ file: nil,
30
+ }
31
31
 
32
32
  parser = OptionParser.new do |parser|
33
33
  parser.banner = "Usage: #{$PROGRAM_NAME} [options]"
@@ -35,24 +35,21 @@ require 'optparse'
35
35
  ##
36
36
  ## check if git has a offline option?? (use same)
37
37
  ## check for other tools - why? why not?
38
-
39
-
40
- parser.on( "--verbose", "--debug",
38
+ # parser.on( "-q", "--quiet",
39
+ # "less debug output/messages - default is (#{!opts[:debug]})" ) do |debug|
40
+ # opts[:debug] = false
41
+ # end
42
+ parser.on( "--verbose", "--debug",
41
43
  "turn on verbose / debug output (default: #{opts[:debug]})" ) do |debug|
42
- opts[:debug] = true
43
- end
44
+ opts[:debug] = true
45
+ end
46
+
47
+ parser.on( "-f FILE", "--file FILE",
48
+ "read datafiles (pathspecs) via .csv file") do |file|
49
+ opts[:file] = file
50
+ end
44
51
 
45
- parser.on( "--metal",
46
- "turn off typed parse tree; show to the metal tokens"+
47
- " (default: #{opts[:metal]})" ) do |metal|
48
- opts[:metal] = true
49
- end
50
52
 
51
- parser.on( "--quick",
52
- "use quick match reader; output matches in json"+
53
- " (default: #{opts[:quick]})" ) do |quick|
54
- opts[:quick] = true
55
- end
56
53
  end
57
54
  parser.parse!( args )
58
55
 
@@ -62,58 +59,110 @@ puts "ARGV:"
62
59
  p args
63
60
 
64
61
 
62
+ ## todo/check - use packs or projects or such
63
+ ## instead of specs - why? why not?
64
+ specs = []
65
+ if opts[:file]
66
+ recs = read_csv( opts[:file] )
67
+ pp recs
68
+ ## note - make pathspecs relative to passed in file arg!!!
69
+ basedir = File.dirname( opts[:file] )
70
+ recs.each do |rec|
71
+ paths = SportDb::Parser::Opts.find( rec['path'], dir: basedir )
72
+ specs << [paths, rec]
73
+ end
74
+ else
75
+ paths = if args.empty?
76
+ [
77
+ '../../../openfootball/euro/2021--europe/euro.txt',
78
+ '../../../openfootball/euro/2024--germany/euro.txt',
79
+ ]
80
+ else
81
+ ## check for directories
82
+ ## and auto-expand
83
+ SportDb::Parser::Opts.expand_args( args )
84
+ end
85
+ specs << [paths, {}]
86
+ end
87
+
88
+
89
+ if opts[:debug]
90
+ SportDb::QuickMatchReader.debug = true
91
+ SportDb::MatchParser.debug = true
92
+ else
93
+ SportDb::QuickMatchReader.debug = false
94
+ SportDb::MatchParser.debug = false
95
+ LogUtils::Logger.root.level = :info
96
+ end
65
97
 
66
98
 
99
+ specs.each_with_index do |(paths, rec),i|
100
+ errors = []
101
+ paths.each_with_index do |path,j|
102
+ puts "==> [#{j+1}/#{paths.size}] reading >#{path}<..."
103
+ quick = SportDb::QuickMatchReader.new( read_text( path ) )
104
+ matches = quick.parse
105
+
106
+ if quick.errors?
107
+ puts "!! #{quick.errors.size} error(s):"
108
+ pp quick.errors
109
+
110
+ quick.errors.each do |err|
111
+ errors << [ path, *err ] # note: use splat (*) to add extra values (starting with msg)
112
+ end
113
+ end
114
+ puts " #{matches.size} match(es)"
115
+ end
116
+
117
+ if errors.size > 0
118
+ puts
119
+ puts "!! #{errors.size} PARSE ERRORS in #{paths.size} datafile(s)"
120
+ pp errors
121
+ else
122
+ puts
123
+ puts " OK - no parse errors in #{paths.size} datafile(s)"
124
+ end
125
+
126
+ ## add errors to rec via rec['errors'] to allow
127
+ ## for further processing/reporting
128
+ rec['errors'] = errors
129
+ end
67
130
 
68
- paths = if args.empty?
69
- [
70
- '../../../openfootball/euro/2021--europe/euro.txt',
71
- '../../../openfootball/euro/2024--germany/euro.txt',
72
- ]
73
- else
74
- ## check for directories
75
- ## and auto-expand
76
-
77
- SportDb::Quick::Opts.expand_args( args )
78
- end
79
131
 
80
132
 
81
- if opts[:quick]
133
+ ###
134
+ ## generate a report if --file option used
135
+ if opts[:file]
82
136
 
83
- paths.each_with_index do |path,i|
84
- puts "==> [#{i+1}/#{paths.size}] reading >#{path}<..."
137
+ buf = String.new
85
138
 
86
- matches = SportDb::QuickMatchReader.read( path )
87
- ## pp matches
88
- ## try json for matches
89
- data = matches.map {|match| match.as_json }
90
- pp data
91
- puts
92
- puts " #{data.size} match(es)"
93
- end
94
- else
95
- SportDb::Parser::Linter.debug = true if opts[:debug]
139
+ buf << "# fbt summary report - #{specs.size} dataset(s)\n\n"
96
140
 
97
- linter = SportDb::Parser::Linter.new
141
+ specs.each_with_index do |(paths, rec),i|
142
+ errors = rec['errors']
98
143
 
99
- errors = []
144
+ if errors.size > 0
145
+ buf << "!! #{errors.size} ERROR(S) "
146
+ else
147
+ buf << " OK "
148
+ end
149
+ buf << "%-20s" % rec['path']
150
+ buf << " - #{paths.size} datafile(s)"
151
+ buf << "\n"
100
152
 
101
- paths.each_with_index do |path,i|
102
- puts "==> [#{i+1}/#{paths.size}] reading >#{path}<..."
103
- linter.read( path, parse: !opts[:metal] )
153
+ if errors.size > 0
154
+ buf << errors.pretty_inspect
155
+ buf << "\n"
156
+ end
157
+ end
104
158
 
105
- errors += linter.errors if linter.errors?
106
- end
159
+ puts
160
+ puts "SUMMARY:"
161
+ puts buf
107
162
 
108
- if errors.size > 0
109
- puts
110
- pp errors
111
- puts
112
- puts "!! #{errors.size} parse error(s) in #{paths.size} datafiles(s)"
113
- else
114
- puts
115
- puts "OK no parse errors found in #{paths.size} datafile(s)"
116
- end
163
+ # maybe write out in the future?
164
+ # basedir = File.dirname( opts[:file] )
165
+ # basename = File.basename( opts[:file], File.extname( opts[:file] ))
117
166
  end
118
167
 
119
168
 
@@ -3,6 +3,12 @@ module SportDb
3
3
 
4
4
  class MatchParser ## simple match parser for team match schedules
5
5
 
6
+ def self.debug=(value) @@debug = value; end
7
+ def self.debug?() @@debug ||= false; end ## note: default is FALSE
8
+ def debug?() self.class.debug?; end
9
+
10
+ include Logging ## e.g. logger#debug, logger#info, etc.
11
+
6
12
 
7
13
  def self.parse( lines, start: )
8
14
  ## todo/fix: add support for txt and lines
@@ -13,11 +19,7 @@ class MatchParser ## simple match parser for team match schedules
13
19
  end
14
20
 
15
21
 
16
- include Logging ## e.g. logger#debug, logger#info, etc.
17
22
 
18
- def self.debug=(value) @@debug = value; end
19
- def self.debug?() @@debug ||= false; end ## note: default is FALSE
20
- def debug?() self.class.debug?; end
21
23
 
22
24
  def _read_lines( txt ) ## todo/check: add alias preproc_lines or build_lines or prep_lines etc. - why? why not?
23
25
  ## returns an array of lines with comments and empty lines striped / removed
@@ -70,10 +72,17 @@ class MatchParser ## simple match parser for team match schedules
70
72
  _read_lines( lines ) : lines
71
73
 
72
74
  @start = start
75
+ @errors = []
73
76
  end
74
77
 
75
78
 
79
+ attr_reader :errors
80
+ def errors?() @errors.size > 0; end
81
+
76
82
  def parse
83
+ ## note: every (new) read call - resets errors list to empty
84
+ @errors = []
85
+
77
86
  @last_date = nil
78
87
  @last_time = nil
79
88
  @last_round = nil
@@ -92,8 +101,6 @@ class MatchParser ## simple match parser for team match schedules
92
101
 
93
102
 
94
103
  @parser = Parser.new
95
-
96
- @errors = []
97
104
  @tree = []
98
105
 
99
106
  attrib_found = false
@@ -509,7 +516,7 @@ class MatchParser ## simple match parser for team match schedules
509
516
  end
510
517
  end
511
518
 
512
- pp [goals1,goals2]
519
+ pp [goals1,goals2] if debug?
513
520
 
514
521
  ## wrap in struct andd add/append to match
515
522
  =begin
@@ -547,7 +554,7 @@ class GoalStruct
547
554
  goals << goal
548
555
  end
549
556
 
550
- pp goals
557
+ pp goals if debug?
551
558
 
552
559
  ## quick & dirty - auto add goals to last match
553
560
  ## note - for hacky (quick& dirty) multi-line support
@@ -629,7 +636,9 @@ class GoalStruct
629
636
  else
630
637
  puts "!! PARSE ERROR - unexpected node type #{node_type} in match line; got:"
631
638
  pp node
632
- exit 1
639
+ ## exit 1
640
+ @errors << ["PARSE ERROR - unexpected node type #{node_type} in match line; got: #{node.inspect}"]
641
+ return
633
642
  end
634
643
  end
635
644
 
@@ -637,7 +646,9 @@ class GoalStruct
637
646
  if teams.size != 2
638
647
  puts "!! PARSE ERROR - expected two teams; got #{teams.size}:"
639
648
  pp teams
640
- exit 1
649
+ ## exit 1
650
+ @errors << ["PARSE ERROR - expected two teams; got #{teams.size}: #{teams.inspect}"]
651
+ return
641
652
  end
642
653
 
643
654
  team1 = teams[0]
@@ -86,7 +86,8 @@ class QuickLeagueOutlineReader
86
86
  ## => Österr. Bundesliga 2018/19, Regular Season
87
87
  ## => Österr. Bundesliga 2018/19, Championship Round
88
88
  ## etc.
89
- values = str.split( /[,<>‹›]/ ) ## note: allow , > < or › ‹ for now
89
+ ## note limit split to two parts only!!!!
90
+ values = str.split( /[,<>‹›]/, 2 ) ## note: allow , > < or › ‹ for now
90
91
  values = values.map { |value| value.strip } ## remove all whitespaces
91
92
  values
92
93
  end
@@ -4,6 +4,12 @@
4
4
  module SportDb
5
5
  class QuickMatchReader
6
6
 
7
+ def self.debug=(value) @@debug = value; end
8
+ def self.debug?() @@debug ||= false; end ## note: default is FALSE
9
+ def debug?() self.class.debug?; end
10
+
11
+
12
+
7
13
  def self.read( path ) ## use - rename to read_file or from_file etc. - why? why not?
8
14
  txt = File.open( path, 'r:utf-8' ) {|f| f.read }
9
15
  parse( txt )
@@ -17,16 +23,43 @@ class QuickMatchReader
17
23
  include Logging
18
24
 
19
25
  def initialize( txt )
26
+ @errors = []
20
27
  @txt = txt
21
28
  end
22
29
 
30
+ attr_reader :errors
31
+ def errors?() @errors.size > 0; end
32
+
33
+
34
+ ###
35
+ # helpers get matches & more after parse; all stored in data
36
+ #
37
+ ## change/rename to event - why? why not?
38
+ def league_name
39
+ league = @data.keys[0]
40
+ season = @data[ league ].keys[0]
41
+
42
+ "#{league} #{season}"
43
+ end
44
+
45
+ def matches
46
+ league = @data.keys[0]
47
+ season = @data[ league ].keys[0]
48
+ @data[league][season]
49
+ end
50
+
51
+
52
+
23
53
  def parse
24
- data = {} # return data hash with leagues
54
+ ## note: every (new) read call - resets errors list to empty
55
+ @errors = []
56
+
57
+ @data = {} # return data hash with leagues
25
58
  # and seasons
26
59
  # for now merge stage into matches
27
60
 
28
61
  secs = QuickLeagueOutlineReader.parse( @txt )
29
- pp secs
62
+ pp secs if debug?
30
63
 
31
64
  secs.each do |sec| ## sec(tion)s
32
65
  season = Season.parse( sec[:season] ) ## convert (str) to season obj!!!
@@ -46,14 +79,20 @@ class QuickMatchReader
46
79
 
47
80
  auto_conf_teams, matches, rounds, groups = parser.parse
48
81
 
49
- puts ">>> #{auto_conf_teams.size} teams:"
50
- pp auto_conf_teams
51
- puts ">>> #{matches.size} matches:"
52
- ## pp matches
53
- puts ">>> #{rounds.size} rounds:"
54
- pp rounds
55
- puts ">>> #{groups.size} groups:"
56
- pp groups
82
+ ## auto-add "upstream" errors from parser
83
+ @errors += parser.errors if parser.errors?
84
+
85
+
86
+ if debug?
87
+ puts ">>> #{auto_conf_teams.size} teams:"
88
+ pp auto_conf_teams
89
+ puts ">>> #{matches.size} matches:"
90
+ ## pp matches
91
+ puts ">>> #{rounds.size} rounds:"
92
+ pp rounds
93
+ puts ">>> #{groups.size} groups:"
94
+ pp groups
95
+ end
57
96
 
58
97
  ## note: pass along stage (if present): stage - optional from heading!!!!
59
98
  if stage
@@ -62,10 +101,10 @@ class QuickMatchReader
62
101
  end
63
102
  end
64
103
 
65
- data[ league ] ||= {}
66
- data[ league ][ season.key ] ||= []
104
+ @data[ league ] ||= {}
105
+ @data[ league ][ season.key ] ||= []
67
106
 
68
- data[ league ][ season.key ] += matches
107
+ @data[ league ][ season.key ] += matches
69
108
  ## note - skip teams, rounds, and groups for now
70
109
  end
71
110
 
@@ -73,21 +112,21 @@ class QuickMatchReader
73
112
  ## allowed in quick style
74
113
 
75
114
 
76
- leagues = data.keys
115
+ leagues = @data.keys
77
116
  if leagues.size != 1
78
117
  puts "!! (QUICK) PARSE ERROR - expected one league only; got #{leagues.size}:"
79
118
  pp leagues
80
119
  exit 1
81
120
  end
82
121
 
83
- seasons = data[ leagues[0] ].keys
122
+ seasons = @data[ leagues[0] ].keys
84
123
  if seasons.size != 1
85
124
  puts "!! (QUICK) PARSE ERROR - expected one #{leagues[0]} season only; got #{seasons.size}:"
86
125
  pp seasons
87
126
  exit 1
88
127
  end
89
128
 
90
- data[ leagues[0] ][ seasons[0] ]
129
+ @data[ leagues[0] ][ seasons[0] ]
91
130
  end # method parse
92
131
 
93
132
  end # class QuickMatchReader
@@ -3,8 +3,8 @@ 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 = 1
7
- PATCH = 2
6
+ MINOR = 2
7
+ PATCH = 1
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
data/lib/sportdb/quick.rb CHANGED
@@ -16,8 +16,8 @@ end
16
16
 
17
17
  ## our own code
18
18
  require_relative 'quick/version'
19
- require_relative 'quick/opts'
20
19
 
20
+ # require_relative 'quick/opts'
21
21
  # require_relative 'quick/linter'
22
22
  # require_relative 'quick/outline_reader'
23
23
 
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.1.2
4
+ version: 0.2.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: 2024-09-18 00:00:00.000000000 Z
11
+ date: 2024-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sportdb-parser
@@ -107,7 +107,6 @@ files:
107
107
  - lib/sportdb/quick/csv/match_parser_csv.rb
108
108
  - lib/sportdb/quick/csv/match_status_parser.rb
109
109
  - lib/sportdb/quick/match_parser.rb
110
- - lib/sportdb/quick/opts.rb
111
110
  - lib/sportdb/quick/quick_league_outline_reader.rb
112
111
  - lib/sportdb/quick/quick_match_reader.rb
113
112
  - lib/sportdb/quick/version.rb
@@ -1,70 +0,0 @@
1
-
2
- module SportDb
3
- module Quick
4
-
5
- ###
6
- ## note - Opts Helpers for now nested inside Parser - keep here? why? why not?
7
- class Opts
8
-
9
- SEASON_RE = %r{ (?:
10
- \d{4}-\d{2}
11
- | \d{4}(--[a-z0-9_-]+)?
12
- )
13
- }x
14
- SEASON = SEASON_RE.source ## "inline" helper for embedding in other regexes - keep? why? why not?
15
-
16
-
17
- ## note: if pattern includes directory add here
18
- ## (otherwise move to more "generic" datafile) - why? why not?
19
- MATCH_RE = %r{ (?: ^|/ ) # beginning (^) or beginning of path (/)
20
- #{SEASON}
21
- /[a-z0-9_-]+\.txt$ ## txt e.g /1-premierleague.txt
22
- }x
23
-
24
-
25
- def self.find( path )
26
- datafiles = []
27
-
28
- ## note: normalize path - use File.expand_path ??
29
- ## change all backslash to slash for now
30
- ## path = path.gsub( "\\", '/' )
31
- path = File.expand_path( path )
32
-
33
- ## check all txt files
34
- ## note: incl. files starting with dot (.)) as candidates
35
- ## (normally excluded with just *)
36
- candidates = Dir.glob( "#{path}/**/{*,.*}.txt" )
37
- ## pp candidates
38
- candidates.each do |candidate|
39
- datafiles << candidate if MATCH_RE.match( candidate )
40
- end
41
-
42
- ## pp datafiles
43
- datafiles
44
- end
45
-
46
-
47
- def self.expand_args( args )
48
- paths = []
49
-
50
- args.each do |arg|
51
- ## check if directory
52
- if Dir.exist?( arg )
53
- datafiles = find( arg )
54
- puts
55
- puts " found #{datafiles.size} match txt datafiles in #{arg}"
56
- pp datafiles
57
- paths += datafiles
58
- else
59
- ## assume it's a file
60
- paths << arg
61
- end
62
- end
63
-
64
- paths
65
- end
66
- end # class Opts
67
-
68
-
69
- end # module Quick
70
- end # module SportDb