<commit_before>class PopupController < ApplicationController
  include StringOperationHelper
  include AuthorizationHelper
  ASSIGNMENT_NAME_SIMILARITY_THRESHOLD = 0.50

  def action_allowed?
    current_user_has_ta_privileges?
  end

  # this can be called from "response_report" by clicking student names from instructor end.
  def author_feedback_popup
    @response_id = params[:response_id]
    @reviewee_id = params[:reviewee_id]
    unless @response_id.nil?
      first_question_in_questionnaire = Answer.where(response_id: @response_id).first.question_id
      questionnaire_id = Question.find(first_question_in_questionnaire).questionnaire_id
      questionnaire = Questionnaire.find(questionnaire_id)
      @maxscore = questionnaire.max_question_score
      @scores = Answer.where(response_id: @response_id)
      @response = Response.find(@response_id)
      @total_percentage = @response.average_score
      @sum = @response.total_score
      @total_possible = @response.maximum_score
    end

    @maxscore = 5 if @maxscore.nil?

    unless @response_id.nil?
      participant = Participant.find(@reviewee_id)
      @user = User.find(participant.user_id)
    end
  end

  # this can be called from "response_report" by clicking team names from instructor end.
  def team_users_popup
    @sum = 0
    @team = Team.find(params[:id])
    @assignment = Assignment.find(@team.parent_id)
    @team_users = TeamsUser.where(team_id: params[:id])

    # id2 is a response_map id
    unless params[:id2].nil?
      # E1973 - we set the reviewer id either to the student's user id or the current reviewer id
      # This results from reviewers being either assignment participants or assignment teams.
      # If the reviewer is a participant, the id is currently the id of the assignment participant.
      # However, we want their user_id. This is not possible for teams, so we just return the current id
      reviewer_id = ResponseMap.find(params[:id2]).reviewer_id
      if @assignment.reviewer_is_team
        @reviewer_id = Participant.find(reviewer_id).user_id
      else
        @reviewer_id = reviewer_id
      end
      # get the last response in each round from response_map id
      (1..@assignment.num_review_rounds).each do |round|
        response = Response.where(map_id: params[:id2], round: round).last
        instance_variable_set('@response_round_' + round.to_s, response)
        next if response.nil?
        instance_variable_set('@response_id_round_' + round.to_s, response.id)
        instance_variable_set('@scores_round_' + round.to_s, Answer.where(response_id: response.id))
        questionnaire = Response.find(response.id).questionnaire_by_answer(instance_variable_get('@scores_round_' + round.to_s).first)
        instance_variable_set('@max_score_round_' + round.to_s, questionnaire.max_question_score ||= 5)
        total_percentage = response.average_score
        total_percentage += '%' if total_percentage.is_a? Float
        instance_variable_set('@total_percentage_round_' + round.to_s, total_percentage)
        instance_variable_set('@sum_round_' + round.to_s, response.total_score)
        instance_variable_set('@total_possible_round_' + round.to_s, response.maximum_score)
      end
    end

    all_assignments = Assignment.where(:instructor_id=>session[:user].id)
    @similar_assignments = []
    all_assignments.each do |assignment|
      if (string_similarity(@assignment.name, assignment.name) > ASSIGNMENT_NAME_SIMILARITY_THRESHOLD)
        @similar_assignments << assignment
      end
    end
    @similar_assignments = @similar_assignments.sort_by { |sim_assignment| -sim_assignment.id }
  end

  def view_review_scores_popup
    @reviewer_id = params[:reviewer_id]
    @assignment_id = params[:assignment_id]
    @review_final_versions = ReviewResponseMap.final_versions_from_reviewer(@assignment_id, @reviewer_id)
    @reviews = []

    assignment = Assignment.find(@assignment_id)
    flash.now[:error] = "This report is not implemented for assignments where the rubric varies by topic." if assignment.vary_by_topic

    # Builds tone analysis report and heatmap when instructor/admin/superadmin clicks on the "View Review Report" Icon for an assignment.
    build_tone_analysis_report
    build_tone_analysis_heatmap
  end

  def build_tone_analysis_report
    uri =  WEBSERVICE_CONFIG['sentiment_webservice_url'] + "analyze_reviews_bulk"
    index = 0
    @sentiment_summary = []
    keys = @review_final_versions.keys
    reviews = []
    round = 0

    # Loops by each review round
    keys.each do |key|
      questionnaire = Questionnaire.find(@review_final_versions[key][:questionnaire_id])
      questions = Question.where(questionnaire_id: questionnaire.id)

      # Loops by each question per review round
      questions.each do |question|
        # Loops an array of reviewee ids by review round
        @review_final_versions[key][:response_ids].each do |responseid|
          # If an answer to a question is not provided by a reviewer, add a default comment so that the tone analysis chart can
          # color the comment grey in the heatmap.  Otherwise, add their comment to the list of reviews.
          if Answer.where(response_id: responseid, question_id: question.id) == []
            comment = "N/A"
            param = {
              id: index,
              text: comment
            }
            reviews[index] = param
            index += 1
          else
            Answer.where(response_id: responseid, question_id: question.id).each do |review|
              comment = review.comments
              comment = "N/A" if review.comments.nil?
              param = {
                id: index,
                text: comment
              }
              reviews[index] = param
              index += 1
            end
          end
        end
      end

      if !reviews.empty?
        index = 0
        revs = {
          reviews: reviews
        }

        # calls web service
        sum_json = RestClient.post uri, revs.to_json, content_type: 'application/json; charset=UTF-8', accept: :json
        # store each summary in a hashmap and use the question as the key
        @sentiment_summary[round] = JSON.parse(sum_json)
      end
      round += 1
    end
  rescue StandardError => err
    logger.error err.message
  end

  def build_tone_analysis_heatmap

    @heatmap_urls = []
    keys = @review_final_versions.keys

    # Loops by each review round
    keys.each_with_index do |key, round|
      next if @sentiment_summary[round].nil?
      content = []
      v_label = []
      h_label = []
      questionnaire_id = Questionnaire.find(@review_final_versions[key][:questionnaire_id])
      questions = Question.where(questionnaire_id: questionnaire_id)<commit_msg>Added brief comments for methods<commit_after>class PopupController < ApplicationController
  include StringOperationHelper
  include AuthorizationHelper
  ASSIGNMENT_NAME_SIMILARITY_THRESHOLD = 0.50

  def action_allowed?
    current_user_has_ta_privileges?
  end

  # this can be called from "response_report" by clicking student names from instructor end.
  def author_feedback_popup
    @response_id = params[:response_id]
    @reviewee_id = params[:reviewee_id]
    unless @response_id.nil?
      first_question_in_questionnaire = Answer.where(response_id: @response_id).first.question_id
      questionnaire_id = Question.find(first_question_in_questionnaire).questionnaire_id
      questionnaire = Questionnaire.find(questionnaire_id)
      @maxscore = questionnaire.max_question_score
      @scores = Answer.where(response_id: @response_id)
      @response = Response.find(@response_id)
      @total_percentage = @response.average_score
      @sum = @response.total_score
      @total_possible = @response.maximum_score
    end

    @maxscore = 5 if @maxscore.nil?

    unless @response_id.nil?
      participant = Participant.find(@reviewee_id)
      @user = User.find(participant.user_id)
    end
  end

  # this can be called from "response_report" by clicking team names from instructor end.
  def team_users_popup
    @sum = 0
    @team = Team.find(params[:id])
    @assignment = Assignment.find(@team.parent_id)
    @team_users = TeamsUser.where(team_id: params[:id])

    # id2 is a response_map id
    unless params[:id2].nil?
      # E1973 - we set the reviewer id either to the student's user id or the current reviewer id
      # This results from reviewers being either assignment participants or assignment teams.
      # If the reviewer is a participant, the id is currently the id of the assignment participant.
      # However, we want their user_id. This is not possible for teams, so we just return the current id
      reviewer_id = ResponseMap.find(params[:id2]).reviewer_id
      if @assignment.reviewer_is_team
        @reviewer_id = Participant.find(reviewer_id).user_id
      else
        @reviewer_id = reviewer_id
      end
      # get the last response in each round from response_map id
      (1..@assignment.num_review_rounds).each do |round|
        response = Response.where(map_id: params[:id2], round: round).last
        instance_variable_set('@response_round_' + round.to_s, response)
        next if response.nil?
        instance_variable_set('@response_id_round_' + round.to_s, response.id)
        instance_variable_set('@scores_round_' + round.to_s, Answer.where(response_id: response.id))
        questionnaire = Response.find(response.id).questionnaire_by_answer(instance_variable_get('@scores_round_' + round.to_s).first)
        instance_variable_set('@max_score_round_' + round.to_s, questionnaire.max_question_score ||= 5)
        total_percentage = response.average_score
        total_percentage += '%' if total_percentage.is_a? Float
        instance_variable_set('@total_percentage_round_' + round.to_s, total_percentage)
        instance_variable_set('@sum_round_' + round.to_s, response.total_score)
        instance_variable_set('@total_possible_round_' + round.to_s, response.maximum_score)
      end
    end

    all_assignments = Assignment.where(:instructor_id=>session[:user].id)
    @similar_assignments = []
    all_assignments.each do |assignment|
      if (string_similarity(@assignment.name, assignment.name) > ASSIGNMENT_NAME_SIMILARITY_THRESHOLD)
        @similar_assignments << assignment
      end
    end
    @similar_assignments = @similar_assignments.sort_by { |sim_assignment| -sim_assignment.id }
  end

  # Views tone analysis report and heatmap
  def view_review_scores_popup
    @reviewer_id = params[:reviewer_id]
    @assignment_id = params[:assignment_id]
    @review_final_versions = ReviewResponseMap.final_versions_from_reviewer(@assignment_id, @reviewer_id)
    @reviews = []

    assignment = Assignment.find(@assignment_id)
    flash.now[:error] = "This report is not implemented for assignments where the rubric varies by topic." if assignment.vary_by_topic

    # Builds tone analysis report and heatmap when instructor/admin/superadmin clicks on the "View Review Report" Icon for an assignment.
    build_tone_analysis_report
    build_tone_analysis_heatmap
  end

  # Builds tone analysis report
  def build_tone_analysis_report
    uri =  WEBSERVICE_CONFIG['sentiment_webservice_url'] + "analyze_reviews_bulk"
    index = 0
    @sentiment_summary = []
    keys = @review_final_versions.keys
    reviews = []
    round = 0

    # Loops by each review round
    keys.each do |key|
      questionnaire = Questionnaire.find(@review_final_versions[key][:questionnaire_id])
      questions = Question.where(questionnaire_id: questionnaire.id)

      # Loops by each question per review round
      questions.each do |question|
        # Loops an array of reviewee ids by review round
        @review_final_versions[key][:response_ids].each do |responseid|
          # If an answer to a question is not provided by a reviewer, add a default comment so that the tone analysis chart can
          # color the comment grey in the heatmap.  Otherwise, add their comment to the list of reviews.
          if Answer.where(response_id: responseid, question_id: question.id) == []
            comment = "N/A"
            param = {
              id: index,
              text: comment
            }
            reviews[index] = param
            index += 1
          else
            Answer.where(response_id: responseid, question_id: question.id).each do |review|
              comment = review.comments
              comment = "N/A" if review.comments.nil?
              param = {
                id: index,
                text: comment
              }
              reviews[index] = param
              index += 1
            end
          end
        end
      end

      if !reviews.empty?
        index = 0
        revs = {
          reviews: reviews
        }

        # calls web service
        sum_json = RestClient.post uri, revs.to_json, content_type: 'application/json; charset=UTF-8', accept: :json
        # store each summary in a hashmap and use the question as the key
        @sentiment_summary[round] = JSON.parse(sum_json)
      end
      round += 1
    end
  rescue StandardError => err
    logger.error err.message
  end

  # Builds tone analysis heatmap
  def build_tone_analysis_heatmap

    @heatmap_urls = []
    keys = @review_final_versions.keys

    # Loops by each review round
    keys.each_with_index do |key, round|
      next if @sentiment_summary[round].nil?
      content = []
      v_label = []
      h_label = []
      questionnaire_id = Questionnaire.find(@review_final_versions[key][:questionnaire_id])
      questions = Question.where(questionnaire_id: questionnaire_id)
{'fraction_non_alphanumeric': 0.08044799063026133, 'fraction_numerical': 0.0032208476685454943, 'mean_word_length': 3.087971274685817, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, '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': '5197857', 'n_tokens_mistral': 4085, 'n_tokens_neox': 3944, 'n_words': 999}