Reviewed-on: #365 Co-authored-by: miteruzo <miteruzo@naver.com> Co-committed-by: miteruzo <miteruzo@naver.com>
このコミットはPull リクエスト #365 でマージされました.
このコミットが含まれているのは:
@@ -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
|
||||
|
||||
新しい課題から参照
ユーザをブロックする