Commit b36bc6f78e2877a3b90eb27a32d2d711a4755268
1 parent
b6cb8ac5
Exists in
master
and in
1 other branch
add median_responses_per_session API call
Showing
6 changed files
with
62 additions
and
0 deletions
Show diff stats
CHANGELOG.md
app/controllers/questions_controller.rb
@@ -91,6 +91,13 @@ class QuestionsController < InheritedResources::Base | @@ -91,6 +91,13 @@ class QuestionsController < InheritedResources::Base | ||
91 | end | 91 | end |
92 | end | 92 | end |
93 | 93 | ||
94 | + def median_responses_per_session | ||
95 | + @question = current_user.questions.find(params[:id]) | ||
96 | + respond_to do |format| | ||
97 | + format.xml{ render :xml => {:median => @question.median_responses_per_session}.to_xml and return} | ||
98 | + end | ||
99 | + end | ||
100 | + | ||
94 | def object_info_by_visitor_id | 101 | def object_info_by_visitor_id |
95 | 102 | ||
96 | object_type = params[:object_type] | 103 | object_type = params[:object_type] |
app/models/question.rb
@@ -672,6 +672,17 @@ class Question < ActiveRecord::Base | @@ -672,6 +672,17 @@ class Question < ActiveRecord::Base | ||
672 | last_appearance | 672 | last_appearance |
673 | end | 673 | end |
674 | 674 | ||
675 | + # a response is either a vote or a skip, get the median per session | ||
676 | + def median_responses_per_session | ||
677 | + median(Question.connection.select_values(" | ||
678 | + SELECT COUNT(*) total FROM ( | ||
679 | + (SELECT voter_id vid FROM votes WHERE question_id = #{id}) | ||
680 | + UNION ALL | ||
681 | + (SELECT skipper_id vid FROM skips WHERE question_id = #{id}) | ||
682 | + ) b GROUP BY b.vid ORDER BY total | ||
683 | + "), true) || 0 | ||
684 | + end | ||
685 | + | ||
675 | def upload_to_participation_ratio | 686 | def upload_to_participation_ratio |
676 | swp = sessions_with_participation | 687 | swp = sessions_with_participation |
677 | return 0.to_f if swp == 0 | 688 | return 0.to_f if swp == 0 |
config/routes.rb
@@ -8,6 +8,7 @@ ActionController::Routing::Routes.draw do |map| | @@ -8,6 +8,7 @@ ActionController::Routing::Routes.draw do |map| | ||
8 | :object_info_by_visitor_id => :get, | 8 | :object_info_by_visitor_id => :get, |
9 | :median_votes_per_session => :get, | 9 | :median_votes_per_session => :get, |
10 | :vote_rate => :get, | 10 | :vote_rate => :get, |
11 | + :median_responses_per_session => :get, | ||
11 | :upload_to_participation_ratio => :get, | 12 | :upload_to_participation_ratio => :get, |
12 | :export => :post} , | 13 | :export => :post} , |
13 | :collection => {:all_num_votes_by_visitor_id => :get, | 14 | :collection => {:all_num_votes_by_visitor_id => :get, |
spec/integration/questions_spec.rb
@@ -252,6 +252,19 @@ describe "Questions" do | @@ -252,6 +252,19 @@ describe "Questions" do | ||
252 | describe "GET 'object_info_totals_by_date'" do | 252 | describe "GET 'object_info_totals_by_date'" do |
253 | end | 253 | end |
254 | 254 | ||
255 | + describe "GET 'median_responses_per_session'" do | ||
256 | + before(:all) { truncate_all } | ||
257 | + it "should return the median responses per session" do | ||
258 | + q = Factory.create(:aoi_question, :site => @api_user) | ||
259 | + Factory.create(:vote_new_user, :question => q) | ||
260 | + v = Factory.create(:vote_new_user, :question => q) | ||
261 | + Factory.create(:vote, :question => q, :voter => v.voter) | ||
262 | + get_auth median_responses_per_session_question_path(q, :format => 'xml') | ||
263 | + response.should be_success | ||
264 | + response.body.should have_tag("median", :text => "1.5") | ||
265 | + end | ||
266 | + end | ||
267 | + | ||
255 | describe "GET 'upload_to_participation_ratio'" do | 268 | describe "GET 'upload_to_participation_ratio'" do |
256 | before(:all) { truncate_all } | 269 | before(:all) { truncate_all } |
257 | it "should return the proper upload:participation ratio" do | 270 | it "should return the proper upload:participation ratio" do |
spec/models/question_spec.rb
@@ -255,6 +255,35 @@ describe Question do | @@ -255,6 +255,35 @@ describe Question do | ||
255 | @q = Factory.create(:aoi_question) | 255 | @q = Factory.create(:aoi_question) |
256 | end | 256 | end |
257 | 257 | ||
258 | + it "should properly calculate median_responses_per_session with no responses" do | ||
259 | + @q.median_responses_per_session.should == 0 | ||
260 | + end | ||
261 | + | ||
262 | + it "should properly calculate median_responses_per_session with 2 sessions" do | ||
263 | + # one session with 1 vote, one with 2 votes | ||
264 | + Factory.create(:vote_new_user, :question => @q) | ||
265 | + v = Factory.create(:vote_new_user, :question => @q) | ||
266 | + Factory.create(:vote, :question => @q, :voter => v.voter) | ||
267 | + @q.median_responses_per_session.should == 1.5 | ||
268 | + end | ||
269 | + | ||
270 | + it "should properly calculate median_responses_per_session with 3 sessions" do | ||
271 | + # one session with 3 skips, 2 votes | ||
272 | + v = Factory.create(:vote_new_user, :question => @q) | ||
273 | + 3.times { Factory.create(:skip, :question => @q, :skipper => v.voter) } | ||
274 | + Factory.create(:vote, :question => @q, :voter => v.voter) | ||
275 | + | ||
276 | + # second session with 3 skips | ||
277 | + v = Factory.create(:skip_new_user, :question => @q) | ||
278 | + 2.times { Factory.create(:skip, :question => @q, :skipper => v.skipper) } | ||
279 | + | ||
280 | + # third session with 4 votes, 5 skips | ||
281 | + v = Factory.create(:vote_new_user, :question => @q) | ||
282 | + 3.times { Factory.create(:skip, :question => @q, :skipper => v.voter) } | ||
283 | + 4.times { Factory.create(:vote, :question => @q, :voter => v.voter) } | ||
284 | + @q.median_responses_per_session.should == 5 | ||
285 | + end | ||
286 | + | ||
258 | it "should give proper stats required for idea:participation ratio" do | 287 | it "should give proper stats required for idea:participation ratio" do |
259 | @q.sessions_with_uploaded_ideas.should == 0 | 288 | @q.sessions_with_uploaded_ideas.should == 0 |
260 | @q.sessions_with_participation.should == 0 | 289 | @q.sessions_with_participation.should == 0 |