diff --git a/app/jobs/scheduled/leader_promotions.rb b/app/jobs/scheduled/leader_promotions.rb index 12697f28f6e..2c47c612d06 100644 --- a/app/jobs/scheduled/leader_promotions.rb +++ b/app/jobs/scheduled/leader_promotions.rb @@ -14,7 +14,7 @@ module Jobs .where(new_value: TrustLevel.levels[:leader].to_s) .exists? - unless Promotion.leader_met?(u) + if Promotion.leader_lost?(u) demoted_user_ids << u.id Promotion.new(u).change_trust_level!(:regular) end diff --git a/app/models/leader_requirements.rb b/app/models/leader_requirements.rb index 7ae44857654..c5761cc6875 100644 --- a/app/models/leader_requirements.rb +++ b/app/models/leader_requirements.rb @@ -6,6 +6,8 @@ class LeaderRequirements TIME_PERIOD = 100 # days + LOW_WATER_MARK = 0.9 + attr_accessor :days_visited, :min_days_visited, :num_topics_replied_to, :min_topics_replied_to, :topics_viewed, :min_topics_viewed, @@ -24,9 +26,20 @@ class LeaderRequirements topics_viewed >= min_topics_viewed && posts_read >= min_posts_read && num_flagged_posts <= max_flagged_posts && + num_flagged_by_users <= max_flagged_by_users && topics_viewed_all_time >= min_topics_viewed_all_time && - posts_read_all_time >= min_posts_read_all_time && - num_flagged_by_users <= max_flagged_by_users + posts_read_all_time >= min_posts_read_all_time + end + + def requirements_lost? + days_visited < min_days_visited * LOW_WATER_MARK || + num_topics_replied_to < min_topics_replied_to * LOW_WATER_MARK || + topics_viewed < min_topics_viewed * LOW_WATER_MARK || + posts_read < min_posts_read * LOW_WATER_MARK || + num_flagged_posts > max_flagged_posts || + num_flagged_by_users > max_flagged_by_users || + topics_viewed_all_time < min_topics_viewed_all_time || + posts_read_all_time < min_posts_read_all_time end def days_visited @@ -34,7 +47,7 @@ class LeaderRequirements end def min_days_visited - (TIME_PERIOD * (SiteSetting.leader_requires_days_visited.to_f / 100.0)).to_i + SiteSetting.leader_requires_days_visited end def num_topics_replied_to diff --git a/lib/promotion.rb b/lib/promotion.rb index a26a772a1d7..88f1c267181 100644 --- a/lib/promotion.rb +++ b/lib/promotion.rb @@ -104,4 +104,8 @@ class Promotion LeaderRequirements.new(user).requirements_met? end + def self.leader_lost?(user) + LeaderRequirements.new(user).requirements_lost? + end + end diff --git a/spec/jobs/leader_promotions_spec.rb b/spec/jobs/leader_promotions_spec.rb index 9fa1aabd90f..3a5d6545890 100644 --- a/spec/jobs/leader_promotions_spec.rb +++ b/spec/jobs/leader_promotions_spec.rb @@ -38,6 +38,7 @@ describe Jobs::LeaderPromotions do end LeaderRequirements.any_instance.stubs(:requirements_met?).returns(false) + LeaderRequirements.any_instance.stubs(:requirements_lost?).returns(true) run_job user.reload.trust_level.should == TrustLevel.levels[:regular] end @@ -49,8 +50,22 @@ describe Jobs::LeaderPromotions do end LeaderRequirements.any_instance.stubs(:requirements_met?).returns(false) + LeaderRequirements.any_instance.stubs(:requirements_lost?).returns(true) run_job user.reload.trust_level.should == TrustLevel.levels[:leader] end + + it "doesn't demote if user hasn't lost requirements (low water mark)" do + user = nil + Timecop.freeze(4.days.ago) do + user = create_leader_user + end + + LeaderRequirements.any_instance.stubs(:requirements_met?).returns(false) + LeaderRequirements.any_instance.stubs(:requirements_lost?).returns(false) + run_job + user.reload.trust_level.should == TrustLevel.levels[:leader] + end + end end diff --git a/spec/models/leader_requirements_spec.rb b/spec/models/leader_requirements_spec.rb index a726a29c89b..432f4c78226 100644 --- a/spec/models/leader_requirements_spec.rb +++ b/spec/models/leader_requirements_spec.rb @@ -144,4 +144,65 @@ describe LeaderRequirements do end end + describe "requirements" do + + before do + leader_requirements.stubs(:min_days_visited).returns(50) + leader_requirements.stubs(:min_topics_replied_to).returns(10) + leader_requirements.stubs(:min_topics_viewed).returns(25) + leader_requirements.stubs(:min_posts_read).returns(25) + leader_requirements.stubs(:min_topics_viewed_all_time).returns(200) + leader_requirements.stubs(:min_posts_read_all_time).returns(500) + leader_requirements.stubs(:max_flagged_posts).returns(5) + leader_requirements.stubs(:max_flagged_by_users).returns(5) + + leader_requirements.stubs(:days_visited).returns(50) + leader_requirements.stubs(:num_topics_replied_to).returns(10) + leader_requirements.stubs(:topics_viewed).returns(25) + leader_requirements.stubs(:posts_read).returns(25) + leader_requirements.stubs(:topics_viewed_all_time).returns(200) + leader_requirements.stubs(:posts_read_all_time).returns(500) + leader_requirements.stubs(:num_flagged_posts).returns(0) + leader_requirements.stubs(:num_flagged_by_users).returns(0) + end + + it "are met when all requirements are met" do + leader_requirements.requirements_met?.should == true + end + + it "are not met if too few days visited" do + leader_requirements.stubs(:days_visited).returns(49) + leader_requirements.requirements_met?.should == false + end + + it "are not lost if requirements are close" do + leader_requirements.stubs(:days_visited).returns(45) + leader_requirements.stubs(:num_topics_replied_to).returns(9) + leader_requirements.stubs(:topics_viewed).returns(23) + leader_requirements.stubs(:posts_read).returns(23) + leader_requirements.requirements_lost?.should == false + end + + it "are lost if not enough visited" do + leader_requirements.stubs(:days_visited).returns(44) + leader_requirements.requirements_lost?.should == true + end + + it "are lost if not enough topics replied to" do + leader_requirements.stubs(:num_topics_replied_to).returns(8) + leader_requirements.requirements_lost?.should == true + end + + it "are lost if not enough topics viewed" do + leader_requirements.stubs(:topics_viewed).returns(22) + leader_requirements.requirements_lost?.should == true + end + + it "are lost if not enough posts read" do + leader_requirements.stubs(:posts_read).returns(22) + leader_requirements.requirements_lost?.should == true + end + + end + end