icu_tournament 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -8
- data/lib/icu_tournament.rb +4 -1
- data/lib/icu_tournament/federation.rb +66 -72
- data/lib/icu_tournament/player.rb +97 -103
- data/lib/icu_tournament/result.rb +82 -89
- data/lib/icu_tournament/team.rb +45 -52
- data/lib/icu_tournament/tournament.rb +153 -163
- data/lib/icu_tournament/tournament_fcsv.rb +123 -129
- data/lib/icu_tournament/tournament_krause.rb +107 -113
- data/lib/icu_tournament/tournament_sp.rb +93 -99
- data/lib/icu_tournament/util.rb +22 -41
- data/lib/icu_tournament/version.rb +3 -1
- metadata +23 -26
- data/lib/icu_tournament/name.rb +0 -274
- data/spec/name_spec.rb +0 -208
@@ -5,105 +5,99 @@ require 'tempfile'
|
|
5
5
|
|
6
6
|
module ICU
|
7
7
|
class Tournament
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
swiss_perfect = tournament.rerank.renumber.serialize('SwissPerfect')
|
102
|
-
|
103
|
-
See ICU::Tournament for more about tie-breaks.
|
104
|
-
|
105
|
-
=end
|
106
|
-
|
8
|
+
#
|
9
|
+
# This is the format produced by the Windows program, SwissPerfect[http://www.swissperfect.com/]. It consists of three
|
10
|
+
# files with the same name but different endings: <em>.ini</em> for meta data such as tournament name and tie-break
|
11
|
+
# rules, <em>.trn</em> for the player details such as name and rating, and <em>.sco</em> for the results. The first
|
12
|
+
# file is text and the other two are in an old binary format known as <em>DBase 3</em>.
|
13
|
+
#
|
14
|
+
# To parse such a set of files, use either the <em>parse_file!</em> or _parse_file_ method supplying the name of any one
|
15
|
+
# of the three files or just the stem name without any ending. In case of error, such as any of the files not being
|
16
|
+
# found, <em>parse_file!</em> will throw an exception while _parse_file_ will return _nil_ and record an error message.
|
17
|
+
# As well as a file name or stem name, you should also supply a start date in the options as SwissPerfect does not
|
18
|
+
# record this information.
|
19
|
+
#
|
20
|
+
# parser = ICU::Tournament::SwissPerfect.new
|
21
|
+
# tournament = parser.parse_file('champs', :start => '2010-07-03') # looks for "champs.ini", "champs.trn" and "champs.sco"
|
22
|
+
# puts tournament ? 'ok' : "problem: #{parser.error}"
|
23
|
+
#
|
24
|
+
# Alternatively, if all three files are in a ZIP archive, the parser will extract them if the name of the
|
25
|
+
# archive file is supplied to the _parse_file_ method and it ends in ".zip" (case insensitive):
|
26
|
+
#
|
27
|
+
# tournament = parser.parse_file('champs.zip', :start => '2010-07-03')
|
28
|
+
#
|
29
|
+
# Or, if the file is a ZIP archive but it's name doesn't end in ".zip", that can be signalled with an option:
|
30
|
+
#
|
31
|
+
# tournament = parser.parse_file('/tmp/a84f21ge', :zip => true, :start => '2010-07-03')
|
32
|
+
#
|
33
|
+
# Note there must be only three files in the archive, they must all have the same stem name and
|
34
|
+
# their endings should be ".ini", ".trn" and ".sco" (case insensitive).
|
35
|
+
#
|
36
|
+
# If no start date is supplied it will default to 2000-01-01, and can be reset later.
|
37
|
+
#
|
38
|
+
# tournament = parser.parse_file('champs.zip')
|
39
|
+
# tournament.start # => '2000-01-01'
|
40
|
+
# tournament.start = '2010-07-03'
|
41
|
+
#
|
42
|
+
# SwissPerfect files have slots for both local and international IDs and these, if present
|
43
|
+
# and if intergers are copied to the _id_ and _fide_ attributes respectively.
|
44
|
+
#
|
45
|
+
# By default, the parser extracts the local rating from the SwissPerfect files and not the international one.
|
46
|
+
# If international ratings are required instead, set the _rating_ option to "intl". For example:
|
47
|
+
#
|
48
|
+
# tournament = parser.parse_file('ncc', :start => '2010-05-08')
|
49
|
+
# tournament.player(2).id # => 12379 (ICU ID)
|
50
|
+
# tournament.player(2).fide # => 1205064 (FIDE ID)
|
51
|
+
# tournament.player(2).rating # => 2556 (ICU rating)
|
52
|
+
#
|
53
|
+
# tournament = parser.parse_file('ncc', :start => '2010-05-08', :rating => 'intl')
|
54
|
+
# tournament.player(2).rating # => 2530 (FIDE rating)
|
55
|
+
#
|
56
|
+
# By default, the parse will fail completely if the ".trn" file contains any invalid federations (see ICU::Federation).
|
57
|
+
# There are two alternative behaviours controlled by setting the _fed_ option:
|
58
|
+
#
|
59
|
+
# tournament = parser.parse_file('ncc', :start => '2010-05-08', :fed == 'skip') # => silently skips invalid federations
|
60
|
+
# tournament = parser.parse_file('ncc', :start => '2010-05-08', :fed == 'ignore') # => ignores all federations
|
61
|
+
#
|
62
|
+
# Note that federations that don't match 3 letters are always silently skipped.
|
63
|
+
#
|
64
|
+
# Because the data is in three parts, some of which are in a legacy binary format, serialization to this format is
|
65
|
+
# not supported. Instead, a method is provided to serialize any tournament type into the text export format of
|
66
|
+
# erfect, an example of which is shown below.
|
67
|
+
#
|
68
|
+
# No Name Loc Id Total 1 2 3
|
69
|
+
#
|
70
|
+
# 1 Griffiths, Ryan-Rhys 6897 3 4:W 2:W 3:W
|
71
|
+
# 2 Flynn, Jamie 5226 2 3:W 1:L 4:W
|
72
|
+
# 3 Hulleman, Leon 6409 1 2:L 4:W 1:L
|
73
|
+
# 4 Dunne, Thomas 10914 0 1:L 3:L 2:L
|
74
|
+
#
|
75
|
+
# This format is important in Irish chess, as it's the format used to submit results to the <em>MicroSoft Access</em>
|
76
|
+
# implementation of the ICU ratings database.
|
77
|
+
#
|
78
|
+
# swiss_perfect = tournament.serialize('SwissPerfect')
|
79
|
+
#
|
80
|
+
# The order of players in the serialized output is always by player number and as a side effect of serialization,
|
81
|
+
# the player numbers will be adjusted to ensure they range from 1 to the total number of players (i.e. renumbered
|
82
|
+
# in order). If you would prefer rank-order instead, then you must first renumber the players by rank (the default
|
83
|
+
# renumbering method) before serializing. For example:
|
84
|
+
#
|
85
|
+
# swiss_perfect = tournament.renumber.serialize('SwissPerfect')
|
86
|
+
#
|
87
|
+
# There should be no need to explicitly rank the tournament first, as that information is already present in
|
88
|
+
# SwissPerfect files (i.e. each player should already have a rank after the files have been parsed).
|
89
|
+
# Additionally, the tie break rules used for the tournament are available from the _tie_break_ method,
|
90
|
+
# for example:
|
91
|
+
#
|
92
|
+
# tournament.tie_breaks # => [:buchholz, :harkness]
|
93
|
+
#
|
94
|
+
# Should you wish to rank the tournament using a different set of tie-break rules, you can do something like the following:
|
95
|
+
#
|
96
|
+
# tournament.tie_breaks = [:wins, :blacks]
|
97
|
+
# swiss_perfect = tournament.rerank.renumber.serialize('SwissPerfect')
|
98
|
+
#
|
99
|
+
# See ICU::Tournament for more about tie-breaks.
|
100
|
+
#
|
107
101
|
class SwissPerfect
|
108
102
|
attr_reader :error
|
109
103
|
|
data/lib/icu_tournament/util.rb
CHANGED
@@ -1,38 +1,16 @@
|
|
1
1
|
module ICU
|
2
2
|
class Util
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Parse dates into yyyy-mm-dd format, preferring European over US convention. Returns nil on error.
|
16
|
-
|
17
|
-
Util.parsedate('1955-11-09') # => '1955-11-09'
|
18
|
-
Util.parsedate('02/03/2009') # => '2009-03-02'
|
19
|
-
Util.parsedate('02/23/2009') # => '2009-02-23'
|
20
|
-
Util.parsedate('16th June 1986') # => '1986-06-16'
|
21
|
-
|
22
|
-
Note that the parse method of the Date class behaves differently in Ruby 1.8.7 and 1.9.1.
|
23
|
-
In 1.8.7 it assumes American dates and will raise ArgumentError on "30/03/2003".
|
24
|
-
In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
25
|
-
|
26
|
-
=end
|
27
|
-
|
28
|
-
if RUBY_VERSION > '1.9'
|
29
|
-
require 'csv'
|
30
|
-
CSV = ::CSV
|
31
|
-
else
|
32
|
-
require 'fastercsv'
|
33
|
-
CSV = ::FasterCSV
|
34
|
-
end
|
35
|
-
|
4
|
+
# Parse dates into yyyy-mm-dd format, preferring European over US convention. Returns nil on error.
|
5
|
+
#
|
6
|
+
# Util.parsedate('1955-11-09') # => '1955-11-09'
|
7
|
+
# Util.parsedate('02/03/2009') # => '2009-03-02'
|
8
|
+
# Util.parsedate('02/23/2009') # => '2009-02-23'
|
9
|
+
# Util.parsedate('16th June 1986') # => '1986-06-16'
|
10
|
+
#
|
11
|
+
# Note that the parse method of the Date class behaves differently in Ruby 1.8 and 1.9.
|
12
|
+
# In 1.8 it assumes American dates and will raise ArgumentError on "30/03/2003".
|
13
|
+
# In 1.9 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
36
14
|
def self.parsedate(date)
|
37
15
|
date = date.to_s.strip
|
38
16
|
return nil unless date.match(/[1-9]/)
|
@@ -44,7 +22,10 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
44
22
|
end
|
45
23
|
end
|
46
24
|
end
|
47
|
-
|
25
|
+
|
26
|
+
#
|
27
|
+
# Miscellaneous accessor helpers.
|
28
|
+
#
|
48
29
|
module Accessor
|
49
30
|
def attr_accessor(name, &block)
|
50
31
|
attr_reader name
|
@@ -55,7 +36,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
55
36
|
end
|
56
37
|
end
|
57
38
|
end
|
58
|
-
|
39
|
+
|
59
40
|
def attr_integer(*names)
|
60
41
|
names.each do |name|
|
61
42
|
attr_accessor(name) do |val|
|
@@ -65,7 +46,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
65
46
|
end
|
66
47
|
end
|
67
48
|
end
|
68
|
-
|
49
|
+
|
69
50
|
def attr_integer_or_nil(*names)
|
70
51
|
names.each do |name|
|
71
52
|
attr_accessor(name) do |val|
|
@@ -80,7 +61,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
80
61
|
end
|
81
62
|
end
|
82
63
|
end
|
83
|
-
|
64
|
+
|
84
65
|
def attr_positive(*names)
|
85
66
|
names.each do |name|
|
86
67
|
attr_accessor(name) do |val|
|
@@ -90,7 +71,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
90
71
|
end
|
91
72
|
end
|
92
73
|
end
|
93
|
-
|
74
|
+
|
94
75
|
def attr_positive_or_nil(*names)
|
95
76
|
names.each do |name|
|
96
77
|
attr_accessor(name) do |val|
|
@@ -105,7 +86,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
105
86
|
end
|
106
87
|
end
|
107
88
|
end
|
108
|
-
|
89
|
+
|
109
90
|
def attr_date(*names)
|
110
91
|
names.each do |name|
|
111
92
|
attr_accessor(name) do |val|
|
@@ -116,7 +97,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
116
97
|
end
|
117
98
|
end
|
118
99
|
end
|
119
|
-
|
100
|
+
|
120
101
|
def attr_date_or_nil(*names)
|
121
102
|
names.each do |name|
|
122
103
|
attr_accessor(name) do |val|
|
@@ -131,7 +112,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
131
112
|
end
|
132
113
|
end
|
133
114
|
end
|
134
|
-
|
115
|
+
|
135
116
|
def attr_string(regex, *names)
|
136
117
|
names.each do |name|
|
137
118
|
attr_accessor(name) do |val|
|
@@ -141,7 +122,7 @@ In 1.9.1 it assumes European dates and will raise ArgumentError on "03/30/2003".
|
|
141
122
|
end
|
142
123
|
end
|
143
124
|
end
|
144
|
-
|
125
|
+
|
145
126
|
def attr_string_or_nil(regex, *names)
|
146
127
|
names.each do |name|
|
147
128
|
attr_accessor(name) do |val|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
- 1
|
8
7
|
- 2
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 1.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mark Orr
|
@@ -18,7 +18,7 @@ date: 2010-12-31 00:00:00 +00:00
|
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: inifile
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
@@ -26,14 +26,14 @@ dependencies:
|
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
|
-
- 1
|
30
|
-
- 4
|
31
29
|
- 0
|
32
|
-
|
30
|
+
- 3
|
31
|
+
- 0
|
32
|
+
version: 0.3.0
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: dbf
|
37
37
|
prerelease: false
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
@@ -41,14 +41,14 @@ dependencies:
|
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
segments:
|
44
|
-
-
|
45
|
-
-
|
46
|
-
-
|
47
|
-
version:
|
44
|
+
- 1
|
45
|
+
- 2
|
46
|
+
- 5
|
47
|
+
version: 1.2.5
|
48
48
|
type: :runtime
|
49
49
|
version_requirements: *id002
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
|
-
name:
|
51
|
+
name: rubyzip
|
52
52
|
prerelease: false
|
53
53
|
requirement: &id003 !ruby/object:Gem::Requirement
|
54
54
|
none: false
|
@@ -56,14 +56,14 @@ dependencies:
|
|
56
56
|
- - ">="
|
57
57
|
- !ruby/object:Gem::Version
|
58
58
|
segments:
|
59
|
-
-
|
60
|
-
-
|
61
|
-
-
|
62
|
-
version:
|
59
|
+
- 0
|
60
|
+
- 9
|
61
|
+
- 4
|
62
|
+
version: 0.9.4
|
63
63
|
type: :runtime
|
64
64
|
version_requirements: *id003
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
|
-
name:
|
66
|
+
name: icu_name
|
67
67
|
prerelease: false
|
68
68
|
requirement: &id004 !ruby/object:Gem::Requirement
|
69
69
|
none: false
|
@@ -72,9 +72,9 @@ dependencies:
|
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
segments:
|
74
74
|
- 0
|
75
|
-
-
|
76
|
-
-
|
77
|
-
version: 0.
|
75
|
+
- 0
|
76
|
+
- 2
|
77
|
+
version: 0.0.2
|
78
78
|
type: :runtime
|
79
79
|
version_requirements: *id004
|
80
80
|
- !ruby/object:Gem::Dependency
|
@@ -87,9 +87,9 @@ dependencies:
|
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
segments:
|
89
89
|
- 2
|
90
|
+
- 3
|
90
91
|
- 0
|
91
|
-
|
92
|
-
version: 2.0.0
|
92
|
+
version: 2.3.0
|
93
93
|
type: :development
|
94
94
|
version_requirements: *id005
|
95
95
|
description: Convert files of chess tournament data in different formats to ruby classes and vice-versa.
|
@@ -103,7 +103,6 @@ extra_rdoc_files:
|
|
103
103
|
- README.rdoc
|
104
104
|
files:
|
105
105
|
- lib/icu_tournament/federation.rb
|
106
|
-
- lib/icu_tournament/name.rb
|
107
106
|
- lib/icu_tournament/player.rb
|
108
107
|
- lib/icu_tournament/result.rb
|
109
108
|
- lib/icu_tournament/team.rb
|
@@ -115,7 +114,6 @@ files:
|
|
115
114
|
- lib/icu_tournament/version.rb
|
116
115
|
- lib/icu_tournament.rb
|
117
116
|
- spec/federation_spec.rb
|
118
|
-
- spec/name_spec.rb
|
119
117
|
- spec/player_spec.rb
|
120
118
|
- spec/result_spec.rb
|
121
119
|
- spec/spec_helper.rb
|
@@ -154,14 +152,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
152
|
version: "0"
|
155
153
|
requirements: []
|
156
154
|
|
157
|
-
rubyforge_project:
|
155
|
+
rubyforge_project: icu_tournament
|
158
156
|
rubygems_version: 1.3.7
|
159
157
|
signing_key:
|
160
158
|
specification_version: 3
|
161
159
|
summary: For reading and writing files of chess tournament data.
|
162
160
|
test_files:
|
163
161
|
- spec/federation_spec.rb
|
164
|
-
- spec/name_spec.rb
|
165
162
|
- spec/player_spec.rb
|
166
163
|
- spec/result_spec.rb
|
167
164
|
- spec/spec_helper.rb
|