* Try a ReactionCategory abstract 'model' * Use ReactionCategory * Lookup category, pre-reaction * Lookup category > constant * Category can sometimes be nil? * Try something friendlier for code reloading * Refactor: extract point calculation out of Reaction * Reaction Category can have color * Rename reaction points service to follow convention * method signature changed as well, calculate -> call * Fix typo, leading comment, and rename data structures for clarity
77 lines
2 KiB
Ruby
77 lines
2 KiB
Ruby
# Reaction uses this class to calculate points before saving
|
|
class CalculateReactionPoints
|
|
DEFAULT_SCORE = 1.0
|
|
|
|
POINTS = {
|
|
"invalid" => 0,
|
|
"User" => 2,
|
|
"confirmed" => 2,
|
|
"positive" => 5,
|
|
"negative" => -5
|
|
}.freeze
|
|
|
|
# Days to ramp up new user points weight
|
|
NEW_USER_RAMPUP_DAYS_COUNT = 10
|
|
|
|
def self.call(reaction)
|
|
new(reaction).calculate_points
|
|
end
|
|
|
|
def initialize(reaction)
|
|
@reaction = reaction
|
|
end
|
|
|
|
def calculate_points
|
|
base_points = reaction_category_score
|
|
|
|
# Adjust for certain states
|
|
base_points = POINTS["invalid"] if status == "invalid"
|
|
base_points /= POINTS["User"] if reactable_type == "User"
|
|
base_points *= POINTS["confirmed"] if status == "confirmed"
|
|
|
|
unless persisted? # Actions we only want to apply upon initial creation
|
|
# Author's comment reaction counts for more weight on to their own posts. (5.0 vs 1.0)
|
|
base_points *= POINTS["positive"] if positive_reaction_to_comment_on_own_article?
|
|
|
|
# New users will have their reaction weight gradually ramp by 0.1 from 0 to 1.0.
|
|
base_points *= new_user_adjusted_points if new_untrusted_user # New users get minimal reaction weight
|
|
end
|
|
|
|
user ? (base_points * user.reputation_modifier) : POINTS["negative"]
|
|
end
|
|
|
|
attr_reader :reaction
|
|
|
|
delegate :category, :persisted?, :positive?, :reactable, :reactable_type, :status, :user, :user_id,
|
|
to: :reaction
|
|
|
|
private
|
|
|
|
def reaction_category
|
|
ReactionCategory[category]
|
|
end
|
|
|
|
def reaction_category_score
|
|
reaction_category&.score || DEFAULT_SCORE
|
|
end
|
|
|
|
def new_untrusted_user
|
|
user.registered_at > NEW_USER_RAMPUP_DAYS_COUNT.days.ago && !user.trusted? && !user.any_admin?
|
|
end
|
|
|
|
def new_user_adjusted_points
|
|
((Time.current - user.registered_at).seconds.in_days / NEW_USER_RAMPUP_DAYS_COUNT)
|
|
end
|
|
|
|
def positive_reaction_to_comment_on_own_article?
|
|
positive? && reaction_to_comment? && own_article?
|
|
end
|
|
|
|
def reaction_to_comment?
|
|
reactable_type == "Comment"
|
|
end
|
|
|
|
def own_article?
|
|
reactable&.commentable&.user_id == user_id
|
|
end
|
|
end
|