class GekanatorQuestionsController < ApplicationController def index return head :not_found unless current_user&.admin? questions = GekanatorQuestion .accepted .includes(:gekanator_question_examples) .order(priority_weight: :desc, id: :asc) render json: { questions: questions.map { |question| question_json(question) } } end private def question_json question condition = condition_json(question.condition).deep_symbolize_keys json = { id: question_id_for(question, condition), text: question_text_for(question, condition), kind: question.kind, condition: condition, source: question.source, priority_weight: question.priority_weight } if question.kind == 'post_similarity' json[:example_answers] = example_answers_json(question) end json end def question_id_for question, condition case condition[:type] when 'tag' "tag:#{ condition[:key] }" when 'source' "source:#{ condition[:host] }" when 'original-year' "original-year:#{ condition[:year] }" when 'original-month' "original-month:#{ condition[:month] }" when 'original-month-day' "original-month-day:#{ condition[:monthDay] || condition[:month_day] }" when 'title-length-at-least' "title:length-at-least:#{ condition[:length] }" when 'title-length-greater-than' "title:length-at-least:#{ condition[:length].to_i + 1 }" when 'title-has-ascii' 'title:ascii' when 'post-similarity' "post-similarity:#{ question.id }" else "catalog:#{ question.id }" end end def condition_json condition json = condition.deep_dup.as_json if json['type'] == 'original-month-day' && json['monthDay'].blank? json['monthDay'] = json.delete('month_day') end if json['type'] == 'title-length-greater-than' json['type'] = 'title-length-at-least' json['length'] = json['length'].to_i + 1 end json end def question_text_for question, condition return question.text unless question.kind == 'title' case condition[:type] when 'title-length-at-least' "タイトルは #{ condition[:length] } 文字以上?" else question.text end end def example_answers_json question question .gekanator_question_examples .group_by(&:post_id) .transform_values { |examples| aggregate_answer(examples) } end def aggregate_answer examples examples .group_by(&:answer) .map { |answer, grouped| [answer, grouped.sum(&:weight), grouped.max_by(&:updated_at)&.updated_at] } .sort_by { |(_answer, weight, updated_at)| [-weight, -(updated_at&.to_f || 0)] } .first &.first end end