New user of the month is so rigged

Key:
nuotm=New User of The Month


Introduction
New User of The Month is a badge that discourse grants to users with “outstanding contributions in their first month” but, this badge is very rigged.


Here is the code that discourse runs to grant nuotm

If you can't access that
# frozen_string_literal: true

module Jobs
  class GrantNewUserOfTheMonthBadges < ::Jobs::Scheduled
    every 1.day

    MAX_AWARDED = 2

    def execute(args)
      badge = Badge.find(Badge::NewUserOfTheMonth)
      return unless SiteSetting.enable_badges? && badge.enabled?

      previous_month_beginning = 1.month.ago.beginning_of_month
      previous_month_end = 1.month.ago.end_of_month

      if UserBadge.where(
           "badge_id = ? AND granted_at BETWEEN ? AND ?",
           badge.id,
           previous_month_beginning,
           Time.zone.now,
         ).exists?
        return
      end

      scores(previous_month_beginning, previous_month_end).each do |user_id, score|
        # Don't bother awarding to users who haven't received any likes
        if score > 0.0
          user = User.find(user_id)
          if user.badges.where(id: Badge::NewUserOfTheMonth).blank?
            BadgeGranter.grant(badge, user, created_at: previous_month_end)

            SystemMessage.new(user).create(
              "new_user_of_the_month",
              month_year: I18n.l(previous_month_beginning, format: :no_day),
              url: "#{Discourse.base_url}/badges",
            )
          end
        end
      end
    end

    def scores(min_user_created_at, max_user_created_at)
      current_owners = UserBadge.where(badge_id: Badge::NewUserOfTheMonth).pluck(:user_id)
      current_owners = [-1] if current_owners.blank?

      # 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.id <= 0         THEN 0.0
                WHEN liked_by.admin           THEN 3.0
                WHEN liked_by.moderator       THEN 3.0
                WHEN liked_by.trust_level = 4 THEN 2.0
                WHEN liked_by.trust_level = 3 THEN 1.5
                WHEN liked_by.trust_level = 2 THEN 1.0
                WHEN liked_by.trust_level = 1 THEN 0.25
                WHEN liked_by.trust_level = 0 THEN 0.1
                ELSE 1.0
                END
              ELSE 0
              END) / (5 + COUNT(DISTINCT p.id))::float 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 = #{PostActionType.types[:like]}
        LEFT OUTER JOIN users        AS liked_by ON liked_by.id = pa.user_id
        LEFT OUTER JOIN topics       AS t        ON t.id = p.topic_id
        WHERE u.active
          AND u.id > 0
          AND u.id NOT IN (#{current_owners.join(",")})
          AND NOT u.staged
          AND NOT u.admin
          AND NOT u.moderator
          AND u.suspended_at IS NULL
          AND u.suspended_till IS NULL
          AND u.created_at BETWEEN :min_user_created_at AND :max_user_created_at
          AND t.archetype <> '#{Archetype.private_message}'
          AND t.deleted_at IS NULL
          AND p.deleted_at IS NULL
        GROUP BY u.id
        HAVING COUNT(DISTINCT p.id) > 1
           AND COUNT(DISTINCT p.topic_id) > 1
           AND COUNT(pa.id) > 1
        ORDER BY score DESC
        LIMIT #{MAX_AWARDED}
      SQL

      Hash[
        *DB.query_single(
          sql,
          min_user_created_at: min_user_created_at,
          max_user_created_at: max_user_created_at,
        )
      ]
    end
  end
end


Now, look at this user


0 likes received, 0 given, 0 posts created
And they got nuotm.
In the code there is this:

“Don’t bother awarding to users who haven’t received any likes”
Hmm…


[WIP, adding more soon]

4 Likes

I COMPLETELY agree, you see random people get the badge, but people who are active and actually contribute a lot almost never get the badge. Some people really try to get likes and are devoted to the discourse, but the people they talk to almost never give likes. And then you have the people who contribute next to nothing and they get the badge awarded to them because the people they talk to are spamming likes for no reason. I personally think that likes should be given if you agree or support the topic/post, not just to be nice, for example I liked the topic because I strongly agree and support it. However, there are people who like every single post on a new user to make them feel welcome, personally I would be fine with a link and a friendly “Welcome to the discourse!” like many users give. So, in conclusion, I agree and conclude that the new user of the month badge should be reverted to a vote in the active community instead of likes.

6 Likes

EXACTLY!!!

2 Likes

I got NUOTM this month (I had a total of 45 likes)

Update:

[quote=“The_weird_person, post:1, topic:37282”]
user


[/quote

I think the badge works by going theough replies and ranking them by how many likes each reply got on average. I had a high average, thus I got the nadge.
They most likely posted in a deleted topic and got a lot of likes before the topic was deleted.

3 Likes