Remove super voters.
This commit is contained in:
@@ -162,7 +162,6 @@ module ApplicationHelper
|
||||
user_class = "user-#{user.level_string.downcase}"
|
||||
user_class += " user-post-approver" if user.can_approve_posts?
|
||||
user_class += " user-post-uploader" if user.can_upload_free?
|
||||
user_class += " user-super-voter" if user.is_super_voter?
|
||||
user_class += " user-banned" if user.is_banned?
|
||||
user_class += " with-style" if CurrentUser.user.style_usernames?
|
||||
if options[:raw_name]
|
||||
|
||||
@@ -11,7 +11,6 @@ module DanbooruMaintenance
|
||||
safely { PostDisapproval.prune! }
|
||||
safely { PostDisapproval.dmail_messages! }
|
||||
safely { regenerate_post_counts! }
|
||||
safely { SuperVoter.init! }
|
||||
safely { TokenBucket.prune! }
|
||||
safely { TagChangeRequestPruner.warn_all }
|
||||
safely { TagChangeRequestPruner.reject_all }
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
require "set"
|
||||
|
||||
class PostVoteSimilarity
|
||||
THRESHOLD = 0.05
|
||||
|
||||
class Element
|
||||
attr_reader :user_id, :score
|
||||
|
||||
def initialize(user_id, score)
|
||||
@user_id = user_id
|
||||
@score = score
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
score <=> other.score
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :user_id
|
||||
|
||||
def initialize(user_id)
|
||||
@user_id = user_id
|
||||
end
|
||||
|
||||
# returns user ids with strong positive correlation
|
||||
def calculate_positive(limit = 10)
|
||||
posts0 = PostVote.positive_post_ids(user_id)
|
||||
set = []
|
||||
|
||||
PostVote.positive_user_ids.each do |uid|
|
||||
posts1 = PostVote.positive_post_ids(uid)
|
||||
score = calculate_with_jaccard(posts0, posts1)
|
||||
if score >= THRESHOLD
|
||||
set << Element.new(uid, score)
|
||||
end
|
||||
end
|
||||
|
||||
set.sort.reverse.first(limit)
|
||||
end
|
||||
|
||||
def calculate_with_jaccard(posts0, posts1)
|
||||
a = (posts0 & posts1).size
|
||||
div = posts0.size + posts1.size - a
|
||||
if div == 0
|
||||
0
|
||||
else
|
||||
a / div.to_f
|
||||
end
|
||||
end
|
||||
|
||||
def calculate_with_cosine(posts0, posts1)
|
||||
a = (posts0 & posts1).size
|
||||
div = Math.sqrt(posts0.size * posts1.size)
|
||||
if div == 0
|
||||
0
|
||||
else
|
||||
a / div
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,25 +7,13 @@ class PostVote < ApplicationRecord
|
||||
|
||||
after_initialize :initialize_attributes, if: :new_record?
|
||||
validates_presence_of :score
|
||||
validates_inclusion_of :score, :in => [SuperVoter::MAGNITUDE, 1, -1, -SuperVoter::MAGNITUDE]
|
||||
validates_inclusion_of :score, in: [1, -1]
|
||||
after_create :update_post_on_create
|
||||
after_destroy :update_post_on_destroy
|
||||
|
||||
scope :positive, -> { where("post_votes.score > 0") }
|
||||
scope :negative, -> { where("post_votes.score < 0") }
|
||||
|
||||
def self.positive_user_ids
|
||||
positive.group(:user_id).having("count(*) > 100").pluck(:user_id)
|
||||
end
|
||||
|
||||
def self.negative_post_ids(user_id)
|
||||
negative.where(user_id: user_id).pluck(:post_id)
|
||||
end
|
||||
|
||||
def self.positive_post_ids(user_id)
|
||||
positive.where(user_id: user_id).pluck(:post_id)
|
||||
end
|
||||
|
||||
def self.visible(user)
|
||||
user.is_admin? ? all : where(user: user)
|
||||
end
|
||||
@@ -40,9 +28,9 @@ class PostVote < ApplicationRecord
|
||||
self.user_id ||= CurrentUser.user.id
|
||||
|
||||
if vote == "up"
|
||||
self.score = magnitude
|
||||
self.score = 1
|
||||
elsif vote == "down"
|
||||
self.score = -magnitude
|
||||
self.score = -1
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,14 +50,6 @@ class PostVote < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def magnitude
|
||||
if user.is_super_voter?
|
||||
SuperVoter::MAGNITUDE
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
def self.available_includes
|
||||
[:user, :post]
|
||||
end
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
class SuperVoter < ApplicationRecord
|
||||
MAGNITUDE = 3
|
||||
DURATION = 1.week
|
||||
|
||||
belongs_to :user
|
||||
validates_uniqueness_of :user_id
|
||||
after_create :update_user_on_create
|
||||
after_destroy :update_user_on_destroy
|
||||
|
||||
def self.prune!
|
||||
where("created_at < ?", DURATION.ago).destroy_all
|
||||
end
|
||||
|
||||
def self.init!
|
||||
prune!
|
||||
|
||||
report = PostVoteSimilarity.new(User.admins.first.id)
|
||||
|
||||
report.calculate_positive(15).each do |element|
|
||||
unless SuperVoter.where("user_id = ?", element.user_id).exists?
|
||||
SuperVoter.create(:user_id => element.user_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def update_user_on_create
|
||||
user.is_super_voter = true
|
||||
user.save
|
||||
end
|
||||
|
||||
def update_user_on_destroy
|
||||
user.is_super_voter = false
|
||||
user.save
|
||||
end
|
||||
end
|
||||
@@ -18,8 +18,7 @@ class User < ApplicationRecord
|
||||
Roles = Levels.constants.map(&:downcase) + [
|
||||
:banned,
|
||||
:approver,
|
||||
:voter,
|
||||
:super_voter
|
||||
:voter
|
||||
]
|
||||
|
||||
# candidates for removal:
|
||||
@@ -35,6 +34,7 @@ class User < ApplicationRecord
|
||||
# - opt_out_tracking
|
||||
# - enable_recommended_posts
|
||||
# - has_mail
|
||||
# - is_super_voter
|
||||
BOOLEAN_ATTRIBUTES = %w(
|
||||
is_banned
|
||||
has_mail
|
||||
@@ -110,7 +110,6 @@ class User < ApplicationRecord
|
||||
has_one :recent_ban, -> {order("bans.id desc")}, :class_name => "Ban"
|
||||
|
||||
has_one :api_key
|
||||
has_one :super_voter
|
||||
has_one :token_bucket
|
||||
has_many :notes, foreign_key: :creator_id
|
||||
has_many :note_versions, :foreign_key => "updater_id"
|
||||
@@ -329,7 +328,6 @@ class User < ApplicationRecord
|
||||
self.level = Levels::ADMIN
|
||||
self.can_approve_posts = true
|
||||
self.can_upload_free = true
|
||||
self.is_super_voter = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -374,7 +372,7 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def is_voter?
|
||||
is_gold? || is_super_voter?
|
||||
is_gold?
|
||||
end
|
||||
|
||||
def is_approver?
|
||||
@@ -532,7 +530,7 @@ class User < ApplicationRecord
|
||||
attributes = %i[
|
||||
id created_at name inviter_id level
|
||||
post_upload_count post_update_count note_update_count is_banned
|
||||
can_approve_posts can_upload_free is_super_voter level_string
|
||||
can_approve_posts can_upload_free level_string
|
||||
]
|
||||
|
||||
if id == CurrentUser.user.id
|
||||
@@ -667,7 +665,7 @@ class User < ApplicationRecord
|
||||
q = q.where("level <= ?", params[:max_level].to_i)
|
||||
end
|
||||
|
||||
%w[can_approve_posts can_upload_free is_super_voter].each do |flag|
|
||||
%w[can_approve_posts can_upload_free].each do |flag|
|
||||
if params[flag].to_s.truthy?
|
||||
q = q.bit_prefs_match(flag, true)
|
||||
elsif params[flag].to_s.falsy?
|
||||
|
||||
@@ -32,10 +32,6 @@ class UserPresenter
|
||||
permissions << "unrestricted uploads"
|
||||
end
|
||||
|
||||
if user.is_super_voter?
|
||||
permissions << "super voter"
|
||||
end
|
||||
|
||||
permissions.join(", ")
|
||||
end
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
<%= f.input :can_upload_free, label: "Unrestricted uploads?", collection: [%w[Yes true], %w[No false]], include_blank: true, selected: params[:search][:can_upload_free] %>
|
||||
<%= f.input :can_approve_posts, label: "Approver?", collection: [%w[Yes true], %w[No false]], include_blank: true, selected: params[:search][:can_approve_posts] %>
|
||||
<%= f.input :is_super_voter, label: "Super voter?", collection: [%w[Yes true], %w[No false]], include_blank: true, selected: params[:search][:is_super_voter] %>
|
||||
|
||||
<%= f.input :order, collection: [["Join date", "date"], ["Name", "name"], ["Upload count", "post_upload_count"], ["Note count", "note_count"], ["Post update count", "post_update_count"]], selected: params[:search][:order] %>
|
||||
<%= f.submit "Search" %>
|
||||
|
||||
Reference in New Issue
Block a user