skating-system 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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