sportdb-quick 0.1.1 → 0.2.0
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/Manifest.txt +1 -1
- data/bin/fbt +120 -58
- data/bin/fbtxt2json +75 -0
- data/lib/sportdb/quick/match_parser.rb +30 -17
- data/lib/sportdb/quick/quick_match_reader.rb +28 -9
- data/lib/sportdb/quick/version.rb +2 -2
- data/lib/sportdb/quick.rb +1 -1
- metadata +4 -3
- data/lib/sportdb/quick/opts.rb +0 -70
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: dc074126897237cd4cdb59c160e6dd41fa5b9e1ec3581472eeb68f520e486a61
         | 
| 4 | 
            +
              data.tar.gz: 32112335ee74977ebd243e4ead540dabb49b291d837933315d57f7d3d86a47b4
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: d0e23a4e07fa3e811c82eed4215d4229bc548e130d7e8bac70a85f8307928e50b28862e14b9a70c887166282c4efdb937d9533c1bfe0b1fddaced7b6b77d6729
         | 
| 7 | 
            +
              data.tar.gz: dd442c2ae016aad05d5aa5e21dcd4420bb45808bdc18cf5759e97a37849527dcd1a9ab89da7a8ecb48a5d5a52956d7f36ae1b506a170dae138234e61925520a1
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/Manifest.txt
    CHANGED
    
    | @@ -3,13 +3,13 @@ Manifest.txt | |
| 3 3 | 
             
            README.md
         | 
| 4 4 | 
             
            Rakefile
         | 
| 5 5 | 
             
            bin/fbt
         | 
| 6 | 
            +
            bin/fbtxt2json
         | 
| 6 7 | 
             
            lib/sportdb/quick.rb
         | 
| 7 8 | 
             
            lib/sportdb/quick/csv/goal.rb
         | 
| 8 9 | 
             
            lib/sportdb/quick/csv/goal_parser_csv.rb
         | 
| 9 10 | 
             
            lib/sportdb/quick/csv/match_parser_csv.rb
         | 
| 10 11 | 
             
            lib/sportdb/quick/csv/match_status_parser.rb
         | 
| 11 12 | 
             
            lib/sportdb/quick/match_parser.rb
         | 
| 12 | 
            -
            lib/sportdb/quick/opts.rb
         | 
| 13 13 | 
             
            lib/sportdb/quick/quick_league_outline_reader.rb
         | 
| 14 14 | 
             
            lib/sportdb/quick/quick_match_reader.rb
         | 
| 15 15 | 
             
            lib/sportdb/quick/version.rb
         | 
    
        data/bin/fbt
    CHANGED
    
    | @@ -26,8 +26,9 @@ require 'optparse' | |
| 26 26 |  | 
| 27 27 | 
             
             args = ARGV
         | 
| 28 28 | 
             
             opts = { debug: false,
         | 
| 29 | 
            -
                       | 
| 30 | 
            -
                       | 
| 29 | 
            +
                      json:  false,
         | 
| 30 | 
            +
                      file:  nil,
         | 
| 31 | 
            +
                    }
         | 
| 31 32 |  | 
| 32 33 | 
             
             parser = OptionParser.new do |parser|
         | 
| 33 34 | 
             
              parser.banner = "Usage: #{$PROGRAM_NAME} [options]"
         | 
| @@ -35,24 +36,26 @@ require 'optparse' | |
| 35 36 | 
             
            ##
         | 
| 36 37 | 
             
            ## check if git has a offline option?? (use same)
         | 
| 37 38 | 
             
            ##             check for other tools - why? why not?
         | 
| 39 | 
            +
                parser.on( "-q", "--quiet",
         | 
| 40 | 
            +
                             "less debug output/messages - default is (#{!opts[:debug]})" ) do |debug|
         | 
| 41 | 
            +
                  opts[:debug] = false
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              # parser.on( "--verbose", "--debug",
         | 
| 44 | 
            +
              #             "turn on verbose / debug output (default: #{opts[:debug]})" ) do |debug|
         | 
| 45 | 
            +
              #  opts[:debug] = true
         | 
| 46 | 
            +
              # end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                parser.on( "-j", "--json",
         | 
| 49 | 
            +
                             "print out in .json - default is (#{opts[:json]})" ) do |json|
         | 
| 50 | 
            +
                  opts[:json] = true
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                parser.on( "-f FILE", "--file FILE",
         | 
| 54 | 
            +
                                "read datafiles (pathspecs) via .csv file") do |file|
         | 
| 55 | 
            +
                  opts[:file] = file
         | 
| 56 | 
            +
                end
         | 
| 38 57 |  | 
| 39 58 |  | 
| 40 | 
            -
              parser.on( "--verbose", "--debug",
         | 
| 41 | 
            -
                           "turn on verbose / debug output (default: #{opts[:debug]})" ) do |debug|
         | 
| 42 | 
            -
                opts[:debug] = true
         | 
| 43 | 
            -
              end
         | 
| 44 | 
            -
             | 
| 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 | 
            -
             | 
| 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 59 | 
             
            end
         | 
| 57 60 | 
             
            parser.parse!( args )
         | 
| 58 61 |  | 
| @@ -62,58 +65,117 @@ puts "ARGV:" | |
| 62 65 | 
             
            p args
         | 
| 63 66 |  | 
| 64 67 |  | 
| 68 | 
            +
                ## todo/check - use packs or projects or such
         | 
| 69 | 
            +
                ##                instead of specs - why? why not?
         | 
| 70 | 
            +
                specs = []
         | 
| 71 | 
            +
                if opts[:file]
         | 
| 72 | 
            +
                      recs = read_csv( opts[:file] )
         | 
| 73 | 
            +
                      pp recs
         | 
| 74 | 
            +
                      ##  note - make pathspecs relative to passed in file arg!!!
         | 
| 75 | 
            +
                      basedir = File.dirname( opts[:file] )
         | 
| 76 | 
            +
                      recs.each do |rec|
         | 
| 77 | 
            +
                         paths = SportDb::Parser::Opts.find( rec['path'], dir: basedir )
         | 
| 78 | 
            +
                         specs << [paths, rec]
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                else
         | 
| 81 | 
            +
                   paths = if args.empty?
         | 
| 82 | 
            +
                             [
         | 
| 83 | 
            +
                               '../../../openfootball/euro/2021--europe/euro.txt',
         | 
| 84 | 
            +
                               '../../../openfootball/euro/2024--germany/euro.txt',
         | 
| 85 | 
            +
                             ]
         | 
| 86 | 
            +
                          else
         | 
| 87 | 
            +
                            ## check for directories
         | 
| 88 | 
            +
                            ##   and auto-expand
         | 
| 89 | 
            +
                            SportDb::Parser::Opts.expand_args( args )
         | 
| 90 | 
            +
                          end
         | 
| 91 | 
            +
                    specs << [paths, {}]
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
             | 
| 95 | 
            +
            if opts[:debug]
         | 
| 96 | 
            +
               SportDb::QuickMatchReader.debug = true
         | 
| 97 | 
            +
               SportDb::MatchParser.debug      = true
         | 
| 98 | 
            +
            else
         | 
| 99 | 
            +
               SportDb::QuickMatchReader.debug = false
         | 
| 100 | 
            +
               SportDb::MatchParser.debug      = false
         | 
| 101 | 
            +
               LogUtils::Logger.root.level = :info
         | 
| 102 | 
            +
            end
         | 
| 65 103 |  | 
| 66 104 |  | 
| 105 | 
            +
              specs.each_with_index do |(paths, rec),i|
         | 
| 106 | 
            +
                errors = []
         | 
| 107 | 
            +
                paths.each_with_index do |path,j|
         | 
| 108 | 
            +
                  puts "==> [#{j+1}/#{paths.size}] reading >#{path}<..."
         | 
| 109 | 
            +
                  quick = SportDb::QuickMatchReader.new( read_text( path ) )
         | 
| 110 | 
            +
                  matches = quick.parse
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  if quick.errors?
         | 
| 113 | 
            +
                    puts "!! #{quick.errors.size} error(s):"
         | 
| 114 | 
            +
                    pp quick.errors
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    quick.errors.each do |err|
         | 
| 117 | 
            +
                      errors << [ path, *err ]   # note: use splat (*) to add extra values (starting with msg)
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  ## pp matches
         | 
| 122 | 
            +
                  ##  try json for matches
         | 
| 123 | 
            +
                  if opts[:json]
         | 
| 124 | 
            +
                    data = matches.map {|match| match.as_json }
         | 
| 125 | 
            +
                    pp data
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
                  puts "  #{matches.size} match(es)"
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                if errors.size > 0
         | 
| 131 | 
            +
                  puts
         | 
| 132 | 
            +
                  puts "!! #{errors.size} PARSE ERRORS in #{paths.size} datafile(s)"
         | 
| 133 | 
            +
                  pp errors
         | 
| 134 | 
            +
                else
         | 
| 135 | 
            +
                  puts
         | 
| 136 | 
            +
                  puts "  OK - no parse errors in #{paths.size} datafile(s)"
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                 ## add errors to rec via rec['errors'] to allow
         | 
| 140 | 
            +
                 ##   for further processing/reporting
         | 
| 141 | 
            +
                 rec['errors'] = errors
         | 
| 142 | 
            +
              end
         | 
| 67 143 |  | 
| 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 144 |  | 
| 80 145 |  | 
| 81 | 
            -
             | 
| 146 | 
            +
            ###
         | 
| 147 | 
            +
            ## generate a report if --file option used
         | 
| 148 | 
            +
            if opts[:file]
         | 
| 82 149 |  | 
| 83 | 
            -
               | 
| 84 | 
            -
                puts "==> [#{i+1}/#{paths.size}] reading >#{path}<..."
         | 
| 150 | 
            +
              buf = String.new
         | 
| 85 151 |  | 
| 86 | 
            -
             | 
| 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]
         | 
| 152 | 
            +
              buf << "# fbt summary report - #{specs.size} dataset(s)\n\n"
         | 
| 96 153 |  | 
| 97 | 
            -
               | 
| 154 | 
            +
              specs.each_with_index do |(paths, rec),i|
         | 
| 155 | 
            +
                 errors = rec['errors']
         | 
| 98 156 |  | 
| 99 | 
            -
             | 
| 157 | 
            +
                 if errors.size > 0
         | 
| 158 | 
            +
                   buf << "!! #{errors.size} ERROR(S)  "
         | 
| 159 | 
            +
                 else
         | 
| 160 | 
            +
                   buf << "   OK          "
         | 
| 161 | 
            +
                 end
         | 
| 162 | 
            +
                 buf << "%-20s" % rec['path']
         | 
| 163 | 
            +
                 buf << " - #{paths.size} datafile(s)"
         | 
| 164 | 
            +
                 buf << "\n"
         | 
| 100 165 |  | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 166 | 
            +
                 if errors.size > 0
         | 
| 167 | 
            +
                     buf << errors.pretty_inspect
         | 
| 168 | 
            +
                     buf << "\n"
         | 
| 169 | 
            +
                 end
         | 
| 170 | 
            +
             end
         | 
| 104 171 |  | 
| 105 | 
            -
             | 
| 106 | 
            -
               | 
| 172 | 
            +
              puts
         | 
| 173 | 
            +
              puts "SUMMARY:"
         | 
| 174 | 
            +
              puts buf
         | 
| 107 175 |  | 
| 108 | 
            -
               | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 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
         | 
| 176 | 
            +
              #  maybe write out in the future?
         | 
| 177 | 
            +
              # basedir  = File.dirname( opts[:file] )
         | 
| 178 | 
            +
              # basename = File.basename( opts[:file], File.extname( opts[:file] ))
         | 
| 117 179 | 
             
            end
         | 
| 118 180 |  | 
| 119 181 |  | 
    
        data/bin/fbtxt2json
    ADDED
    
    | @@ -0,0 +1,75 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## tip: to test run:
         | 
| 4 | 
            +
            ##   ruby -I ./lib bin/fbtxt2json
         | 
| 5 | 
            +
             | 
| 6 | 
            +
             | 
| 7 | 
            +
            ## our own code
         | 
| 8 | 
            +
            require 'sportdb/quick'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'optparse'
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
             args = ARGV
         | 
| 17 | 
            +
             opts = { debug: false,
         | 
| 18 | 
            +
                    }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             parser = OptionParser.new do |parser|
         | 
| 21 | 
            +
              parser.banner = "Usage: #{$PROGRAM_NAME} [options]"
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ##
         | 
| 24 | 
            +
            ## check if git has a offline option?? (use same)
         | 
| 25 | 
            +
            ##             check for other tools - why? why not?
         | 
| 26 | 
            +
                parser.on( "-q", "--quiet",
         | 
| 27 | 
            +
                             "less debug output/messages - default is (#{!opts[:debug]})" ) do |debug|
         | 
| 28 | 
            +
                  opts[:debug] = false
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
            parser.parse!( args )
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            puts "OPTS:"
         | 
| 34 | 
            +
            p opts
         | 
| 35 | 
            +
            puts "ARGV:"
         | 
| 36 | 
            +
            p args
         | 
| 37 | 
            +
             | 
| 38 | 
            +
             | 
| 39 | 
            +
            path = if args.empty?
         | 
| 40 | 
            +
                      '../../../openfootball/euro/2021--europe/euro.txt'
         | 
| 41 | 
            +
                   elsif args.size == 1
         | 
| 42 | 
            +
                       args[0]
         | 
| 43 | 
            +
                   else
         | 
| 44 | 
            +
                      puts "!! wrong number of args, got #{args.size} - #{args.inspect} - only one arg supported/expected"
         | 
| 45 | 
            +
                      exit 1
         | 
| 46 | 
            +
                   end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
             | 
| 49 | 
            +
            if opts[:debug]
         | 
| 50 | 
            +
               SportDb::QuickMatchReader.debug = true
         | 
| 51 | 
            +
               SportDb::MatchParser.debug      = true
         | 
| 52 | 
            +
            else
         | 
| 53 | 
            +
               SportDb::QuickMatchReader.debug = false
         | 
| 54 | 
            +
               SportDb::MatchParser.debug      = false
         | 
| 55 | 
            +
               LogUtils::Logger.root.level = :info
         | 
| 56 | 
            +
            end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
             | 
| 59 | 
            +
                  puts "==> reading >#{path}<..."
         | 
| 60 | 
            +
                  quick = SportDb::QuickMatchReader.new( read_text( path ) )
         | 
| 61 | 
            +
                  matches = quick.parse
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  data = matches.map {|match| match.as_json }
         | 
| 64 | 
            +
                  pp data
         | 
| 65 | 
            +
                  puts
         | 
| 66 | 
            +
                  puts "  #{matches.size} match(es)"
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  if quick.errors?
         | 
| 69 | 
            +
                    puts "!! #{quick.errors.size} parse error(s):"
         | 
| 70 | 
            +
                    pp quick.errors
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
             | 
| 74 | 
            +
            puts "bye"
         | 
| 75 | 
            +
             | 
| @@ -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
         | 
| @@ -566,12 +573,13 @@ class GoalStruct | |
| 566 573 | 
             
                logger.debug( "parse match: >#{nodes}<" )
         | 
| 567 574 |  | 
| 568 575 | 
             
                ## collect (possible) nodes by type
         | 
| 569 | 
            -
                num | 
| 570 | 
            -
                date | 
| 571 | 
            -
                time | 
| 572 | 
            -
                teams | 
| 573 | 
            -
                score | 
| 574 | 
            -
                more | 
| 576 | 
            +
                num    = nil
         | 
| 577 | 
            +
                date   = nil
         | 
| 578 | 
            +
                time   = nil
         | 
| 579 | 
            +
                teams  = []
         | 
| 580 | 
            +
                score  = nil
         | 
| 581 | 
            +
                more   = []
         | 
| 582 | 
            +
                status = nil
         | 
| 575 583 |  | 
| 576 584 | 
             
                while !nodes.empty?
         | 
| 577 585 | 
             
                    node = nodes.shift
         | 
| @@ -608,6 +616,8 @@ class GoalStruct | |
| 608 616 |  | 
| 609 617 | 
             
                         score = Score.new( *values )
         | 
| 610 618 | 
             
                         ## pp score
         | 
| 619 | 
            +
                    elsif node_type == :status  # e.g. awarded, canceled, postponed, etc.
         | 
| 620 | 
            +
                         status = node[1]
         | 
| 611 621 | 
             
                    elsif node_type == :vs
         | 
| 612 622 | 
             
                       ## skip; do nothing
         | 
| 613 623 | 
             
            ##
         | 
| @@ -626,7 +636,9 @@ class GoalStruct | |
| 626 636 | 
             
                    else
         | 
| 627 637 | 
             
                        puts "!! PARSE ERROR - unexpected node type #{node_type} in match line; got:"
         | 
| 628 638 | 
             
                        pp node
         | 
| 629 | 
            -
                        exit 1
         | 
| 639 | 
            +
                        ## exit 1
         | 
| 640 | 
            +
                        @errors << ["PARSE ERROR - unexpected node type #{node_type} in match line; got: #{node.inspect}"]
         | 
| 641 | 
            +
                        return
         | 
| 630 642 | 
             
                    end
         | 
| 631 643 | 
             
                end
         | 
| 632 644 |  | 
| @@ -634,7 +646,9 @@ class GoalStruct | |
| 634 646 | 
             
                if teams.size != 2
         | 
| 635 647 | 
             
                  puts "!! PARSE ERROR - expected two teams; got #{teams.size}:"
         | 
| 636 648 | 
             
                  pp teams
         | 
| 637 | 
            -
                  exit 1
         | 
| 649 | 
            +
                  ## exit 1
         | 
| 650 | 
            +
                  @errors << ["PARSE ERROR - expected two teams; got #{teams.size}: #{teams.inspect}"]
         | 
| 651 | 
            +
                  return
         | 
| 638 652 | 
             
                end
         | 
| 639 653 |  | 
| 640 654 | 
             
                team1 = teams[0]
         | 
| @@ -711,7 +725,6 @@ class GoalStruct | |
| 711 725 | 
             
                time_str = time    if date && time
         | 
| 712 726 |  | 
| 713 727 |  | 
| 714 | 
            -
                status = nil
         | 
| 715 728 | 
             
                ground = nil
         | 
| 716 729 |  | 
| 717 730 | 
             
                @matches << Import::Match.new( num:     num,
         | 
| @@ -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,23 @@ 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 | 
            +
             | 
| 23 33 | 
             
              def parse
         | 
| 34 | 
            +
                ## note: every (new) read call - resets errors list to empty
         | 
| 35 | 
            +
                @errors = []
         | 
| 36 | 
            +
             | 
| 24 37 | 
             
                data = {}   # return data hash with leagues
         | 
| 25 38 | 
             
                            #    and seasons
         | 
| 26 39 | 
             
                            #   for now merge stage into matches
         | 
| 27 40 |  | 
| 28 41 | 
             
                secs = QuickLeagueOutlineReader.parse( @txt )
         | 
| 29 | 
            -
                pp secs
         | 
| 42 | 
            +
                pp secs    if debug?
         | 
| 30 43 |  | 
| 31 44 | 
             
                secs.each do |sec|   ## sec(tion)s
         | 
| 32 45 | 
             
                  season = Season.parse( sec[:season] )   ## convert (str) to season obj!!!
         | 
| @@ -46,14 +59,20 @@ class QuickMatchReader | |
| 46 59 |  | 
| 47 60 | 
             
                  auto_conf_teams,  matches, rounds, groups = parser.parse
         | 
| 48 61 |  | 
| 49 | 
            -
                   | 
| 50 | 
            -
                   | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
                   | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 62 | 
            +
                  ## auto-add "upstream" errors from parser
         | 
| 63 | 
            +
                  @errors += parser.errors  if parser.errors?
         | 
| 64 | 
            +
             | 
| 65 | 
            +
             | 
| 66 | 
            +
                  if debug?
         | 
| 67 | 
            +
                    puts ">>> #{auto_conf_teams.size} teams:"
         | 
| 68 | 
            +
                    pp auto_conf_teams
         | 
| 69 | 
            +
                    puts ">>> #{matches.size} matches:"
         | 
| 70 | 
            +
                    ## pp matches
         | 
| 71 | 
            +
                    puts ">>> #{rounds.size} rounds:"
         | 
| 72 | 
            +
                    pp rounds
         | 
| 73 | 
            +
                    puts ">>> #{groups.size} groups:"
         | 
| 74 | 
            +
                    pp groups
         | 
| 75 | 
            +
                  end
         | 
| 57 76 |  | 
| 58 77 | 
             
                  ## note: pass along stage (if present): stage  - optional from heading!!!!
         | 
| 59 78 | 
             
                  if stage
         | 
    
        data/lib/sportdb/quick.rb
    CHANGED
    
    
    
        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.2.0
         | 
| 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- | 
| 11 | 
            +
            date: 2024-09-19 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: sportdb-parser
         | 
| @@ -90,6 +90,7 @@ description: sportdb-quick - football.txt (quick) match readers and more | |
| 90 90 | 
             
            email: gerald.bauer@gmail.com
         | 
| 91 91 | 
             
            executables:
         | 
| 92 92 | 
             
            - fbt
         | 
| 93 | 
            +
            - fbtxt2json
         | 
| 93 94 | 
             
            extensions: []
         | 
| 94 95 | 
             
            extra_rdoc_files:
         | 
| 95 96 | 
             
            - CHANGELOG.md
         | 
| @@ -101,13 +102,13 @@ files: | |
| 101 102 | 
             
            - README.md
         | 
| 102 103 | 
             
            - Rakefile
         | 
| 103 104 | 
             
            - bin/fbt
         | 
| 105 | 
            +
            - bin/fbtxt2json
         | 
| 104 106 | 
             
            - lib/sportdb/quick.rb
         | 
| 105 107 | 
             
            - lib/sportdb/quick/csv/goal.rb
         | 
| 106 108 | 
             
            - lib/sportdb/quick/csv/goal_parser_csv.rb
         | 
| 107 109 | 
             
            - lib/sportdb/quick/csv/match_parser_csv.rb
         | 
| 108 110 | 
             
            - lib/sportdb/quick/csv/match_status_parser.rb
         | 
| 109 111 | 
             
            - lib/sportdb/quick/match_parser.rb
         | 
| 110 | 
            -
            - lib/sportdb/quick/opts.rb
         | 
| 111 112 | 
             
            - lib/sportdb/quick/quick_league_outline_reader.rb
         | 
| 112 113 | 
             
            - lib/sportdb/quick/quick_match_reader.rb
         | 
| 113 114 | 
             
            - lib/sportdb/quick/version.rb
         | 
    
        data/lib/sportdb/quick/opts.rb
    DELETED
    
    | @@ -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
         |