このコミットが含まれているのは:
@@ -1,7 +1,7 @@
|
||||
class TheatrePostSelector
|
||||
Candidate = Struct.new(:post, :weight, :penalty, :tags, keyword_init: true)
|
||||
|
||||
def initialize(theatre:)
|
||||
def initialize theatre:
|
||||
@theatre = theatre
|
||||
end
|
||||
|
||||
@@ -20,13 +20,15 @@ class TheatrePostSelector
|
||||
candidates.last.post
|
||||
end
|
||||
|
||||
def weight_json(limit: 20)
|
||||
def weight_json limit: 20
|
||||
candidates = weighted_candidates
|
||||
sorted = candidates.sort_by { |candidate| [candidate.weight, candidate.post.id] }
|
||||
|
||||
{ tag_penalties: tag_penalty_json,
|
||||
{
|
||||
tag_penalties: tag_penalty_json,
|
||||
lightest_posts: post_weight_json(sorted.first(limit)),
|
||||
heaviest_posts: post_weight_json(sorted.reverse.first(limit)) }
|
||||
heaviest_posts: post_weight_json(sorted.reverse.first(limit))
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
@@ -41,7 +43,13 @@ class TheatrePostSelector
|
||||
posts.map do |post|
|
||||
post_tags = post.tags.to_a
|
||||
penalty = post_tags.sum { |tag| penalties[tag.id].to_i }
|
||||
Candidate.new(post:, penalty:, tags: post_tags, weight: 1.0 / (1.0 + penalty))
|
||||
|
||||
Candidate.new(
|
||||
post:,
|
||||
penalty:,
|
||||
tags: post_tags,
|
||||
weight: 1.0 / (1.0 + penalty)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -58,35 +66,59 @@ class TheatrePostSelector
|
||||
|
||||
def tag_penalties
|
||||
@tag_penalties ||=
|
||||
if active_user_ids.empty?
|
||||
{}
|
||||
else
|
||||
TheatreSkipEventVoter
|
||||
if active_user_ids.empty?
|
||||
{}
|
||||
else
|
||||
TheatreSkipEventVoter
|
||||
.joins(theatre_skip_event: :event_tags)
|
||||
.where(user_id: active_user_ids)
|
||||
.group('theatre_skip_event_tags.tag_id')
|
||||
.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def tag_penalty_json
|
||||
return [] if tag_penalties.empty?
|
||||
|
||||
tags = Tag.where(id: tag_penalties.keys).includes(:tag_name).index_by(&:id)
|
||||
tag_penalties.map { |tag_id, penalty|
|
||||
tag = tags[tag_id]
|
||||
next unless tag
|
||||
|
||||
{ tag: TagRepr.inline(tag), penalty: }
|
||||
}.compact.sort_by { |row| [-row[:penalty], row[:tag]['name'].to_s] }
|
||||
tag_penalties
|
||||
.map { |tag_id, penalty|
|
||||
tag = tags[tag_id]
|
||||
next unless tag
|
||||
|
||||
{
|
||||
tag: light_tag_json(tag),
|
||||
penalty:
|
||||
}
|
||||
}
|
||||
.compact
|
||||
.sort_by { |row| [-row[:penalty], row[:tag][:name].to_s] }
|
||||
end
|
||||
|
||||
def post_weight_json(candidates)
|
||||
def post_weight_json candidates
|
||||
candidates.map { |candidate|
|
||||
{ post: PostRepr.base(candidate.post),
|
||||
{
|
||||
post: light_post_json(candidate.post),
|
||||
weight: candidate.weight,
|
||||
penalty: candidate.penalty,
|
||||
tags: candidate.tags.map { |tag| TagRepr.inline(tag) } }
|
||||
tags: candidate.tags.map { |tag| light_tag_json(tag) }
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def light_post_json post
|
||||
{
|
||||
id: post.id,
|
||||
title: post.title,
|
||||
url: post.url
|
||||
}
|
||||
end
|
||||
|
||||
def light_tag_json tag
|
||||
{
|
||||
id: tag.id,
|
||||
name: tag.name
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
新しい課題から参照
ユーザをブロックする