グカネータ / 質問パターン見直し (#41) (#365)

Reviewed-on: #365
Co-authored-by: miteruzo <miteruzo@naver.com>
Co-committed-by: miteruzo <miteruzo@naver.com>
このコミットはPull リクエスト #365 でマージされました.
このコミットが含まれているのは:
2026-06-12 01:35:31 +09:00
committed by みてるぞ
コミット def6870f06
14個のファイルの変更1077行の追加190行の削除
+44 -22
ファイルの表示
@@ -27,26 +27,20 @@ class GekanatorGamesController < ApplicationController
game = GekanatorGame.find_by(id: params[:id])
return head :not_found unless game
asked_ids = Array(game.answers).filter_map { |answer| answer_question_id(answer) }
existing_example_ids =
GekanatorQuestionExample.where(post_id: game.correct_post_id)
.select(:gekanator_question_id)
# Direct examples only for now; post_similarity-based expansion is deferred.
questions =
GekanatorQuestion
.accepted
.includes(:gekanator_question_examples)
.where(kind: 'post_similarity', source: 'user_suggested')
.where.not(id: existing_example_ids)
.order(priority_weight: :desc, id: :asc)
.to_a
selected = weighted_sample_questions(
questions,
post_id: game.correct_post_id,
limit: 2)
render json: {
questions: questions.filter_map { |question|
json = extra_question_json(question)
next if asked_ids.include?(json[:id].to_s)
next if asked_ids.include?("post-similarity:#{ json[:id] }")
json
}.first(2)
questions: selected.map { |question| extra_question_json(question) }
}
end
@@ -84,11 +78,10 @@ class GekanatorGamesController < ApplicationController
gekanator_question: question,
post: game.correct_post,
user: current_user)
example.assign_attributes(
gekanator_game: game,
example.record_answer!(
answer: item[:answer],
source: 'post_game_extra',
weight: 1.0)
gekanator_game: game)
example.save!
end
end
@@ -107,12 +100,41 @@ class GekanatorGamesController < ApplicationController
}
end
def answer_question_id answer
value = if answer.is_a?(Hash)
answer['question_id'].presence || answer[:question_id].presence ||
answer['questionId'].presence || answer[:questionId].presence
def weighted_sample_questions questions, post_id:, limit:
remaining = questions.uniq(&:id)
selected = []
while selected.length < limit && remaining.any?
weighted =
remaining.map { |question|
[question, selection_weight_for(question, post_id: post_id)]
}
total_weight = weighted.sum { |_question, weight| weight }
break if total_weight <= 0
target = rand * total_weight
cumulative = 0.0
chosen =
weighted.find do |_question, weight|
cumulative += weight
cumulative >= target
end&.first || weighted.first.first
selected << chosen
remaining.reject! { |question| question.id == chosen.id }
end
value&.to_s
selected
end
def selection_weight_for question, post_id:
sample_count =
question.gekanator_question_examples.sum { |example|
next 0 unless example.post_id == post_id
example.sample_count.presence || 1
}
question.priority_weight.to_f / (1.0 + sample_count * 0.15)
end
end