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
@@ -1,132 +1,126 @@
|
|
1
1
|
module ICU
|
2
2
|
class Tournament
|
3
|
-
|
4
|
-
=
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
of the parser
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
* the
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
t.add_result(ICU::Result.new(8, 1, 'L', :opponent => 8, :colour => 'B'))
|
125
|
-
t.add_result(ICU::Result.new(9, 1, 'D', :opponent => 9, :colour => 'W'))
|
126
|
-
puts t.serialize('ForeignCSV')
|
127
|
-
|
128
|
-
=end
|
129
|
-
|
3
|
+
#
|
4
|
+
# This is a format ({specification}[http://www.icu.ie/articles/display.php?id=172]) used by the ICU[http://icu.ie]
|
5
|
+
# for players to submit their individual results in foreign tournaments for domestic rating.
|
6
|
+
#
|
7
|
+
# Suppose, for example, that the following data is the file <em>tournament.csv</em>:
|
8
|
+
#
|
9
|
+
# Event,"Isle of Man Masters, 2007"
|
10
|
+
# Start,2007-09-22
|
11
|
+
# Rounds,9
|
12
|
+
# Website,http://www.bcmchess.co.uk/monarch2007/
|
13
|
+
#
|
14
|
+
# Player,456,Fox,Anthony
|
15
|
+
# 1,0,B,Taylor,Peter P.,2209,,ENG
|
16
|
+
# 2,=,W,Nadav,Egozi,2205,,ISR
|
17
|
+
# 3,=,B,Cafolla,Peter,2048,,IRL
|
18
|
+
# 4,1,W,Spanton,Tim R.,1982,,ENG
|
19
|
+
# 5,1,B,Grant,Alan,2223,,SCO
|
20
|
+
# 6,0,-
|
21
|
+
# 7,=,W,Walton,Alan J.,2223,,ENG
|
22
|
+
# 8,0,B,Bannink,Bernard,2271,FM,NED
|
23
|
+
# 9,=,W,Phillips,Roy,2271,,MAU
|
24
|
+
# Total,4
|
25
|
+
#
|
26
|
+
# This file can be parsed as follows.
|
27
|
+
#
|
28
|
+
# parser = ICU::Tournament::ForeignCSV.new
|
29
|
+
# tournament = parser.parse_file('tournament.csv')
|
30
|
+
#
|
31
|
+
# If the file is correctly specified, the return value from the <em>parse_file</em> method is an instance of
|
32
|
+
# ICU::Tournament (rather than <em>nil</em>, which indicates an error). In this example the file is valid, so:
|
33
|
+
#
|
34
|
+
# tournament.name # => "Isle of Man Masters, 2007"
|
35
|
+
# tournament.start # => "2007-09-22"
|
36
|
+
# tournament.rounds # => 9
|
37
|
+
# tournament.website # => "http://www.bcmchess.co.uk/monarch2007/"
|
38
|
+
#
|
39
|
+
# The main player (the player whose results are being reported for rating) played 9 rounds
|
40
|
+
# but only 8 other players (he had a bye in round 6), so the total number of players is 9.
|
41
|
+
#
|
42
|
+
# tournament.players.size # => 9
|
43
|
+
#
|
44
|
+
# Each player has a unique number for the tournament. The main player always occurs first in this type of file, so his number is 1.
|
45
|
+
#
|
46
|
+
# player = tournament.player(1)
|
47
|
+
# player.name # => "Fox, Anthony"
|
48
|
+
#
|
49
|
+
# This player has 4 points from 9 rounds but only 8 of his results are are rateable (because of the bye).
|
50
|
+
#
|
51
|
+
# player.points # => 4.0
|
52
|
+
# player.results.size # => 9
|
53
|
+
# player.results.find_all{ |r| r.rateable }.size # => 8
|
54
|
+
#
|
55
|
+
# The other players all have numbers greater than 1.
|
56
|
+
#
|
57
|
+
# opponents = tournamnet.players.reject { |o| o.num == 1 }
|
58
|
+
#
|
59
|
+
# There are 8 opponents (of the main player) each with exactly one game.
|
60
|
+
#
|
61
|
+
# opponents.size # => 8
|
62
|
+
# opponents.find_all{ |o| o.results.size == 1 }.size # => 8
|
63
|
+
#
|
64
|
+
# However, none of the opponents' results are rateable because they are foreign to the domestic rating list
|
65
|
+
# to which the main player belongs. For example:
|
66
|
+
#
|
67
|
+
# opponent = tournament.players(2)
|
68
|
+
# opponent.name # => "Taylor, Peter P."
|
69
|
+
# opponent.results[0].rateable # => false
|
70
|
+
#
|
71
|
+
# If the file contains errors, then the return value from <em>parse_file</em> is <em>nil</em> and
|
72
|
+
# an error message is returned by the <em>error</em> method of the parser object. The method
|
73
|
+
# <em>parse_file!</em> is similar except that it raises errors, and the methods <em>parse</em>
|
74
|
+
# and <em>parse!</em> are similar except their inputs are strings rather than file names.
|
75
|
+
#
|
76
|
+
# A tournament can be serialized back to CSV format (the reverse of parsing) with the _serialize_ method
|
77
|
+
# of the parser object.
|
78
|
+
#
|
79
|
+
# csv = parser.serialize(tournament)
|
80
|
+
#
|
81
|
+
# Or equivalently, the _serialize_ instance method of the tournament, if the appropriate parser name is supplied.
|
82
|
+
#
|
83
|
+
# csv = tournament.serialize('ForeignCSV')
|
84
|
+
#
|
85
|
+
# Extra condtions, over and above the normal validation rules, apply before any tournament validates or can be serialized in this format.
|
86
|
+
#
|
87
|
+
# * the tournament must have a _site_ attribute
|
88
|
+
# * there must be at least one player with an _id_ (interpreted as an ICU ID number)
|
89
|
+
# * all foreign players (those without an ICU ID) must have a _fed_ attribute (federation)
|
90
|
+
# * all ICU players must have a result in every round (even if it is just bye or is unrateable)
|
91
|
+
# * the opponents of all ICU players must have a federation (this could include other ICU players)
|
92
|
+
#
|
93
|
+
# If any of these are not satisfied, then the following method calls will all raise an exception:
|
94
|
+
#
|
95
|
+
# tournament.validate!(:type => 'ForeignCSV')
|
96
|
+
# tournament.serialize('ForeignCSV')
|
97
|
+
# ICU::Tournament::ForeignCSV.new.serialize(tournament)
|
98
|
+
#
|
99
|
+
# You can also build the tournament object from scratch using your own data and then serialize it.
|
100
|
+
# For example, here are the commands to reproduce the example above.
|
101
|
+
#
|
102
|
+
# t = ICU::Tournament.new("Isle of Man Masters, 2007", '2007-09-22', :rounds => 9)
|
103
|
+
# t.site = 'http://www.bcmchess.co.uk/monarch2007/'
|
104
|
+
# t.add_player(ICU::Player.new('Anthony', 'Fox', 1, :rating => 2100, :fed => 'IRL', :id => 456))
|
105
|
+
# t.add_player(ICU::Player.new('Peter P.', 'Taylor', 2, :rating => 2209, :fed => 'ENG'))
|
106
|
+
# t.add_player(ICU::Player.new('Egozi', 'Nadav', 3, :rating => 2205, :fed => 'ISR'))
|
107
|
+
# t.add_player(ICU::Player.new('Peter', 'Cafolla', 4, :rating => 2048, :fed => 'IRL'))
|
108
|
+
# t.add_player(ICU::Player.new('Tim R.', 'Spanton', 5, :rating => 1982, :fed => 'ENG'))
|
109
|
+
# t.add_player(ICU::Player.new('Alan', 'Grant', 6, :rating => 2223, :fed => 'SCO'))
|
110
|
+
# t.add_player(ICU::Player.new('Alan J.', 'Walton', 7, :rating => 2223, :fed => 'ENG'))
|
111
|
+
# t.add_player(ICU::Player.new('Bernard', 'Bannink', 8, :rating => 2271, :fed => 'NED', :title => 'FM'))
|
112
|
+
# t.add_player(ICU::Player.new('Roy', 'Phillips', 9, :rating => 2271, :fed => 'MAU'))
|
113
|
+
# t.add_result(ICU::Result.new(1, 1, 'L', :opponent => 2, :colour => 'B'))
|
114
|
+
# t.add_result(ICU::Result.new(2, 1, 'D', :opponent => 3, :colour => 'W'))
|
115
|
+
# t.add_result(ICU::Result.new(3, 1, 'D', :opponent => 4, :colour => 'B'))
|
116
|
+
# t.add_result(ICU::Result.new(4, 1, 'W', :opponent => 5, :colour => 'W'))
|
117
|
+
# t.add_result(ICU::Result.new(5, 1, 'W', :opponent => 6, :colour => 'B'))
|
118
|
+
# t.add_result(ICU::Result.new(6, 1, 'L'))
|
119
|
+
# t.add_result(ICU::Result.new(7, 1, 'D', :opponent => 7, :colour => 'W'))
|
120
|
+
# t.add_result(ICU::Result.new(8, 1, 'L', :opponent => 8, :colour => 'B'))
|
121
|
+
# t.add_result(ICU::Result.new(9, 1, 'D', :opponent => 9, :colour => 'W'))
|
122
|
+
# puts t.serialize('ForeignCSV')
|
123
|
+
#
|
130
124
|
class ForeignCSV
|
131
125
|
attr_reader :error
|
132
126
|
|
@@ -135,7 +129,7 @@ For example, here are the commands to reproduce the example above.
|
|
135
129
|
@state, @line, @round, @sum, @error = 0, 0, nil, nil, nil
|
136
130
|
@tournament = Tournament.new('Dummy', '2000-01-01')
|
137
131
|
|
138
|
-
|
132
|
+
CSV.parse(csv, :row_sep => :auto) do |r|
|
139
133
|
@line += 1 # increment line number
|
140
134
|
next if r.size == 0 # skip empty lines
|
141
135
|
r = r.map{|c| c.nil? ? '' : c.strip} # trim all spaces, turn nils to blanks
|
@@ -207,7 +201,7 @@ For example, here are the commands to reproduce the example above.
|
|
207
201
|
# Serialise a tournament back into CSV format.
|
208
202
|
def serialize(t, arg={})
|
209
203
|
t.validate!(:type => self)
|
210
|
-
|
204
|
+
CSV.generate do |csv|
|
211
205
|
csv << ["Event", t.name]
|
212
206
|
csv << ["Start", t.start]
|
213
207
|
csv << ["Rounds", t.rounds]
|
@@ -1,118 +1,112 @@
|
|
1
1
|
module ICU
|
2
2
|
class Tournament
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
[
|
102
|
-
[
|
103
|
-
[
|
104
|
-
[
|
105
|
-
[
|
106
|
-
[
|
107
|
-
[
|
108
|
-
[
|
109
|
-
|
110
|
-
[112 Deputy(ies)] Get or set with _deputy_. Free text.
|
111
|
-
[122 Time control] Get or set with _time_control_. Free text.
|
112
|
-
[132 Round dates] Get an array of dates using _round_dates_ or one specific round date by calling _round_date_ with a round number.
|
113
|
-
|
114
|
-
=end
|
115
|
-
|
3
|
+
#
|
4
|
+
# This is the {format}[http://www.fide.com/component/content/article/5-whats-news/2245-736-general-data-exchange-format-for-tournament-results]
|
5
|
+
# used to submit tournament results to FIDE[http://www.fide.com] for rating.
|
6
|
+
#
|
7
|
+
# Suppose, for example, that the following data is the file <em>tournament.tab</em>:
|
8
|
+
#
|
9
|
+
# 012 Fantasy Tournament
|
10
|
+
# 032 IRL
|
11
|
+
# 042 2009.09.09
|
12
|
+
# 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
|
13
|
+
# 132 09.09.09 09.09.10 09.09.11
|
14
|
+
# 001 1 w Mouse,Minerva 1900 USA 1234567 1928.05.15 1.0 2 2 b 0 3 w 1
|
15
|
+
# 001 2 m m Duck,Daffy 2200 IRL 7654321 1937.04.17 2.0 1 1 w 1 3 b 1
|
16
|
+
# 001 3 m g Mouse,Mickey 2600 USA 1726354 1928.05.15 0.0 3 1 b 0 2 w 0
|
17
|
+
#
|
18
|
+
# This file can be parsed as follows.
|
19
|
+
#
|
20
|
+
# parser = ICU::Tournament::Krause.new
|
21
|
+
# tournament = parser.parse_file('tournament.tab')
|
22
|
+
#
|
23
|
+
# If the file is correctly specified, the return value from the <em>parse_file</em> method is an instance of
|
24
|
+
# ICU::Tournament (rather than <em>nil</em>, which indicates an error). In this example the file is valid, so:
|
25
|
+
#
|
26
|
+
# tournament.name # => "Fantasy Tournament"
|
27
|
+
# tournament.start # => "2009-09-09"
|
28
|
+
# tournament.fed # => "IRL"
|
29
|
+
# tournament.players.size # => 9
|
30
|
+
#
|
31
|
+
# Some values, not explicitly set in the file, are deduced:
|
32
|
+
#
|
33
|
+
# tournament.rounds # => 3
|
34
|
+
# tournament.finish # => "2009-09-11"
|
35
|
+
#
|
36
|
+
# A player can be retrieved from the tournament via the _players_ array or by sending a valid player number to the _player_ method.
|
37
|
+
#
|
38
|
+
# minnie = tournament.player(1)
|
39
|
+
# minnie.name # => "Mouse, Minerva"
|
40
|
+
# minnie.points # => 1.0
|
41
|
+
# minnie.results.size # => 2
|
42
|
+
#
|
43
|
+
# daffy = tournament.player(2)
|
44
|
+
# daffy.title # => "IM"
|
45
|
+
# daffy.rating # => 2200
|
46
|
+
# daffy.fed # => "IRL"
|
47
|
+
# daffy.id # => 7654321
|
48
|
+
# daffy.fide # => nil
|
49
|
+
# daffy.dob # => "1937-04-17"
|
50
|
+
#
|
51
|
+
# By default, ID numbers in the input are interpreted as local IDs. If, instead, they should be interpreted as
|
52
|
+
# FIDE IDs, add the following option:
|
53
|
+
#
|
54
|
+
# tournament = parser.parse_file('tournament.tab', :fide => true)
|
55
|
+
# daffy = tournament.player(2)
|
56
|
+
# daffy.id # => nil
|
57
|
+
# daffy.fide # => 7654321
|
58
|
+
#
|
59
|
+
# If the ranking numbers are missing from the file or inconsistent (e.g. player A is ranked above player B
|
60
|
+
# but has less points than player B) they are recalculated as a side effect of the parse.
|
61
|
+
#
|
62
|
+
# daffy.rank # => 1
|
63
|
+
# minnie.rank # => 2
|
64
|
+
# mickey.rank # => 3
|
65
|
+
#
|
66
|
+
# Comments in the input file (lines that do not start with a valid data identification number) are available from the parser
|
67
|
+
# instance via its _comments_ method (returning a string). Note that these comments are reset evry time the instance is used
|
68
|
+
# to parse another file.
|
69
|
+
#
|
70
|
+
# parser.comments # => "0123456789..."
|
71
|
+
#
|
72
|
+
# If the file contains errors, then the return value from <em>parse_file</em> is <em>nil</em> and
|
73
|
+
# an error message is returned by the <em>error</em> method of the parser object. The method
|
74
|
+
# <em>parse_file!</em> is similar except that it raises errors, and the methods <em>parse</em>
|
75
|
+
# and <em>parse!</em> are similar except their inputs are strings rather than file names.
|
76
|
+
#
|
77
|
+
# A tournament can be serialized back to Krause format (the reverse of parsing) with the _serialize_ method of the parser.
|
78
|
+
#
|
79
|
+
# krause = parser.serialize(tournament)
|
80
|
+
#
|
81
|
+
# Or alternatively, by the _serialize_ method of the tournament object if the name of the serializer is supplied.
|
82
|
+
#
|
83
|
+
# krause = tournament.serialize('Krause')
|
84
|
+
#
|
85
|
+
# By default, local (ICU) IDs are used for the serialization, but both methods accept an option that
|
86
|
+
# causes FIDE IDs to be used instead:
|
87
|
+
#
|
88
|
+
# krause = parser.serialize(tournament, :fide => true)
|
89
|
+
# krause = parser.serialize(tournament, :fide => true)
|
90
|
+
#
|
91
|
+
# The following lists Krause data identification numbers, their description and, where available, their corresponding
|
92
|
+
# attributes in an ICU::Tournament instance.
|
93
|
+
#
|
94
|
+
# [001 Player record] Use _players_ to get all players or _player_ with a player number to get a single instance.
|
95
|
+
# [012 Name] Get or set with _name_. Free text. A tounament name is mandatory.
|
96
|
+
# [013 Teams] Create an ICU::Team, add player numbers to it, use _add_team_ to add to tournament, _get_team_/_teams_ to retrive it/them.
|
97
|
+
# [022 City] Get or set with _city_. Free text.
|
98
|
+
# [032 Federation] Get or set with _fed_. Getter returns either _nil_ or a three letter code. Setter can take various formats (see ICU::Federation).
|
99
|
+
# [042 Start date] Get or set with _start_. Getter returns <em>yyyy-mm-dd</em> format, but setter can use any reasonable date format. Start date is mandadory.
|
100
|
+
# [052 End date] Get or set with _finish_. Returns either <em>yyyy-mm-dd</em> format or _nil_ if not set. Like _start_, can be set with various date formats.
|
101
|
+
# [062 Number of players] Not used. Treated as comment in parsed files. Can be determined from the size of the _players_ array.
|
102
|
+
# [072 Number of rated players] Not used. Treated as comment in parsed files. Can be determined by analysing the array returned by _players_.
|
103
|
+
# [082 Number of teams] Not used. Treated as comment in parsed files.
|
104
|
+
# [092 Type of tournament] Get or set with _type_. Free text.
|
105
|
+
# [102 Arbiter(s)] Get or set with -arbiter_. Free text.
|
106
|
+
# [112 Deputy(ies)] Get or set with _deputy_. Free text.
|
107
|
+
# [122 Time control] Get or set with _time_control_. Free text.
|
108
|
+
# [132 Round dates] Get an array of dates using _round_dates_ or one specific round date by calling _round_date_ with a round number.
|
109
|
+
#
|
116
110
|
class Krause
|
117
111
|
attr_reader :error, :comments
|
118
112
|
|