156 lines
4.4 KiB
Ruby
156 lines
4.4 KiB
Ruby
# This class performs calculations to determine if a user qualifies for
|
|
# the Leader (3) trust level.
|
|
class LeaderRequirements
|
|
|
|
include ActiveModel::Serialization
|
|
|
|
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,
|
|
:posts_read, :min_posts_read,
|
|
:topics_viewed_all_time, :min_topics_viewed_all_time,
|
|
:posts_read_all_time, :min_posts_read_all_time,
|
|
:num_flagged_posts, :max_flagged_posts
|
|
|
|
def initialize(user)
|
|
@user = user
|
|
end
|
|
|
|
def requirements_met?
|
|
days_visited >= min_days_visited &&
|
|
num_topics_replied_to >= min_topics_replied_to &&
|
|
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
|
|
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
|
|
@user.user_visits.where("visited_at > ? and posts_read > 0", TIME_PERIOD.days.ago).count
|
|
end
|
|
|
|
def min_days_visited
|
|
SiteSetting.leader_requires_days_visited
|
|
end
|
|
|
|
def num_topics_replied_to
|
|
@user.posts.select('distinct topic_id').where('created_at > ? AND post_number > 1', TIME_PERIOD.days.ago).count
|
|
end
|
|
|
|
def min_topics_replied_to
|
|
SiteSetting.leader_requires_topics_replied_to
|
|
end
|
|
|
|
def topics_viewed_query
|
|
TopicViewItem.where(user_id: @user.id).select('topic_id')
|
|
end
|
|
|
|
def topics_viewed
|
|
topics_viewed_query.where('viewed_at > ?', TIME_PERIOD.days.ago).count
|
|
end
|
|
|
|
def min_topics_viewed
|
|
(LeaderRequirements.num_topics_in_time_period.to_i * (SiteSetting.leader_requires_topics_viewed.to_f / 100.0)).round
|
|
end
|
|
|
|
def posts_read
|
|
@user.user_visits.where('visited_at > ?', TIME_PERIOD.days.ago).pluck(:posts_read).sum
|
|
end
|
|
|
|
def min_posts_read
|
|
(LeaderRequirements.num_posts_in_time_period.to_i * (SiteSetting.leader_requires_posts_read.to_f / 100.0)).round
|
|
end
|
|
|
|
def topics_viewed_all_time
|
|
topics_viewed_query.count
|
|
end
|
|
|
|
def min_topics_viewed_all_time
|
|
SiteSetting.leader_requires_topics_viewed_all_time
|
|
end
|
|
|
|
def posts_read_all_time
|
|
@user.user_visits.pluck(:posts_read).sum
|
|
end
|
|
|
|
def min_posts_read_all_time
|
|
SiteSetting.leader_requires_posts_read_all_time
|
|
end
|
|
|
|
def num_flagged_posts
|
|
PostAction.with_deleted
|
|
.where(post_id: flagged_post_ids)
|
|
.where.not(user_id: @user.id)
|
|
.where.not(agreed_at: nil)
|
|
.pluck(:post_id)
|
|
.uniq.count
|
|
end
|
|
|
|
def max_flagged_posts
|
|
SiteSetting.leader_requires_max_flagged
|
|
end
|
|
|
|
def num_flagged_by_users
|
|
PostAction.with_deleted
|
|
.where(post_id: flagged_post_ids)
|
|
.where.not(user_id: @user.id)
|
|
.where.not(agreed_at: nil)
|
|
.pluck(:user_id)
|
|
.uniq.count
|
|
end
|
|
|
|
def max_flagged_by_users
|
|
SiteSetting.leader_requires_max_flagged
|
|
end
|
|
|
|
def self.clear_cache
|
|
$redis.del NUM_TOPICS_KEY
|
|
$redis.del NUM_POSTS_KEY
|
|
end
|
|
|
|
|
|
CACHE_DURATION = 1.day.seconds - 60
|
|
NUM_TOPICS_KEY = "tl3_num_topics"
|
|
NUM_POSTS_KEY = "tl3_num_posts"
|
|
|
|
def self.num_topics_in_time_period
|
|
$redis.get(NUM_TOPICS_KEY) || begin
|
|
count = Topic.listable_topics.visible.created_since(TIME_PERIOD.days.ago).count
|
|
$redis.setex NUM_TOPICS_KEY, CACHE_DURATION, count
|
|
count
|
|
end
|
|
end
|
|
|
|
def self.num_posts_in_time_period
|
|
$redis.get(NUM_POSTS_KEY) || begin
|
|
count = Post.public_posts.visible.created_since(TIME_PERIOD.days.ago).count
|
|
$redis.setex NUM_POSTS_KEY, CACHE_DURATION, count
|
|
count
|
|
end
|
|
end
|
|
|
|
def flagged_post_ids
|
|
@user.posts
|
|
.with_deleted
|
|
.where('created_at > ? AND (spam_count > 0 OR inappropriate_count > 0)', TIME_PERIOD.days.ago)
|
|
.pluck(:id)
|
|
end
|
|
end
|