sportdb-search 0.0.1
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 +7 -0
- data/CHANGELOG.md +3 -0
- data/Manifest.txt +9 -0
- data/README.md +28 -0
- data/Rakefile +29 -0
- data/lib/sportdb/search/sport.rb +323 -0
- data/lib/sportdb/search/structs.rb +132 -0
- data/lib/sportdb/search/version.rb +24 -0
- data/lib/sportdb/search/world.rb +127 -0
- data/lib/sportdb/search.rb +223 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a675e2ad48a651c6b31ccc0f68f838907384a93078269dff90c87e5424472a56
|
4
|
+
data.tar.gz: 8abf21926e4e3924ef71df5da72330c834fe0a54679efffdb6657e90361e4bac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db536b42aabda47e6a6eb7b2da08a7454f91c017801948a86ee7207762a5ffc9ebc5eb7a32e65378aeea4ad8a93af7c0db390458e667dd6cc350c2d3e9dfa24e
|
7
|
+
data.tar.gz: 5b69bf93a1dd374d2dcf50907c26aeaf7781af34ba127d91830f09d8e9406dfcf1345b806222258ba6da7d7bf2df8590790d8f3763298c9a1909ca536a02097a
|
data/CHANGELOG.md
ADDED
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# sportdb-search - find national teams, clubs, leagues & more
|
2
|
+
|
3
|
+
* home :: [github.com/sportdb/sport.db](https://github.com/sportdb/sport.db)
|
4
|
+
* bugs :: [github.com/sportdb/sport.db/issues](https://github.com/sportdb/sport.db/issues)
|
5
|
+
* gem :: [rubygems.org/gems/sportdb-search](https://rubygems.org/gems/sportdb-search)
|
6
|
+
* rdoc :: [rubydoc.info/gems/sportdb-search](http://rubydoc.info/gems/sportdb-search)
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
|
13
|
+
to be done
|
14
|
+
|
15
|
+
|
16
|
+
## License
|
17
|
+
|
18
|
+
The `sportdb-search` scripts are dedicated to the public domain.
|
19
|
+
Use it as you please with no restrictions whatsoever.
|
20
|
+
|
21
|
+
|
22
|
+
## Questions? Comments?
|
23
|
+
|
24
|
+
Yes, you can. More than welcome.
|
25
|
+
See [Help & Support »](https://github.com/openfootball/help)
|
26
|
+
|
27
|
+
|
28
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
require './lib/sportdb/search/version.rb'
|
3
|
+
|
4
|
+
Hoe.spec 'sportdb-search' do
|
5
|
+
|
6
|
+
self.version = SportDb::Module::Search::VERSION
|
7
|
+
|
8
|
+
self.summary = "sportdb-search - find national teams, clubs, leagues & more"
|
9
|
+
self.description = summary
|
10
|
+
|
11
|
+
self.urls = { home: 'https://github.com/sportdb/sport.db' }
|
12
|
+
|
13
|
+
self.author = 'Gerald Bauer'
|
14
|
+
self.email = 'gerald.bauer@gmail.com'
|
15
|
+
|
16
|
+
# switch extension to .markdown for gihub formatting
|
17
|
+
self.readme_file = 'README.md'
|
18
|
+
self.history_file = 'CHANGELOG.md'
|
19
|
+
|
20
|
+
self.licenses = ['Public Domain']
|
21
|
+
|
22
|
+
self.extra_deps = [
|
23
|
+
['sportdb-catalogs', '>= 1.2.3'],
|
24
|
+
]
|
25
|
+
|
26
|
+
self.spec_extras = {
|
27
|
+
required_ruby_version: '>= 3.1.0'
|
28
|
+
}
|
29
|
+
end
|
@@ -0,0 +1,323 @@
|
|
1
|
+
###
|
2
|
+
# sport search service api for leagues, clubs and more
|
3
|
+
#
|
4
|
+
# core api is:
|
5
|
+
|
6
|
+
|
7
|
+
class SportSearch
|
8
|
+
|
9
|
+
class PlayerSearch < Search
|
10
|
+
###################
|
11
|
+
## core required delegates - use delegate generator - why? why not?
|
12
|
+
def match_by( name:, country: nil, year: nil )
|
13
|
+
@service.match_by( name: name,
|
14
|
+
country: country,
|
15
|
+
year: year )
|
16
|
+
end
|
17
|
+
|
18
|
+
###############
|
19
|
+
### more deriv support functions / helpers
|
20
|
+
def match( name ) match_by( name: name ); end
|
21
|
+
## add more here - why? why not?
|
22
|
+
end # class PlayerSearch
|
23
|
+
|
24
|
+
|
25
|
+
class LeagueSearch < Search
|
26
|
+
|
27
|
+
###################
|
28
|
+
## core required delegates - use delegate generator - why? why not?
|
29
|
+
def match_by( name: nil, code: nil, country: nil )
|
30
|
+
## todo/fix upstream - remove "generic" match_by() - why? why not?
|
31
|
+
###
|
32
|
+
if code && name.nil?
|
33
|
+
@service.match_by_code( code, country: country )
|
34
|
+
elsif name && code.nil?
|
35
|
+
@service.match_by_name( name, country: country )
|
36
|
+
else
|
37
|
+
raise ArgumentError, "LeagueSearch#match_by - one (and only one arg) required - code: or name:"
|
38
|
+
end
|
39
|
+
## @service.match_by( name: name,
|
40
|
+
## country: country )
|
41
|
+
end
|
42
|
+
|
43
|
+
## all-in-one query (name or code)
|
44
|
+
def match( q, country: nil )
|
45
|
+
@service.match_by_name_or_code( q, country: country )
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
###############
|
50
|
+
### more deriv support functions / helpers
|
51
|
+
def find!( q )
|
52
|
+
league = find( q )
|
53
|
+
if league.nil?
|
54
|
+
puts "** !!! ERROR - no league match found for >#{q}<, add to leagues table; sorry"
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
league
|
58
|
+
end
|
59
|
+
|
60
|
+
def find( q )
|
61
|
+
league = nil
|
62
|
+
recs = match( q )
|
63
|
+
# pp m
|
64
|
+
|
65
|
+
if recs.empty?
|
66
|
+
## fall through/do nothing
|
67
|
+
elsif recs.size > 1
|
68
|
+
puts "** !!! ERROR - ambigious league query; too many leagues (#{recs.size}) found:"
|
69
|
+
pp recs
|
70
|
+
exit 1
|
71
|
+
else
|
72
|
+
league = recs[0]
|
73
|
+
end
|
74
|
+
|
75
|
+
league
|
76
|
+
end
|
77
|
+
end # class LeagueSearch
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
class GroundSearch < Search
|
82
|
+
###################
|
83
|
+
## core required delegates - use delegate generator - why? why not?
|
84
|
+
def match_by( name:, country: nil, city: nil )
|
85
|
+
@service.match_by( name: name,
|
86
|
+
country: country,
|
87
|
+
city: city )
|
88
|
+
end
|
89
|
+
|
90
|
+
###############
|
91
|
+
### more deriv support functions / helpers
|
92
|
+
def match( name ) match_by( name: name ); end
|
93
|
+
## add more here - why? why not?
|
94
|
+
end # class GroundSearch
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
class NationalTeamSearch < Search
|
99
|
+
###################
|
100
|
+
## core required delegates - use delegate generator - why? why not?
|
101
|
+
|
102
|
+
## changle core api to match( q ) only - why? why not?
|
103
|
+
## and make find and find! derivs???
|
104
|
+
def find( q ) @service.find( q ); end
|
105
|
+
def find!( q ) @service.find!( q ); end
|
106
|
+
end # class NationalTeamSearch
|
107
|
+
|
108
|
+
|
109
|
+
class ClubSearch < Search
|
110
|
+
###################
|
111
|
+
## core required delegates - use delegate generator - why? why not?
|
112
|
+
|
113
|
+
## add mods here - why? why not?
|
114
|
+
|
115
|
+
def match_by( name:, country: nil,
|
116
|
+
league: nil,
|
117
|
+
mods: nil )
|
118
|
+
## for now assume "global" mods - checks only for name
|
119
|
+
##
|
120
|
+
if mods && mods[ name ]
|
121
|
+
club = mods[ name ]
|
122
|
+
return [club] # note: wrap (single record) in array
|
123
|
+
end
|
124
|
+
|
125
|
+
## note: add "auto-magic" country calculation via league record
|
126
|
+
## if league is a national league for football clubs
|
127
|
+
if league
|
128
|
+
raise ArgumentError, "match_by - league AND country NOT supported; sorry" if country
|
129
|
+
### find countries via league
|
130
|
+
### support league.intl? too - why? why not?
|
131
|
+
### or only nationa league
|
132
|
+
raise ArgumentError, "match_by - league - only national club leagues supported (not int'l or national teams for now); sorry" unless league.national? && league.clubs?
|
133
|
+
|
134
|
+
### calc countries
|
135
|
+
### uses "global" func in sports-catalogs for now
|
136
|
+
## move code here - why? why not?
|
137
|
+
country = find_countries_for_league( league )
|
138
|
+
@service.match_by( name: name,
|
139
|
+
country: country )
|
140
|
+
else
|
141
|
+
@service.match_by( name: name,
|
142
|
+
country: country )
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
## todo/fix/check: use rename to find_canon or find_canonical() or something??
|
148
|
+
## remove (getting used?) - why? why not?
|
149
|
+
# def []( name ) ## lookup by canoncial name only; todo/fix: add find alias why? why not?
|
150
|
+
# puts "WARN!! do not use ClubIndex#[] for lookup >#{name}< - will get removed!!!"
|
151
|
+
# @clubs[ name ]
|
152
|
+
# end
|
153
|
+
|
154
|
+
|
155
|
+
###############
|
156
|
+
### more deriv support functions / helpers
|
157
|
+
def match( name ) match_by( name: name ); end
|
158
|
+
|
159
|
+
##########
|
160
|
+
# "legacy" finders - return zero or one club
|
161
|
+
## (if more than one match, exit/raise error/exception)
|
162
|
+
def find( name ) find_by( name: name ); end
|
163
|
+
def find!( name ) find_by!( name: name ); end
|
164
|
+
|
165
|
+
## find - always returns a single record / match or nil
|
166
|
+
## if there is more than one match than find aborts / fails
|
167
|
+
def find_by!( name:, country: nil,
|
168
|
+
league: nil ) ## todo/fix: add international or league flag?
|
169
|
+
club = find_by( name: name,
|
170
|
+
country: country,
|
171
|
+
league: league )
|
172
|
+
|
173
|
+
if club.nil?
|
174
|
+
puts "** !!! ERROR - no match for club >#{name}<"
|
175
|
+
exit 1
|
176
|
+
end
|
177
|
+
|
178
|
+
club
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
def find_by( name:, country: nil,
|
183
|
+
league: nil ) ## todo/fix: add international or league flag?
|
184
|
+
## note: allow passing in of country key too (auto-counvert)
|
185
|
+
## and country struct too
|
186
|
+
## - country assumes / allows the country key or fifa code for now
|
187
|
+
recs = match_by( name: name,
|
188
|
+
country: country,
|
189
|
+
league: league )
|
190
|
+
|
191
|
+
club = nil
|
192
|
+
if recs.empty?
|
193
|
+
## puts "** !!! WARN !!! no match for club >#{name}<"
|
194
|
+
elsif recs.size > 1
|
195
|
+
puts "** !!! ERROR - too many matches (#{recs.size}) for club >#{name}<:"
|
196
|
+
pp recs
|
197
|
+
exit 1
|
198
|
+
else # bingo; match - assume size == 1
|
199
|
+
club = recs[0]
|
200
|
+
end
|
201
|
+
|
202
|
+
club
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
#######
|
207
|
+
# more support methods
|
208
|
+
def build_mods( mods )
|
209
|
+
## e.g.
|
210
|
+
## { 'Arsenal | Arsenal FC' => 'Arsenal, ENG',
|
211
|
+
## 'Liverpool | Liverpool FC' => 'Liverpool, ENG',
|
212
|
+
## 'Barcelona' => 'Barcelona, ESP',
|
213
|
+
## 'Valencia' => 'Valencia, ESP' }
|
214
|
+
|
215
|
+
mods.reduce({}) do |h,(club_names, club_line)|
|
216
|
+
|
217
|
+
values = club_line.split( ',' )
|
218
|
+
values = values.map { |value| value.strip } ## strip all spaces
|
219
|
+
|
220
|
+
## todo/fix: make sure country is present !!!!
|
221
|
+
club_name, country_name = values
|
222
|
+
club = find_by!( name: club_name, country: country_name )
|
223
|
+
|
224
|
+
values = club_names.split( '|' )
|
225
|
+
values = values.map { |value| value.strip } ## strip all spaces
|
226
|
+
|
227
|
+
values.each do |club_name|
|
228
|
+
h[club_name] = club
|
229
|
+
end
|
230
|
+
h
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end # class ClubSearch
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
## todo/check - change to EventInfoSearch - why? why not?
|
238
|
+
class EventSearch < Search
|
239
|
+
##
|
240
|
+
## todo - eventinfo search still open / up for change
|
241
|
+
|
242
|
+
###################
|
243
|
+
## core required delegates - use delegate generator - why? why not?
|
244
|
+
def seasons( league )
|
245
|
+
@service.seasons( league )
|
246
|
+
end
|
247
|
+
def find_by( league:, season: )
|
248
|
+
@service.find_by( league: league,
|
249
|
+
season: season )
|
250
|
+
end
|
251
|
+
end # class EventSearch
|
252
|
+
|
253
|
+
|
254
|
+
####
|
255
|
+
## virtual table for season lookup
|
256
|
+
## note - use EventSeaon to avoid name conflict with (global) Season class
|
257
|
+
## find a better name SeasonInfo or SeasonFinder or SeasonStore
|
258
|
+
## or SeasonQ or ??
|
259
|
+
class EventSeasonSearch
|
260
|
+
def initialize( events: )
|
261
|
+
@events = events
|
262
|
+
end
|
263
|
+
|
264
|
+
###############
|
265
|
+
## todo/fix: find a better algo to guess season for date!!!
|
266
|
+
##
|
267
|
+
def find_by( date:, league: )
|
268
|
+
date = Date.strptime( date, '%Y-%m-%d' ) if date.is_a?( String )
|
269
|
+
|
270
|
+
infos = @events.seasons( league )
|
271
|
+
|
272
|
+
infos.each do |info|
|
273
|
+
return info.season if info.include?( date )
|
274
|
+
end
|
275
|
+
nil
|
276
|
+
end
|
277
|
+
end # class EventSeasonSearch
|
278
|
+
|
279
|
+
|
280
|
+
######
|
281
|
+
### add virtual team search ( clubs + national teams)
|
282
|
+
## note: no record base!!!!!
|
283
|
+
class TeamSearch
|
284
|
+
## note: "virtual" index lets you search clubs and/or national_teams (don't care)
|
285
|
+
|
286
|
+
def initialize( clubs:, national_teams: )
|
287
|
+
@clubs = clubs
|
288
|
+
@national_teams = national_teams
|
289
|
+
end
|
290
|
+
|
291
|
+
## todo/check: rename to/use map_by! for array version - why? why not?
|
292
|
+
def find_by!( name:, league:, mods: nil )
|
293
|
+
if name.is_a?( Array )
|
294
|
+
recs = []
|
295
|
+
name.each do |q|
|
296
|
+
recs << _find_by!( name: q, league: league, mods: mods )
|
297
|
+
end
|
298
|
+
recs
|
299
|
+
else ## assume single name
|
300
|
+
_find_by!( name: name, league: league, mods: mods )
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
def _find_by!( name:, league:, mods: nil )
|
306
|
+
if mods && mods[ league.key ] && mods[ league.key ][ name ]
|
307
|
+
mods[ league.key ][ name ]
|
308
|
+
else
|
309
|
+
if league.clubs?
|
310
|
+
if league.intl? ## todo/fix: add intl? to ActiveRecord league!!!
|
311
|
+
@clubs.find!( name )
|
312
|
+
else ## assume clubs in domestic/national league tournament
|
313
|
+
## note - search by league countries (may incl. more than one country
|
314
|
+
## e.g. us incl. ca, fr incl. mc, ch incl. li, etc.
|
315
|
+
@clubs.find_by!( name: name, league: league )
|
316
|
+
end
|
317
|
+
else ## assume national teams (not clubs)
|
318
|
+
@national_teams.find!( name )
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end # method _find_by!
|
322
|
+
end # class TeamSearch
|
323
|
+
end # class SportSearch
|
@@ -0,0 +1,132 @@
|
|
1
|
+
###
|
2
|
+
# note - extend all structs for with search api
|
3
|
+
#
|
4
|
+
# todo - add more helpers!!!!
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# todo - fix - move all non-core search functionality/machinery
|
8
|
+
# over here - why? why not?
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
module Sports
|
13
|
+
|
14
|
+
class Country
|
15
|
+
def self._search #### use service/api or such - why? why not?
|
16
|
+
SportDb::Import.world.countries
|
17
|
+
end
|
18
|
+
def self.find_by( code: nil, name: nil )
|
19
|
+
_search.find_by( code: code, name: name )
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.find( q ) ## find by code (first) or name (second)
|
23
|
+
_search.find( q )
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.parse_heading( line )
|
27
|
+
## fix - move parse code here from search - why? why not?
|
28
|
+
_search.parse( line )
|
29
|
+
end
|
30
|
+
|
31
|
+
## add alternate names/aliases
|
32
|
+
class << self
|
33
|
+
alias_method :[], :find ### keep shortcut - why? why not?
|
34
|
+
alias_method :heading, :parse_heading
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# open question - what name to use build or parse_line or ?
|
39
|
+
# or parse_recs for CountryReader?
|
40
|
+
# remove CountryReader helper methods - why? why not?
|
41
|
+
# use parse_heading/heading for now !!!
|
42
|
+
#
|
43
|
+
# def self.parse( line ) or build( line ) ??
|
44
|
+
# SportDb::Import.world.countries.parse( line )
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# !!!! note - conflict with
|
48
|
+
# def self.read( path ) CountryReader.read( path ); end
|
49
|
+
# def self.parse( txt ) CountryReader.parse( txt ); end
|
50
|
+
#
|
51
|
+
end # class Country
|
52
|
+
|
53
|
+
|
54
|
+
###
|
55
|
+
## todo/fix - add find_by( code: ), find_by( name: )
|
56
|
+
## split - why? why not?
|
57
|
+
|
58
|
+
|
59
|
+
class League
|
60
|
+
def self._search #### use service/api or such - why? why not?
|
61
|
+
SportDb::Import.catalog.leagues
|
62
|
+
end
|
63
|
+
def self.match_by( name: nil, code: nil,
|
64
|
+
country: nil )
|
65
|
+
_search.match_by( name: name, code: code,
|
66
|
+
country: country )
|
67
|
+
end
|
68
|
+
def self.match( q, country: nil )
|
69
|
+
_search.match( q, country: country )
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.find!( q ) _search.find!( q ); end
|
73
|
+
def self.find( q ) _search_find( q ); end
|
74
|
+
end # class League
|
75
|
+
|
76
|
+
|
77
|
+
class NationalTeam
|
78
|
+
def self._search #### use service/api or such - why? why not?
|
79
|
+
SportDb::Import.catalog.national_teams
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.find( q ) _search.find( q ); end
|
83
|
+
def self.find!( q ) _search_find!( q ); end
|
84
|
+
end # class NationalTeam
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
class Club
|
89
|
+
def self._search #### use service/api or such - why? why not?
|
90
|
+
SportDb::Import.catalog.clubs
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.match_by( name:, country: nil,
|
94
|
+
league: nil,
|
95
|
+
mods: nil )
|
96
|
+
_search.match_by( name: name, country: country,
|
97
|
+
league: league, mods: mods )
|
98
|
+
end
|
99
|
+
def self.match( name ) match_by( name: name ); end
|
100
|
+
|
101
|
+
def self.find( name ) _search.find_by( name: name ); end
|
102
|
+
def self.find!( name ) _search.find_by!( name: name ); end
|
103
|
+
|
104
|
+
def self.find_by!( name:, country: nil,
|
105
|
+
league: nil )
|
106
|
+
_search.find_by!( name: name, country: country,
|
107
|
+
league: league )
|
108
|
+
end
|
109
|
+
def self.find_by( name:, country: nil,
|
110
|
+
league: nil )
|
111
|
+
_search.find_by( name: name, country: country,
|
112
|
+
league: league )
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.build_mods( mods )
|
116
|
+
_search_build_mods( mods )
|
117
|
+
end
|
118
|
+
end # class Club
|
119
|
+
|
120
|
+
|
121
|
+
class Ground
|
122
|
+
def self._search
|
123
|
+
SportDb::Import.catalog.grounds
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.match_by( name:, country: nil, city: nil )
|
127
|
+
_search.match_by( name: name,
|
128
|
+
country: country,
|
129
|
+
city: city )
|
130
|
+
end
|
131
|
+
end # class Ground
|
132
|
+
end # module Sports
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SportDb
|
2
|
+
module Module
|
3
|
+
module Search
|
4
|
+
|
5
|
+
MAJOR = 0 ## todo: namespace inside version or something - why? why not??
|
6
|
+
MINOR = 0
|
7
|
+
PATCH = 1
|
8
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
9
|
+
|
10
|
+
def self.version
|
11
|
+
VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.banner
|
15
|
+
"sportdb-search/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.root
|
19
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) )
|
20
|
+
end
|
21
|
+
|
22
|
+
end # module Search
|
23
|
+
end # module Module
|
24
|
+
end # module SportDb
|
@@ -0,0 +1,127 @@
|
|
1
|
+
###
|
2
|
+
# world search service api for countries and more
|
3
|
+
#
|
4
|
+
# core api is:
|
5
|
+
# - world.countries.find_by_code
|
6
|
+
# - .find_by_name
|
7
|
+
|
8
|
+
|
9
|
+
class WorldSearch
|
10
|
+
|
11
|
+
class CitySearch < Search
|
12
|
+
###################
|
13
|
+
## core required delegates - use delegate generator - why? why not?
|
14
|
+
def match_by( name: )
|
15
|
+
@service.match_by( name: name )
|
16
|
+
end
|
17
|
+
end # class CitySearch
|
18
|
+
|
19
|
+
|
20
|
+
class CountrySearch < Search
|
21
|
+
###################
|
22
|
+
## core required delegates - use delegate generator - why? why not?
|
23
|
+
def find_by_code( code )
|
24
|
+
puts "!! DEPRECATED - use CountrySearch#find_by( code: )"
|
25
|
+
@service.find_by_code( code )
|
26
|
+
end
|
27
|
+
def find_by_name( name )
|
28
|
+
puts "!! DEPRECATED - use CountrySearch#find_by( name: )"
|
29
|
+
@service.find_by_name( name )
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_by( code: nil, name: nil )
|
33
|
+
## todo/fix upstream - change to find_by( code:, name:, ) too
|
34
|
+
if code && name.nil?
|
35
|
+
@service.find_by_code( code )
|
36
|
+
elsif name && code.nil?
|
37
|
+
@service.find_by_name( name )
|
38
|
+
else
|
39
|
+
raise ArgumentError, "CountrySearch#find_by - one (and only one arg) required - code: or name:"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def find( q )
|
44
|
+
@service.find_by_name_or_code( q )
|
45
|
+
end
|
46
|
+
alias_method :[], :find ### keep shortcut - why? why not?
|
47
|
+
|
48
|
+
|
49
|
+
###############
|
50
|
+
### more deriv support functions / helpers
|
51
|
+
|
52
|
+
###
|
53
|
+
## split/parse country line
|
54
|
+
##
|
55
|
+
## split on bullet e.g.
|
56
|
+
## split into name and code with regex - make code optional
|
57
|
+
##
|
58
|
+
## Examples:
|
59
|
+
## Österreich • Austria (at)
|
60
|
+
## Österreich • Austria
|
61
|
+
## Austria
|
62
|
+
## Deutschland (de) • Germany
|
63
|
+
##
|
64
|
+
## todo/check: support more formats - why? why not?
|
65
|
+
## e.g. Austria, AUT (e.g. with comma - why? why not?)
|
66
|
+
def parse( line )
|
67
|
+
values = line.split( '•' ) ## use/support multi-lingual separator
|
68
|
+
country = nil
|
69
|
+
values.each do |value|
|
70
|
+
value = value.strip
|
71
|
+
## check for trailing country code e.g. (at), (eng), etc
|
72
|
+
## allow code 1 to 5 for now - northern cyprus(fifa) with 5 letters?.
|
73
|
+
## add/allow gb-eng, gb-wal (official iso2!!), in the future too - why? why not?
|
74
|
+
if value =~ /[ ]+\((?<code>[A-Za-z]{1,5})\)$/ ## e.g. Austria (at)
|
75
|
+
code = $~[:code]
|
76
|
+
name = value[0...(value.size-code.size-2)].strip ## note: add -2 for brackets
|
77
|
+
candidates = [ find_by( code: code ), find_by( name: name ) ]
|
78
|
+
if candidates[0].nil?
|
79
|
+
puts "** !!! ERROR Country.parse_heading - unknown code >#{code}< in line: #{line}"
|
80
|
+
pp line
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
if candidates[1].nil?
|
84
|
+
puts "** !!! ERROR Country.parse_heading - unknown name >#{code}< in line: #{line}"
|
85
|
+
pp line
|
86
|
+
exit 1
|
87
|
+
end
|
88
|
+
if candidates[0] != candidates[1]
|
89
|
+
puts "** !!! ERROR Country.parse_heading - name and code do NOT match the same country:"
|
90
|
+
pp line
|
91
|
+
pp candidates
|
92
|
+
exit 1
|
93
|
+
end
|
94
|
+
if country && country != candidates[0]
|
95
|
+
puts "** !!! ERROR Country.parse_heading - names do NOT match the same country:"
|
96
|
+
pp line
|
97
|
+
pp country
|
98
|
+
pp candidates
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
country = candidates[0]
|
102
|
+
else
|
103
|
+
## just assume value is name or code
|
104
|
+
candidate = find( value )
|
105
|
+
if candidate.nil?
|
106
|
+
puts "** !!! ERROR Country.parse_heading - unknown name or code >#{value}< in line: #{line}"
|
107
|
+
pp line
|
108
|
+
exit 1
|
109
|
+
end
|
110
|
+
if country && country != candidate
|
111
|
+
puts "** !!! ERROR Country.parse_heading - names do NOT match the same country:"
|
112
|
+
pp line
|
113
|
+
pp country
|
114
|
+
pp candidate
|
115
|
+
exit 1
|
116
|
+
end
|
117
|
+
country = candidate
|
118
|
+
end
|
119
|
+
end
|
120
|
+
country
|
121
|
+
end # method parse
|
122
|
+
end # class CountrySearch
|
123
|
+
end # class WorldSearch
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
@@ -0,0 +1,223 @@
|
|
1
|
+
## note: sportdb/catalogs pulls in sportdb/structs and footballdb/data
|
2
|
+
require 'sportdb/catalogs'
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
## move to base?
|
7
|
+
### shared basics for search
|
8
|
+
class SportSearch
|
9
|
+
class Search ## base search service - use/keep - why? why not?
|
10
|
+
def initialize( service ) @service = service; end
|
11
|
+
end # class Search
|
12
|
+
end
|
13
|
+
|
14
|
+
class WorldSearch
|
15
|
+
class Search ## base search service - use/keep - why? why not?
|
16
|
+
def initialize( service ) @service = service; end
|
17
|
+
end # class Search
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
## our own code
|
23
|
+
require_relative 'search/version'
|
24
|
+
require_relative 'search/sport'
|
25
|
+
require_relative 'search/world'
|
26
|
+
|
27
|
+
|
28
|
+
########
|
29
|
+
### setup sport search apis
|
30
|
+
class SportSearch
|
31
|
+
def initialize( leagues:,
|
32
|
+
national_teams:,
|
33
|
+
clubs:,
|
34
|
+
grounds:,
|
35
|
+
events:,
|
36
|
+
players:
|
37
|
+
)
|
38
|
+
@leagues = LeagueSearch.new( leagues )
|
39
|
+
@national_teams = NationalTeamSearch.new( national_teams )
|
40
|
+
@clubs = ClubSearch.new( clubs )
|
41
|
+
@events = EventSearch.new( events )
|
42
|
+
|
43
|
+
@grounds = GroundSearch.new( grounds )
|
44
|
+
|
45
|
+
@players = PlayerSearch.new( players )
|
46
|
+
|
47
|
+
## virtual deriv ("composite") search services
|
48
|
+
@teams = TeamSearch.new( clubs: @clubs,
|
49
|
+
national_teams: @national_teams )
|
50
|
+
@event_seasons = EventSeasonSearch.new( events: @events )
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def leagues() @leagues; end
|
55
|
+
def national_teams() @national_teams; end
|
56
|
+
def clubs() @clubs; end
|
57
|
+
def events() @events; end
|
58
|
+
def grounds() @grounds; end
|
59
|
+
|
60
|
+
def players() @players; end
|
61
|
+
|
62
|
+
def teams() @teams; end ## note - virtual table
|
63
|
+
def seasons() @event_seasons; end ## note - virtual table
|
64
|
+
|
65
|
+
def countries
|
66
|
+
puts
|
67
|
+
puts "[WARN] do NOT use catalog.countries, deprecated!!!"
|
68
|
+
puts " please, switch to new world.countries search service"
|
69
|
+
puts
|
70
|
+
exit 1
|
71
|
+
end
|
72
|
+
end # class SportSearch
|
73
|
+
|
74
|
+
|
75
|
+
class WorldSearch
|
76
|
+
def initialize( countries:, cities: )
|
77
|
+
## change service to country_service or such - why? why not?
|
78
|
+
## add city_service and such later
|
79
|
+
@countries = CountrySearch.new( countries )
|
80
|
+
@cities = CitySearch.new( cities )
|
81
|
+
end
|
82
|
+
|
83
|
+
####
|
84
|
+
# note: for now setup only for countries & cities
|
85
|
+
def countries() @countries; end
|
86
|
+
def cities() @cities; end
|
87
|
+
end # class WorldSearch
|
88
|
+
|
89
|
+
|
90
|
+
#######
|
91
|
+
## add configuration
|
92
|
+
|
93
|
+
module SportDb
|
94
|
+
module Import
|
95
|
+
class Configuration
|
96
|
+
def world
|
97
|
+
@world ||= WorldSearch.new(
|
98
|
+
countries: CatalogDb::Metal::Country,
|
99
|
+
cities: CatalogDb::Metal::City,
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
def catalog
|
104
|
+
@catalog ||= SportSearch.new(
|
105
|
+
leagues: CatalogDb::Metal::League,
|
106
|
+
national_teams: CatalogDb::Metal::NationalTeam,
|
107
|
+
clubs: CatalogDb::Metal::Club,
|
108
|
+
grounds: CatalogDb::Metal::Ground,
|
109
|
+
events: CatalogDb::Metal::EventInfo,
|
110
|
+
players: CatalogDb::Metal::Player, # note - via players.db !!!
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
###
|
115
|
+
# find a better name for setting - why? why not?
|
116
|
+
# how about catalogdb or ???
|
117
|
+
attr_reader :catalog_path
|
118
|
+
def catalog_path=(path)
|
119
|
+
@catalog_path = path
|
120
|
+
########
|
121
|
+
# reset database here to new path
|
122
|
+
CatalogDb::Metal::Record.database = path
|
123
|
+
@catalog_path
|
124
|
+
end
|
125
|
+
|
126
|
+
###
|
127
|
+
# find a better name for setting - why? why not?
|
128
|
+
# how about playersdb or ???
|
129
|
+
attr_reader :players_path
|
130
|
+
def players_path=(path)
|
131
|
+
@players_path = path
|
132
|
+
########
|
133
|
+
# reset database here to new path
|
134
|
+
CatalogDb::Metal::PlayerRecord.database = path
|
135
|
+
|
136
|
+
@players_path
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
end # class Configuration
|
141
|
+
|
142
|
+
## e.g. use config.catalog -- keep Import.catalog as a shortcut (for "read-only" access)
|
143
|
+
def self.world() config.world; end
|
144
|
+
def self.catalog() config.catalog; end
|
145
|
+
|
146
|
+
## lets you use
|
147
|
+
## SportDb::Import.configure do |config|
|
148
|
+
## config.catalog_path = './catalog.db'
|
149
|
+
## end
|
150
|
+
def self.configure() yield( config ); end
|
151
|
+
def self.config() @config ||= Configuration.new; end
|
152
|
+
end # module Import
|
153
|
+
end # module SportDb
|
154
|
+
|
155
|
+
|
156
|
+
module Sports
|
157
|
+
## note: just forward to SportDb::Import configuration!!!!!
|
158
|
+
## keep Sports module / namespace "clean" - why? why not?
|
159
|
+
## that is, only include data structures (e.g. Match,League,etc) for now - why? why not?
|
160
|
+
def self.configure() yield( config ); end
|
161
|
+
def self.config() SportDb::Import.config; end
|
162
|
+
end # module Sports
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
###
|
169
|
+
## add/augment core classes with search services
|
170
|
+
require_relative 'search/structs'
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
module SportDb
|
175
|
+
module Import
|
176
|
+
Season = ::Season ## add a convenience alias for top-level Season class
|
177
|
+
|
178
|
+
## add "old" convenience aliases for structs - why? why not?
|
179
|
+
## todo/check: just use include Sports !!!!
|
180
|
+
Country = ::Sports::Country
|
181
|
+
League = ::Sports::League
|
182
|
+
Group = ::Sports::Group
|
183
|
+
Round = ::Sports::Round
|
184
|
+
Match = ::Sports::Match
|
185
|
+
Matchlist = ::Sports::Matchlist
|
186
|
+
Goal = ::Sports::Goal
|
187
|
+
Team = ::Sports::Team
|
188
|
+
NationalTeam = ::Sports::NationalTeam
|
189
|
+
Club = ::Sports::Club
|
190
|
+
Standings = ::Sports::Standings
|
191
|
+
TeamUsage = ::Sports::TeamUsage
|
192
|
+
|
193
|
+
Ground = ::Sports::Ground
|
194
|
+
|
195
|
+
Player = ::Sports::Player
|
196
|
+
|
197
|
+
EventInfo = ::Sports::EventInfo
|
198
|
+
|
199
|
+
|
200
|
+
class Team
|
201
|
+
## add convenience lookup helper / method for name by season for now
|
202
|
+
## use clubs history - for now kept separate from struct - why? why not?
|
203
|
+
def name_by_season( season )
|
204
|
+
## note: returns / fallback to "regular" name if no records found in history
|
205
|
+
SportDb::Import.catalog.clubs_history.find_name_by( name: name, season: season ) || name
|
206
|
+
end
|
207
|
+
end # class Team
|
208
|
+
|
209
|
+
end # module Import
|
210
|
+
end # module SportDb
|
211
|
+
|
212
|
+
|
213
|
+
###
|
214
|
+
## add default/built-in catalog here - why? why not?
|
215
|
+
## todo/fix - set catalog_path on demand
|
216
|
+
## note: for now required for world search setup etc.
|
217
|
+
## SportDb::Import.config.catalog_path = "#{FootballDb::Data.data_dir}/catalog.db"
|
218
|
+
##
|
219
|
+
## note - for now set as default upstream in sportdb-catalogs!!!
|
220
|
+
|
221
|
+
|
222
|
+
puts SportDb::Module::Search.banner # say hello
|
223
|
+
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sportdb-search
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gerald Bauer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-08-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sportdb-catalogs
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.2.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rdoc
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '7'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '4.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '7'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: hoe
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '4.1'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '4.1'
|
61
|
+
description: sportdb-search - find national teams, clubs, leagues & more
|
62
|
+
email: gerald.bauer@gmail.com
|
63
|
+
executables: []
|
64
|
+
extensions: []
|
65
|
+
extra_rdoc_files:
|
66
|
+
- CHANGELOG.md
|
67
|
+
- Manifest.txt
|
68
|
+
- README.md
|
69
|
+
files:
|
70
|
+
- CHANGELOG.md
|
71
|
+
- Manifest.txt
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- lib/sportdb/search.rb
|
75
|
+
- lib/sportdb/search/sport.rb
|
76
|
+
- lib/sportdb/search/structs.rb
|
77
|
+
- lib/sportdb/search/version.rb
|
78
|
+
- lib/sportdb/search/world.rb
|
79
|
+
homepage: https://github.com/sportdb/sport.db
|
80
|
+
licenses:
|
81
|
+
- Public Domain
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options:
|
85
|
+
- "--main"
|
86
|
+
- README.md
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 3.1.0
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubygems_version: 3.4.10
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: sportdb-search - find national teams, clubs, leagues & more
|
104
|
+
test_files: []
|