このコミットが含まれているのは:
2026-06-07 00:05:18 +09:00
コミット 364d154b6a
8個のファイルの変更482行の追加283行の削除
+50 -18
ファイルの表示
@@ -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