skating-system 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2008 Laurie Young
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 ADDED
@@ -0,0 +1,200 @@
1
+ Skating System
2
+ --------------
3
+
4
+ Provides an implementation of the skating system used for scoring dance comeptitions, as well as a few other types of competition.
5
+
6
+ Usage
7
+ ------
8
+
9
+ First create a hash of the judges marks
10
+ @couples_marks = { @entree1=>{@judge1=>1, @judge2=>1, @judge3=>3 },
11
+ @entree2=>{@judge1=>2, @judge2=>3, @judge3=>2 },
12
+ @entree3=>{@judge1=>3, @judge2=>2, @judge3=>1 }}
13
+
14
+
15
+ Create a new PerformanceResults object, and then call its score method
16
+ @performance_resuts = SkatingSystem::PerformanceResults.new
17
+ @performance_resuts.score(@couples_marks)
18
+ Then you can access the ranking for the couples via
19
+ @performance_resuts.ranking.should be(@ranking)
20
+
21
+
22
+ The skating system is as follows:
23
+
24
+
25
+ ********* The Marking of Adjudicators' Cards
26
+ 1.
27
+ In all rounds each judge must vote for the number of couples
28
+ demanded by the Chairman of Adjudicators.
29
+
30
+ 2.
31
+ In the Final round each judge shall place all the competing
32
+ couples in order of merit in each of the dances.
33
+
34
+ 3.
35
+ In the Final round the judge shall mark his first couple 1, his
36
+ second couple 2, his third 3, and so on in each of the dances.
37
+
38
+ 4.
39
+ A judge must not tie couples for any place in the Final of any dance.
40
+
41
+ Note:
42
+
43
+ Number of Couples to Dance in a Final
44
+
45
+ 1.
46
+ In the Final round the open system of marking shall be used.
47
+
48
+ 2.
49
+ When judges are instructed to select six couples for a
50
+ Final and six couples are clearly chosen only that number
51
+ shall dance. The same procedure would be observed if the
52
+ Chairman's instructions were for any other number.
53
+
54
+ 3.
55
+ If it is intended that six couples shall dance in a Final
56
+ and through a tie more couples qualify for consideration
57
+ the number to dance shall be decided by the Chairman. The
58
+ same procedure would be observed if it is intended to have
59
+ a Final of any other number.
60
+
61
+ ********* The Allocation of Positions in Each Dance
62
+ 5.
63
+ The winner of a particular dance is the couple who is placed
64
+ first by an absolute majority of judges; second, the couple who
65
+ is placed second or higher by an absolute majority. The
66
+ remaining positions are allocated in a similar way.
67
+
68
+ If More that One Couple have a Majority for the Same Position
69
+
70
+ 6.
71
+ The couple with the largest majority shall be allocated the
72
+ position under review, and the couple with the next largest
73
+ majority, the following position.
74
+
75
+ Note:
76
+
77
+ If the position under review is the "2nd" and two couples have a
78
+ majority of "2nd and higher" places, the couple with the larger
79
+ majority shall be placed "2nd" and the other couple "3rd".
80
+
81
+ We now examine the remaining competitors' markings, and the
82
+ couple with the largest majority of "3rd and higher" places
83
+ shall be allocated the next position, which in this example, is
84
+ the "4th".
85
+
86
+ If none of the remaining couples has a majority of "3rd and
87
+ higher" places, then include the "4th" places (and, if
88
+ necessary, lower places).
89
+
90
+ ********* If Two or More Couples have an Equal Majority for the Same Position
91
+ 7.
92
+ a) If such majorities are equal, then the lowest total of marks
93
+ given by those judges who form the majority, shall determine the
94
+ allocation of the position under review.
95
+
96
+ Note:
97
+
98
+ If the position under review is the "2nd" and two couples have a
99
+ similar majority of "2nd and higher" places, the couple with the
100
+ lower total of marks given by those judges who form the
101
+ majority, shall be allocated the "2nd" position and the other
102
+ couple the "3rd".
103
+
104
+ b) If the totals of the marks are equal, then the next lower
105
+ place (or places, if necessary), in respect of the particular
106
+ couples concerned, must be included.
107
+
108
+ Note:
109
+
110
+ It should be noted that only the couples who have a majority for
111
+ the position under review (say, for example, the "2nd" position)
112
+ must be considered at this stage, and only their "3rd" places
113
+ (and, if necessary, lower places) should be referred to, until
114
+ the "2nd" position has been allocated.
115
+
116
+ A definite result will eventually be obtained unless the
117
+ remaining markings are exactly the same, and should the latter
118
+ be the case, there will, of course, be a tie for "2nd"
119
+ position. If two couples were concerned, they would be allocated
120
+ "2 1/2" each.
121
+
122
+
123
+ ********* If No Couple receives a Majority for the Position Under Review
124
+ 8.
125
+ If no couple receives a majority of "Firsts" then the winner is
126
+ the couple who are placed "2nd and higher" by a majority of
127
+ judges.
128
+
129
+ If no couple receives a majority of "1st" and "2nd" places, then
130
+ the "3rd" places (and if necessary, lower places) must be
131
+ included. (Subject to Rules 6 and 7).
132
+
133
+ The "2nd" and other places should be calculated in a similar
134
+ way.
135
+
136
+ ********* Compilation of the Final Summary
137
+ 9.
138
+ When all the dances have been concluded, the order ascertained
139
+ for each dance shall be carried to another sheet, showing the
140
+ position achieved by each couple in each dance. The first in
141
+ each dance shall be given one mark, the second two, and so
142
+ on. These place marks shall be added up and the couple with the
143
+ lowest aggregate shall be the winner.
144
+
145
+
146
+ ********* If there is a Tie for a Place in the Final Summary
147
+ 10.
148
+ a) If this results in a tie for first place, the winner shall be
149
+ the couple who has actually won the greater number of dances.
150
+
151
+ b) If there is a tie for the "2nd" place, the "2nd" prize shall
152
+ be awarded to the couple who has obtained "2nd and higher" in
153
+ the greatest number of dances. If the couples have obtained the
154
+ same number of "2nd and higher" place marks, then add the "2nd
155
+ and higher" place marks together and the couple with the lowest
156
+ total should be awarded second prize.
157
+
158
+ Note:
159
+
160
+ If more than two couples tie for second place, the second prize
161
+ shall be awarded to the couple who has obtained the most "2nd
162
+ and higher" place marks. Still only considering the remaining
163
+ "tied" couples, the "3rd" prize is awarded to the couple who has
164
+ won the most "3rd and higher" place marks.
165
+
166
+ c) If there is a tie for any remaining places they shall be
167
+ decided on similar principles.
168
+
169
+ 11.
170
+
171
+ If after applying Rules 9 and 10 this still results in a tie,
172
+ then treat the judges' marks of the "tied" couples over all
173
+ dances, as for an individual dance (Rules 5 to 8). If this still
174
+ results in a tie, there shall be at the discretion of the
175
+ organizers of the competition, either a re-dance or the prizes
176
+ for the places under review shall be divided.
177
+
178
+ a) If the tie is for first place, a majority of "1st" marks to
179
+ the credit of either of the "tied" couples (4 dances-5
180
+ judges-majority 11) would win. If neither of the "tied" couples
181
+ receive a majority of "firsts" see Rule 8.
182
+
183
+ b) If the tie is for second place, a majority of "2nd and
184
+ higher" marks to the credit of either of the "tied" couples
185
+ would be necessary. If neither of the "tied" couples obtain a
186
+ majority of "2nd and higher" marks see Rule 8.
187
+
188
+ c) The "3rd" or any other "tied" places should be decided on similar principles.
189
+
190
+ d) If 3 (or more) couples tie for a place under Rule 10 (say,
191
+ 2nd place) Rule 11 is applied to all couples concerned in the
192
+ tie, and the best couple is awarded the "2nd" place. Rule 10 is
193
+ now applied to the remaining "tied" couples for consideration of
194
+ the place now under review, which is the "3rd". However, if they
195
+ now tie for "3rd" under Rule 10, then Rule 11 is again applied
196
+ to these "tied" couples, commencing this time with the "3rd and
197
+ higher" judges's marks in the individual dances.
198
+
199
+ It is distributed under the MIT Licence, see licence.txt for the details
200
+
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = skating-system
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Wildfalcon. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "skating-system"
8
+ gem.summary = "Dancesport skating system implementation"
9
+ gem.description = %Q{Convert judges scores from a dance-competition into results}
10
+ gem.email = "laurie@wildfalcon.com"
11
+ gem.homepage = "http://github.com/wildfalcon/skating-system"
12
+ gem.authors = ["Wildfalcon"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "foobar #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,6 @@
1
+ require 'skating_system/performance_results'
2
+ require 'skating_system/ranking'
3
+ require 'skating_system/scorer'
4
+
5
+ module SkatingSystem
6
+ end
@@ -0,0 +1,114 @@
1
+ module SkatingSystem
2
+ class PerformanceResults
3
+
4
+ def score(marks)
5
+ @marks = marks
6
+ @majority = (@marks[@marks.keys.first].size/2).ceil
7
+
8
+ tally_marks
9
+
10
+ compute_results
11
+
12
+ @marks.each do |entree, marks|
13
+ @marks[entree].merge!(@tally[entree])
14
+ @marks[entree].merge!(@results[entree])
15
+ end
16
+ end
17
+
18
+ #Generate the ranking table for this performance
19
+ def ranking
20
+ return @ranking if @ranking
21
+ @ranking =SkatingSystem::Ranking.new
22
+ @marks.each do |entree, data|
23
+ @ranking.add(data[:result], entree)
24
+ end
25
+ @ranking
26
+ end
27
+
28
+ def [](key)
29
+ @marks[key]
30
+ end
31
+
32
+
33
+
34
+ private
35
+ def sum_marks(entree, position)
36
+ sum=0
37
+ @marks[entree].each do |judge, place|
38
+ sum += place if place <= position
39
+ end
40
+ sum
41
+ end
42
+
43
+ def compute_results
44
+ @results={ }
45
+ @marks.each do |entree, marks|
46
+ @results[entree] ||= { }
47
+ end
48
+
49
+ @next_result_to_compute = 1
50
+
51
+ 1.upto(@marks.size) do |place|
52
+
53
+
54
+ sorted_candidate = candidates(place).sort do |entree1, entree2|
55
+ comparator = @tally[entree2][place] <=> @tally[entree1][place]
56
+ if comparator==0
57
+ comparator = sum_marks(entree1, place) <=> sum_marks(entree2, place)
58
+ end
59
+ comparator
60
+ end
61
+
62
+ sorted_candidate.each do |entree|
63
+ @results[entree][:result]=@next_result_to_compute
64
+ @next_result_to_compute += 1
65
+ end
66
+ end
67
+ end
68
+
69
+ #Computes an array of entrees that are candidates for this position
70
+ def candidates(place)
71
+ candidates = []
72
+ @tally.each do |entree, places|
73
+ unless @results[entree][:result]
74
+ candidates << entree if places[place] > @majority
75
+ end
76
+ end
77
+ candidates
78
+ end
79
+
80
+ #Tallys the number of judges who marked each entree in each place or heigher
81
+ # and writes the results to @tally
82
+ # eg given the results
83
+ # A B C
84
+ # 1 1 1 3
85
+ # 2 2 3 2
86
+ # 3 3 2 3
87
+ # it assigns the tally
88
+ # 1 2 3
89
+ # 1 2 2 3
90
+ # 2 0 2 3
91
+ # 3 0 1 3
92
+ def tally_marks
93
+ @tally={ }
94
+ @marks.each do |entree, marks|
95
+ @tally[entree] ||= { }
96
+ 1.upto(@marks.size) do |place|
97
+ @tally[entree][place] = 0
98
+ end
99
+ end
100
+
101
+ @marks.each do |entree, marks|
102
+ marks.each do |judge, placing|
103
+ placing.upto(@marks.size) do |place|
104
+ @tally[entree][place] += 1
105
+ end
106
+ end
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+ end
113
+
114
+
@@ -0,0 +1,34 @@
1
+ module SkatingSystem
2
+ class Ranking
3
+ attr_accessor :rank_table
4
+
5
+ def initialize
6
+ @rank_table={ }
7
+ end
8
+
9
+ #Ads a new result to this ranking
10
+ def add(place, competitor)
11
+ raise "too many couples in higher placings" if places_higher_than(place) >= place
12
+
13
+ competitors = @rank_table[place] || []
14
+ competitors << competitor
15
+ @rank_table[place] = competitors
16
+ end
17
+
18
+ def place_for(competitor)
19
+ rank_table.each do |key, value|
20
+ return key if value.include?(competitor)
21
+ end
22
+ raise "Unkown competitor"
23
+ end
24
+
25
+ def places_higher_than(place)
26
+ higher_placings = 0
27
+ 1.upto(place-1) do |p|
28
+ higher_placings += @rank_table[p] ? @rank_table[p].size : 0
29
+ end
30
+ return higher_placings
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ module SkatingSystem
2
+ class Scorer
3
+ def score(scorable)
4
+ score_performance(scorable) if scorable.respond_to?(:couples_marks)
5
+ end
6
+
7
+ def score_performance(performance)
8
+ results = PerformanceResults.new
9
+ results.score(performance.couples_marks)
10
+ results
11
+ end
12
+
13
+ end
14
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,107 @@
1
+ require File.dirname(__FILE__)+'/../spec_helper'
2
+
3
+ describe SkatingSystem::PerformanceResults, "tallying the marks" do
4
+ before(:all) do
5
+ @performance_resuts = SkatingSystem::PerformanceResults.new
6
+
7
+ @judge1 = mock("Judge")
8
+ @judge2 = mock("Judge")
9
+ @judge3 = mock("Judge")
10
+
11
+ @entree1 = mock("Entree")
12
+ @entree2 = mock("Entree")
13
+ @entree3 = mock("Entree")
14
+
15
+ # A B C 1 2 3
16
+ # 1 1 1 3 2 2 3 1
17
+ # 2 2 3 2 0 2 3 2
18
+ # 3 3 2 3 0 1 3 3
19
+ @couples_marks = { @entree1=>{@judge1=>1, @judge2=>1, @judge3=>3 },
20
+ @entree2=>{@judge1=>2, @judge2=>3, @judge3=>2 },
21
+ @entree3=>{@judge1=>3, @judge2=>2, @judge3=>3 }}
22
+
23
+ @performance_resuts.score(@couples_marks)
24
+ end
25
+
26
+ it "should know how many first places entree1 got" do
27
+ @performance_resuts[@entree1][1].should be(2)
28
+ end
29
+
30
+ it "should know how many first places entree2 got" do
31
+ @performance_resuts[@entree2][1].should be(0)
32
+ end
33
+
34
+ it "should know how many first places entree3 got" do
35
+ @performance_resuts[@entree3][1].should be(0)
36
+ end
37
+
38
+ it "should know how many 2nd or better places entree1 got" do
39
+ @performance_resuts[@entree1][2].should be(2)
40
+ end
41
+
42
+ it "should know how many 2nd or better places entree2 got" do
43
+ @performance_resuts[@entree2][2].should be(2)
44
+ end
45
+
46
+ it "should know how many 2nd or better places entree3 got" do
47
+ @performance_resuts[@entree3][2].should be(1)
48
+ end
49
+
50
+ it "should know how many 3rd or better places entree1 got" do
51
+ @performance_resuts[@entree1][3].should be(3)
52
+ end
53
+
54
+ it "should know how many 3rd or better places entree2 got" do
55
+ @performance_resuts[@entree2][3].should be(3)
56
+ end
57
+
58
+ it "should know how many 3rd or better places entree3 got" do
59
+ @performance_resuts[@entree3][3].should be(3)
60
+ end
61
+ end
62
+
63
+ describe SkatingSystem::PerformanceResults, "getting the rankings" do
64
+ before(:each) do
65
+ @performance_resuts = SkatingSystem::PerformanceResults.new
66
+
67
+ @judge1 = mock("Judge")
68
+ @judge2 = mock("Judge")
69
+ @judge3 = mock("Judge")
70
+
71
+ @entree1 = mock("Entree")
72
+ @entree2 = mock("Entree")
73
+ @entree3 = mock("Entree")
74
+
75
+ # A B C 1 2 3
76
+ # 1 1 1 3 2 2 3 1
77
+ # 2 2 3 2 0 2 3 2
78
+ # 3 3 2 3 0 1 3 3
79
+ @couples_marks = { @entree1=>{@judge1=>1, @judge2=>1, @judge3=>3 },
80
+ @entree2=>{@judge1=>2, @judge2=>3, @judge3=>2 },
81
+ @entree3=>{@judge1=>3, @judge2=>2, @judge3=>3 }}
82
+
83
+ SkatingSystem::Ranking.stub!(:new).and_return(@ranking = mock(SkatingSystem::Ranking))
84
+ @ranking.stub!(:add)
85
+
86
+ @performance_resuts.score(@couples_marks)
87
+ end
88
+
89
+ it "should return a Ranking when asked for one" do
90
+ @performance_resuts.ranking.should be(@ranking)
91
+ end
92
+
93
+ it "should add couple 1 to the ranking in first place" do
94
+ @ranking.should_receive(:add).with(1, @entree1)
95
+ @performance_resuts.ranking
96
+ end
97
+
98
+ it "should add couple 2 to the ranking in second place" do
99
+ @ranking.should_receive(:add).with(2, @entree2)
100
+ @performance_resuts.ranking
101
+ end
102
+
103
+ it "should add couple 3 to the ranking in third place" do
104
+ @ranking.should_receive(:add).with(3, @entree3)
105
+ @performance_resuts.ranking
106
+ end
107
+ end
@@ -0,0 +1,61 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe SkatingSystem::Ranking do
4
+ before(:each) do
5
+ @ranking = SkatingSyatem::Ranking.new
6
+ end
7
+ end
8
+
9
+
10
+ describe SkatingSystem::Ranking, "adding new results" do
11
+
12
+ before(:each) do
13
+ @ranking = SkatingSystem::Ranking.new
14
+ end
15
+
16
+ it "should put an entry in first place when they are entered in first place" do
17
+ entree = mock("Entree")
18
+ @ranking.add(1, entree)
19
+ @ranking.place_for(entree).should be(1)
20
+ end
21
+
22
+ it "should put both entries in first place when entered in first place, even if there is already a first place" do
23
+ entree1 = mock("Entree")
24
+ entree2 = mock("Entree")
25
+ @ranking.add(1, entree1)
26
+ @ranking.add(1, entree2)
27
+ @ranking.place_for(entree1).should be(1)
28
+ @ranking.place_for(entree2).should be(1)
29
+ end
30
+
31
+ it "should put an entry in second place when entred in second place" do
32
+ entree = mock("Entree")
33
+ @ranking.add(2, entree)
34
+ @ranking.place_for(entree).should be(2)
35
+ end
36
+
37
+ it "should put both in second place when netered in second place, even if there is already a second place" do
38
+ entree1 = mock("Entree")
39
+ entree2 = mock("Entree")
40
+ @ranking.add(2, entree1)
41
+ @ranking.add(2, entree2)
42
+ @ranking.place_for(entree1).should be(2)
43
+ @ranking.place_for(entree2).should be(2)
44
+ end
45
+
46
+ it "should not allow an entry in second place if there are two first places" do
47
+ entree1 = mock("Entree")
48
+ entree2 = mock("Entree")
49
+ entree3 = mock("Entree")
50
+ @ranking.add(1, entree1)
51
+ @ranking.add(1, entree2)
52
+ lambda{ @ranking.add(2, entree3)}.should raise_error
53
+ end
54
+
55
+ it "should reise an exception if asked about an unknown entree" do
56
+ lambda{ @ranking.place_for(mock("Entree"))}.should raise_error
57
+ end
58
+
59
+
60
+
61
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+
4
+ describe "scoring a final performance" do
5
+ before(:each) do
6
+ @scorer = SkatingSystem::Scorer.new
7
+ @performance = mock("Performance")
8
+ @couples_marks = {:key=>:value }
9
+ SkatingSystem::PerformanceResults.stub!(:new).and_return(@pr=mock(SkatingSystem::PerformanceResults, :score=>nil))
10
+ @performance.stub!(:couples_marks).and_return(@couples_marks)
11
+ end
12
+
13
+ it "should check if the scorable thing respondes to :couples_marks" do
14
+ @performance.should_receive(:respond_to?).with(:couples_marks).and_return(true)
15
+ @scorer.score(@performance)
16
+ end
17
+
18
+ it "should delegate to score_performance" do
19
+ @scorer.should_receive(:score_performance).with(@performance)
20
+ @scorer.score(@performance)
21
+ end
22
+
23
+ it "should return a the new Performance" do
24
+ @scorer.score_performance(@performance).should be(@pr)
25
+ end
26
+
27
+ it "should ask the PerformanceResults to score itself" do
28
+ @pr.should_receive(:score).with(@couples_marks)
29
+ @scorer.score(@performance)
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ dir = File.dirname(__FILE__)
2
+ lib_path = File.expand_path("#{dir}/../lib")
3
+ $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
4
+
5
+ require 'rubygems'
6
+ require 'skating_system'
7
+ require 'ruby-debug'
8
+
9
+ Spec::Runner.configure do |config|
10
+
11
+ end
data/stories/all.rb ADDED
@@ -0,0 +1,5 @@
1
+ require File.join(File.dirname(__FILE__), *%w[helper])
2
+
3
+ %w[final_performance].each do |dir|
4
+ require File.join(File.dirname(__FILE__), "#{dir}/stories")
5
+ end
@@ -0,0 +1,69 @@
1
+ Story: Scrutineering a final round dance
2
+
3
+ As a scrutineer
4
+ I want to scrutineer a final round
5
+ So that I can tell who won.
6
+
7
+ Scenario: clear cut case
8
+ Given couples 101, 102, 103, 104, 105, 106
9
+ And judges A, B, C, D, E
10
+
11
+ When couple 101 gets 1, 1, 1, 1, 1
12
+ And couple 102 gets 2, 2, 2, 2, 2
13
+ And couple 103 gets 3, 3, 3, 3, 3
14
+ And couple 104 gets 4, 4, 4, 4, 4
15
+ And couple 105 gets 5, 5, 5, 5, 5
16
+ And couple 106 gets 6, 6, 6, 6, 6
17
+ And I compute the results
18
+
19
+ Then couple 101 is in place 1
20
+ And couple 102 is in place 2
21
+ And couple 103 is in place 3
22
+ And couple 104 is in place 4
23
+ And couple 105 is in place 5
24
+ And couple 106 is in place 6
25
+
26
+ Scenario: Decidable on rule 5
27
+ Given couples 101, 102, 103
28
+ And judges A, B, C
29
+
30
+ When couple 101 gets 1, 1, 1
31
+ And couple 102 gets 2, 3, 2
32
+ And couple 103 gets 3, 2, 3
33
+ And I compute the results
34
+
35
+ Then couple 101 is in place 1
36
+ And couple 102 is in place 2
37
+ And couple 103 is in place 3
38
+
39
+ Scenario: requiring rule 6
40
+ Given couples 101, 102, 103, 104, 105
41
+ And judges A, B, C, D, E
42
+
43
+ When couple 101 gets 1, 1, 1, 5, 5
44
+ And couple 102 gets 4, 2, 4, 1, 2
45
+ And couple 103 gets 2, 4, 2, 2, 1
46
+ And couple 104 gets 3, 5, 3, 4, 4
47
+ And couple 105 gets 5, 3, 5, 3, 3
48
+ And I compute the results
49
+ Then couple 101 is in place 1
50
+ And couple 102 is in place 3
51
+ And couple 103 is in place 2
52
+ And couple 104 is in place 5
53
+ And couple 105 is in place 4
54
+
55
+ Scenario: requiring rule 7
56
+ Given couples 101, 102, 103, 104, 105
57
+ And judges A, B, C, D, E
58
+
59
+ When couple 101 gets 1, 1, 1, 5, 5
60
+ And couple 102 gets 2, 4, 3, 2, 2
61
+ And couple 103 gets 4, 2, 4, 1, 1
62
+ And couple 104 gets 3, 5, 2, 4, 4
63
+ And couple 105 gets 5, 3, 5, 3, 3
64
+ And I compute the results
65
+ Then couple 101 is in place 1
66
+ And couple 102 is in place 3
67
+ And couple 103 is in place 2
68
+ And couple 104 is in place 5
69
+ And couple 105 is in place 4
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), *%w[.. helper])
2
+
3
+ with_steps_for :scrutineering_a_final_performance do
4
+ Dir["#{File.dirname(__FILE__)}/*"].each do |file|
5
+ run file if File.file?(file) && !(file =~ /\.rb$/)
6
+ end
7
+ end
data/stories/helper.rb ADDED
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift File.expand_path("#{File.dirname(__FILE__)}/../lib")
2
+ require 'rubygems'
3
+ require 'skating_system'
4
+ require 'ruby-debug'
5
+ require 'spec'
6
+ require 'spec/story'
7
+ require File.join(File.dirname(__FILE__), *%w[resources steps scrutineering_a_final_performance])
@@ -0,0 +1,43 @@
1
+ steps_for(:scrutineering_a_final_performance) do
2
+
3
+ class Judges
4
+ def initialize(letters)
5
+ @judge_letters = letters
6
+ end
7
+
8
+ def hashed_marks(marks)
9
+ h = {}
10
+ @judge_letters.each_with_index do |judge, index|
11
+ h[judge]=marks[index].to_i
12
+ end
13
+ h
14
+ end
15
+ end
16
+
17
+
18
+ Given /couples ((?:(?:\d+)(?:, )?)+)/ do |numbers|
19
+ couples = numbers.split(", ")
20
+ @couples_marks = { }
21
+ couples.each do |c|
22
+ @couples_marks[c]={}
23
+ end
24
+ end
25
+
26
+ Given /judges ((?:(?:\w)(?:, )?)+)/ do |letters|
27
+ @judges = Judges.new(letters.split(", "))
28
+ end
29
+
30
+ When /couple (\d+) gets ((?:(?:\d+)(?:, )?)+)/ do |number, marks|
31
+ @couples_marks[number]=@judges.hashed_marks(marks.split(", "))
32
+ end
33
+
34
+ When "I compute the results" do
35
+ @res=SkatingSystem::PerformanceResults.new
36
+ @res.score(@couples_marks)
37
+ end
38
+
39
+ Then "couple $couple is in place $place" do |couple, place|
40
+ @res[couple][:result].should be(place.to_i)
41
+ end
42
+
43
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skating-system
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - Wildfalcon
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-06 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 2
30
+ - 9
31
+ version: 1.2.9
32
+ type: :development
33
+ version_requirements: *id001
34
+ description: Convert judges scores from a dance-competition into results
35
+ email: laurie@wildfalcon.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - LICENSE
42
+ - README
43
+ - README.rdoc
44
+ files:
45
+ - .gitignore
46
+ - LICENSE
47
+ - README
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - lib/skating_system.rb
52
+ - lib/skating_system/performance_results.rb
53
+ - lib/skating_system/ranking.rb
54
+ - lib/skating_system/scorer.rb
55
+ - spec/spec.opts
56
+ - spec/spec/performance_results_spec.rb
57
+ - spec/spec/ranking_spec.rb
58
+ - spec/spec/scorer_spec.rb
59
+ - spec/spec_helper.rb
60
+ - stories/all.rb
61
+ - stories/final_performance/final_performance
62
+ - stories/final_performance/stories.rb
63
+ - stories/helper.rb
64
+ - stories/resources/steps/scrutineering_a_final_performance.rb
65
+ has_rdoc: true
66
+ homepage: http://github.com/wildfalcon/skating-system
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --charset=UTF-8
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ requirements: []
89
+
90
+ rubyforge_project:
91
+ rubygems_version: 1.3.6
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Dancesport skating system implementation
95
+ test_files:
96
+ - spec/spec/performance_results_spec.rb
97
+ - spec/spec/ranking_spec.rb
98
+ - spec/spec/scorer_spec.rb
99
+ - spec/spec_helper.rb