<commit_before># frozen_string_literal: true

class CustomizeDeploymentService
  def initialize(deployment, author_id, lti_uid)
    @deployment = deployment
    @author_identifier = AuthorIdentifier.new author_id, lti_uid
  end

  def customize(answers_needed: 0, quiz_id: nil, custom_questions: [])
    if answers_needed.zero?
      @deployment.answers_needed = 0
      @deployment.save
      return @deployment
    end

    begin
      ActiveRecord::Base.transaction do
        @deployment.answers_needed = answers_needed

        @deployment.quiz = find_quiz quiz_id
        delete_questions_not_included_in(custom_questions.map { |q| q['id'] })
        upsert_questions custom_questions
        set_quiz_author

        @deployment.save!
      end
    rescue ActiveRecord::RecordInvalid => invalid
      return invalid.record
    end

    @deployment
  end

  private

  def set_quiz_author
    @deployment.quiz.update @author_identifier.quiz_attributes
  end

  def find_quiz(quiz_id)
    quiz = Quiz.where(id: quiz_id).try(:first)
    if quiz && @author_identifier.author.quiz?(quiz)
      quiz
    else
      create_quiz_from_template quiz_id
    end
  end

  def create_quiz_from_template(template_id)
    Quiz.create! case: @deployment.case,
                 template_id: template_id,
                 customized: true
  end

  def delete_questions_not_included_in(question_ids)
    @deployment.quiz.custom_questions.each do |question|
      question.destroy unless question_ids.include? question.id
    end
  end

  def upsert_questions(custom_questions)
    custom_questions.each do |question|
      if question['id']
        Question.find(question['id']).update! question
      else
        @deployment.quiz.custom_questions.create! question
      end
    end
  end
<commit_msg>Fixes the customization of deployments (#71)<commit_after># frozen_string_literal: true

class CustomizeDeploymentService
  def initialize(deployment, author_id, lti_uid)
    @deployment = deployment
    @author_identifier = AuthorIdentifier.new author_id, lti_uid
  end

  def customize(answers_needed: 0, quiz_id: nil, custom_questions: [])
    ActiveRecord::Base.transaction do
      @deployment.answers_needed = answers_needed
      return @deployment.tap(&:save!) if answers_needed.zero?

      # There will be a quiz administered
      @deployment.quiz = get_quiz quiz_id, with_customizations: custom_questions
      return @deployment.tap(&:save!) if custom_questions.empty?

      # The quiz has custom questions
      customize_quiz custom_questions
      @deployment.tap(&:save!)
    end
  rescue ActiveRecord::RecordInvalid => invalid
    return invalid.record
  end

  private

  def get_quiz(quiz_id, with_customizations:)
    quiz = Quiz.where(id: quiz_id).try(:first)
    return quiz if should_use_existing_quiz quiz, with_customizations

    create_quiz_from_template quiz_id
  end

  def should_use_existing_quiz(quiz, with_customizations)
    return false unless quiz # Can’t use existing if there isn’t one
    return true if @author_identifier.author.quiz? quiz # Can mutate their own
    with_customizations.empty? # Copy on write (only copy if needed)
  end

  def create_quiz_from_template(template_id)
    Quiz.create! case: @deployment.case,
                 template_id: template_id,
                 customized: true
  end

  def customize_quiz(custom_questions)
    delete_questions_not_included_in(custom_questions.map { |q| q['id'] })
    upsert_questions custom_questions
    set_quiz_author
  end

  def set_quiz_author
    @deployment.quiz.update @author_identifier.quiz_attributes
  end

  def delete_questions_not_included_in(question_ids)
    @deployment.quiz.custom_questions.each do |question|
      question.destroy unless question_ids.include? question.id
    end
  end

  def upsert_questions(custom_questions)
    custom_questions.each do |question|
      if question['id']
        Question.find(question['id']).update! question
      else
        @deployment.quiz.custom_questions.create! question
      end
    end
  end

{'fraction_non_alphanumeric': 0.07274969173859433, 'fraction_numerical': 0.0012330456226880395, 'mean_word_length': 3.4966740576496673, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3390439', 'n_tokens_mistral': 1316, 'n_tokens_neox': 1222, 'n_words': 273}