sportdb-formats 2.0.1 → 2.1.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.
@@ -1,372 +0,0 @@
1
- ###
2
- # sport search service api for leagues, clubs and more
3
- #
4
- # core api is:
5
-
6
-
7
- class SportSearch
8
-
9
- class Search ## base search service - use/keep - why? why not?
10
- def initialize( service ) @service = service; end
11
- end # class Search
12
-
13
-
14
- class PlayerSearch < Search
15
- ###################
16
- ## core required delegates - use delegate generator - why? why not?
17
- def match_by( name:, country: nil, year: nil )
18
- @service.match_by( name: name,
19
- country: country,
20
- year: year )
21
- end
22
-
23
- ###############
24
- ### more deriv support functions / helpers
25
- def match( name ) match_by( name: name ); end
26
- ## add more here - why? why not?
27
- end # class PlayerSearch
28
-
29
-
30
- class LeagueSearch < Search
31
-
32
- ###################
33
- ## core required delegates - use delegate generator - why? why not?
34
- def match_by( name: nil, code: nil, country: nil )
35
- ## todo/fix upstream - remove "generic" match_by() - why? why not?
36
- ###
37
- if code && name.nil?
38
- @service.match_by_code( code, country: country )
39
- elsif name && code.nil?
40
- @service.match_by_name( name, country: country )
41
- else
42
- raise ArgumentError, "LeagueSearch#match_by - one (and only one arg) required - code: or name:"
43
- end
44
- ## @service.match_by( name: name,
45
- ## country: country )
46
- end
47
-
48
- ## all-in-one query (name or code)
49
- def match( q, country: nil )
50
- @service.match_by_name_or_code( q, country: country )
51
- end
52
-
53
-
54
- ###############
55
- ### more deriv support functions / helpers
56
- def find!( q )
57
- league = find( q )
58
- if league.nil?
59
- puts "** !!! ERROR - no league match found for >#{q}<, add to leagues table; sorry"
60
- exit 1
61
- end
62
- league
63
- end
64
-
65
- def find( q )
66
- league = nil
67
- recs = match( q )
68
- # pp m
69
-
70
- if recs.empty?
71
- ## fall through/do nothing
72
- elsif recs.size > 1
73
- puts "** !!! ERROR - ambigious league query; too many leagues (#{recs.size}) found:"
74
- pp recs
75
- exit 1
76
- else
77
- league = recs[0]
78
- end
79
-
80
- league
81
- end
82
- end # class LeagueSearch
83
-
84
-
85
-
86
- class GroundSearch < Search
87
- ###################
88
- ## core required delegates - use delegate generator - why? why not?
89
- def match_by( name:, country: nil, city: nil )
90
- @service.match_by( name: name,
91
- country: country,
92
- city: city )
93
- end
94
-
95
- ###############
96
- ### more deriv support functions / helpers
97
- def match( name ) match_by( name: name ); end
98
- ## add more here - why? why not?
99
- end # class GroundSearch
100
-
101
-
102
-
103
- class NationalTeamSearch < Search
104
- ###################
105
- ## core required delegates - use delegate generator - why? why not?
106
-
107
- ## changle core api to match( q ) only - why? why not?
108
- ## and make find and find! derivs???
109
- def find( q ) @service.find( q ); end
110
- def find!( q ) @service.find!( q ); end
111
- end # class NationalTeamSearch
112
-
113
-
114
- class ClubSearch < Search
115
- ###################
116
- ## core required delegates - use delegate generator - why? why not?
117
-
118
- ## add mods here - why? why not?
119
-
120
- def match_by( name:, country: nil,
121
- league: nil,
122
- mods: nil )
123
- ## for now assume "global" mods - checks only for name
124
- ##
125
- if mods && mods[ name ]
126
- club = mods[ name ]
127
- return [club] # note: wrap (single record) in array
128
- end
129
-
130
- ## note: add "auto-magic" country calculation via league record
131
- ## if league is a national league for football clubs
132
- if league
133
- raise ArgumentError, "match_by - league AND country NOT supported; sorry" if country
134
- ### find countries via league
135
- ### support league.intl? too - why? why not?
136
- ### or only nationa league
137
- raise ArgumentError, "match_by - league - only national club leagues supported (not int'l or national teams for now); sorry" unless league.national? && league.clubs?
138
-
139
- ### calc countries
140
- ### uses "global" func in sports-catalogs for now
141
- ## move code here - why? why not?
142
- country = find_countries_for_league( league )
143
- @service.match_by( name: name,
144
- country: country )
145
- else
146
- @service.match_by( name: name,
147
- country: country )
148
- end
149
- end
150
-
151
-
152
- ## todo/fix/check: use rename to find_canon or find_canonical() or something??
153
- ## remove (getting used?) - why? why not?
154
- # def []( name ) ## lookup by canoncial name only; todo/fix: add find alias why? why not?
155
- # puts "WARN!! do not use ClubIndex#[] for lookup >#{name}< - will get removed!!!"
156
- # @clubs[ name ]
157
- # end
158
-
159
-
160
- ###############
161
- ### more deriv support functions / helpers
162
- def match( name ) match_by( name: name ); end
163
-
164
- ##########
165
- # "legacy" finders - return zero or one club
166
- ## (if more than one match, exit/raise error/exception)
167
- def find( name ) find_by( name: name ); end
168
- def find!( name ) find_by!( name: name ); end
169
-
170
- ## find - always returns a single record / match or nil
171
- ## if there is more than one match than find aborts / fails
172
- def find_by!( name:, country: nil,
173
- league: nil ) ## todo/fix: add international or league flag?
174
- club = find_by( name: name,
175
- country: country,
176
- league: league )
177
-
178
- if club.nil?
179
- puts "** !!! ERROR - no match for club >#{name}<"
180
- exit 1
181
- end
182
-
183
- club
184
- end
185
-
186
-
187
- def find_by( name:, country: nil,
188
- league: nil ) ## todo/fix: add international or league flag?
189
- ## note: allow passing in of country key too (auto-counvert)
190
- ## and country struct too
191
- ## - country assumes / allows the country key or fifa code for now
192
- recs = match_by( name: name,
193
- country: country,
194
- league: league )
195
-
196
- club = nil
197
- if recs.empty?
198
- ## puts "** !!! WARN !!! no match for club >#{name}<"
199
- elsif recs.size > 1
200
- puts "** !!! ERROR - too many matches (#{recs.size}) for club >#{name}<:"
201
- pp recs
202
- exit 1
203
- else # bingo; match - assume size == 1
204
- club = recs[0]
205
- end
206
-
207
- club
208
- end
209
-
210
-
211
- #######
212
- # more support methods
213
- def build_mods( mods )
214
- ## e.g.
215
- ## { 'Arsenal | Arsenal FC' => 'Arsenal, ENG',
216
- ## 'Liverpool | Liverpool FC' => 'Liverpool, ENG',
217
- ## 'Barcelona' => 'Barcelona, ESP',
218
- ## 'Valencia' => 'Valencia, ESP' }
219
-
220
- mods.reduce({}) do |h,(club_names, club_line)|
221
-
222
- values = club_line.split( ',' )
223
- values = values.map { |value| value.strip } ## strip all spaces
224
-
225
- ## todo/fix: make sure country is present !!!!
226
- club_name, country_name = values
227
- club = find_by!( name: club_name, country: country_name )
228
-
229
- values = club_names.split( '|' )
230
- values = values.map { |value| value.strip } ## strip all spaces
231
-
232
- values.each do |club_name|
233
- h[club_name] = club
234
- end
235
- h
236
- end
237
- end
238
- end # class ClubSearch
239
-
240
-
241
-
242
- ## todo/check - change to EventInfoSearch - why? why not?
243
- class EventSearch < Search
244
- ##
245
- ## todo - eventinfo search still open / up for change
246
-
247
- ###################
248
- ## core required delegates - use delegate generator - why? why not?
249
- def seasons( league )
250
- @service.seasons( league )
251
- end
252
- def find_by( league:, season: )
253
- @service.find_by( league: league,
254
- season: season )
255
- end
256
- end # class EventSearch
257
-
258
-
259
- ####
260
- ## virtual table for season lookup
261
- ## note - use EventSeaon to avoid name conflict with (global) Season class
262
- ## find a better name SeasonInfo or SeasonFinder or SeasonStore
263
- ## or SeasonQ or ??
264
- class EventSeasonSearch
265
- def initialize( events: )
266
- @events = events
267
- end
268
-
269
- ###############
270
- ## todo/fix: find a better algo to guess season for date!!!
271
- ##
272
- def find_by( date:, league: )
273
- date = Date.strptime( date, '%Y-%m-%d' ) if date.is_a?( String )
274
-
275
- infos = @events.seasons( league )
276
-
277
- infos.each do |info|
278
- return info.season if info.include?( date )
279
- end
280
- nil
281
- end
282
- end # class EventSeasonSearch
283
-
284
-
285
- ######
286
- ### add virtual team search ( clubs + national teams)
287
- ## note: no record base!!!!!
288
- class TeamSearch
289
- ## note: "virtual" index lets you search clubs and/or national_teams (don't care)
290
-
291
- def initialize( clubs:, national_teams: )
292
- @clubs = clubs
293
- @national_teams = national_teams
294
- end
295
-
296
- ## todo/check: rename to/use map_by! for array version - why? why not?
297
- def find_by!( name:, league:, mods: nil )
298
- if name.is_a?( Array )
299
- recs = []
300
- name.each do |q|
301
- recs << _find_by!( name: q, league: league, mods: mods )
302
- end
303
- recs
304
- else ## assume single name
305
- _find_by!( name: name, league: league, mods: mods )
306
- end
307
- end
308
-
309
-
310
- def _find_by!( name:, league:, mods: nil )
311
- if mods && mods[ league.key ] && mods[ league.key ][ name ]
312
- mods[ league.key ][ name ]
313
- else
314
- if league.clubs?
315
- if league.intl? ## todo/fix: add intl? to ActiveRecord league!!!
316
- @clubs.find!( name )
317
- else ## assume clubs in domestic/national league tournament
318
- ## note - search by league countries (may incl. more than one country
319
- ## e.g. us incl. ca, fr incl. mc, ch incl. li, etc.
320
- @clubs.find_by!( name: name, league: league )
321
- end
322
- else ## assume national teams (not clubs)
323
- @national_teams.find!( name )
324
- end
325
- end
326
- end # method _find_by!
327
- end # class TeamSearch
328
-
329
-
330
-
331
- def initialize( leagues:,
332
- national_teams:,
333
- clubs:,
334
- grounds:,
335
- events:,
336
- players:
337
- )
338
- @leagues = LeagueSearch.new( leagues )
339
- @national_teams = NationalTeamSearch.new( national_teams )
340
- @clubs = ClubSearch.new( clubs )
341
- @events = EventSearch.new( events )
342
-
343
- @grounds = GroundSearch.new( grounds )
344
-
345
- @players = PlayerSearch.new( players )
346
-
347
- ## virtual deriv ("composite") search services
348
- @teams = TeamSearch.new( clubs: @clubs,
349
- national_teams: @national_teams )
350
- @event_seasons = EventSeasonSearch.new( events: @events )
351
-
352
- end
353
-
354
- def countries
355
- puts
356
- puts "[WARN] do NOT use catalog.countries, deprecated!!!"
357
- puts " please, switch to new world.countries search service"
358
- puts
359
- exit 1
360
- end
361
-
362
- def leagues() @leagues; end
363
- def national_teams() @national_teams; end
364
- def clubs() @clubs; end
365
- def events() @events; end
366
- def grounds() @grounds; end
367
-
368
- def players() @players; end
369
-
370
- def teams() @teams; end ## note - virtual table
371
- def seasons() @event_seasons; end ## note - virtual table
372
- end # class SportSearch
@@ -1,116 +0,0 @@
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 ) _search.match( q ); end
69
-
70
- def self.find!( q ) _search.find!( q ); end
71
- def self.find( q ) _search_find( q ); end
72
- end # class League
73
-
74
-
75
- class NationalTeam
76
- def self._search #### use service/api or such - why? why not?
77
- SportDb::Import.catalog.national_teams
78
- end
79
-
80
- def self.find( q ) _search.find( q ); end
81
- def self.find!( q ) _search_find!( q ); end
82
- end # class NationalTeam
83
-
84
-
85
- class Club
86
- def self._search #### use service/api or such - why? why not?
87
- SportDb::Import.catalog.clubs
88
- end
89
-
90
- def self.match_by( name:, country: nil,
91
- league: nil,
92
- mods: nil )
93
- _search.match_by( name: name, country: country,
94
- league: league, mods: mods )
95
- end
96
- def self.match( name ) match_by( name: name ); end
97
-
98
- def self.find( name ) _search.find_by( name: name ); end
99
- def self.find!( name ) _search.find_by!( name: name ); end
100
-
101
- def self.find_by!( name:, country: nil,
102
- league: nil )
103
- _search.find_by!( name: name, country: country,
104
- league: league )
105
- end
106
- def self.find_by( name:, country: nil,
107
- league: nil )
108
- _search.find_by( name: name, country: country,
109
- league: league )
110
- end
111
-
112
- def self.build_mods( mods )
113
- _search_build_mods( mods )
114
- end
115
- end # class Club
116
- end # module Sports
@@ -1,157 +0,0 @@
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
12
- def initialize( service ) @service = service; end
13
-
14
- ###################
15
- ## core required delegates - use delegate generator - why? why not?
16
- def match_by( name: )
17
- @service.match_by( name: name )
18
- end
19
- end # class CitySearch
20
-
21
-
22
- class CountrySearch
23
- def initialize( service ) @service = service; end
24
-
25
- ###################
26
- ## core required delegates - use delegate generator - why? why not?
27
- def find_by_code( code )
28
- puts "!! DEPRECATED - use CountrySearch#find_by( code: )"
29
- @service.find_by_code( code )
30
- end
31
- def find_by_name( name )
32
- puts "!! DEPRECATED - use CountrySearch#find_by( name: )"
33
- @service.find_by_name( name )
34
- end
35
-
36
- def find_by( code: nil, name: nil )
37
- ## todo/fix upstream - change to find_by( code:, name:, ) too
38
- if code && name.nil?
39
- @service.find_by_code( code )
40
- elsif name && code.nil?
41
- @service.find_by_name( name )
42
- else
43
- raise ArgumentError, "CountrySearch#find_by - one (and only one arg) required - code: or name:"
44
- end
45
- end
46
-
47
- def find( q )
48
- @service.find_by_name_or_code( q )
49
- end
50
- alias_method :[], :find ### keep shortcut - why? why not?
51
-
52
-
53
- ###############
54
- ### more deriv support functions / helpers
55
-
56
- ###
57
- ## split/parse country line
58
- ##
59
- ## split on bullet e.g.
60
- ## split into name and code with regex - make code optional
61
- ##
62
- ## Examples:
63
- ## Österreich • Austria (at)
64
- ## Österreich • Austria
65
- ## Austria
66
- ## Deutschland (de) • Germany
67
- ##
68
- ## todo/check: support more formats - why? why not?
69
- ## e.g. Austria, AUT (e.g. with comma - why? why not?)
70
- def parse( line )
71
- values = line.split( '•' ) ## use/support multi-lingual separator
72
- country = nil
73
- values.each do |value|
74
- value = value.strip
75
- ## check for trailing country code e.g. (at), (eng), etc
76
- ## allow code 1 to 5 for now - northern cyprus(fifa) with 5 letters?.
77
- ## add/allow gb-eng, gb-wal (official iso2!!), in the future too - why? why not?
78
- if value =~ /[ ]+\((?<code>[A-Za-z]{1,5})\)$/ ## e.g. Austria (at)
79
- code = $~[:code]
80
- name = value[0...(value.size-code.size-2)].strip ## note: add -2 for brackets
81
- candidates = [ find_by( code: code ), find_by( name: name ) ]
82
- if candidates[0].nil?
83
- puts "** !!! ERROR Country.parse_heading - unknown code >#{code}< in line: #{line}"
84
- pp line
85
- exit 1
86
- end
87
- if candidates[1].nil?
88
- puts "** !!! ERROR Country.parse_heading - unknown name >#{code}< in line: #{line}"
89
- pp line
90
- exit 1
91
- end
92
- if candidates[0] != candidates[1]
93
- puts "** !!! ERROR Country.parse_heading - name and code do NOT match the same country:"
94
- pp line
95
- pp candidates
96
- exit 1
97
- end
98
- if country && country != candidates[0]
99
- puts "** !!! ERROR Country.parse_heading - names do NOT match the same country:"
100
- pp line
101
- pp country
102
- pp candidates
103
- exit 1
104
- end
105
- country = candidates[0]
106
- else
107
- ## just assume value is name or code
108
- candidate = find( value )
109
- if candidate.nil?
110
- puts "** !!! ERROR Country.parse_heading - unknown name or code >#{value}< in line: #{line}"
111
- pp line
112
- exit 1
113
- end
114
- if country && country != candidate
115
- puts "** !!! ERROR Country.parse_heading - names do NOT match the same country:"
116
- pp line
117
- pp country
118
- pp candidate
119
- exit 1
120
- end
121
- country = candidate
122
- end
123
- end
124
- country
125
- end # method parse
126
- end # class CountrySearch
127
-
128
-
129
- def initialize( countries:, cities: )
130
- ## change service to country_service or such - why? why not?
131
- ## add city_service and such later
132
- @countries = CountrySearch.new( countries )
133
- @cities = CitySearch.new( cities )
134
- end
135
-
136
- ####
137
- # note: for now setup only for countries
138
- def countries() @countries; end
139
- def cities() @cities; end
140
- end # class WorldSearch
141
-
142
-
143
-
144
-
145
-
146
- class DummyCountrySearch
147
- def find_by_code( code )
148
- puts "[WARN] no world search configured; cannot find country by code"
149
- nil
150
- end
151
- def find_by_name( name )
152
- puts "[WARN] no world search configured; cannot find country by name"
153
- nil
154
- end
155
- end # class DummyCountrySearch
156
-
157
-