fifa 2020.9.15 → 2024.9.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +2 -0
- data/Manifest.txt +4 -4
- data/README.md +17 -6
- data/Rakefile +3 -3
- data/lib/fifa/country_index.rb +63 -0
- data/lib/fifa/country_reader.rb +138 -0
- data/lib/fifa/org_index.rb +76 -0
- data/lib/fifa/outline_reader.rb +99 -0
- data/lib/fifa/version.rb +5 -9
- data/lib/fifa.rb +32 -77
- metadata +25 -20
- data/lib/fifa/countries.rb +0 -42
- data/test/helper.rb +0 -11
- data/test/test_countries.rb +0 -45
- data/test/test_orgs.rb +0 -100
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b0433ec0eba0cc3f885559be4eed61be2dbfc0196bf0091a48d822bae08ca9f8
|
4
|
+
data.tar.gz: 728d2e5268c8c53e5e077968b87591a5b64961d530a8e10f79620c8b4e44f735
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f5e4d09b02249f04f38c726c27036d1a5a5f9148bec74a8e8e75970f950ea511f2d04a866c9e9dfb0f7306647b11f036cfeb3a0ea8f7e6dfa5ca7e2602e74f6
|
7
|
+
data.tar.gz: 4751c4632be3719f6e2aa51228ca9ba4da4b8e8b35bf3a2c172598b788152e2f1aa752bc3134460a5cdade27b62f885c103ac4eb2d5fc02e92108cdd83d21f91
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
@@ -5,8 +5,8 @@ README.md
|
|
5
5
|
Rakefile
|
6
6
|
config/countries.txt
|
7
7
|
lib/fifa.rb
|
8
|
-
lib/fifa/
|
8
|
+
lib/fifa/country_index.rb
|
9
|
+
lib/fifa/country_reader.rb
|
10
|
+
lib/fifa/org_index.rb
|
11
|
+
lib/fifa/outline_reader.rb
|
9
12
|
lib/fifa/version.rb
|
10
|
-
test/helper.rb
|
11
|
-
test/test_countries.rb
|
12
|
-
test/test_orgs.rb
|
data/README.md
CHANGED
@@ -5,17 +5,17 @@
|
|
5
5
|
* bugs :: [github.com/sportdb/football.db/issues](https://github.com/sportdb/football.db/issues)
|
6
6
|
* gem :: [rubygems.org/gems/fifa](https://rubygems.org/gems/fifa)
|
7
7
|
* rdoc :: [rubydoc.info/gems/fifa](http://rubydoc.info/gems/fifa)
|
8
|
-
|
8
|
+
|
9
9
|
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
13
|
-
Get and pretty print (pp) all countries
|
13
|
+
Get and pretty print (pp) all countries (incl. historic and non-members)
|
14
14
|
|
15
15
|
``` ruby
|
16
16
|
require 'fifa'
|
17
17
|
|
18
|
-
pp Fifa.countries
|
18
|
+
pp Fifa.world.countries
|
19
19
|
```
|
20
20
|
|
21
21
|
resulting in:
|
@@ -108,6 +108,17 @@ Fifa.members( 'Europe' ).size #=> 55 members
|
|
108
108
|
...
|
109
109
|
```
|
110
110
|
|
111
|
+
|
112
|
+
Bonus convenience shortcuts include:
|
113
|
+
|
114
|
+
``` ruby
|
115
|
+
Fifa.countries.size #=> 211 members
|
116
|
+
Uefa.countries.size #=> 55 members
|
117
|
+
Conmebol.countries.size #=> 10 members
|
118
|
+
```
|
119
|
+
|
120
|
+
|
121
|
+
|
111
122
|
That's it.
|
112
123
|
|
113
124
|
|
@@ -165,8 +176,8 @@ The `fifa` scripts are dedicated to the public domain.
|
|
165
176
|
Use it as you please with no restrictions whatsoever.
|
166
177
|
|
167
178
|
|
179
|
+
|
168
180
|
## Questions? Comments?
|
169
181
|
|
170
|
-
|
171
|
-
[
|
172
|
-
Thanks!
|
182
|
+
Yes, you can. More than welcome.
|
183
|
+
See [Help & Support »](https://github.com/openfootball/help)
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ Hoe.spec 'fifa' do
|
|
11
11
|
self.urls = { home: 'https://github.com/sportdb/football.db' }
|
12
12
|
|
13
13
|
self.author = 'Gerald Bauer'
|
14
|
-
self.email = '
|
14
|
+
self.email = 'gerald.bauer@google.com'
|
15
15
|
|
16
16
|
# switch extension to .markdown for gihub formatting
|
17
17
|
self.readme_file = 'README.md'
|
@@ -20,11 +20,11 @@ Hoe.spec 'fifa' do
|
|
20
20
|
self.licenses = ['Public Domain']
|
21
21
|
|
22
22
|
self.extra_deps = [
|
23
|
-
['sportdb-
|
23
|
+
['sportdb-structs', '>= 0.4.0'],
|
24
24
|
]
|
25
25
|
|
26
26
|
self.spec_extras = {
|
27
|
-
required_ruby_version: '>=
|
27
|
+
required_ruby_version: '>= 3.1.0'
|
28
28
|
}
|
29
29
|
|
30
30
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
module Fifa
|
3
|
+
|
4
|
+
|
5
|
+
## built-in countries for (quick starter) auto-add
|
6
|
+
class CountryIndex
|
7
|
+
|
8
|
+
def initialize( recs=nil )
|
9
|
+
@countries = []
|
10
|
+
@by_code = {} ## countries by codes (fifa, internet, etc)
|
11
|
+
@orgs = OrgIndex.new
|
12
|
+
|
13
|
+
add( recs ) if recs
|
14
|
+
end
|
15
|
+
|
16
|
+
def countries() @countries; end
|
17
|
+
def size() @countries.size; end
|
18
|
+
def each( &blk ) @countries.each { |country| blk.call( country ) }; end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
def members( key=:fifa ) ## default to fifa members
|
23
|
+
@orgs.members( key )
|
24
|
+
end
|
25
|
+
|
26
|
+
## for testing/debugging return org keys
|
27
|
+
## return OrgIndex instead - why? why not?
|
28
|
+
def orgs() @orgs.keys; end
|
29
|
+
|
30
|
+
|
31
|
+
def find( q )
|
32
|
+
key = q.to_s.downcase ## allow symbols (and always downcase e.g. AUT to aut etc.)
|
33
|
+
@by_code[ key ]
|
34
|
+
end
|
35
|
+
alias_method :[], :find
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
def add( recs )
|
40
|
+
@countries += recs
|
41
|
+
|
42
|
+
_add( recs) ## step one add to our own index
|
43
|
+
@orgs.add( recs ) ## step two add to orgs (helper) index (for members)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def _add( recs )
|
48
|
+
###########################################
|
49
|
+
## auto-fill countries
|
50
|
+
## pp recs
|
51
|
+
recs.each do |rec|
|
52
|
+
key = rec.code.downcase ## add codes lookups - key, fifa, ...
|
53
|
+
if @by_code[ key ]
|
54
|
+
puts "** !!! ERROR !!! country code (fifa) >#{rec.code}< already exits!!"
|
55
|
+
exit 1
|
56
|
+
else
|
57
|
+
@by_code[ key ] = rec
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end # method add
|
61
|
+
end # class CountryIndex
|
62
|
+
|
63
|
+
end # class Module
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Fifa
|
2
|
+
class CountryReader
|
3
|
+
|
4
|
+
|
5
|
+
Country = Sports::Country
|
6
|
+
|
7
|
+
|
8
|
+
def self.read( path ) ## use - rename to read_file or from_file etc. - why? why not?
|
9
|
+
txt = File.open( path, 'r:utf-8' ) { |f| f.read }
|
10
|
+
parse( txt )
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.parse( txt )
|
14
|
+
new( txt ).parse
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def initialize( txt )
|
19
|
+
@txt = txt
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse
|
23
|
+
countries = []
|
24
|
+
last_country = nil ## note/check/fix: use countries[-1] - why? why not?
|
25
|
+
|
26
|
+
OutlineReader.parse( @txt ).each do |node|
|
27
|
+
|
28
|
+
node_type = node[0]
|
29
|
+
|
30
|
+
if [:h1, :h2].include?( node_type )
|
31
|
+
## skip headings (and headings) for now too
|
32
|
+
elsif node_type == :p ## paragraph
|
33
|
+
lines = node[1]
|
34
|
+
lines.each do |line|
|
35
|
+
if line.start_with?( '|' )
|
36
|
+
## assume continuation with line of alternative names
|
37
|
+
## note: skip leading pipe
|
38
|
+
values = line[1..-1].split( '|' ) # team names - allow/use pipe(|)
|
39
|
+
## strip and squish (white)spaces
|
40
|
+
# e.g. East Germany (-1989) => East Germany (-1989)
|
41
|
+
values = values.map { |value| value.strip.gsub( /[ \t]+/, ' ' ) }
|
42
|
+
last_country.alt_names += values
|
43
|
+
elsif line =~ /^-[ ]*(\d{4})
|
44
|
+
[ ]+
|
45
|
+
(.+)$
|
46
|
+
/x ## check for historic lines e.g. -1989
|
47
|
+
year = $1.to_i
|
48
|
+
parts = $2.split( /=>|⇒/ )
|
49
|
+
values = parts[0].split( ',' )
|
50
|
+
values = values.map { |value| value.strip.gsub( /[ \t]+/, ' ' ) }
|
51
|
+
|
52
|
+
name = values[0]
|
53
|
+
code = values[1]
|
54
|
+
|
55
|
+
last_country = country = Country.new( name: "#{name} (-#{year})",
|
56
|
+
code: code )
|
57
|
+
## country.alt_names << name ## note: for now do NOT add name without year to alt_names - gets auto-add by index!!!
|
58
|
+
|
59
|
+
countries << country
|
60
|
+
## todo/fix: add reference to country today (in parts[1] !!!!)
|
61
|
+
else
|
62
|
+
## assume "regular" line
|
63
|
+
## check if starts with id (todo/check: use a more "strict"/better regex capture pattern!!!)
|
64
|
+
## note: allow country codes upto 4 (!!) e.g. Northern Cyprus
|
65
|
+
if line =~ /^([a-z]{2,4})
|
66
|
+
[ ]+
|
67
|
+
(.+)$/x
|
68
|
+
key = $1
|
69
|
+
values = $2.split( ',' )
|
70
|
+
## strip and squish (white)spaces
|
71
|
+
# e.g. East Germany (-1989) => East Germany (-1989)
|
72
|
+
values = values.map { |value| value.strip.gsub( /[ \t]+/, ' ' ) }
|
73
|
+
|
74
|
+
## note: remove "overlords" from geo-tree marked territories e.g. UK, US, etc. from name
|
75
|
+
## e.g. England › UK => England
|
76
|
+
## Puerto Rico › US => Puerto Rico
|
77
|
+
geos = split_geo( values[0] )
|
78
|
+
name = geos[0] ## note: ignore all other geos for now
|
79
|
+
|
80
|
+
## note: allow country codes up to 4 (!!) e.g. Northern Cyprus
|
81
|
+
code = if values[1] && values[1] =~ /^[A-Z]{3,4}$/ ## note: also check format
|
82
|
+
values[1]
|
83
|
+
else
|
84
|
+
if values[1]
|
85
|
+
puts "** !!! ERROR !!! wrong code format >#{values[1]}<; expected three (or four)-letter all up-case"
|
86
|
+
else
|
87
|
+
puts "** !!! ERROR !!! missing code for (canonical) country name"
|
88
|
+
end
|
89
|
+
exit 1
|
90
|
+
end
|
91
|
+
|
92
|
+
tags = if values[2] ## check if tags presents
|
93
|
+
split_tags( values[2] )
|
94
|
+
else
|
95
|
+
[]
|
96
|
+
end
|
97
|
+
|
98
|
+
last_country = country = Country.new( key: key,
|
99
|
+
name: name,
|
100
|
+
code: code,
|
101
|
+
tags: tags )
|
102
|
+
countries << country
|
103
|
+
else
|
104
|
+
puts "** !! ERROR - missing key for (canonical) country name"
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end # each line
|
109
|
+
else
|
110
|
+
puts "** !! ERROR - unknown node type / (input) source line:"
|
111
|
+
pp node
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
end # each node
|
115
|
+
|
116
|
+
countries
|
117
|
+
end # method parse
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
#######################################
|
122
|
+
## helpers
|
123
|
+
def split_tags( str )
|
124
|
+
tags = str.split( /[|<>‹›]/ ) ## allow pipe (|) and (<>‹›) as divider for now - add more? why? why not?
|
125
|
+
tags = tags.map { |tag| tag.strip }
|
126
|
+
tags
|
127
|
+
end
|
128
|
+
|
129
|
+
def split_geo( str ) ## todo/check: rename to parse_geo(s) - why? why not?
|
130
|
+
## split into geo tree
|
131
|
+
geos = str.split( /[<>‹›]/ ) ## note: allow > < or › ‹ for now
|
132
|
+
geos = geos.map { |geo| geo.strip } ## remove all whitespaces
|
133
|
+
geos
|
134
|
+
end
|
135
|
+
|
136
|
+
end # class CountryReader
|
137
|
+
|
138
|
+
end # module Fifa
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
module Fifa
|
3
|
+
|
4
|
+
class CountryIndex ## note - OrdIndex (helper) nested inside CountryIndex - why? why not?
|
5
|
+
class OrgIndex ## change to MemberIndex or AssocIndex or such - why? why not?
|
6
|
+
|
7
|
+
ALT_KEYS = {
|
8
|
+
'world' => 'fifa',
|
9
|
+
'europe' => 'uefa', #=> Union of European Football Associations
|
10
|
+
'northamericacentralamericacaribbean' => 'concacaf', #=> Confederation of North, Central American and Caribbean Association Football
|
11
|
+
'northcentralamericacaribbean' => 'concacaf', ## e.g. North & Central America and the Caribbean
|
12
|
+
'northamerica' => 'nafu', # => North American Football Union
|
13
|
+
'centralamerica' => 'uncaf', #=> Unión Centroamericana de Fútbol
|
14
|
+
'caribbean' => 'cfu', #=> Caribbean Football Union
|
15
|
+
'africa' => 'caf', # => Confédération Africaine de Football
|
16
|
+
'eastcentralafrica' => 'cecafa', # => Council for East and Central Africa Football Associations
|
17
|
+
'southernafrica' => 'cosafa', # => Council of Southern Africa Football Associations
|
18
|
+
'westafrica' => 'wafu', # => West African Football Union/Union du Football de l'Ouest Afrique
|
19
|
+
'northafrica' => 'unaf', # => Union of North African Federations
|
20
|
+
'centralafrica' => 'uniffac', # => Union des Fédérations du Football de l'Afrique Centrale
|
21
|
+
'asia' => 'afc', # => Asian Football Confederation
|
22
|
+
'middleeast' => 'waff', # => West Asian Football Federation -- note: excludes Iran and Israel
|
23
|
+
'eastasia' => 'eaff',
|
24
|
+
'centralasia' => 'cafa',
|
25
|
+
'southasia' => 'saff',
|
26
|
+
'southeastasia' => 'aff',
|
27
|
+
'oceania' => 'ofc', # => Oceania Football Confederation
|
28
|
+
'pacific' => 'ofc',
|
29
|
+
'southamerica' => 'conmebol', #=> Confederación Sudamericana de Fútbol
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
def initialize( countries=nil )
|
34
|
+
@orgs = {} ## countries by org (key)
|
35
|
+
|
36
|
+
add( countries ) if countries
|
37
|
+
end
|
38
|
+
|
39
|
+
def add( countries )
|
40
|
+
countries.each do |country|
|
41
|
+
## note: assumes all tags are sport / fifa tags for now
|
42
|
+
country.tags.each do |tag|
|
43
|
+
@orgs[ tag ] ||= []
|
44
|
+
@orgs[ tag ] << country
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def keys() @orgs.keys; end
|
51
|
+
|
52
|
+
def members( key=:fifa ) ## default to fifa members
|
53
|
+
key = key.to_s.downcase
|
54
|
+
countries = @orgs[ key ]
|
55
|
+
|
56
|
+
if countries.nil? ## (re)try / check with alternative (convenience) org name
|
57
|
+
alt_key = ALT_KEYS[ _norm_org( key ) ]
|
58
|
+
countries = @orgs[ alt_key ] if alt_key
|
59
|
+
end
|
60
|
+
countries
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def _norm_org( name )
|
65
|
+
## remove space, comma, ampersand (&) and words: and, the
|
66
|
+
name.gsub( / [ ,&] |
|
67
|
+
\band\b |
|
68
|
+
\bthe\b
|
69
|
+
/x, '' )
|
70
|
+
end
|
71
|
+
|
72
|
+
end # class OrgIndex
|
73
|
+
end # class CountryIndex
|
74
|
+
end # module Fifa
|
75
|
+
|
76
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Fifa
|
2
|
+
|
3
|
+
## todo/fix:
|
4
|
+
## for convenience use a copy-n-paste version here
|
5
|
+
## reuse from upstream - DO NOT DUPLICATE
|
6
|
+
## move outline reader to cocos (for easy reuse) in the future - why? why not?
|
7
|
+
|
8
|
+
class OutlineReader
|
9
|
+
|
10
|
+
def self.debug=(value) @@debug = value; end
|
11
|
+
def self.debug?() @@debug ||= false; end
|
12
|
+
def debug?() self.class.debug?; end
|
13
|
+
|
14
|
+
|
15
|
+
def self.read( path ) ## use - rename to read_file or from_file etc. - why? why not?
|
16
|
+
txt = File.open( path, 'r:utf-8' ) {|f| f.read }
|
17
|
+
parse( txt )
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.parse( txt )
|
21
|
+
new( txt ).parse
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize( txt )
|
25
|
+
@txt = txt
|
26
|
+
end
|
27
|
+
|
28
|
+
## note: skip "decorative" only heading e.g. ========
|
29
|
+
## todo/check: find a better name e.g. HEADING_EMPTY_RE or HEADING_LINE_RE or ???
|
30
|
+
HEADING_BLANK_RE = %r{\A
|
31
|
+
={1,}
|
32
|
+
\z}x
|
33
|
+
|
34
|
+
## note: like in wikimedia markup (and markdown) all optional trailing ==== too
|
35
|
+
HEADING_RE = %r{\A
|
36
|
+
(?<marker>={1,}) ## 1. leading ======
|
37
|
+
[ ]*
|
38
|
+
(?<text>[^=]+) ## 2. text (note: for now no "inline" = allowed)
|
39
|
+
[ ]*
|
40
|
+
=* ## 3. (optional) trailing ====
|
41
|
+
\z}x
|
42
|
+
|
43
|
+
def parse
|
44
|
+
outline=[] ## outline structure
|
45
|
+
start_para = true ## start new para(graph) on new text line?
|
46
|
+
|
47
|
+
@txt.each_line do |line|
|
48
|
+
line = line.strip ## todo/fix: keep leading and trailing spaces - why? why not?
|
49
|
+
|
50
|
+
if line.empty? ## todo/fix: keep blank line nodes?? and just remove comments and process headings?! - why? why not?
|
51
|
+
start_para = true
|
52
|
+
next
|
53
|
+
end
|
54
|
+
|
55
|
+
break if line == '__END__'
|
56
|
+
|
57
|
+
next if line.start_with?( '#' ) ## skip comments too
|
58
|
+
## strip inline (until end-of-line) comments too
|
59
|
+
## e.g Eupen | KAS Eupen ## [de]
|
60
|
+
## => Eupen | KAS Eupen
|
61
|
+
## e.g bq Bonaire, BOE # CONCACAF
|
62
|
+
## => bq Bonaire, BOE
|
63
|
+
line = line.sub( /#.*/, '' ).strip
|
64
|
+
pp line if debug?
|
65
|
+
|
66
|
+
## todo/check: also use heading blank as paragraph "breaker" or treat it like a comment ?? - why? why not?
|
67
|
+
next if HEADING_BLANK_RE.match( line ) # skip "decorative" only heading e.g. ========
|
68
|
+
|
69
|
+
## note: like in wikimedia markup (and markdown) all optional trailing ==== too
|
70
|
+
if m=HEADING_RE.match( line )
|
71
|
+
start_para = true
|
72
|
+
|
73
|
+
heading_marker = m[:marker]
|
74
|
+
heading_level = heading_marker.length ## count number of = for heading level
|
75
|
+
heading = m[:text].strip
|
76
|
+
|
77
|
+
puts "heading #{heading_level} >#{heading}<" if debug?
|
78
|
+
outline << [:"h#{heading_level}", heading]
|
79
|
+
else ## assume it's a (plain/regular) text line
|
80
|
+
if start_para
|
81
|
+
outline << [:p, [line]]
|
82
|
+
start_para = false
|
83
|
+
else
|
84
|
+
node = outline[-1] ## get last entry
|
85
|
+
if node[0] == :p ## assert it's a p(aragraph) node!!!
|
86
|
+
node[1] << line ## add line to p(aragraph)
|
87
|
+
else
|
88
|
+
puts "!! ERROR - invalid outline state / format - expected p(aragraph) node; got:"
|
89
|
+
pp node
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
outline
|
96
|
+
end # method read
|
97
|
+
end # class OutlineReader
|
98
|
+
|
99
|
+
end # module Fifa
|
data/lib/fifa/version.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
|
3
|
-
|
4
|
-
##
|
5
|
-
|
6
|
-
class Fifa
|
7
|
-
MAJOR = 2020 ## todo: namespace inside version or something - why? why not??
|
2
|
+
module Fifa
|
3
|
+
MAJOR = 2024 ## todo: namespace inside version or something - why? why not??
|
8
4
|
MINOR = 9
|
9
|
-
PATCH =
|
5
|
+
PATCH = 21
|
10
6
|
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
11
7
|
|
12
8
|
def self.version
|
@@ -14,7 +10,7 @@ class Fifa
|
|
14
10
|
end
|
15
11
|
|
16
12
|
def self.banner
|
17
|
-
"fifa/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
|
13
|
+
"fifa/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
18
14
|
end
|
19
15
|
|
20
16
|
def self.root
|
@@ -24,4 +20,4 @@ class Fifa
|
|
24
20
|
def self.data_dir ## rename to config_dir - why? why not?
|
25
21
|
"#{root}/config"
|
26
22
|
end
|
27
|
-
end #
|
23
|
+
end # module Fifa
|
data/lib/fifa.rb
CHANGED
@@ -1,97 +1,52 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
1
|
## 3rd party gems
|
5
|
-
require 'sportdb/
|
2
|
+
require 'sportdb/structs' ## pull-in Sports::Country
|
6
3
|
|
7
4
|
|
8
5
|
###
|
9
6
|
# our own code
|
10
|
-
|
11
|
-
require 'fifa/countries'
|
12
|
-
|
13
|
-
|
14
|
-
class Fifa
|
15
|
-
def self.countries() country_index.countries; end ## return all country (struct-like) records
|
16
|
-
def self.[]( key ) country_index[ key ]; end
|
17
|
-
|
18
|
-
|
19
|
-
ALT_ORG_NAMES = {
|
20
|
-
'world' => 'fifa',
|
21
|
-
'europe' => 'uefa', #=> Union of European Football Associations
|
22
|
-
'northamericacentralamericacaribbean' => 'concacaf', #=> Confederation of North, Central American and Caribbean Association Football
|
23
|
-
'northcentralamericacaribbean' => 'concacaf', ## e.g. North & Central America and the Caribbean
|
24
|
-
'northamerica' => 'nafu', # => North American Football Union
|
25
|
-
'centralamerica' => 'uncaf', #=> Unión Centroamericana de Fútbol
|
26
|
-
'caribbean' => 'cfu', #=> Caribbean Football Union
|
27
|
-
'africa' => 'caf', # => Confédération Africaine de Football
|
28
|
-
'eastcentralafrica' => 'cecafa', # => Council for East and Central Africa Football Associations
|
29
|
-
'southernafrica' => 'cosafa', # => Council of Southern Africa Football Associations
|
30
|
-
'westafrica' => 'wafu', # => West African Football Union/Union du Football de l'Ouest Afrique
|
31
|
-
'northafrica' => 'unaf', # => Union of North African Federations
|
32
|
-
'centralafrica' => 'uniffac', # => Union des Fédérations du Football de l'Afrique Centrale
|
33
|
-
'asia' => 'afc', # => Asian Football Confederation
|
34
|
-
'middleeast' => 'waff', # => West Asian Football Federation -- note: excludes Iran and Israel
|
35
|
-
'eastasia' => 'eaff',
|
36
|
-
'centralasia' => 'cafa',
|
37
|
-
'southasia' => 'saff',
|
38
|
-
'southeastasia' => 'aff',
|
39
|
-
'oceania' => 'ofc', # => Oceania Football Confederation
|
40
|
-
'pacific' => 'ofc',
|
41
|
-
'southamerica' => 'conmebol', #=> Confederación Sudamericana de Fútbol
|
42
|
-
}
|
43
|
-
|
44
|
-
def self.members( key=:fifa ) ## default to fifa members
|
45
|
-
key = key.to_s.downcase
|
46
|
-
countries = org_index[ key ]
|
47
|
-
|
48
|
-
if countries.nil? ## (re)try / check with alternative (convenience) org name
|
49
|
-
alt_key = ALT_ORG_NAMES[ normalize_org( key ) ]
|
50
|
-
countries = org_index[ alt_key ] if alt_key
|
51
|
-
end
|
52
|
-
countries
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.normalize_org( name )
|
56
|
-
## remove space, comma, ampersand (&) and words: and, the
|
57
|
-
name.gsub( /[ ,&]|\band\b|\bthe\b/, '' )
|
58
|
-
end
|
59
|
-
|
7
|
+
require_relative 'fifa/version' # let version always go first
|
60
8
|
|
61
|
-
|
9
|
+
require_relative 'fifa/outline_reader'
|
10
|
+
require_relative 'fifa/country_reader'
|
62
11
|
|
12
|
+
require_relative 'fifa/country_index'
|
13
|
+
require_relative 'fifa/org_index'
|
63
14
|
|
64
|
-
private
|
65
|
-
def self.country_index
|
66
|
-
@country_index ||= build_country_index
|
67
|
-
end
|
68
15
|
|
69
|
-
|
70
|
-
|
71
|
-
|
16
|
+
module Fifa
|
17
|
+
def self.world
|
18
|
+
@world ||= begin
|
19
|
+
world = CountryIndex.new
|
20
|
+
recs = CountryReader.read( "#{Fifa.data_dir}/countries.txt" )
|
21
|
+
world.add( recs )
|
22
|
+
world
|
23
|
+
end
|
72
24
|
end
|
73
25
|
|
74
26
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
27
|
+
## note: only returns fifa member countries (use world.countries for all) !!!
|
28
|
+
def self.countries() world.members( :fifa ); end
|
78
29
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
## note: assumes all tags are sport / fifa tags for now
|
83
|
-
country.tags.each do |tag|
|
84
|
-
orgs[ tag ] ||= []
|
85
|
-
orgs[ tag ] << country
|
86
|
-
end
|
87
|
-
end
|
88
|
-
orgs
|
89
|
-
end
|
30
|
+
## search service (using world - note: NOT scoped/limted to members only)
|
31
|
+
def self.[]( q ) world[ q ]; end
|
32
|
+
def self.members( key=:fifa ) world.members( key ); end
|
90
33
|
end # class Fifa
|
91
34
|
|
92
35
|
|
36
|
+
|
37
|
+
## add Uefa convenience module with scoped search/lookup - why? why not?
|
38
|
+
module Uefa
|
39
|
+
def self.countries() Fifa.world.members(:uefa); end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Conmebol
|
43
|
+
def self.countries() Fifa.members( :conmebol ); end
|
44
|
+
end
|
45
|
+
|
93
46
|
## add a convenience upcase alias
|
94
|
-
FIFA
|
47
|
+
FIFA = Fifa
|
48
|
+
UEFA = Uefa
|
49
|
+
CONMEBOL = Conmebol # Confederación Sudamericana de Fútbol
|
95
50
|
|
96
51
|
|
97
52
|
|
metadata
CHANGED
@@ -1,60 +1,66 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fifa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2024.9.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: sportdb-
|
14
|
+
name: sportdb-structs
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.4.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:
|
26
|
+
version: 0.4.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rdoc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '4.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '7'
|
34
37
|
type: :development
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '4.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '7'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: hoe
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
53
|
+
version: '4.1'
|
48
54
|
type: :development
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - "~>"
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
60
|
+
version: '4.1'
|
55
61
|
description: fifa - the world's football countries and codes (incl. non-member countries
|
56
62
|
and irregular codes)
|
57
|
-
email:
|
63
|
+
email: gerald.bauer@google.com
|
58
64
|
executables: []
|
59
65
|
extensions: []
|
60
66
|
extra_rdoc_files:
|
@@ -71,16 +77,16 @@ files:
|
|
71
77
|
- Rakefile
|
72
78
|
- config/countries.txt
|
73
79
|
- lib/fifa.rb
|
74
|
-
- lib/fifa/
|
80
|
+
- lib/fifa/country_index.rb
|
81
|
+
- lib/fifa/country_reader.rb
|
82
|
+
- lib/fifa/org_index.rb
|
83
|
+
- lib/fifa/outline_reader.rb
|
75
84
|
- lib/fifa/version.rb
|
76
|
-
- test/helper.rb
|
77
|
-
- test/test_countries.rb
|
78
|
-
- test/test_orgs.rb
|
79
85
|
homepage: https://github.com/sportdb/football.db
|
80
86
|
licenses:
|
81
87
|
- Public Domain
|
82
88
|
metadata: {}
|
83
|
-
post_install_message:
|
89
|
+
post_install_message:
|
84
90
|
rdoc_options:
|
85
91
|
- "--main"
|
86
92
|
- README.md
|
@@ -90,16 +96,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
96
|
requirements:
|
91
97
|
- - ">="
|
92
98
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
99
|
+
version: 3.1.0
|
94
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
101
|
requirements:
|
96
102
|
- - ">="
|
97
103
|
- !ruby/object:Gem::Version
|
98
104
|
version: '0'
|
99
105
|
requirements: []
|
100
|
-
|
101
|
-
|
102
|
-
signing_key:
|
106
|
+
rubygems_version: 3.4.10
|
107
|
+
signing_key:
|
103
108
|
specification_version: 4
|
104
109
|
summary: fifa - the world's football countries and codes (incl. non-member countries
|
105
110
|
and irregular codes)
|
data/lib/fifa/countries.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
class Fifa
|
5
|
-
|
6
|
-
## built-in countries for (quick starter) auto-add
|
7
|
-
class CountryIndex
|
8
|
-
|
9
|
-
def initialize( recs )
|
10
|
-
@countries = {} ## countries by fifa code
|
11
|
-
|
12
|
-
add( recs )
|
13
|
-
end
|
14
|
-
|
15
|
-
def countries ## all country records
|
16
|
-
@countries.values
|
17
|
-
end
|
18
|
-
|
19
|
-
def []( key )
|
20
|
-
key = key.to_s.upcase ## allow symbols (and always upcase e.g. aut to AUT etc.)
|
21
|
-
@countries[ key ]
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
def add( recs )
|
26
|
-
###########################################
|
27
|
-
## auto-fill countries
|
28
|
-
## pp recs
|
29
|
-
recs.each do |rec|
|
30
|
-
|
31
|
-
## add codes lookups - key, fifa, ...
|
32
|
-
if @countries[ rec.code ]
|
33
|
-
puts "** !!! ERROR !!! country code (fifa) >#{rec.code}< already exits!!"
|
34
|
-
exit 1
|
35
|
-
else
|
36
|
-
@countries[ rec.code ] = rec
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end # method add
|
40
|
-
end # class CountryIndex
|
41
|
-
|
42
|
-
end # class Fifa
|
data/test/helper.rb
DELETED
data/test/test_countries.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
###
|
4
|
-
# to run use
|
5
|
-
# ruby -I ./lib -I ./test test/test_countries.rb
|
6
|
-
|
7
|
-
|
8
|
-
require 'helper'
|
9
|
-
|
10
|
-
class TestCountries < MiniTest::Test
|
11
|
-
|
12
|
-
def test_read_countries
|
13
|
-
recs = SportDb::Import::CountryReader.read( "#{Fifa.data_dir}/countries.txt" )
|
14
|
-
## pp recs
|
15
|
-
|
16
|
-
assert_equal [{ key: 'bi', code: 'BDI', name: 'Burundi', tags: ['fifa','caf','cecafa']},
|
17
|
-
{ key: 'dj', code: 'DJI', name: 'Djibouti', tags: ['fifa','caf','cecafa']}],
|
18
|
-
recs[0..1].map { |rec| { key: rec.key, code: rec.code, name: rec.name, tags: rec.tags }}
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
def test_countries
|
23
|
-
pp Fifa.countries
|
24
|
-
|
25
|
-
eng = Fifa['ENG']
|
26
|
-
assert_equal eng, Fifa['eng']
|
27
|
-
assert_equal eng, Fifa[:eng]
|
28
|
-
|
29
|
-
assert_equal 'eng', eng.key
|
30
|
-
assert_equal 'England', eng.name
|
31
|
-
assert_equal 'ENG', eng.code
|
32
|
-
assert_equal ['fifa','uefa'], eng.tags
|
33
|
-
|
34
|
-
|
35
|
-
aut = Fifa['AUT']
|
36
|
-
assert_equal aut, Fifa['aut']
|
37
|
-
assert_equal aut, Fifa[:aut]
|
38
|
-
|
39
|
-
assert_equal 'at', aut.key
|
40
|
-
assert_equal 'Austria', aut.name
|
41
|
-
assert_equal 'AUT', aut.code
|
42
|
-
assert_equal ['fifa','uefa'], aut.tags
|
43
|
-
end
|
44
|
-
|
45
|
-
end # class TestCountries
|
data/test/test_orgs.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
###
|
4
|
-
# to run use
|
5
|
-
# ruby -I ./lib -I ./test test/test_orgs.rb
|
6
|
-
|
7
|
-
|
8
|
-
require 'helper'
|
9
|
-
|
10
|
-
class TestOrgs < MiniTest::Test
|
11
|
-
|
12
|
-
def test_orgs
|
13
|
-
orgs = Fifa.orgs
|
14
|
-
pp orgs
|
15
|
-
|
16
|
-
## print counts
|
17
|
-
puts "#{'%3d' % Fifa.countries.size} countries:"
|
18
|
-
orgs.each do |org|
|
19
|
-
countries = Fifa.members( org )
|
20
|
-
puts "#{'%3d' % countries.size} #{org}"
|
21
|
-
end
|
22
|
-
|
23
|
-
## pp Fifa.members( 'OFC' ).sort_by {|rec| rec.name }
|
24
|
-
|
25
|
-
assert_equal 47, Fifa.members( 'AFC' ).size # => Asian Football Confederation
|
26
|
-
assert_equal 56, Fifa.members( 'CAF' ).size # => Confédération Africaine de Football
|
27
|
-
assert_equal 41, Fifa.members( 'CONCACAF' ).size # => Confederation of North, Central American and Caribbean Association Football
|
28
|
-
assert_equal 10, Fifa.members( 'CONMEBOL' ).size # => Confederación Sudamericana de Fútbol
|
29
|
-
assert_equal 14, Fifa.members( 'OFC' ).size # => Oceania Football Confederation
|
30
|
-
assert_equal 55, Fifa.members( 'UEFA' ).size # => Union of European Football Associations
|
31
|
-
|
32
|
-
assert_equal 3, Fifa.members( 'NAFU' ).size # => North American Football Union
|
33
|
-
assert_equal 7, Fifa.members( 'UNCAF' ).size # => Unión Centroamericana de Fútbol
|
34
|
-
assert_equal 31, Fifa.members( 'CFU' ).size # => Caribbean Football Union
|
35
|
-
|
36
|
-
assert_equal 12, Fifa.members( 'WAFF' ).size # => West Asian Football Federation
|
37
|
-
assert_equal 10, Fifa.members( 'EAFF' ).size # => East Asian Football Federation
|
38
|
-
assert_equal 6, Fifa.members( 'CAFA' ).size # => Central Asian Football Association
|
39
|
-
assert_equal 7, Fifa.members( 'SAFF' ).size # => South Asian Football Federation
|
40
|
-
assert_equal 12, Fifa.members( 'AFF' ).size # => ASEAN Football Federation
|
41
|
-
|
42
|
-
assert_equal 12, Fifa.members( 'CECAFA' ).size # => Council for East and Central Africa Football Associations
|
43
|
-
assert_equal 14, Fifa.members( 'COSAFA' ).size # => Council of Southern Africa Football Associations
|
44
|
-
assert_equal 16, Fifa.members( 'WAFU' ).size # => West African Football Union/Union du Football de l'Ouest Afrique
|
45
|
-
assert_equal 5, Fifa.members( 'UNAF' ).size # => Union of North African Federations
|
46
|
-
assert_equal 8, Fifa.members( 'UNIFFAC' ).size # => Union des Fédérations du Football de l'Afrique Centrale
|
47
|
-
|
48
|
-
assert_equal 211, Fifa.members( 'FIFA' ).size
|
49
|
-
|
50
|
-
|
51
|
-
## print countries NOT members of fifa (but of confederation)
|
52
|
-
puts "non-fifa member codes:"
|
53
|
-
Fifa.countries.each do |country|
|
54
|
-
if country.tags.empty? == false &&
|
55
|
-
country.tags.include?( 'fifa' ) == false
|
56
|
-
puts " #{country.name}, #{country.code}, #{country.tags.join(' | ')}"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
## print countries NOT members of fifa or any confederation (irregular codes)
|
61
|
-
puts "irregular codes:"
|
62
|
-
Fifa.countries.each do |country|
|
63
|
-
puts " #{country.name}, #{country.code}" if country.tags.empty?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
def test_alt_names
|
69
|
-
## check normalize org key / name
|
70
|
-
assert_equal 'NorthAmericaCentralAmericaCaribbean', Fifa.normalize_org( 'North America, Central America and the Caribbean' )
|
71
|
-
assert_equal 'NorthCentralAmericaCaribbean', Fifa.normalize_org( 'North and Central America and the Caribbean' )
|
72
|
-
assert_equal 'NorthCentralAmericaCaribbean', Fifa.normalize_org( 'North & Central America & Caribbean' )
|
73
|
-
|
74
|
-
|
75
|
-
assert_equal Fifa.members( 'FIFA' ).size, Fifa.members( 'World' ).size
|
76
|
-
assert_equal Fifa.members( 'UEFA' ).size, Fifa.members( 'Europe' ).size
|
77
|
-
assert_equal Fifa.members( 'CAF' ).size, Fifa.members( 'Africa' ).size
|
78
|
-
assert_equal Fifa.members( 'CECAFA' ).size, Fifa.members( 'East and Central Africa' ).size
|
79
|
-
assert_equal Fifa.members( 'COSAFA' ).size, Fifa.members( 'Southern Africa' ).size
|
80
|
-
assert_equal Fifa.members( 'WAFU' ).size, Fifa.members( 'West Africa' ).size
|
81
|
-
assert_equal Fifa.members( 'UNAF' ).size, Fifa.members( 'North Africa' ).size
|
82
|
-
assert_equal Fifa.members( 'UNIFFAC' ).size, Fifa.members( 'Central Africa' ).size
|
83
|
-
assert_equal Fifa.members( 'CONCACAF' ).size, Fifa.members( 'North America, Central America and the Caribbean' ).size
|
84
|
-
assert_equal Fifa.members( 'CONCACAF' ).size, Fifa.members( 'North and Central America and the Caribbean' ).size
|
85
|
-
assert_equal Fifa.members( 'CONCACAF' ).size, Fifa.members( 'North & Central America & Caribbean' ).size
|
86
|
-
assert_equal Fifa.members( 'NAFU' ).size, Fifa.members( 'North America' ).size
|
87
|
-
assert_equal Fifa.members( 'UNCAF' ).size, Fifa.members( 'Central America' ).size
|
88
|
-
assert_equal Fifa.members( 'CFU' ).size, Fifa.members( 'Caribbean' ).size
|
89
|
-
assert_equal Fifa.members( 'CONMEBOL' ).size, Fifa.members( 'South America' ).size
|
90
|
-
assert_equal Fifa.members( 'AFC' ).size, Fifa.members( 'Asia' ).size
|
91
|
-
assert_equal Fifa.members( 'WAFF' ).size, Fifa.members( 'Middle East' ).size
|
92
|
-
assert_equal Fifa.members( 'EAFF' ).size, Fifa.members( 'East Asia' ).size
|
93
|
-
assert_equal Fifa.members( 'CAFA' ).size, Fifa.members( 'Central Asia' ).size
|
94
|
-
assert_equal Fifa.members( 'SAFF' ).size, Fifa.members( 'South Asia' ).size
|
95
|
-
assert_equal Fifa.members( 'AFF' ).size, Fifa.members( 'Southeast Asia' ).size
|
96
|
-
assert_equal Fifa.members( 'OFC' ).size, Fifa.members( 'Oceania' ).size
|
97
|
-
assert_equal Fifa.members( 'OFC' ).size, Fifa.members( 'Pacific' ).size
|
98
|
-
end
|
99
|
-
|
100
|
-
end # class TestOrgs
|