mirror of
https://github.com/discourse/discourse.git
synced 2025-03-21 10:15:48 +08:00
New badge, Rookie of the Month, for two new high quality users.
This commit is contained in:
parent
f42b6054e6
commit
893e93dfbe
@ -1,5 +1,4 @@
|
||||
module Jobs
|
||||
|
||||
class CalculateAvgTime < Jobs::Scheduled
|
||||
every 1.day
|
||||
|
||||
|
63
app/jobs/scheduled/grant_rookie_badges.rb
Normal file
63
app/jobs/scheduled/grant_rookie_badges.rb
Normal file
@ -0,0 +1,63 @@
|
||||
require 'badge_granter'
|
||||
|
||||
module Jobs
|
||||
class GrantRookieBadges < Jobs::Scheduled
|
||||
every 1.month
|
||||
|
||||
MAX_AWARDED = 2
|
||||
|
||||
def execute(args)
|
||||
badge = Badge.find(Badge::RookieOfTheMonth)
|
||||
scores.each do |user_id, score|
|
||||
# Don't bother awarding to users who haven't received any likes
|
||||
if score > 0.0
|
||||
BadgeGranter.grant(badge, User.find(user_id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def scores
|
||||
scores = {}
|
||||
|
||||
# Find recent accounts and come up with a score based on how many likes they
|
||||
# received, based on how much they posted and how old the accounts of the people
|
||||
# who voted on them are.
|
||||
sql = <<~SQL
|
||||
SELECT u.id,
|
||||
SUM(CASE
|
||||
WHEN pa.id IS NOT NULL THEN
|
||||
CASE
|
||||
WHEN liked_by.created_at > (CURRENT_TIMESTAMP - '1 week'::INTERVAL) THEN 0.1
|
||||
WHEN liked_by.created_at > (CURRENT_TIMESTAMP - '1 month'::INTERVAL) THEN 0.5
|
||||
ELSE 1.0
|
||||
END
|
||||
ELSE 0
|
||||
END) / COUNT(DISTINCT p.id) AS score
|
||||
FROM users AS u
|
||||
INNER JOIN user_stats AS us ON u.id = us.user_id
|
||||
LEFT OUTER JOIN posts AS p ON p.user_id = u.id
|
||||
LEFT OUTER JOIN post_actions AS pa ON
|
||||
pa.post_id = p.id AND pa.post_action_type_id = :like
|
||||
LEFT OUTER JOIN users AS liked_by ON liked_by.id = pa.user_id
|
||||
WHERE u.active AND
|
||||
u.id > 0 AND
|
||||
NOT(u.admin) AND
|
||||
NOT(u.moderator) AND
|
||||
u.created_at >= CURRENT_TIMESTAMP - '1 month'::INTERVAL
|
||||
GROUP BY u.id
|
||||
HAVING COUNT(p.id) > 0
|
||||
ORDER BY score DESC
|
||||
LIMIT :max_awarded
|
||||
SQL
|
||||
|
||||
User.exec_sql(sql, {
|
||||
like: PostActionType.types[:like],
|
||||
max_awarded: MAX_AWARDED
|
||||
}).each do |row|
|
||||
scores[row['id'].to_i] = row['score'].to_f
|
||||
end
|
||||
scores
|
||||
end
|
||||
|
||||
end
|
||||
end
|
@ -56,6 +56,8 @@ class Badge < ActiveRecord::Base
|
||||
GivesBack = 32
|
||||
Empathetic = 39
|
||||
|
||||
RookieOfTheMonth = 44
|
||||
|
||||
# other consts
|
||||
AutobiographerMinBioLength = 10
|
||||
|
||||
|
@ -3290,6 +3290,11 @@ en:
|
||||
description: Replied to a Post via email
|
||||
long_description: |
|
||||
This badge is granted the first time you reply to a post via email :e-mail:.
|
||||
rookie_of_the_month:
|
||||
name: "Rookie of the Month"
|
||||
description: Contributed a lot of value in their first month
|
||||
long_description: |
|
||||
This badge is granted to two high quality users who joined in the last month. The quality is determined by how many of their posts were liked and by whom.
|
||||
|
||||
admin_login:
|
||||
success: "Email Sent"
|
||||
|
@ -401,6 +401,20 @@ Badge.seed do |b|
|
||||
b.system = true
|
||||
end
|
||||
|
||||
Badge.seed do |b|
|
||||
b.id = Badge::RookieOfTheMonth
|
||||
b.name = "Rookie of the Month"
|
||||
b.badge_type_id = BadgeType::Bronze
|
||||
b.multiple_grant = false
|
||||
b.target_posts = false
|
||||
b.show_posts = false
|
||||
b.query = nil
|
||||
b.badge_grouping_id = BadgeGrouping::GettingStarted
|
||||
b.default_badge_grouping_id = BadgeGrouping::GettingStarted
|
||||
b.trigger = Badge::Trigger::None
|
||||
b.system = true
|
||||
end
|
||||
|
||||
Badge.where("NOT system AND id < 100").each do |badge|
|
||||
new_id = [Badge.maximum(:id) + 1, 100].max
|
||||
old_id = badge.id
|
||||
|
68
spec/jobs/grant_rookie_badges_spec.rb
Normal file
68
spec/jobs/grant_rookie_badges_spec.rb
Normal file
@ -0,0 +1,68 @@
|
||||
require 'rails_helper'
|
||||
require_dependency 'jobs/scheduled/grant_rookie_badges'
|
||||
|
||||
describe Jobs::GrantRookieBadges do
|
||||
|
||||
let(:granter) { described_class.new }
|
||||
|
||||
it "runs correctly" do
|
||||
user = Fabricate(:user, created_at: 1.week.ago)
|
||||
p = Fabricate(:post, user: user)
|
||||
|
||||
old_user = Fabricate(:user, created_at: 6.months.ago)
|
||||
PostAction.act(old_user, p, PostActionType.types[:like])
|
||||
|
||||
granter.execute({})
|
||||
|
||||
badge = user.user_badges.where(badge_id: Badge::RookieOfTheMonth)
|
||||
expect(badge).to be_present
|
||||
|
||||
end
|
||||
|
||||
describe '.scores' do
|
||||
|
||||
it "doesn't award it to accounts over a month old" do
|
||||
user = Fabricate(:user, created_at: 2.months.ago)
|
||||
Fabricate(:post, user: user)
|
||||
expect(granter.scores.keys).not_to include(user.id)
|
||||
end
|
||||
|
||||
it "returns active accounts created in the last month" do
|
||||
user = Fabricate(:user, created_at: 1.week.ago)
|
||||
Fabricate(:post, user: user)
|
||||
expect(granter.scores.keys).to include(user.id)
|
||||
end
|
||||
|
||||
it "likes from older accounts are scored higher" do
|
||||
user = Fabricate(:user, created_at: 1.week.ago)
|
||||
p = Fabricate(:post, user: user)
|
||||
|
||||
new_user = Fabricate(:user, created_at: 2.days.ago)
|
||||
med_user = Fabricate(:user, created_at: 3.weeks.ago)
|
||||
old_user = Fabricate(:user, created_at: 6.months.ago)
|
||||
|
||||
PostAction.act(new_user, p, PostActionType.types[:like])
|
||||
PostAction.act(med_user, p, PostActionType.types[:like])
|
||||
PostAction.act(old_user, p, PostActionType.types[:like])
|
||||
expect(granter.scores[user.id]).to eq(1.6)
|
||||
|
||||
# It goes down the more they post
|
||||
Fabricate(:post, user: user)
|
||||
expect(granter.scores[user.id]).to eq(0.8)
|
||||
end
|
||||
|
||||
it "is limited to two accounts" do
|
||||
u1 = Fabricate(:user, created_at: 1.week.ago)
|
||||
u2 = Fabricate(:user, created_at: 2.weeks.ago)
|
||||
u3 = Fabricate(:user, created_at: 3.weeks.ago)
|
||||
|
||||
Fabricate(:post, user: u1)
|
||||
Fabricate(:post, user: u2)
|
||||
Fabricate(:post, user: u3)
|
||||
|
||||
expect(granter.scores.keys.size).to eq(2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user