sportdb-formats 1.2.1 → 2.0.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 +6 -7
- data/Rakefile +7 -3
- data/lib/sportdb/formats/csv/goal.rb +192 -0
- data/lib/sportdb/formats/csv/goal_parser_csv.rb +28 -0
- data/lib/sportdb/formats/csv/match_parser_csv.rb +490 -0
- data/lib/sportdb/formats/csv/match_status_parser.rb +90 -0
- data/lib/sportdb/formats/match/conf_parser.rb +14 -2
- data/lib/sportdb/formats/match/match_parser.rb +498 -489
- data/lib/sportdb/formats/name_helper.rb +87 -0
- data/lib/sportdb/formats/search/sport.rb +67 -52
- data/lib/sportdb/formats/search/structs.rb +116 -0
- data/lib/sportdb/formats/search/world.rb +40 -22
- data/lib/sportdb/formats/version.rb +3 -3
- data/lib/sportdb/formats.rb +82 -15
- metadata +69 -14
- data/lib/sportdb/formats/goals.rb +0 -321
- data/lib/sportdb/formats/lines_reader.rb +0 -47
- data/lib/sportdb/formats/match/mapper.rb +0 -319
- data/lib/sportdb/formats/match/mapper_teams.rb +0 -23
- data/lib/sportdb/formats/match/match_parser_auto_conf.rb +0 -270
- data/lib/sportdb/formats/outline_reader.rb +0 -90
- data/lib/sportdb/formats/parser_helper.rb +0 -90
    
        data/lib/sportdb/formats.rb
    CHANGED
    
    | @@ -1,25 +1,51 @@ | |
| 1 1 | 
             
            ## 3rd party gems
         | 
| 2 2 | 
             
            require 'sportdb/structs'
         | 
| 3 | 
            +
            require 'sportdb/parser'
         | 
| 4 | 
            +
            require 'date/formats'
         | 
| 3 5 |  | 
| 4 6 |  | 
| 5 7 | 
             
            require 'zip'     ## todo/check: if zip is alreay included in a required module
         | 
| 6 8 |  | 
| 7 9 |  | 
| 10 | 
            +
            ## note -  add cocos (code commons)
         | 
| 11 | 
            +
            ##
         | 
| 12 | 
            +
            ##  pulls in read_csv & parse_csv etc.
         | 
| 13 | 
            +
            require 'cocos'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            require 'logutils'
         | 
| 17 | 
            +
            module SportDb
         | 
| 18 | 
            +
              ## logging machinery shortcut; use LogUtils for now
         | 
| 19 | 
            +
              Logging = LogUtils::Logging
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
             | 
| 8 23 |  | 
| 9 24 |  | 
| 10 25 | 
             
            ###
         | 
| 11 26 | 
             
            # our own code
         | 
| 12 27 | 
             
            require_relative 'formats/version' # let version always go first
         | 
| 13 28 |  | 
| 14 | 
            -
            require_relative 'formats/outline_reader'
         | 
| 15 29 | 
             
            require_relative 'formats/datafile'
         | 
| 16 30 | 
             
            require_relative 'formats/datafile_package'
         | 
| 17 31 | 
             
            require_relative 'formats/package'
         | 
| 18 32 |  | 
| 33 | 
            +
            require_relative 'formats/name_helper'
         | 
| 34 | 
            +
             | 
| 19 35 |  | 
| 20 | 
            -
            require_relative 'formats/parser_helper'
         | 
| 21 36 |  | 
| 22 | 
            -
             | 
| 37 | 
            +
            ## let's put test configuration in its own namespace / module
         | 
| 38 | 
            +
            module SportDb
         | 
| 39 | 
            +
              class Test    ## todo/check: works with module too? use a module - why? why not?
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                ####
         | 
| 42 | 
            +
                #  todo/fix:  find a better way to configure shared test datasets - why? why not?
         | 
| 43 | 
            +
                #    note: use one-up (..) directory for now as default - why? why not?
         | 
| 44 | 
            +
                def self.data_dir()        @data_dir ||= '../test'; end
         | 
| 45 | 
            +
                def self.data_dir=( path ) @data_dir = path; end
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end   # module SportDb
         | 
| 48 | 
            +
             | 
| 23 49 |  | 
| 24 50 |  | 
| 25 51 | 
             
            ###
         | 
| @@ -29,13 +55,10 @@ module SportDb | |
| 29 55 | 
             
            module Import
         | 
| 30 56 |  | 
| 31 57 | 
             
            class Configuration
         | 
| 32 | 
            -
              ## note: add more configs (open class), see sportdb-structs for original config!!!
         | 
| 33 | 
            -
             | 
| 34 | 
            -
              ## add 
         | 
| 35 58 | 
             
              def world()        @world ||= WorldSearch.new( countries: DummyCountrySearch.new ); end
         | 
| 36 59 | 
             
              def world=(world)  @world = world; end
         | 
| 37 60 |  | 
| 38 | 
            -
              ##  | 
| 61 | 
            +
              ## todo/fix - add/move catalog here from   sportdb-catalogs!!!
         | 
| 39 62 | 
             
              ## def catalog()         @catalog ||= Catalog.new;  end
         | 
| 40 63 | 
             
              ## def catalog(catalog)  @catalog = catalog; end
         | 
| 41 64 | 
             
            end # class Configuration
         | 
| @@ -43,11 +66,62 @@ end # class Configuration | |
| 43 66 | 
             
              ##  e.g. use config.catalog  -- keep Import.catalog as a shortcut (for "read-only" access)
         | 
| 44 67 | 
             
              ## def self.catalog() config.catalog;  end
         | 
| 45 68 | 
             
              def self.world()   config.world;    end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              ## lets you use
         | 
| 71 | 
            +
              ##   SportDb::Import.configure do |config|
         | 
| 72 | 
            +
              ##      config.catalog_path = './catalog.db'
         | 
| 73 | 
            +
              ##   end
         | 
| 74 | 
            +
            def self.configure()  yield( config ); end
         | 
| 75 | 
            +
            def self.config()  @config ||= Configuration.new;  end
         | 
| 46 76 | 
             
            end   # module Import
         | 
| 47 77 | 
             
            end   # module SportDb
         | 
| 48 78 |  | 
| 79 | 
            +
             | 
| 49 80 | 
             
            require_relative 'formats/search/world'
         | 
| 50 81 | 
             
            require_relative 'formats/search/sport'
         | 
| 82 | 
            +
            require_relative 'formats/search/structs'
         | 
| 83 | 
            +
             | 
| 84 | 
            +
             | 
| 85 | 
            +
             | 
| 86 | 
            +
            module Sports
         | 
| 87 | 
            +
              ## note: just forward to SportDb::Import configuration!!!!!
         | 
| 88 | 
            +
              ##  keep Sports module / namespace "clean" - why? why not?
         | 
| 89 | 
            +
              ##    that is, only include data structures (e.g. Match,League,etc) for now - why? why not?
         | 
| 90 | 
            +
              def self.configure()  yield( config ); end
         | 
| 91 | 
            +
              def self.config()  SportDb::Import.config; end
         | 
| 92 | 
            +
            end   # module Sports
         | 
| 93 | 
            +
             | 
| 94 | 
            +
             | 
| 95 | 
            +
            ###
         | 
| 96 | 
            +
            #  csv (tabular dataset) support / machinery
         | 
| 97 | 
            +
            require_relative 'formats/csv/match_status_parser'
         | 
| 98 | 
            +
            require_relative 'formats/csv/goal'
         | 
| 99 | 
            +
            require_relative 'formats/csv/goal_parser_csv'
         | 
| 100 | 
            +
            require_relative 'formats/csv/match_parser_csv'
         | 
| 101 | 
            +
             | 
| 102 | 
            +
             | 
| 103 | 
            +
            ### add convenience shortcut helpers
         | 
| 104 | 
            +
            module Sports
         | 
| 105 | 
            +
              class Match
         | 
| 106 | 
            +
                def self.read_csv( path, headers: nil, filters: nil, converters: nil, sep: nil )
         | 
| 107 | 
            +
                   SportDb::CsvMatchParser.read( path,
         | 
| 108 | 
            +
                                                   headers:    headers,
         | 
| 109 | 
            +
                                                   filters:    filters,
         | 
| 110 | 
            +
                                                   converters: converters,
         | 
| 111 | 
            +
                                                   sep:        sep )
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                def self.parse_csv( txt, headers: nil, filters: nil, converters: nil, sep: nil )
         | 
| 115 | 
            +
                   SportDb::CsvMatchParser.parse( txt,
         | 
| 116 | 
            +
                                                    headers:    headers,
         | 
| 117 | 
            +
                                                    filters:    filters,
         | 
| 118 | 
            +
                                                    converters: converters,
         | 
| 119 | 
            +
                                                    sep:        sep )
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
              end # class Match
         | 
| 122 | 
            +
            end # module Sports
         | 
| 123 | 
            +
             | 
| 124 | 
            +
             | 
| 51 125 |  | 
| 52 126 |  | 
| 53 127 |  | 
| @@ -77,7 +151,7 @@ module SportDb | |
| 77 151 |  | 
| 78 152 | 
             
                Player       = ::Sports::Player
         | 
| 79 153 |  | 
| 80 | 
            -
             | 
| 154 | 
            +
             | 
| 81 155 | 
             
                class Team
         | 
| 82 156 | 
             
                  ## add convenience lookup helper / method for name by season for now
         | 
| 83 157 | 
             
                  ##   use clubs history - for now kept separate from struct - why? why not?
         | 
| @@ -91,14 +165,7 @@ module SportDb | |
| 91 165 | 
             
            end     # module SportDb
         | 
| 92 166 |  | 
| 93 167 |  | 
| 94 | 
            -
            require_relative 'formats/goals'
         | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
            require_relative 'formats/match/mapper'
         | 
| 99 | 
            -
            require_relative 'formats/match/mapper_teams'
         | 
| 100 168 | 
             
            require_relative 'formats/match/match_parser'
         | 
| 101 | 
            -
            require_relative 'formats/match/match_parser_auto_conf'
         | 
| 102 169 | 
             
            require_relative 'formats/match/conf_parser'
         | 
| 103 170 |  | 
| 104 171 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: sportdb-formats
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 2.0.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- | 
| 11 | 
            +
            date: 2024-08-22 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: sportdb-structs
         | 
| @@ -16,28 +16,84 @@ dependencies: | |
| 16 16 | 
             
                requirements:
         | 
| 17 17 | 
             
                - - ">="
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: 0. | 
| 19 | 
            +
                    version: 0.3.0
         | 
| 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. | 
| 26 | 
            +
                    version: 0.3.0
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: sportdb-parser
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ">="
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: 0.2.0
         | 
| 34 | 
            +
              type: :runtime
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ">="
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: 0.2.0
         | 
| 41 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            +
              name: date-formats
         | 
| 43 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 | 
            +
                requirements:
         | 
| 45 | 
            +
                - - ">="
         | 
| 46 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            +
                    version: 1.0.2
         | 
| 48 | 
            +
              type: :runtime
         | 
| 49 | 
            +
              prerelease: false
         | 
| 50 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 | 
            +
                requirements:
         | 
| 52 | 
            +
                - - ">="
         | 
| 53 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            +
                    version: 1.0.2
         | 
| 55 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            +
              name: cocos
         | 
| 57 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 | 
            +
                requirements:
         | 
| 59 | 
            +
                - - ">="
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: 0.4.0
         | 
| 62 | 
            +
              type: :runtime
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - ">="
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: 0.4.0
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: logutils
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - ">="
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: 0.6.1
         | 
| 76 | 
            +
              type: :runtime
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - ">="
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: 0.6.1
         | 
| 27 83 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 84 | 
             
              name: rubyzip
         | 
| 29 85 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 86 | 
             
                requirements:
         | 
| 31 87 | 
             
                - - ">="
         | 
| 32 88 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version:  | 
| 89 | 
            +
                    version: 2.3.2
         | 
| 34 90 | 
             
              type: :runtime
         | 
| 35 91 | 
             
              prerelease: false
         | 
| 36 92 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 93 | 
             
                requirements:
         | 
| 38 94 | 
             
                - - ">="
         | 
| 39 95 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            -
                    version:  | 
| 96 | 
            +
                    version: 2.3.2
         | 
| 41 97 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 98 | 
             
              name: rdoc
         | 
| 43 99 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -87,23 +143,22 @@ files: | |
| 87 143 | 
             
            - Rakefile
         | 
| 88 144 | 
             
            - lib/sportdb/formats.rb
         | 
| 89 145 | 
             
            - lib/sportdb/formats/country/country_reader.rb
         | 
| 146 | 
            +
            - lib/sportdb/formats/csv/goal.rb
         | 
| 147 | 
            +
            - lib/sportdb/formats/csv/goal_parser_csv.rb
         | 
| 148 | 
            +
            - lib/sportdb/formats/csv/match_parser_csv.rb
         | 
| 149 | 
            +
            - lib/sportdb/formats/csv/match_status_parser.rb
         | 
| 90 150 | 
             
            - lib/sportdb/formats/datafile.rb
         | 
| 91 151 | 
             
            - lib/sportdb/formats/datafile_package.rb
         | 
| 92 152 | 
             
            - lib/sportdb/formats/event/event_reader.rb
         | 
| 93 | 
            -
            - lib/sportdb/formats/goals.rb
         | 
| 94 153 | 
             
            - lib/sportdb/formats/ground/ground_reader.rb
         | 
| 95 154 | 
             
            - lib/sportdb/formats/league/league_outline_reader.rb
         | 
| 96 155 | 
             
            - lib/sportdb/formats/league/league_reader.rb
         | 
| 97 | 
            -
            - lib/sportdb/formats/lines_reader.rb
         | 
| 98 156 | 
             
            - lib/sportdb/formats/match/conf_parser.rb
         | 
| 99 | 
            -
            - lib/sportdb/formats/match/mapper.rb
         | 
| 100 | 
            -
            - lib/sportdb/formats/match/mapper_teams.rb
         | 
| 101 157 | 
             
            - lib/sportdb/formats/match/match_parser.rb
         | 
| 102 | 
            -
            - lib/sportdb/formats/ | 
| 103 | 
            -
            - lib/sportdb/formats/outline_reader.rb
         | 
| 158 | 
            +
            - lib/sportdb/formats/name_helper.rb
         | 
| 104 159 | 
             
            - lib/sportdb/formats/package.rb
         | 
| 105 | 
            -
            - lib/sportdb/formats/parser_helper.rb
         | 
| 106 160 | 
             
            - lib/sportdb/formats/search/sport.rb
         | 
| 161 | 
            +
            - lib/sportdb/formats/search/structs.rb
         | 
| 107 162 | 
             
            - lib/sportdb/formats/search/world.rb
         | 
| 108 163 | 
             
            - lib/sportdb/formats/team/club_index_history.rb
         | 
| 109 164 | 
             
            - lib/sportdb/formats/team/club_reader.rb
         | 
| @@ -125,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 125 180 | 
             
              requirements:
         | 
| 126 181 | 
             
              - - ">="
         | 
| 127 182 | 
             
                - !ruby/object:Gem::Version
         | 
| 128 | 
            -
                  version:  | 
| 183 | 
            +
                  version: 3.1.0
         | 
| 129 184 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 130 185 | 
             
              requirements:
         | 
| 131 186 | 
             
              - - ">="
         | 
| @@ -1,321 +0,0 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            module SportDb
         | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
            class GoalsPlayerStruct
         | 
| 7 | 
            -
              ##
         | 
| 8 | 
            -
              # note: player with own goal (o.g) gets listed on other team
         | 
| 9 | 
            -
              #  (thus, player might have two entries if also scored for its own team)
         | 
| 10 | 
            -
              #
         | 
| 11 | 
            -
              attr_accessor :name
         | 
| 12 | 
            -
              attr_accessor :minutes   # ary of minutes e.g. 30', 45+2', 72'
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              def initialize
         | 
| 15 | 
            -
                @minutes = []
         | 
| 16 | 
            -
              end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
              def pretty_print( printer ) 
         | 
| 19 | 
            -
                buf = String.new
         | 
| 20 | 
            -
                buf << "<GoalsPlayerStruct: #{@name} "
         | 
| 21 | 
            -
                buf << @minutes.pretty_print_inspect
         | 
| 22 | 
            -
                buf << ">"
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                printer.text( buf ) 
         | 
| 25 | 
            -
              end
         | 
| 26 | 
            -
            end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
            class GoalsMinuteStruct
         | 
| 30 | 
            -
              attr_accessor :minute, :offset
         | 
| 31 | 
            -
              attr_accessor :penalty, :owngoal    # flags
         | 
| 32 | 
            -
             | 
| 33 | 
            -
              def initialize
         | 
| 34 | 
            -
                @offset  = 0
         | 
| 35 | 
            -
                @penalty = false
         | 
| 36 | 
            -
                @owngoal = false
         | 
| 37 | 
            -
              end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
              def pretty_print( printer ) 
         | 
| 40 | 
            -
                buf = String.new
         | 
| 41 | 
            -
                buf << "<GoalsMinuteStruct: #{@minute}"
         | 
| 42 | 
            -
                buf << "+#{@offset}"    if @offset && @offset > 0
         | 
| 43 | 
            -
                buf << "'"
         | 
| 44 | 
            -
                buf << " (o.g.)"  if @owngoal
         | 
| 45 | 
            -
                buf << " (pen.)"  if @penalty
         | 
| 46 | 
            -
                buf << ">"
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                printer.text( buf ) 
         | 
| 49 | 
            -
              end
         | 
| 50 | 
            -
            end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
            class GoalStruct
         | 
| 54 | 
            -
              ######
         | 
| 55 | 
            -
              # flat struct for goals - one entry per goals
         | 
| 56 | 
            -
              attr_accessor :name
         | 
| 57 | 
            -
              attr_accessor :team   #  1 or 2 ? check/todo: add team1 or team2 flag?
         | 
| 58 | 
            -
              attr_accessor :minute, :offset
         | 
| 59 | 
            -
              attr_accessor :penalty, :owngoal
         | 
| 60 | 
            -
              attr_accessor :score1, :score2  # gets calculated
         | 
| 61 | 
            -
             | 
| 62 | 
            -
              ## add pos  for sequence number? e.g. 1,2,3,4  (1st goald, 2nd goal, etc.) ???
         | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
              def initialize( **kwargs )    ## add/allow quick and dirty quick init with keywords
         | 
| 66 | 
            -
                if kwargs.empty?
         | 
| 67 | 
            -
                  # do nothing
         | 
| 68 | 
            -
                else
         | 
| 69 | 
            -
                  kwargs.each do |key,value|
         | 
| 70 | 
            -
                    send( "#{key}=", value )
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
                end
         | 
| 73 | 
            -
              end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
              def ==(o)
         | 
| 76 | 
            -
                o.class == self.class && o.state == state
         | 
| 77 | 
            -
              end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
              def state
         | 
| 80 | 
            -
                [@name, @team, @minute, @offset, @penalty, @owngoal, @score1, @score2]
         | 
| 81 | 
            -
              end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
              def pretty_print( printer ) 
         | 
| 85 | 
            -
                buf = String.new
         | 
| 86 | 
            -
                buf << "<GoalStruct: #{@score1}-#{@score2} #{@name} #{@minute}"
         | 
| 87 | 
            -
                buf << "+#{@offset}"    if @offset && @offset > 0
         | 
| 88 | 
            -
                buf << "'"
         | 
| 89 | 
            -
                buf << " (o.g.)"  if @owngoal
         | 
| 90 | 
            -
                buf << " (pen.)"  if @penalty
         | 
| 91 | 
            -
                buf << " for #{@team}"     ### team 1 or 2 - use home/away
         | 
| 92 | 
            -
                buf << ">"
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                printer.text( buf ) 
         | 
| 95 | 
            -
              end
         | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
            end
         | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
            # todo: find a better name? to avoid confusing w/ GoalsParser? use MatchGoalsParser or similar?
         | 
| 103 | 
            -
            class GoalsFinder
         | 
| 104 | 
            -
              include LogUtils::Logging
         | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
              def initialize
         | 
| 108 | 
            -
                # nothing here for now
         | 
| 109 | 
            -
              end
         | 
| 110 | 
            -
             | 
| 111 | 
            -
              def find!( line, opts={} )
         | 
| 112 | 
            -
                # remove end-of-line comments
         | 
| 113 | 
            -
                line = line.sub( /#.*$/ ) do |_|
         | 
| 114 | 
            -
                         logger.debug "   cutting off end of line comment - >>#{$&}<<"
         | 
| 115 | 
            -
                         ''
         | 
| 116 | 
            -
                       end
         | 
| 117 | 
            -
             | 
| 118 | 
            -
                # remove [] if presents e.g. [Neymar 12']
         | 
| 119 | 
            -
                line = line.gsub( /[\[\]]/, '' )
         | 
| 120 | 
            -
                # remove (single match) if line starts w/ - (allow spaces)  e.g. [-;Neymar 12'] or [ - ;Neymar 12']
         | 
| 121 | 
            -
                line = line.sub( /^[ ]*-[ ]*/, '' )
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                # split into left hand side (lhs) for team1 and
         | 
| 124 | 
            -
                #            right hand side (rhs) for team2
         | 
| 125 | 
            -
             | 
| 126 | 
            -
                values = line.split( ';' )
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                # note: allow empty right hand side (e.g. team2 did NOT score any goals e.g. 3-0 etc.)
         | 
| 129 | 
            -
                lhs = values[0]
         | 
| 130 | 
            -
                rhs = values[1]
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                lhs = lhs.strip   unless lhs.nil?
         | 
| 133 | 
            -
                rhs = rhs.strip   unless rhs.nil?
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                parser = GoalsParser.new
         | 
| 136 | 
            -
                ## todo/check: only call if not nil?
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                logger.debug "  lhs (team1): >#{lhs}<"
         | 
| 139 | 
            -
                lhs_data = parser.parse!( lhs )
         | 
| 140 | 
            -
                pp lhs_data
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                logger.debug "  rhs (team2): >#{rhs}<"
         | 
| 143 | 
            -
                rhs_data = parser.parse!( rhs )
         | 
| 144 | 
            -
                pp rhs_data
         | 
| 145 | 
            -
             | 
| 146 | 
            -
                ### merge into flat goal structs
         | 
| 147 | 
            -
                goals = []
         | 
| 148 | 
            -
                lhs_data.each do |player|
         | 
| 149 | 
            -
                  player.minutes.each do |minute|
         | 
| 150 | 
            -
                    goal = GoalStruct.new
         | 
| 151 | 
            -
                    goal.name    = player.name
         | 
| 152 | 
            -
                    goal.team    = 1
         | 
| 153 | 
            -
                    goal.minute  = minute.minute
         | 
| 154 | 
            -
                    goal.offset  = minute.offset
         | 
| 155 | 
            -
                    goal.penalty = minute.penalty
         | 
| 156 | 
            -
                    goal.owngoal = minute.owngoal
         | 
| 157 | 
            -
                    goals << goal
         | 
| 158 | 
            -
                  end
         | 
| 159 | 
            -
                end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                rhs_data.each do |player|
         | 
| 162 | 
            -
                  player.minutes.each do |minute|
         | 
| 163 | 
            -
                    goal = GoalStruct.new
         | 
| 164 | 
            -
                    goal.name    = player.name
         | 
| 165 | 
            -
                    goal.team    = 2
         | 
| 166 | 
            -
                    goal.minute  = minute.minute
         | 
| 167 | 
            -
                    goal.offset  = minute.offset
         | 
| 168 | 
            -
                    goal.penalty = minute.penalty
         | 
| 169 | 
            -
                    goal.owngoal = minute.owngoal
         | 
| 170 | 
            -
                    goals << goal
         | 
| 171 | 
            -
                  end
         | 
| 172 | 
            -
                end
         | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
                # sort by minute + offset
         | 
| 176 | 
            -
                goals = goals.sort do |l,r|
         | 
| 177 | 
            -
                  res = l.minute <=> r.minute
         | 
| 178 | 
            -
                  if res == 0
         | 
| 179 | 
            -
                    res =  l.offset <=> r.offset  # pass 2: sort by offset
         | 
| 180 | 
            -
                  end
         | 
| 181 | 
            -
                  res
         | 
| 182 | 
            -
                end
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                ## calc score1,score2
         | 
| 185 | 
            -
                score1 = 0
         | 
| 186 | 
            -
                score2 = 0
         | 
| 187 | 
            -
                goals.each do |goal|
         | 
| 188 | 
            -
                  if goal.team == 1
         | 
| 189 | 
            -
                    score1 += 1
         | 
| 190 | 
            -
                  elsif goal.team == 2
         | 
| 191 | 
            -
                    score2 += 1
         | 
| 192 | 
            -
                  else
         | 
| 193 | 
            -
                    # todo: should not happen: issue warning
         | 
| 194 | 
            -
                  end
         | 
| 195 | 
            -
                  goal.score1 = score1
         | 
| 196 | 
            -
                  goal.score2 = score2
         | 
| 197 | 
            -
                end
         | 
| 198 | 
            -
             | 
| 199 | 
            -
                logger.debug "  #{goals.size} goals:"
         | 
| 200 | 
            -
                pp goals
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                goals
         | 
| 203 | 
            -
              end
         | 
| 204 | 
            -
             | 
| 205 | 
            -
            end  # class GoalsFinder
         | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
            class GoalsParser
         | 
| 209 | 
            -
              include LogUtils::Logging
         | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
              ### todo/fix:
         | 
| 213 | 
            -
              ##    let's use stringscanner for parsing line - why? why not?
         | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
              # note: use ^ for start of string only!!!
         | 
| 217 | 
            -
              # - for now slurp everything up to digits (inlc. spaces - use strip to remove)
         | 
| 218 | 
            -
              # todo/check: use/rename to NAME_UNTIL_REGEX ??? ( add lookahead for spaces?)
         | 
| 219 | 
            -
              NAME_REGEX = /^
         | 
| 220 | 
            -
                            [^0-9]+
         | 
| 221 | 
            -
                           /x
         | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
              # todo/check: change to MINUTE_REGEX ??
         | 
| 225 | 
            -
              # add MINUTE_SKIP_REGEX or MINUTE_SEP_REGEX /^[ ,]+/
         | 
| 226 | 
            -
              # todo/fix:  split out  penalty and owngoal flag in PATTERN constant for reuse
         | 
| 227 | 
            -
              #   note - offset  90+10 possible!!!!
         | 
| 228 | 
            -
              #    note - allow  p/pen./pen  or  o.g. or og
         | 
| 229 | 
            -
              MINUTES_REGEX = /^      # note: use ^ for start of string only!!!
         | 
| 230 | 
            -
                                (?<minute>[0-9]{1,3})
         | 
| 231 | 
            -
                                (?:\+
         | 
| 232 | 
            -
                                  (?<offset>[0-9]{1,2})
         | 
| 233 | 
            -
                                )?
         | 
| 234 | 
            -
                                '
         | 
| 235 | 
            -
                                (?:[ ]*
         | 
| 236 | 
            -
                                  \(
         | 
| 237 | 
            -
                                  (?<type>p|pen\.?|
         | 
| 238 | 
            -
                                          og|o\.g\.)
         | 
| 239 | 
            -
                                  \)
         | 
| 240 | 
            -
                                )?
         | 
| 241 | 
            -
                              /ix
         | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
              def initialize
         | 
| 246 | 
            -
                # nothing here for now
         | 
| 247 | 
            -
              end
         | 
| 248 | 
            -
             | 
| 249 | 
            -
              def parse!( line, opts={} )
         | 
| 250 | 
            -
             | 
| 251 | 
            -
                ## for now assume
         | 
| 252 | 
            -
                ##    everything up-to  0-9 and , and () is part of player name
         | 
| 253 | 
            -
             | 
| 254 | 
            -
                ## try parsing lhs
         | 
| 255 | 
            -
                ##  todo: check for  empty -    remove (make it same as empty string)
         | 
| 256 | 
            -
             | 
| 257 | 
            -
                players = []
         | 
| 258 | 
            -
             | 
| 259 | 
            -
                name = get_player_name!( line )
         | 
| 260 | 
            -
                while name
         | 
| 261 | 
            -
                  logger.debug "  found player name >#{name}< - remaining >#{line}<"
         | 
| 262 | 
            -
             | 
| 263 | 
            -
                  player = GoalsPlayerStruct.new
         | 
| 264 | 
            -
                  player.name = name
         | 
| 265 | 
            -
             | 
| 266 | 
            -
                  minute_hash = nil 
         | 
| 267 | 
            -
                  while minute_hash=get_minute_hash!( line )   ## note: returns nil if no (regex) match
         | 
| 268 | 
            -
                    logger.debug "  found minutes >#{minute_hash.inspect}< - remaining >#{line}<"
         | 
| 269 | 
            -
             | 
| 270 | 
            -
                    minute = GoalsMinuteStruct.new
         | 
| 271 | 
            -
                    minute.minute = minute_hash[:minute].to_i
         | 
| 272 | 
            -
                    minute.offset = minute_hash[:offset].to_i  if minute_hash[:offset]
         | 
| 273 | 
            -
                    if minute_hash[:type]
         | 
| 274 | 
            -
                      minute.owngoal = true  if minute_hash[:type] =~ /og|o\.g\./i
         | 
| 275 | 
            -
                      minute.penalty = true  if minute_hash[:type] =~ /p|pen\.?/i
         | 
| 276 | 
            -
                    end
         | 
| 277 | 
            -
                    player.minutes << minute
         | 
| 278 | 
            -
             | 
| 279 | 
            -
                    # remove commas and spaces (note: use ^ for start of string only!!!)
         | 
| 280 | 
            -
                    line.sub!( /^[ ,]+/, '' )
         | 
| 281 | 
            -
                  end
         | 
| 282 | 
            -
             | 
| 283 | 
            -
                  players << player
         | 
| 284 | 
            -
                  name = get_player_name!( line )
         | 
| 285 | 
            -
                end
         | 
| 286 | 
            -
             | 
| 287 | 
            -
                players
         | 
| 288 | 
            -
              end   # method parse!
         | 
| 289 | 
            -
             | 
| 290 | 
            -
            private
         | 
| 291 | 
            -
              def get_player_name!( line )
         | 
| 292 | 
            -
                m = NAME_REGEX.match( line )
         | 
| 293 | 
            -
                if m
         | 
| 294 | 
            -
                  ## remove from line
         | 
| 295 | 
            -
                  line.slice!( 0...m[0].length )
         | 
| 296 | 
            -
                  m[0].strip    # remove leading and trailing spaces
         | 
| 297 | 
            -
                else
         | 
| 298 | 
            -
                  nil
         | 
| 299 | 
            -
                end
         | 
| 300 | 
            -
              end
         | 
| 301 | 
            -
             | 
| 302 | 
            -
              def get_minute_hash!( line )
         | 
| 303 | 
            -
                m = MINUTES_REGEX.match( line ) # note: use ^ for start of string only!!!
         | 
| 304 | 
            -
                if m
         | 
| 305 | 
            -
                  h = {}
         | 
| 306 | 
            -
                  ## todo/fix - hash conversion no longer need in ruby 3+!!
         | 
| 307 | 
            -
                  ##               double check - and remove (simplify) !!!!
         | 
| 308 | 
            -
                  # - note: do NOT forget to turn name into symbol for lookup in new hash (name.to_sym)
         | 
| 309 | 
            -
                  m.names.each { |n| h[n.to_sym] = m[n] } # or use match_data.names.zip( match_data.captures ) - more cryptic but "elegant"??
         | 
| 310 | 
            -
             | 
| 311 | 
            -
                  ## remove matched string from line
         | 
| 312 | 
            -
                  line.slice!( 0...m[0].length )
         | 
| 313 | 
            -
                  h
         | 
| 314 | 
            -
                else
         | 
| 315 | 
            -
                  nil
         | 
| 316 | 
            -
                end
         | 
| 317 | 
            -
              end
         | 
| 318 | 
            -
             | 
| 319 | 
            -
            end # class GoalsParser
         | 
| 320 | 
            -
             | 
| 321 | 
            -
            end # module SportDb
         | 
| @@ -1,47 +0,0 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            module SportDb
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            class LinesReader   ## change to LinesEnumerator - why? why not?
         | 
| 5 | 
            -
                    def initialize( lines )
         | 
| 6 | 
            -
                        @iter = lines.each  ## get (external) enumerator (same as to_enum)
         | 
| 7 | 
            -
                        @lineno = 0
         | 
| 8 | 
            -
                    end
         | 
| 9 | 
            -
                
         | 
| 10 | 
            -
                    def each( &blk )
         | 
| 11 | 
            -
                    ## note - StopIteration is rescued (automagically) by Kernel#loop.
         | 
| 12 | 
            -
                    ##            no need to rescue ourselves here
         | 
| 13 | 
            -
                        loop do
         | 
| 14 | 
            -
                          line = @iter.next   ## note - raises StopIteration  
         | 
| 15 | 
            -
                          blk.call( line )
         | 
| 16 | 
            -
                        end
         | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
                
         | 
| 19 | 
            -
                    def each_with_index( &blk )
         | 
| 20 | 
            -
                        ## note - StopIteration is rescued (automagically) by Kernel#loop.
         | 
| 21 | 
            -
                            loop do
         | 
| 22 | 
            -
                              line = @iter.next   ## note - raises StopIteration 
         | 
| 23 | 
            -
                              blk.call( line, @lineno )
         | 
| 24 | 
            -
                              @lineno += 1
         | 
| 25 | 
            -
                            end
         | 
| 26 | 
            -
                    end
         | 
| 27 | 
            -
                    
         | 
| 28 | 
            -
                    def peek
         | 
| 29 | 
            -
                        begin  
         | 
| 30 | 
            -
                          @iter.peek
         | 
| 31 | 
            -
                        rescue StopIteration
         | 
| 32 | 
            -
                            nil
         | 
| 33 | 
            -
                        end
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            -
                
         | 
| 36 | 
            -
                    def next
         | 
| 37 | 
            -
                        ## todo/check - do NOT catch StopIteration for next - why? why not?
         | 
| 38 | 
            -
                        begin
         | 
| 39 | 
            -
                            line = @iter.next
         | 
| 40 | 
            -
                            @lineno += 1
         | 
| 41 | 
            -
                            line
         | 
| 42 | 
            -
                        rescue StopIteration
         | 
| 43 | 
            -
                            nil
         | 
| 44 | 
            -
                        end
         | 
| 45 | 
            -
                    end    
         | 
| 46 | 
            -
            end  # class LinesReader  
         | 
| 47 | 
            -
            end # module SportDb
         |