diff --git a/app/queries/comments/community_wellness_query.rb b/app/queries/comments/community_wellness_query.rb index 5b6a508c1..da2d63d96 100644 --- a/app/queries/comments/community_wellness_query.rb +++ b/app/queries/comments/community_wellness_query.rb @@ -2,8 +2,8 @@ # [ # { # "user_id"=>11, -# "serialized_weeks_ago"=>"1,16,20", -# "serialized_comment_counts"=>"2,2,1" +# "serialized_weeks_ago"=>"0,1,16,20", +# "serialized_comment_counts"=>"2,2,1,3" # }, # ... # ] @@ -33,19 +33,19 @@ module Comments SELECT user_id, COUNT(user_id) AS number_of_comments_with_positive_reaction, /* Get the number of weeks, since today for posts */ - (trunc((extract(epoch FROM (current_timestamp- created_at))) / 604800) + 1) AS weeks_ago + trunc((extract(epoch FROM (current_timestamp- created_at))) / 604800) AS weeks_ago FROM comments INNER JOIN ( SELECT DISTINCT reactable_id FROM reactions WHERE reactable_type = 'Comment' - AND created_at > (now() - interval '224' day) + AND created_at > (now() - interval '231' day) EXCEPT SELECT DISTINCT reactable_id FROM reactions WHERE reactable_type = 'Comment' - AND created_at > (now() - interval '224' day) + AND created_at > (now() - interval '231' day) AND category IN ('thumbsdown', 'vomit')) AS negative_reactions ON comments.id = negative_reactions.reactable_id INNER JOIN @@ -53,13 +53,14 @@ module Comments SELECT count(id) AS number_of_comments, user_id AS comment_counts_user_id FROM comments - WHERE created_at >= (now() - interval '7' day) + /* This interval filters week 1 (what we care about) */ + WHERE created_at >= (now() - interval '14' day) + AND created_at <= (now() - interval '7' day) GROUP BY user_id) AS comment_counts ON comments.user_id = comment_counts_user_id AND comment_counts.number_of_comments > 1 - /* Don’t select anything older than 224 days ago, or 32 weeks ago */ - WHERE created_at > (now() - interval '224' day) - AND created_at < (now() - interval '3' day) + /* Don’t select anything older than 231 days ago, or 33 weeks ago */ + WHERE created_at > (now() - interval '231' day) GROUP BY user_id, weeks_ago) AS user_comment_counts_by_week GROUP BY user_id SQL diff --git a/app/services/badges/award_community_wellness.rb b/app/services/badges/award_community_wellness.rb index 6c27f65db..fe973de15 100644 --- a/app/services/badges/award_community_wellness.rb +++ b/app/services/badges/award_community_wellness.rb @@ -13,13 +13,16 @@ module Badges # `weeks_ago` can have values like the following: # - [1,2,10,11,12] - # - [5] - # - [1,2,3,4,5,6,7,8] + # - [0,5] + # - [0,1,2,3,4,5,6,7,8] # - [1,4,17] # We only care for active streak (starting at 1) so we need to filter # these to check how far back the (continuous) streak goes week_streak = 0 weeks_ago.each_with_index do |week, index| + # Week 0 are comments that exist but aren't at least 1 week old yet + next if week.zero? + # Must have 2 or more non-flagged comments posted on that week next unless comment_counts[index] > 1 diff --git a/spec/queries/comments/community_wellness_query_spec.rb b/spec/queries/comments/community_wellness_query_spec.rb index d4be717de..8f9960fed 100644 --- a/spec/queries/comments/community_wellness_query_spec.rb +++ b/spec/queries/comments/community_wellness_query_spec.rb @@ -15,38 +15,43 @@ RSpec.describe Comments::CommunityWellnessQuery, type: :query do # don't meet the query criteria: min 2 comments in a week within last 32 weeks before do # User 3 - only one comment - create_comment_time_ago(user3.id, 5.days.ago, commentable: articles.sample) + create_comment_time_ago(user3.id, 8.days.ago, commentable: articles.sample) # User 4 - has 3 comments but doesn't meet criteria bc comments are too old - create_comment_time_ago(user4.id, 226.days.ago, commentable: articles.sample) - create_comment_time_ago(user4.id, 227.days.ago, commentable: articles.sample) - create_comment_time_ago(user4.id, 227.days.ago, commentable: articles.sample) + create_comment_time_ago(user4.id, 233.days.ago, commentable: articles.sample) + create_comment_time_ago(user4.id, 237.days.ago, commentable: articles.sample) + create_comment_time_ago(user4.id, 239.days.ago, commentable: articles.sample) end context "when multiple users match criteria" do before do - # User 1 - week 1 + # User 1 - week 0 create_comment_time_ago(user1.id, 5.days.ago, commentable: articles.sample) create_comment_time_ago(user1.id, 6.days.ago, commentable: articles.sample) - # User 1 - week 2 + # User 1 - week 1 create_comment_time_ago(user1.id, 8.days.ago, commentable: articles.sample) create_comment_time_ago(user1.id, 11.days.ago, commentable: articles.sample) - - # User 2 - week 1 - create_comment_time_ago(user2.id, 4.days.ago, commentable: articles.sample) - create_comment_time_ago(user2.id, 6.days.ago, commentable: articles.sample) # User 1 - week 2 + create_comment_time_ago(user1.id, 15.days.ago, commentable: articles.sample) + create_comment_time_ago(user1.id, 15.days.ago, commentable: articles.sample) + + # User 2 - week 0 + create_comment_time_ago(user2.id, 1.day.ago, commentable: articles.sample) + # User 2 - week 1 create_comment_time_ago(user2.id, 9.days.ago, commentable: articles.sample) create_comment_time_ago(user2.id, 13.days.ago, commentable: articles.sample) - # User 1 - week 3 - create_comment_time_ago(user2.id, 17.days.ago, commentable: articles.sample) + # User 2 - week 2 create_comment_time_ago(user2.id, 17.days.ago, commentable: articles.sample) create_comment_time_ago(user2.id, 18.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 18.days.ago, commentable: articles.sample) + # User 2 - week 3 + create_comment_time_ago(user2.id, 22.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 23.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 23.days.ago, commentable: articles.sample) - # User 5 - has 2 comments in the first week but too early to award because - # comments must be 3 days old or more to give mods time to flag before award - create_comment_time_ago(user5.id, 2.days.ago, commentable: articles.sample) - create_comment_time_ago(user5.id, 6.days.ago, commentable: articles.sample) + # User 5 - week 1 + create_comment_time_ago(user5.id, 8.days.ago, commentable: articles.sample) + create_comment_time_ago(user5.id, 10.days.ago, commentable: articles.sample) end it "returns the correct data structure (array of hashes w/ correct keys)" do @@ -69,40 +74,46 @@ RSpec.describe Comments::CommunityWellnessQuery, type: :query do expect(result_user_ids).to contain_exactly(user1.id, user2.id, user5.id) index1 = result.index { |hash| hash["user_id"] == user1.id } - expect(result[index1]["serialized_weeks_ago"]).to eq("1,2") - expect(result[index1]["serialized_comment_counts"]).to eq("2,2") + expect(result[index1]["serialized_weeks_ago"]).to eq("0,1,2") + expect(result[index1]["serialized_comment_counts"]).to eq("2,2,2") index2 = result.index { |hash| hash["user_id"] == user2.id } - expect(result[index2]["serialized_weeks_ago"]).to eq("1,2,3") - expect(result[index2]["serialized_comment_counts"]).to eq("2,2,3") + expect(result[index2]["serialized_weeks_ago"]).to eq("0,1,2,3") + expect(result[index2]["serialized_comment_counts"]).to eq("1,2,3,3") - # user5 will still appear in the query because it has 2 comments in the - # week but the count will reflect only those that are 3+ days old + # user5 will still appear in the query despite not having any comments in + # week 0, because we start counting at week 1 to award the badge index5 = result.index { |hash| hash["user_id"] == user5.id } expect(result[index5]["serialized_weeks_ago"]).to eq("1") - expect(result[index5]["serialized_comment_counts"]).to eq("1") + expect(result[index5]["serialized_comment_counts"]).to eq("2") end end context "when users match criteria but mod reaction reduces their comment counts" do before do - # User 1 - week 1 - create_comment_time_ago(user1.id, 5.days.ago, commentable: articles.sample, flagged_by: mod) + # User 1 - week 0 + create_comment_time_ago(user1.id, 5.days.ago, commentable: articles.sample) create_comment_time_ago(user1.id, 6.days.ago, commentable: articles.sample) - # User 1 - week 2 - create_comment_time_ago(user1.id, 8.days.ago, commentable: articles.sample) + # User 1 - week 1 + create_comment_time_ago(user1.id, 8.days.ago, commentable: articles.sample, flagged_by: mod) create_comment_time_ago(user1.id, 11.days.ago, commentable: articles.sample) - - # User 2 - week 1 - create_comment_time_ago(user2.id, 4.days.ago, commentable: articles.sample) - create_comment_time_ago(user2.id, 6.days.ago, commentable: articles.sample) # User 1 - week 2 + create_comment_time_ago(user1.id, 15.days.ago, commentable: articles.sample) + create_comment_time_ago(user1.id, 15.days.ago, commentable: articles.sample) + + # User 2 - week 0 + create_comment_time_ago(user2.id, 1.day.ago, commentable: articles.sample) + # User 2 - week 1 create_comment_time_ago(user2.id, 9.days.ago, commentable: articles.sample) - create_comment_time_ago(user2.id, 13.days.ago, commentable: articles.sample, flagged_by: mod) - # User 1 - week 3 - create_comment_time_ago(user2.id, 17.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 13.days.ago, commentable: articles.sample) + # User 2 - week 2 create_comment_time_ago(user2.id, 17.days.ago, commentable: articles.sample) create_comment_time_ago(user2.id, 18.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 18.days.ago, commentable: articles.sample) + # User 2 - week 3 + create_comment_time_ago(user2.id, 22.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 23.days.ago, commentable: articles.sample) + create_comment_time_ago(user2.id, 23.days.ago, commentable: articles.sample, flagged_by: mod) end it "matches the correct comment count for each week in result hash" do @@ -112,16 +123,17 @@ RSpec.describe Comments::CommunityWellnessQuery, type: :query do # Result includes both users because they have > 1 comment per week expect(result_user_ids).to contain_exactly(user1.id, user2.id) - # user1 must have `1` in first week comment count because one of their 2 - # comments is flagged by a moderator + # user1 must have `1` in first week (1) comment count because one out of + # their two comments is flagged by a moderator index1 = result.index { |hash| hash["user_id"] == user1.id } - expect(result[index1]["serialized_weeks_ago"]).to eq("1,2") - expect(result[index1]["serialized_comment_counts"]).to eq("1,2") + expect(result[index1]["serialized_weeks_ago"]).to eq("0,1,2") + expect(result[index1]["serialized_comment_counts"]).to eq("2,1,2") - # Second + # user1 must have `2` in third week (3) comment count because one out of + # their three comments is flagged by a moderator index2 = result.index { |hash| hash["user_id"] == user2.id } - expect(result[index2]["serialized_weeks_ago"]).to eq("1,2,3") - expect(result[index2]["serialized_comment_counts"]).to eq("2,1,3") + expect(result[index2]["serialized_weeks_ago"]).to eq("0,1,2,3") + expect(result[index2]["serialized_comment_counts"]).to eq("1,2,3,2") end end end diff --git a/spec/services/badges/award_community_wellness_spec.rb b/spec/services/badges/award_community_wellness_spec.rb index e7480d19a..28849bee3 100644 --- a/spec/services/badges/award_community_wellness_spec.rb +++ b/spec/services/badges/award_community_wellness_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Badges::AwardCommunityWellness, type: :service do # Create 2 comments per-week to be tested, i.e. week 8 would create 2 # comments on each of the 8 weeks (calculated on days_ago per week) reward_weeks[index].times do |week| - days_ago = (5 + (week * 7)).days.ago + days_ago = (8 + (week * 7)).days.ago create_comment_time_ago(users[index].id, days_ago, commentable: articles.sample) create_comment_time_ago(users[index].id, days_ago, commentable: articles.sample) end