diff --git a/CHANGELOG.md b/CHANGELOG.md index d5ed9f9..fa2ea9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ + * Added upload_to_participation_ratio call to API * Added vote_rate call to API ## Pairwise 3.0.0 (Feb 10, 2012) ### diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 707a963..f6105b6 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -209,9 +209,16 @@ class QuestionsController < InheritedResources::Base def vote_rate @question = current_user.questions.find(params[:id]) response = {:voterate => @question.vote_rate} - logger.info(@question.inspect) respond_to do |format| - format.xml { render :xml => response.to_xml and return} + format.xml { render :xml => response.to_xml and return} + end + end + + def upload_to_participation_ratio + @question = current_user.questions.find(params[:id]) + response = {:uploadparticipationratio => @question.upload_to_participation_ratio} + respond_to do |format| + format.xml { render :xml => response.to_xml and return} end end diff --git a/app/models/question.rb b/app/models/question.rb index 29feeb4..5e37a3f 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -672,15 +672,44 @@ class Question < ActiveRecord::Base last_appearance end + def upload_to_participation_ratio + swp = sessions_with_participation + return 0.to_f if swp == 0 + sessions_with_uploaded_ideas.to_f / swp.to_f + end + + # total number of sessions that have uploaded an idea + def sessions_with_uploaded_ideas + choices.find(:all, + :conditions => ["creator_id <> ?", creator_id], + :group => :creator_id + ).count + end + + # total sessions with at least one vote, skip, or uploaded idea + def sessions_with_participation + Question.connection.select_one(" + SELECT COUNT(*) FROM ( + (SELECT DISTINCT(skipper_id) vid FROM skips WHERE question_id = #{id}) + UNION + (SELECT DISTINCT(voter_id) vid FROM votes WHERE question_id = #{id} AND valid_record = 1) + UNION + (SELECT DISTINCT(creator_id) vid FROM choices WHERE question_id = #{id}) + ) AS t WHERE vid <> #{creator_id} + ").values.first + end + def vote_rate - return 0.to_f if total_uniq_sessions == 0 - sessions_with_vote.to_f / total_uniq_sessions.to_f + tus = total_uniq_sessions + return 0.to_f if tus == 0 + sessions_with_vote.to_f / tus.to_f end def total_uniq_sessions appearances.count(:select => "DISTINCT(voter_id)") end + # total number of sessions with at least one vote def sessions_with_vote Question.connection.select_one(" SELECT COUNT(DISTINCT(appearances.voter_id)) from appearances LEFT JOIN votes ON (votes.voter_id = appearances.voter_id) WHERE votes.id IS NOT NULL AND appearances.question_id = #{self.id} diff --git a/config/routes.rb b/config/routes.rb index c4d88b0..84a9a74 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,7 @@ ActionController::Routing::Routes.draw do |map| :object_info_by_visitor_id => :get, :median_votes_per_session => :get, :vote_rate => :get, + :upload_to_participation_ratio => :get, :export => :post} , :collection => {:all_num_votes_by_visitor_id => :get, :all_object_info_totals_by_date => :get, diff --git a/spec/factories.rb b/spec/factories.rb index 9604dd7..76b334a 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -61,6 +61,10 @@ Factory.define(:choice) do |f| f.creator {|c| c.association(:visitor, :site => c.question.site)} end +Factory.define(:choice_new_user, :parent => :choice) do |f| + f.creator {|c| Factory.build(:visitor, :site => c.question.site)} +end + Factory.define(:vote) do |f| f.association :question, :factory => :aoi_question f.prompt {|v| v.question.prompts.first} @@ -80,6 +84,9 @@ Factory.define(:skip) do |f| f.prompt {|s| s.question.prompts.first} f.skipper {|s| s.question.creator} end +Factory.define(:skip_new_user, :parent => :skip) do |f| + f.skipper {|a| Factory.build(:visitor, :site => a.question.site)} +end Factory.define(:appearance) do |f| f.association :question, :factory => :aoi_question diff --git a/spec/integration/questions_spec.rb b/spec/integration/questions_spec.rb index 305f203..a02cb1a 100644 --- a/spec/integration/questions_spec.rb +++ b/spec/integration/questions_spec.rb @@ -252,6 +252,38 @@ describe "Questions" do describe "GET 'object_info_totals_by_date'" do end + describe "GET 'upload_to_participation_ratio'" do + before(:all) { truncate_all } + it "should return the proper upload:participation ratio" do + q = Factory.create(:aoi_question, :site => @api_user) + get_auth upload_to_participation_ratio_question_path(q, :format => 'xml') + response.should be_success + response.body.should have_tag("uploadparticipationratio", :text => "0.0") + + # 10 voting only sessions + 10.times { Factory.create(:vote_new_user, :question => q) } + # 7 users who voted and added ideas + 7.times do + v = Factory.create(:vote_new_user, :question => q) + Factory.create(:choice, :creator => v.voter, :question => q) + end + # 2 users who only skip + 2.times { Factory.create(:skip_new_user, :question => q) } + # 3 users who did everything + 3.times do + v = Factory.create(:vote_new_user, :question => q) + Factory.create(:choice, :creator => v.voter, :question => q) + Factory.create(:skip, :skipper => v.voter, :question => q) + end + # 5 users who only added ideas + 5.times { Factory.create(:choice_new_user, :question => q) } + + get_auth upload_to_participation_ratio_question_path(q, :format => 'xml') + response.should be_success + response.body.should have_tag("uploadparticipationratio", :text => "0.555555555555556") + end + end + describe "GET 'vote_rate'" do before(:all) { truncate_all } it "should return the proper vote rate one vote" do diff --git a/spec/models/question_spec.rb b/spec/models/question_spec.rb index ed75649..283f73d 100644 --- a/spec/models/question_spec.rb +++ b/spec/models/question_spec.rb @@ -249,6 +249,57 @@ describe Question do (endTime - start).should < 20 end + context "ratio of uploaded ideas to participation" do + before(:all) do + truncate_all + @q = Factory.create(:aoi_question) + end + + it "should give proper stats required for idea:participation ratio" do + @q.sessions_with_uploaded_ideas.should == 0 + @q.sessions_with_participation.should == 0 + @q.upload_to_participation_ratio.should == 0.0 + + # 10 voting only sessions + 10.times { Factory.create(:vote_new_user, :question => @q) } + @q.sessions_with_uploaded_ideas.should == 0 + @q.sessions_with_participation.should == 10 + @q.upload_to_participation_ratio.should == 0.0 + + # 7 users who voted and added ideas + 7.times do + v = Factory.create(:vote_new_user, :question => @q) + Factory.create(:choice, :creator => v.voter, :question => @q) + end + @q.sessions_with_uploaded_ideas.should == 7 + @q.sessions_with_participation.should == 17 + @q.upload_to_participation_ratio.round(3).should == 0.412 + + # 2 users who only skip + 2.times { Factory.create(:skip_new_user, :question => @q) } + @q.sessions_with_uploaded_ideas.should == 7 + @q.sessions_with_participation.should == 19 + @q.upload_to_participation_ratio.round(3).should == 0.368 + + # 3 users who did everything + 3.times do + v = Factory.create(:vote_new_user, :question => @q) + Factory.create(:choice, :creator => v.voter, :question => @q) + Factory.create(:skip, :skipper => v.voter, :question => @q) + end + @q.sessions_with_uploaded_ideas.should == 10 + @q.sessions_with_participation.should == 22 + @q.upload_to_participation_ratio.round(3).should == 0.455 + + # 5 users who only added ideas + 5.times { Factory.create(:choice_new_user, :question => @q) } + @q.sessions_with_uploaded_ideas.should == 15 + @q.sessions_with_participation.should == 27 + @q.upload_to_participation_ratio.round(3).should == 0.556 + + end + end + context "vote rate" do before(:all) do truncate_all -- libgit2 0.21.2