119 行
3.7 KiB
Ruby
119 行
3.7 KiB
Ruby
class GekanatorGamesController < ApplicationController
|
|
def create
|
|
return head :not_found unless current_user&.admin?
|
|
|
|
guessed_post_id = params.require(:guessed_post_id)
|
|
correct_post_id = params[:correct_post_id].presence
|
|
answers = params.require(:answers).as_json
|
|
|
|
game = GekanatorGame.new(
|
|
user: current_user,
|
|
guessed_post_id:,
|
|
correct_post_id:,
|
|
won: correct_post_id.present? && guessed_post_id.to_i == correct_post_id.to_i,
|
|
question_count: answers.length,
|
|
answers:)
|
|
|
|
if game.save
|
|
render json: { id: game.id }, status: :created
|
|
else
|
|
render json: { errors: game.errors.full_messages }, status: :unprocessable_entity
|
|
end
|
|
end
|
|
|
|
def extra_questions
|
|
return head :not_found unless current_user&.admin?
|
|
|
|
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
|
|
.where(kind: 'post_similarity', source: 'user_suggested')
|
|
.where.not(id: existing_example_ids)
|
|
.order(priority_weight: :desc, id: :asc)
|
|
|
|
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)
|
|
}
|
|
end
|
|
|
|
def extra_question_answers
|
|
return head :not_found unless current_user&.admin?
|
|
|
|
game = GekanatorGame.find_by(id: params[:id])
|
|
return head :not_found unless game
|
|
|
|
answer_params = params.require(:answers)
|
|
if !answer_params.is_a?(Array)
|
|
return render_validation_error fields: { answers: ['配列で指定してください.'] }
|
|
end
|
|
|
|
answers = answer_params.map { |answer|
|
|
{
|
|
question_id: answer.require(:question_id).to_i,
|
|
answer: answer.require(:answer)
|
|
}
|
|
}
|
|
questions = GekanatorQuestion.where(id: answers.map { _1[:question_id] })
|
|
question_by_id = questions.index_by(&:id)
|
|
if questions.length != answers.length
|
|
return render_validation_error fields: { answers: ['質問が見つかりません.'] }
|
|
end
|
|
if questions.any? { |question| question.status != 'accepted' || question.kind != 'post_similarity' }
|
|
return render_validation_error fields: { answers: ['質問が不正です.'] }
|
|
end
|
|
|
|
ActiveRecord::Base.transaction do
|
|
answers.each do |item|
|
|
question = question_by_id[item[:question_id]]
|
|
example =
|
|
GekanatorQuestionExample.find_or_initialize_by(
|
|
gekanator_question: question,
|
|
post: game.correct_post,
|
|
user: current_user)
|
|
example.assign_attributes(
|
|
gekanator_game: game,
|
|
answer: item[:answer],
|
|
source: 'post_game_extra',
|
|
weight: 1.0)
|
|
example.save!
|
|
end
|
|
end
|
|
|
|
render json: { count: answers.length }, status: :created
|
|
end
|
|
|
|
private
|
|
|
|
def extra_question_json question
|
|
{
|
|
id: question.id,
|
|
text: question.text,
|
|
source: question.source,
|
|
priority_weight: question.priority_weight
|
|
}
|
|
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
|
|
end
|
|
|
|
value&.to_s
|
|
end
|
|
end
|