icu_tournament 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/LICENCE +22 -0
- data/README.rdoc +75 -0
- data/Rakefile +57 -0
- data/VERSION.yml +5 -0
- data/lib/icu_tournament.rb +8 -0
- data/lib/icu_tournament/federation.rb +303 -0
- data/lib/icu_tournament/name.rb +274 -0
- data/lib/icu_tournament/player.rb +204 -0
- data/lib/icu_tournament/result.rb +191 -0
- data/lib/icu_tournament/team.rb +90 -0
- data/lib/icu_tournament/tournament.rb +508 -0
- data/lib/icu_tournament/tournament_fcsv.rb +310 -0
- data/lib/icu_tournament/tournament_krause.rb +329 -0
- data/lib/icu_tournament/util.rb +156 -0
- data/spec/federation_spec.rb +176 -0
- data/spec/name_spec.rb +208 -0
- data/spec/player_spec.rb +313 -0
- data/spec/result_spec.rb +203 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/team_spec.rb +60 -0
- data/spec/tournament_fcsv_spec.rb +548 -0
- data/spec/tournament_krause_spec.rb +379 -0
- data/spec/tournament_spec.rb +733 -0
- data/spec/util_spec.rb +357 -0
- metadata +97 -0
data/.gitignore
ADDED
data/LICENCE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2009 Mark Orr
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
= ChessIcu
|
2
|
+
|
3
|
+
For reading or writing files of chess tournament data.
|
4
|
+
|
5
|
+
|
6
|
+
== Install
|
7
|
+
|
8
|
+
sudo gem install icu_tournament --source http://gemcutter.org
|
9
|
+
|
10
|
+
For Ruby prior to version 1.9 you also need:
|
11
|
+
|
12
|
+
sudo gem install fastercsv
|
13
|
+
|
14
|
+
|
15
|
+
== Usage
|
16
|
+
|
17
|
+
There are two main uses for this gem:
|
18
|
+
|
19
|
+
* You have chess tournament data that needs to be written to a file in one of the supported formats.
|
20
|
+
For example, your data is in a spreadsheet but you need it in Krause format so you can upload it to the FIDE rating server.
|
21
|
+
|
22
|
+
* You have a file in a supported format and you need to extract the information it contains.
|
23
|
+
For example, you have a Krause formatted file and want to extract the data and insert it into a database.
|
24
|
+
|
25
|
+
The currently supported formats (more are planned) are:
|
26
|
+
|
27
|
+
* ICU::Tournament::Krause - the format used by FIDE.
|
28
|
+
* ICU::Tournament::ForeignCSV - used by Irish players to report their individual results in foreign tournaments.
|
29
|
+
|
30
|
+
|
31
|
+
== Writing Files
|
32
|
+
|
33
|
+
Here's how the 1972 Fischer-Spassky match could be formatted to Krause. First a tournament object is created
|
34
|
+
and the players (just two in this case) are added with unique ID numbers. To keep the example short, not all
|
35
|
+
the information that a Krause file might contain is included here (see ICU::Tournament::Krause for more details).
|
36
|
+
|
37
|
+
t = ICU::Tournament.new('World Championship', '1972-07-11')
|
38
|
+
t.add_player(ICU::Player.new('Robert J.', 'Fischer', 1))
|
39
|
+
t.add_player(ICU::Player.new('Boris V.', 'Spassky', 2))
|
40
|
+
|
41
|
+
Then the results for each round are added using the ID numbers to refer to the players.
|
42
|
+
|
43
|
+
t.add_result(ICU::Result.new(1, 1, 'L', :opponent => 2, :colour => 'B'))
|
44
|
+
|
45
|
+
Read this as: in round 1, player 1 lost against opponent 2 with the black pieces.
|
46
|
+
|
47
|
+
t.add_result(ICU::Result.new(2, 1, 'L', :opponent => 2, :colour => 'W', :rateable => false))
|
48
|
+
|
49
|
+
In round 2 player 1 lost by default against player 2. Similarly for all the other rounds:
|
50
|
+
|
51
|
+
t.add_result(ICU::Result.new(3, 1, 'W', :opponent => 2, :colour => 'B'))
|
52
|
+
# ...
|
53
|
+
t.add_result(ICU::Result.new(21, 1, 'W', :opponent => 2, :colour => 'B'))
|
54
|
+
|
55
|
+
Then finally, to create the file:
|
56
|
+
|
57
|
+
open('match.txt', 'w') { |f| f.puts @t.serialize('Krause') }
|
58
|
+
|
59
|
+
|
60
|
+
== Reading Files
|
61
|
+
|
62
|
+
Suppose you have a tournament file in Krause format. Parse it into a tournament object like this:
|
63
|
+
|
64
|
+
data = open('tournament.txt') { |f| f.read }
|
65
|
+
parser = ICU::Tournament::Krause.new
|
66
|
+
tournament = parser.parse(data)
|
67
|
+
|
68
|
+
On success, the _parse_ method returns an object of type ICU::Tournament. A tournament (ICU::Tournament)
|
69
|
+
has two or more players (ICU::Player), and each player has one or more results (ICU::Result). See the
|
70
|
+
rdoc for more details. On error, the _parse_ method returns _nil_ and an error message can be retrieved
|
71
|
+
from the parser (parser.error).
|
72
|
+
|
73
|
+
== Author
|
74
|
+
|
75
|
+
Mark Orr, rating officer for the Irish Chess Union (ICU[http://icu.ie]).
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "icu_tournament"
|
10
|
+
gem.summary = "For reading and writing files of chess tournament data."
|
11
|
+
gem.description = "Convert files of chess tournament data in different formats to ruby classes and vice-versa."
|
12
|
+
gem.homepage = "http://github.com/sanichi/icu_tournament"
|
13
|
+
gem.authors = ["Mark Orr"]
|
14
|
+
gem.email = "mark.j.l.orr@googlemail.com"
|
15
|
+
gem.files = FileList['[A-Z]*', '{lib,spec}/**/*', '.gitignore']
|
16
|
+
gem.has_rdoc = true
|
17
|
+
gem.rdoc_options = "--charset=UTF-8"
|
18
|
+
gem.add_dependency('fastercsv', '>= 1.4.0')
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler."
|
23
|
+
end
|
24
|
+
|
25
|
+
task :default => :spec
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
30
|
+
spec.spec_opts = ['--colour --format nested --loadby mtime --reverse']
|
31
|
+
end
|
32
|
+
|
33
|
+
Spec::Rake::SpecTask.new(:fcsv) do |spec|
|
34
|
+
spec.libs << 'lib' << 'spec'
|
35
|
+
spec.spec_files = FileList['spec/tournament_fcsv_spec.rb']
|
36
|
+
spec.spec_opts = ['--colour --format nested']
|
37
|
+
end
|
38
|
+
|
39
|
+
Spec::Rake::SpecTask.new(:krs) do |spec|
|
40
|
+
spec.libs << 'lib' << 'spec'
|
41
|
+
spec.spec_files = FileList['spec/tournament_krause_spec.rb']
|
42
|
+
spec.spec_opts = ['--colour --format nested']
|
43
|
+
end
|
44
|
+
|
45
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
46
|
+
if File.exist?('VERSION.yml')
|
47
|
+
config = YAML.load(File.read('VERSION.yml'))
|
48
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
49
|
+
else
|
50
|
+
version = ""
|
51
|
+
end
|
52
|
+
|
53
|
+
rdoc.rdoc_dir = 'rdoc'
|
54
|
+
rdoc.title = "ChessIcu #{version}"
|
55
|
+
rdoc.rdoc_files.include('README*')
|
56
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
57
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# :enddoc:
|
2
|
+
|
3
|
+
icu_tournament_files = Array.new
|
4
|
+
icu_tournament_files.concat %w{util name federation}
|
5
|
+
icu_tournament_files.concat %w{player result team tournament}
|
6
|
+
icu_tournament_files.concat %w{fcsv krause}.map{ |f| "tournament_#{f}"}
|
7
|
+
|
8
|
+
icu_tournament_files.each { |file| require "icu_tournament/#{file}" }
|
@@ -0,0 +1,303 @@
|
|
1
|
+
module ICU
|
2
|
+
|
3
|
+
=begin rdoc
|
4
|
+
|
5
|
+
== Federations
|
6
|
+
|
7
|
+
This class can be used to map a string into an object representing a chess federation.
|
8
|
+
In FIDE, chess federations are generally either referred to by their full names such as
|
9
|
+
_Ireland_ or _Russia_ or by three letter codes such as _IRL_ or _RUS_. The three letter
|
10
|
+
codes are mostly the same as those found in the international standard known as
|
11
|
+
{ISO 3166-1 alpha-3}[http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3], but with
|
12
|
+
some differences (e.g. for England, Scotland and Wales).
|
13
|
+
|
14
|
+
You cannot directly create instances of this class using _new_. Instead, you supply
|
15
|
+
a string to the class method _find_ and, if the string supplied uniguely identifies a
|
16
|
+
federation, an instance is returned which responds to _name_ and _code_.
|
17
|
+
|
18
|
+
fed = ICU::Federation.find('IRL')
|
19
|
+
fed.name # => "Ireland"
|
20
|
+
fed.code # => "IRL"
|
21
|
+
|
22
|
+
If the string is not sufficient to identify a federation, the _find_ method returns _nil_.
|
23
|
+
|
24
|
+
fed = ICU::Federation.find('ZYX') # => nil
|
25
|
+
|
26
|
+
If the string is three letters long and matches (case insenstively) one of the unique
|
27
|
+
federation codes, then the instance corresponding to that federation is returned.
|
28
|
+
|
29
|
+
ICU::Federation.find('rUs').code # => "RUS"
|
30
|
+
|
31
|
+
If the string is more than three letters long and if it is a substring (case insensitive)
|
32
|
+
of exactly one federation name, then that federation is returned.
|
33
|
+
|
34
|
+
ICU::Federation.find('ongoli').name # => "Mongolia"
|
35
|
+
|
36
|
+
In all other cases, nil is returned. In the following example, the string matches more than one federation.
|
37
|
+
|
38
|
+
ICU::Federation.find('land') # => nil
|
39
|
+
|
40
|
+
The method is not fooled by irrelevant white space.
|
41
|
+
|
42
|
+
ICU::Federation.find(' united states ').code # => 'USA'
|
43
|
+
|
44
|
+
The class method _menu_ will return an array of two-element arrays each of which contain a name
|
45
|
+
and a code.
|
46
|
+
|
47
|
+
ICU::Federation.menu # => [['Afghanistan', 'AFG'], ['Albania', 'ALB], ...]
|
48
|
+
|
49
|
+
Such an array could be used, for example, as the basis of a selection menu in a web application.
|
50
|
+
Various options are available to alter the array returned. Use the _:order_ option to order by code
|
51
|
+
instead of the default (by country name).
|
52
|
+
|
53
|
+
ICU::Federation.menu(:order => 'code') # => [..., ['Ireland', 'IRL'], ['Iraq', 'IRQ], ...]
|
54
|
+
|
55
|
+
To put one country at the top (followed by the rest, in order) supply the country's code with the _:top_ option:
|
56
|
+
|
57
|
+
ICU::Federation.menu(:top => 'IRL') # => [['Ireland', 'IRL'], ['Afghanistan', 'AFG], ...]
|
58
|
+
|
59
|
+
To supply an extra "None" item at the top, specify its label with the _:none_ option:
|
60
|
+
|
61
|
+
ICU::Federation.menu(:none => 'None') # => [['None', ''], ['Afghanistan', 'AFG], ...]
|
62
|
+
|
63
|
+
The "None" option's code is the empty string and it come above the "top" option if both are specified.
|
64
|
+
|
65
|
+
=end
|
66
|
+
|
67
|
+
class Federation
|
68
|
+
attr_reader :code, :name
|
69
|
+
private_class_method :new
|
70
|
+
|
71
|
+
# Given a code, name or part of a name, return the corresponding federation instance.
|
72
|
+
# If there is no match or more than one match, _nil_ is returned.
|
73
|
+
def self.find(str=nil)
|
74
|
+
return nil unless str
|
75
|
+
str = str.to_s
|
76
|
+
return nil if str.length < 3
|
77
|
+
compile unless @@objects
|
78
|
+
str = str.strip.squeeze(' ').downcase
|
79
|
+
return @@codes[str] if str.length == 3
|
80
|
+
return @@names[str] if @@names[str]
|
81
|
+
matches = Array.new
|
82
|
+
@@names.each_key do |name|
|
83
|
+
matches << @@names[name] if name.index(str)
|
84
|
+
end
|
85
|
+
matches.uniq!
|
86
|
+
return nil unless matches.length == 1
|
87
|
+
matches[0]
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.menu(opts = {})
|
91
|
+
compile unless @@objects;
|
92
|
+
top, menu = nil, []
|
93
|
+
@@objects.each {|o| opts[:top] == o.code ? top = [o.name, o.code] : menu.push([o.name, o.code]) }
|
94
|
+
opts[:order] == 'code' ? menu.sort!{|a,b| a.last <=> b.last} : menu.sort!{|a,b| a.first <=> b.first}
|
95
|
+
menu.unshift(top) if top
|
96
|
+
menu.unshift([opts[:none], '']) if opts[:none]
|
97
|
+
menu
|
98
|
+
end
|
99
|
+
|
100
|
+
def initialize(code, name) # :nodoc: because new is private
|
101
|
+
@code = code
|
102
|
+
@name = name
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def self.compile
|
108
|
+
return if @@objects
|
109
|
+
@@names = Hash.new
|
110
|
+
@@codes = Hash.new
|
111
|
+
@@objects = Array.new
|
112
|
+
@@data.each do |d|
|
113
|
+
object = new(d[0], d[1])
|
114
|
+
@@objects << object
|
115
|
+
@@codes[d[0].downcase] = object
|
116
|
+
(1..d.length-1).each do |i|
|
117
|
+
@@names[d[i].downcase] = object
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# The data structures compiled.
|
123
|
+
@@objects, @@codes, @@names = nil, nil, nil
|
124
|
+
|
125
|
+
# An array of data that gets compiled into other data structures.
|
126
|
+
@@data =
|
127
|
+
[
|
128
|
+
['AFG', 'Afghanistan'],
|
129
|
+
['ALB', 'Albania'],
|
130
|
+
['ALG', 'Algeria'],
|
131
|
+
['AND', 'Andorra'],
|
132
|
+
['ANG', 'Angola'],
|
133
|
+
['ANT', 'Antigua'],
|
134
|
+
['ARG', 'Argentina'],
|
135
|
+
['ARM', 'Armenia'],
|
136
|
+
['ARU', 'Aruba'],
|
137
|
+
['AUS', 'Australia'],
|
138
|
+
['AUT', 'Austria'],
|
139
|
+
['AZE', 'Azerbaijan'],
|
140
|
+
['BAH', 'Bahamas'],
|
141
|
+
['BRN', 'Bahrain'],
|
142
|
+
['BAN', 'Bangladesh'],
|
143
|
+
['BAR', 'Barbados'],
|
144
|
+
['BLR', 'Belarus'],
|
145
|
+
['BEL', 'Belgium'],
|
146
|
+
['BIZ', 'Belize'],
|
147
|
+
['BEN', 'Benin Republic'],
|
148
|
+
['BER', 'Bermuda'],
|
149
|
+
['BHU', 'Bhutan'],
|
150
|
+
['BOL', 'Bolivia'],
|
151
|
+
['BIH', 'Bosnia and Herzegovina'],
|
152
|
+
['BOT', 'Botswana'],
|
153
|
+
['BRA', 'Brazil'],
|
154
|
+
['IVB', 'British Virgin Islands'],
|
155
|
+
['BRU', 'Brunei Darussalam'],
|
156
|
+
['BUL', 'Bulgaria'],
|
157
|
+
['BUR', 'Burkina Faso'],
|
158
|
+
['BDI', 'Burundi'],
|
159
|
+
['CAM', 'Cambodia'],
|
160
|
+
['CMR', 'Cameroon'],
|
161
|
+
['CAN', 'Canada'],
|
162
|
+
['CHA', 'Chad'],
|
163
|
+
['CHI', 'Chile'],
|
164
|
+
['CHN', 'China'],
|
165
|
+
['TPE', 'Chinese Taipei'],
|
166
|
+
['COL', 'Colombia'],
|
167
|
+
['CRC', 'Costa Rica'],
|
168
|
+
['CRO', 'Croatia'],
|
169
|
+
['CUB', 'Cuba'],
|
170
|
+
['CYP', 'Cyprus'],
|
171
|
+
['CZE', 'Czech Republic'],
|
172
|
+
['DEN', 'Denmark'],
|
173
|
+
['DJI', 'Djibouti'],
|
174
|
+
['DOM', 'Dominican Republic'],
|
175
|
+
['ECU', 'Ecuador'],
|
176
|
+
['EGY', 'Egypt'],
|
177
|
+
['ESA', 'El Salvador'],
|
178
|
+
['ENG', 'England'],
|
179
|
+
['EST', 'Estonia'],
|
180
|
+
['ETH', 'Ethiopia'],
|
181
|
+
['FAI', 'Faroe Islands'],
|
182
|
+
['FIJ', 'Fiji'],
|
183
|
+
['FIN', 'Finland'],
|
184
|
+
['FRA', 'France'],
|
185
|
+
['GAB', 'Gabon'],
|
186
|
+
['GAM', 'Gambia'],
|
187
|
+
['GEO', 'Georgia'],
|
188
|
+
['GER', 'Germany'],
|
189
|
+
['GHA', 'Ghana'],
|
190
|
+
['GRE', 'Greece'],
|
191
|
+
['GUA', 'Guatemala'],
|
192
|
+
['GCI', 'Guernsey'],
|
193
|
+
['GUY', 'Guyana'],
|
194
|
+
['HAI', 'Haiti'],
|
195
|
+
['HON', 'Honduras'],
|
196
|
+
['HKG', 'Hong Kong'],
|
197
|
+
['HUN', 'Hungary'],
|
198
|
+
['ISL', 'Iceland'],
|
199
|
+
['IND', 'India'],
|
200
|
+
['INA', 'Indonesia'],
|
201
|
+
['IRI', 'Iran'],
|
202
|
+
['IRQ', 'Iraq'],
|
203
|
+
['IRL', 'Ireland'],
|
204
|
+
['ISR', 'Israel'],
|
205
|
+
['ITA', 'Italy'],
|
206
|
+
['CIV', 'Ivory Coast'],
|
207
|
+
['JAM', 'Jamaica'],
|
208
|
+
['JPN', 'Japan'],
|
209
|
+
['JCI', 'Jersey'],
|
210
|
+
['JOR', 'Jordan'],
|
211
|
+
['KAZ', 'Kazakhstan'],
|
212
|
+
['KEN', 'Kenya'],
|
213
|
+
['KUW', 'Kuwait'],
|
214
|
+
['KGZ', 'Kyrgyzstan'],
|
215
|
+
['LAT', 'Latvia'],
|
216
|
+
['LIB', 'Lebanon'],
|
217
|
+
['LBA', 'Libya'],
|
218
|
+
['LIE', 'Liechtenstein'],
|
219
|
+
['LTU', 'Lithuania'],
|
220
|
+
['LUX', 'Luxembourg'],
|
221
|
+
['MAC', 'Macau'],
|
222
|
+
['MKD', 'Macedonia', 'Former YUG Rep of Macedonia', 'Former Yugoslav Republic of Macedonia', 'FYROM'],
|
223
|
+
['MAD', 'Madagascar'],
|
224
|
+
['MAW', 'Malawi'],
|
225
|
+
['MAS', 'Malaysia'],
|
226
|
+
['MDV', 'Maldives'],
|
227
|
+
['MLI', 'Mali'],
|
228
|
+
['MLT', 'Malta'],
|
229
|
+
['MAU', 'Mauritania'],
|
230
|
+
['MRI', 'Mauritius'],
|
231
|
+
['MEX', 'Mexico'],
|
232
|
+
['MDA', 'Moldova'],
|
233
|
+
['MNC', 'Monaco'],
|
234
|
+
['MGL', 'Mongolia'],
|
235
|
+
['MNE', 'Montenegro'],
|
236
|
+
['MAR', 'Morocco'],
|
237
|
+
['MOZ', 'Mozambique'],
|
238
|
+
['MYA', 'Myanmar'],
|
239
|
+
['NAM', 'Namibia'],
|
240
|
+
['NEP', 'Nepal'],
|
241
|
+
['NED', 'Netherlands'],
|
242
|
+
['AHO', 'Netherlands Antilles'],
|
243
|
+
['NZL', 'New Zealand'],
|
244
|
+
['NCA', 'Nicaragua'],
|
245
|
+
['NGR', 'Nigeria'],
|
246
|
+
['NOR', 'Norway'],
|
247
|
+
['PAK', 'Pakistan'],
|
248
|
+
['PLW', 'Palau'],
|
249
|
+
['PLE', 'Palestine'],
|
250
|
+
['PAN', 'Panama'],
|
251
|
+
['PNG', 'Papua New Guinea'],
|
252
|
+
['PAR', 'Paraguay'],
|
253
|
+
['PER', 'Peru'],
|
254
|
+
['PHI', 'Philippines'],
|
255
|
+
['POL', 'Poland'],
|
256
|
+
['POR', 'Portugal'],
|
257
|
+
['PUR', 'Puerto Rico'],
|
258
|
+
['QAT', 'Qatar'],
|
259
|
+
['ROU', 'Romania'],
|
260
|
+
['RUS', 'Russia'],
|
261
|
+
['RWA', 'Rwanda'],
|
262
|
+
['SMR', 'San Marino'],
|
263
|
+
['STP', 'Sao Tome and Principe'],
|
264
|
+
['SCO', 'Scotland'],
|
265
|
+
['SEN', 'Senegal'],
|
266
|
+
['SRB', 'Serbia'],
|
267
|
+
['SEY', 'Seychelles'],
|
268
|
+
['SIN', 'Singapore'],
|
269
|
+
['SVK', 'Slovakia'],
|
270
|
+
['SLO', 'Slovenia'],
|
271
|
+
['SOM', 'Somalia'],
|
272
|
+
['RSA', 'South Africa'],
|
273
|
+
['KOR', 'South Korea'],
|
274
|
+
['ESP', 'Spain'],
|
275
|
+
['SRI', 'Sri Lanka'],
|
276
|
+
['SUD', 'Sudan'],
|
277
|
+
['SUR', 'Surinam'],
|
278
|
+
['SWE', 'Sweden'],
|
279
|
+
['SUI', 'Switzerland'],
|
280
|
+
['SYR', 'Syria'],
|
281
|
+
['TJK', 'Tajikistan'],
|
282
|
+
['TAN', 'Tanzania'],
|
283
|
+
['THA', 'Thailand'],
|
284
|
+
['TRI', 'Trinidad and Tobago'],
|
285
|
+
['TUN', 'Tunisia'],
|
286
|
+
['TUR', 'Turkey'],
|
287
|
+
['TKM', 'Turkmenistan'],
|
288
|
+
['UGA', 'Uganda'],
|
289
|
+
['UKR', 'Ukraine'],
|
290
|
+
['UAE', 'United Arab Emirates'],
|
291
|
+
['USA', 'United States of America'],
|
292
|
+
['URU', 'Uruguay'],
|
293
|
+
['ISV', 'US Virgin Islands'],
|
294
|
+
['UZB', 'Uzbekistan'],
|
295
|
+
['VEN', 'Venezuela'],
|
296
|
+
['VIE', 'Vietnam'],
|
297
|
+
['WLS', 'Wales'],
|
298
|
+
['YEM', 'Yemen'],
|
299
|
+
['ZAM', 'Zambia'],
|
300
|
+
['ZIM', 'Zimbabwe'],
|
301
|
+
]
|
302
|
+
end
|
303
|
+
end
|