2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2019-01-04 01:03:01 +08:00
|
|
|
class ReviewableScore < ActiveRecord::Base
|
|
|
|
belongs_to :reviewable
|
|
|
|
belongs_to :user
|
|
|
|
belongs_to :reviewed_by, class_name: 'User'
|
|
|
|
belongs_to :meta_topic, class_name: 'Topic'
|
|
|
|
|
|
|
|
# To keep things simple the types correspond to `PostActionType` for backwards
|
|
|
|
# compatibility, but we can add extra reasons for scores.
|
|
|
|
def self.types
|
|
|
|
@types ||= PostActionType.flag_types.merge(
|
|
|
|
needs_approval: 9
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.statuses
|
|
|
|
@statuses ||= Enum.new(
|
|
|
|
pending: 0,
|
|
|
|
agreed: 1,
|
|
|
|
disagreed: 2,
|
|
|
|
ignored: 3
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.score_transitions
|
|
|
|
{
|
|
|
|
approved: statuses[:agreed],
|
|
|
|
rejected: statuses[:disagreed],
|
|
|
|
ignored: statuses[:ignored]
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
# Generate `pending?`, `rejected?`, etc helper methods
|
|
|
|
statuses.each do |name, id|
|
|
|
|
define_method("#{name}?") { status == id }
|
|
|
|
self.class.define_method(name) { where(status: id) }
|
|
|
|
end
|
|
|
|
|
|
|
|
def score_type
|
|
|
|
Reviewable::Collection::Item.new(reviewable_score_type)
|
|
|
|
end
|
|
|
|
|
|
|
|
def took_action?
|
|
|
|
take_action_bonus > 0
|
|
|
|
end
|
|
|
|
|
|
|
|
# A user's flag score is:
|
|
|
|
# 1.0 + trust_level + user_accuracy_bonus
|
|
|
|
# (trust_level is 5 for staff)
|
|
|
|
def self.user_flag_score(user)
|
|
|
|
1.0 + (user.staff? ? 5.0 : user.trust_level.to_f) + user_accuracy_bonus(user)
|
|
|
|
end
|
|
|
|
|
|
|
|
# A user's accuracy bonus is:
|
|
|
|
# if 5 or less flags => 0.0
|
|
|
|
# if > 5 flags => (agreed flags / total flags) * 5.0
|
|
|
|
def self.user_accuracy_bonus(user)
|
|
|
|
user_stat = user&.user_stat
|
|
|
|
return 0.0 if user_stat.blank?
|
|
|
|
|
2019-09-04 23:56:25 +08:00
|
|
|
calc_user_accuracy_bonus(
|
|
|
|
user_stat.flags_agreed,
|
|
|
|
user_stat.flags_disagreed,
|
|
|
|
user_stat.flags_ignored
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.calc_user_accuracy_bonus(agreed, disagreed, ignored)
|
|
|
|
agreed ||= 0
|
|
|
|
disagreed ||= 0
|
|
|
|
ignored ||= 0
|
|
|
|
|
|
|
|
total = (agreed + disagreed + ignored).to_f
|
2019-01-04 01:03:01 +08:00
|
|
|
return 0.0 if total <= 5
|
|
|
|
|
2019-09-04 23:56:25 +08:00
|
|
|
(agreed / total) * 5.0
|
2019-01-04 01:03:01 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def reviewable_conversation
|
|
|
|
return if meta_topic.blank?
|
|
|
|
Reviewable::Conversation.new(meta_topic)
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: reviewable_scores
|
|
|
|
#
|
2019-05-03 06:34:12 +08:00
|
|
|
# id :bigint not null, primary key
|
2019-01-04 01:03:01 +08:00
|
|
|
# reviewable_id :integer not null
|
|
|
|
# user_id :integer not null
|
|
|
|
# reviewable_score_type :integer not null
|
|
|
|
# status :integer not null
|
|
|
|
# score :float default(0.0), not null
|
|
|
|
# take_action_bonus :float default(0.0), not null
|
|
|
|
# reviewed_by_id :integer
|
|
|
|
# reviewed_at :datetime
|
|
|
|
# meta_topic_id :integer
|
|
|
|
# created_at :datetime not null
|
|
|
|
# updated_at :datetime not null
|
2019-04-12 21:55:27 +08:00
|
|
|
# reason :string
|
2019-01-04 01:03:01 +08:00
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
|
|
|
# index_reviewable_scores_on_reviewable_id (reviewable_id)
|
|
|
|
# index_reviewable_scores_on_user_id (user_id)
|
|
|
|
#
|