icu_tournament 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ coverage
2
+ rdoc
3
+ pkg
4
+ tmp
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,5 @@
1
+ ---
2
+ :build:
3
+ :major: 0
4
+ :minor: 8
5
+ :patch: 9
@@ -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