sportdb-catalogs 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4615353b8720394e2c0edcd97de249822923718bf9d7703e4ce2f93f4411b372
4
- data.tar.gz: ac4536c29d15caf8bf5c3de62539785f17fbad3e6098c5e0d18282c1e5cccb2a
3
+ metadata.gz: '09d5c1b4a2fea093abfc294ccbf6149315a335a07a5e934d25fb652215e0ab23'
4
+ data.tar.gz: 991f6cd9ee018fa4f7d84be847c5868a024ac240ec5d29cb60636addbd1984c5
5
5
  SHA512:
6
- metadata.gz: 93dc76f6a2dd70d04a9ebb6700e66bbcd41a98cd517a9f1ed24b6a2ad667806963ffd2fda6991a02600c3aa4d61c45431201b4f350a37b4a080e53bf664866ec
7
- data.tar.gz: f0cc52b6590c598ec8ae40abdb7b8238a647617b10825b76d4c910bcd01ca7facde765cf977e0abb807312fa7fa55ffa83a239446962b209c8a747004e43e03a
6
+ metadata.gz: ffaca4423b4dc8adba0db61187dfcf2cc0b1fb5c47255953ed08e8e13bc1a0e2967673d7f1a60f5d6a7045b93ff3575fc27114ed86be15c27f72041287e59a91
7
+ data.tar.gz: ded797ffeae2ce160c1d6477416fa90d8b26433e78aca4bdc61c82bf0bdf8eef95f346c2f2fe95e070be962d8789d511d222379057245a9d649388b0a40d93c1
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 1.2.1
1
+ ### 1.2.2
2
2
  ### 0.0.1 / 2019-06-29
3
3
 
4
4
  * Everything is new. First release.
data/README.md CHANGED
@@ -9,23 +9,19 @@
9
9
 
10
10
 
11
11
 
12
- ## Usage
12
+ ## Usage
13
13
 
14
14
  Let's use the [/clubs datasets](https://github.com/openfootball/clubs)
15
- (1500+ football clubs from around the world)
15
+ (3000+ football clubs from around the world)
16
16
  to match name "variants" e.g. `Arsenal` to canonical global unique
17
17
  names e.g. `Arsenal FC, London, England`:
18
18
 
19
19
  ``` ruby
20
20
  require 'sportdb/catalogs'
21
21
 
22
- ## note: requires a local copy of the football.db clubs datasets
23
- ## see https://github.com/openfootball/clubs
24
- SportDb::Import.config.clubs_dir = './clubs'
22
+ Club = CatalogDb::Metal::Club
25
23
 
26
- CLUBS = SportDb::Import.catalog.clubs
27
-
28
- m = CLUBS.match( 'Arsenal' )
24
+ m = Club.match_by( name: 'Arsenal' )
29
25
  m.size # 3 club matches found
30
26
  #=> 3
31
27
  m[0].name; m[0].city; m[0].country
@@ -36,20 +32,20 @@ m[2].name; m[2].city; m[2].country
36
32
  #=> "Arsenal de Sarandí", "Sarandí", "Argentina"
37
33
 
38
34
 
39
- m = CLUBS.match_by( name: 'Arsenal', country: 'eng' )
35
+ m = Club.match_by( name: 'Arsenal', country: 'eng' )
40
36
  # -or- try alternative names (and auto-generated spelling variants)
41
- m = CLUBS.match_by( name: 'Arsenal FC', country: 'eng' )
42
- m = CLUBS.match_by( name: 'Arsenal F.C.', country: 'eng' )
43
- m = CLUBS.match_by( name: '...A.r.s.e.n.a.l... F.C...', country: 'eng' )
37
+ m = Club.match_by( name: 'Arsenal FC', country: 'eng' )
38
+ m = Club.match_by( name: 'Arsenal F.C.', country: 'eng' )
39
+ m = Club.match_by( name: '...A.r.s.e.n.a.l... F.C...', country: 'eng' )
44
40
  m.size # 1 club match found
45
41
  #=> 1
46
42
  m[0].name; m[0].city; m[0].country
47
43
  #=> "Arsenal FC", "London", "England"
48
44
 
49
- m = CLUBS.match_by( name: 'Arsenal', country: 'ar' )
45
+ m = Club.match_by( name: 'Arsenal', country: 'ar' )
50
46
  # -or- try alternative names (and auto-generated spelling variants)
51
- m = CLUBS.match_by( name: 'Arsenal Sarandí', country: 'ar' )
52
- m = CLUBS.match_by( name: 'Arsenal Sarandi', country: 'ar' )
47
+ m = Club.match_by( name: 'Arsenal Sarandí', country: 'ar' )
48
+ m = Club.match_by( name: 'Arsenal Sarandi', country: 'ar' )
53
49
  m.size # 1 club match found
54
50
  #=> 1
55
51
  m[0].name; m[0].city; m[0].country
@@ -57,15 +53,15 @@ m[0].name; m[0].city; m[0].country
57
53
 
58
54
 
59
55
  # try some more
60
- m = CLUBS.match( 'AZ' )
56
+ m = Club.match_by( name: 'AZ' )
61
57
  m[0].name; m[0].city; m[0].country
62
58
  #=> "AZ Alkmaar", "Alkmaar", "Netherlands"
63
59
 
64
- m = CLUBS.match( 'Bayern' )
60
+ m = Club.match_by( name: 'Bayern' )
65
61
  # -or- try alternative names (and auto-generated spelling variants)
66
- m = CLUBS.match( 'Bayern München' )
67
- m = CLUBS.match( 'Bayern Munchen' )
68
- m = CLUBS.match( 'Bayern Muenchen' )
62
+ m = Club.match_by( name: 'Bayern München' )
63
+ m = Club.match_by( name: 'Bayern Munchen' )
64
+ m = Club.match_by( name: 'Bayern Muenchen' )
69
65
  m[0].name; m[0].city; m[0].country
70
66
  #=> "Bayern München", "München", "Germany"
71
67
 
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ Hoe.spec 'sportdb-catalogs' do
20
20
  self.licenses = ['Public Domain']
21
21
 
22
22
  self.extra_deps = [
23
- ['sportdb-formats', '>= 2.0.0'],
23
+ ['sportdb-structs', '>= 0.3.1'],
24
24
  ['sqlite3'], ## add sqlite for "metal" use (no activerecord etc.)
25
25
  ['footballdb-data'] ## add builtin default db
26
26
  ]
@@ -8,29 +8,29 @@ module Metal
8
8
 
9
9
 
10
10
  class BaseRecord ## or just use Base or such - why? why not?
11
-
12
- def self.execute( sql )
11
+
12
+ def self.execute( sql )
13
13
  ## puts "==> sql query [#{self.name}]"
14
14
  ## puts sql
15
- database.execute( sql )
15
+ database.execute( sql )
16
16
  end
17
-
17
+
18
18
  def self.tablename=(name) @tablename = name; end
19
19
  def self.tablename() @tablename; end
20
-
21
- def self.columns=(names)
20
+
21
+ def self.columns=(names)
22
22
  ## note: auto-add table name to qualify
23
- @columns = names.map {|name| "#{self.tablename}.#{name}" }
23
+ @columns = names.map {|name| "#{self.tablename}.#{name}" }
24
24
  @columns
25
25
  end
26
26
  def self.columns() @columns; end
27
-
27
+
28
28
  def self.count
29
29
  sql = "SELECT count(*) FROM #{self.tablename}"
30
30
  rows = execute( sql )
31
31
  rows[0][0] # e.g. returns [[241]]
32
32
  end
33
-
33
+
34
34
  ## helpers from country - use a helper module for includes (share with clubs etc.) - why? why not?
35
35
  # include NameHelper
36
36
  extend SportDb::NameHelper
@@ -48,7 +48,7 @@ class BaseRecord ## or just use Base or such - why? why not?
48
48
  ## use TypeError - why? why not? or if exits ValueError?
49
49
  raise ArgumentError, "0 or 1 expected for bool in sqlite; got #{value}"
50
50
  end
51
- end
51
+ end
52
52
 
53
53
 
54
54
  ##
@@ -58,7 +58,7 @@ class BaseRecord ## or just use Base or such - why? why not?
58
58
  if country.is_a?( String ) || country.is_a?( Symbol )
59
59
  # note: query/find country via catalog db
60
60
  rec = Country.find_by_code( country )
61
- rec = Country.find_by_name( country ) if rec.nil?
61
+ rec = Country.find_by_name( country ) if rec.nil?
62
62
  if rec.nil?
63
63
  puts "** !!! ERROR !!! - unknown country >#{country}< - no match found, sorry - add to world/countries.txt in config"
64
64
  exit 1
@@ -72,41 +72,50 @@ end # class BaseRecord
72
72
 
73
73
 
74
74
  class PlayerRecord < BaseRecord
75
+
76
+ ## lets you query if datbase setup
77
+ def self.database?() defined?( @@db ); end
78
+
75
79
  def self.database
76
80
  ### note: only one database for all derived records/tables!!!
77
81
  ## thus MUST use @@ and not @!!!!!
78
82
  ## todo - change later to built-in database
79
83
  ## or download on request???
80
- @@db ||= SQLite3::Database.new( './players.db' )
84
+ @@db ||= SQLite3::Database.new( './players.db', readonly: true )
81
85
  @@db
82
86
  end
83
-
87
+
84
88
  def self.database=(path)
85
89
  puts "==> setting (internal) players db to: >#{path}<"
86
- @@db = SQLite3::Database.new( path )
90
+ @@db = SQLite3::Database.new( path, readonly: true )
87
91
  pp @@db
88
92
  @@db
89
- end
93
+ end
90
94
  end # class PlayerRecord
91
95
 
92
96
 
93
97
 
94
98
  ##############
95
99
  ### todo (fix) / rename to CatalogRecord - why? why not?
96
- class Record < BaseRecord
100
+ class Record < BaseRecord
97
101
  ## add db alias why? why not?
102
+
103
+ ## lets you query if datbase setup
104
+ def self.database?() defined?( @@db ); end
105
+
98
106
  def self.database
99
107
  ### note: only one database for all derived records/tables!!!
100
108
  ## thus MUST use @@ and not @!!!!!
101
109
  ##
102
110
  ## default to built-in via footballdb-data gem for now!!!
103
- @@db ||= SQLite3::Database.new( './catalog.db' )
111
+ @@db ||= SQLite3::Database.new( "#{FootballDb::Data.data_dir}/catalog.db",
112
+ readonly: true )
104
113
  @@db
105
114
  end
106
115
 
107
116
  def self.database=(path)
108
117
  puts "==> setting (internal) catalog db to: >#{path}<"
109
- @@db = SQLite3::Database.new( path )
118
+ @@db = SQLite3::Database.new( path, readonly: true )
110
119
  pp @@db
111
120
  @@db
112
121
  end
@@ -118,14 +127,14 @@ def self._to_league( key )
118
127
  League._record( key )
119
128
  end
120
129
 
121
- def self._to_country( key )
130
+ def self._to_country( key )
122
131
  # note: use cached record or (faster) key lookup on fallback
123
- Country._record( key )
132
+ Country._record( key )
124
133
  end
125
134
 
126
135
  def self._to_city( key ) ### rename; use find_by_key / find_by( key: )
127
136
  # note: use cached record or (faster) key lookup on fallback
128
- City._record( key )
137
+ City._record( key )
129
138
  end
130
139
 
131
140
 
@@ -4,20 +4,19 @@ module Metal
4
4
  class EventInfo < Record
5
5
  self.tablename = 'event_infos'
6
6
 
7
- self.columns = ['league_key',
8
- 'season',
9
- 'teams',
7
+ self.columns = ['league_key',
8
+ 'season',
9
+ 'teams',
10
10
  'matches',
11
11
  'goals',
12
- 'start_date',
12
+ 'start_date',
13
13
  'end_date']
14
-
14
+
15
15
 
16
16
  def self._build_event_info( row )
17
17
  ## note: cache structs by key (do NOT rebuild duplicates; reuse)
18
18
  @cache ||= Hash.new
19
- ## note: move EventInfo from sports/format to structs - why? why not?
20
- @cache[ row[0] ] ||= SportDb::Import::EventInfo.new(
19
+ @cache[ row[0] ] ||= Sports::EventInfo.new(
21
20
  league: _to_league( row[0] ),
22
21
  season: Season.parse(row[1]),
23
22
  teams: row[2],
@@ -25,35 +24,35 @@ class EventInfo < Record
25
24
  goals: row[4],
26
25
  start_date: row[5] ? Date.strptime( row[5], '%Y-%m-%d' ) : nil,
27
26
  end_date: row[6] ? Date.strptime( row[6], '%Y-%m-%d' ) : nil,
28
- )
29
- end
30
-
27
+ )
28
+ end
29
+
31
30
 
32
31
  def self.seasons( league )
33
- league_key = league.is_a?( String ) ? League.find!( league ).key
32
+ league_key = league.is_a?( String ) ? League.find!( league ).key
34
33
  : league.key
35
34
 
36
35
  rows = execute( <<-SQL )
37
36
  SELECT #{self.columns.join(', ')}
38
- FROM event_infos
39
- WHERE event_infos.league_key = '#{league_key}'
37
+ FROM event_infos
38
+ WHERE event_infos.league_key = '#{league_key}'
40
39
  SQL
41
40
 
42
41
  rows.map {|row| _build_event_info( row ) }
43
42
  end
44
43
 
45
-
44
+
46
45
  def self.find_by( league:, season: )
47
- league_key = league.is_a?( String ) ? League.find!( league ).key
46
+ league_key = league.is_a?( String ) ? League.find!( league ).key
48
47
  : league.key
49
- season_key = season.is_a?( String ) ? Season.parse(season).key
48
+ season_key = season.is_a?( String ) ? Season.parse(season).key
50
49
  : season.key
51
50
 
52
51
  rows = execute( <<-SQL )
53
52
  SELECT #{self.columns.join(', ')}
54
- FROM event_infos
53
+ FROM event_infos
55
54
  WHERE event_infos.league_key = '#{league_key}' AND
56
- event_infos.season = '#{season_key}'
55
+ event_infos.season = '#{season_key}'
57
56
  SQL
58
57
 
59
58
  if rows.empty?
@@ -5,7 +5,7 @@ module Catalogs
5
5
 
6
6
  MAJOR = 1 ## todo: namespace inside version or something - why? why not??
7
7
  MINOR = 2
8
- PATCH = 1
8
+ PATCH = 2
9
9
  VERSION = [MAJOR,MINOR,PATCH].join('.')
10
10
 
11
11
  def self.version
@@ -1,7 +1,4 @@
1
- ### our own sportdb libs / gems
2
- ### try min. dependencies - change to structs only (NOT formats) - why? why not?
3
- ## require 'sportdb/structs'
4
- require 'sportdb/formats'
1
+ require 'sportdb/structs'
5
2
 
6
3
  require 'sqlite3'
7
4
 
@@ -15,77 +12,17 @@ require_relative 'catalogs/base' ## base record
15
12
  require_relative 'catalogs/country'
16
13
  require_relative 'catalogs/city'
17
14
 
18
- require_relative 'catalogs/club'
15
+ require_relative 'catalogs/club'
19
16
  require_relative 'catalogs/national_team'
20
17
  require_relative 'catalogs/league'
21
18
  require_relative 'catalogs/event_info'
22
- require_relative 'catalogs/ground'
19
+ require_relative 'catalogs/ground'
23
20
 
24
21
  ## more
25
22
  require_relative 'catalogs/player'
26
23
 
27
24
 
28
25
 
29
- module SportDb
30
- module Import
31
-
32
- class Configuration
33
- ## note: add more configs (open class), see sportdb-structs for original config!!!
34
-
35
- ###
36
- # find a better name for setting - why? why not?
37
- # how about catalogdb or ???
38
- attr_reader :catalog_path
39
- def catalog_path=(path)
40
- @catalog_path = path
41
- ########
42
- # reset database here to new path
43
- CatalogDb::Metal::Record.database = path
44
-
45
- ## plus automagically set world search too (to use CatalogDb)
46
- self.world = WorldSearch.new(
47
- countries: CatalogDb::Metal::Country,
48
- cities: CatalogDb::Metal::City,
49
- )
50
-
51
- @catalog_path
52
- end
53
-
54
- def catalog
55
- @catalog ||= SportSearch.new(
56
- leagues: CatalogDb::Metal::League,
57
- national_teams: CatalogDb::Metal::NationalTeam,
58
- clubs: CatalogDb::Metal::Club,
59
- grounds: CatalogDb::Metal::Ground,
60
- events: CatalogDb::Metal::EventInfo,
61
- players: CatalogDb::Metal::Player, # note - via players.db !!!
62
- )
63
- end
64
-
65
- ###
66
- # find a better name for setting - why? why not?
67
- # how about playersdb or ???
68
- attr_reader :players_path
69
- def players_path=(path)
70
- @players_path = path
71
- ########
72
- # reset database here to new path
73
- CatalogDb::Metal::PlayerRecord.database = path
74
-
75
- @players_path
76
- end
77
- end # class Configuration
78
-
79
-
80
- ## e.g. use config.catalog -- keep Import.catalog as a shortcut (for "read-only" access)
81
- def self.catalog() config.catalog; end
82
- end # module Import
83
- end # module SportDb
84
-
85
-
86
-
87
-
88
-
89
26
  ###
90
27
  # add status
91
28
  module CatalogDb
@@ -94,34 +31,48 @@ module Metal
94
31
  def self.tables
95
32
 
96
33
  puts "==> table stats"
97
- catalog_path = SportDb::Import.config.catalog_path
98
- if catalog_path
99
- puts " #{File.basename(catalog_path)} in (#{File.dirname(catalog_path)})"
100
- puts " #{Country.count} countries / #{City.count} cities"
34
+ if Record.database?
35
+ db = Record.database
36
+ filename = db.filename
37
+ if filename # note - nil for memory or tempary db?
38
+ puts " #{File.basename(filename)} in (#{File.dirname(filename)})"
39
+ else
40
+ puts "no filename; memory or temporary db?"
41
+ end
42
+
43
+ ## pp Record.database
44
+ ## puts
45
+ puts " #{Country.count} countries / #{City.count} cities"
101
46
  puts " #{NationalTeam.count} national teams"
102
47
  puts " #{League.count} leagues"
103
48
  puts " #{Club.count} clubs"
104
49
  puts " #{Ground.count} grounds"
105
50
  ## add more
106
-
107
51
  else
108
52
  puts " - no catalog.db set - "
109
53
  end
110
54
 
111
- ## todo/fix:
112
- ## check if players_path configured???
113
- players_path = SportDb::Import.config.players_path
114
- if players_path
115
- puts " #{File.basename(players_path)} in (#{File.dirname(players_path)})"
55
+
56
+ if PlayerRecord.database?
57
+ db = PlayerRecord.database
58
+ filename = db.filename
59
+ if filename # note - nil for memory or tempary db?
60
+ puts " #{File.basename(filename)} in (#{File.dirname(filename)})"
61
+ else
62
+ puts "no filename; memory or temporary db?"
63
+ end
64
+
65
+ ## pp PlayerRecord.database
66
+ ## puts
116
67
  puts " #{Player.count} players"
117
68
  else
118
- puts " - no players.db set -"
69
+ puts " - no players.db set -"
119
70
  end
120
71
  end
121
72
 
122
73
  end # module Metal
123
74
  end # module CatalogDb
124
-
75
+
125
76
 
126
77
 
127
78
  ###
@@ -131,34 +82,34 @@ end # module CatalogDb
131
82
  ## what name to use?
132
83
  ## find_countries_for_league_clubs or such
133
84
  ## find_countries_for_league - why? why not?
134
- ## note - returns array of countries OR single country
85
+ ## note - returns array of countries OR single country
135
86
 
136
87
  def find_countries_for_league( league )
137
- ## todo/fix: assert league is a League with country record/struct !!!!!
88
+ ## todo/fix: assert league is a League with country record/struct !!!!!
138
89
 
139
- countries = []
90
+ countries = []
140
91
  countries << league.country ### assume league.country is already db record/struct - why? why not?
141
- ## check for 2nd countries for known leagues
92
+ ## check for 2nd countries for known leagues
142
93
  ## (re)try with second country - quick hacks for known leagues
143
94
  ## e.g. Swanse, cardiff in premier league
144
95
  ## san mariono in serie a (italy)
145
96
  ## monaco in ligue 1 (france)
146
97
  ## etc.
147
98
  ## add andorra to spanish la liga (e.g. andorra fc???)
148
-
99
+
149
100
  case league.country.key
150
- when 'eng' then countries << CatalogDb::Metal::Country._record('wal')
101
+ when 'eng' then countries << CatalogDb::Metal::Country._record('wal')
151
102
  when 'sco' then countries << CatalogDb::Metal::Country._record('eng')
152
- when 'ie' then countries << CatalogDb::Metal::Country._record('nir')
153
- when 'fr' then countries << CatalogDb::Metal::Country._record('mc')
154
- when 'es' then countries << CatalogDb::Metal::Country._record('ad')
103
+ when 'ie' then countries << CatalogDb::Metal::Country._record('nir')
104
+ when 'fr' then countries << CatalogDb::Metal::Country._record('mc')
105
+ when 'es' then countries << CatalogDb::Metal::Country._record('ad')
155
106
  when 'it' then countries << CatalogDb::Metal::Country._record('sm')
156
- when 'ch' then countries << CatalogDb::Metal::Country._record('li')
107
+ when 'ch' then countries << CatalogDb::Metal::Country._record('li')
157
108
  when 'us' then countries << CatalogDb::Metal::Country._record('ca')
158
109
  when 'au' then countries << CatalogDb::Metal::Country._record('nz')
159
- end
110
+ end
160
111
 
161
- ## use single ("unwrapped") item for one country
112
+ ## use single ("unwrapped") item for one country
162
113
  ## otherwise use array
163
114
  country = countries.size == 1 ? countries[0] : countries
164
115
  country
@@ -168,15 +119,8 @@ end
168
119
 
169
120
 
170
121
 
171
-
172
122
  require 'footballdb/data' ## pull in catalog.db (built-in/default data/db)
173
123
 
174
- ###
175
- ## add default/built-in catalog here - why? why not?
176
- ## todo/fix - set catalog_path on demand
177
- ## note: for now required for world search setup etc.
178
- SportDb::Import.config.catalog_path = "#{FootballDb::Data.data_dir}/catalog.db"
179
-
180
124
 
181
125
 
182
126
  puts SportDb::Module::Catalogs.banner # say hello
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb-catalogs
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-22 00:00:00.000000000 Z
11
+ date: 2024-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: sportdb-formats
14
+ name: sportdb-structs
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.0
19
+ version: 0.3.1
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: 2.0.0
26
+ version: 0.3.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sqlite3
29
29
  requirement: !ruby/object:Gem::Requirement