<commit_before>#
# This part contains various test_request helpers for interfacing
# with Grader::Engine.  There are TestRequestRoomMaker and
# TestRequestReporter.

module Grader

  #
  # A TestRequestRoomMaker is a helper object for Engine
  # - finds grading room: in user_result_dir/(user)/test_request/ ...
  # - prepare problem configuration for grading --- basically it copy
  #   all config files, and copy user's input into the testcase
  #   directory.  First, it finds the template from problem template
  #   directory; if it can't find a template, it'll use the template
  #   from default template.
  class TestRequestRoomMaker
    def initialize
      @config = Grader::Configuration.get_instance
    end
    
    def produce_grading_room(test_request)
      grading_room = grading_room_dir(test_request)
      FileUtils.mkdir_p(grading_room)
      grading_room
    end
    
    def find_problem_home(test_request)
      problem_name = test_request.problem_name

      template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name

      raise "Test Request: error template not found" if !File.exists?(template_dir)
      
      problem_home = problem_home_dir(test_request)
      FileUtils.mkdir_p(problem_home)
      
      copy_problem_template(template_dir,problem_home)
      link_input_file(test_request,problem_home)

      problem_home
    end
    
    def save_source(test_request,source_name)
      dir = self.produce_grading_room(test_request)
      submission = test_request.submission
      f = File.open("#{dir}/#{source_name}","w")
      f.write(submission.source)
      f.close
    end
    
    def clean_up(test_request)
      problem_home = problem_home_dir(test_request)
      remove_data_files(problem_home)
    end
    
    protected
    def grading_room_dir(test_request)
      problem_name = test_request.problem_name
      user = test_request.user
      "#{@config.user_result_dir}" + 
        "/#{user.login}/test_request" +
        "/#{problem_name}/#{test_request.id}"
    end
    
    def problem_home_dir(test_request)
      problem_name = test_request.problem_name
      user = test_request.user
      "#{@config.user_result_dir}" + 
        "/#{user.login}/test_request/#{problem_name}"
    end
    
    def copy_problem_template(template_dir,problem_home)
      cmd = "cp -R #{template_dir}/* #{problem_home}"
      system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
    end
    
    def link_input_file(test_request,problem_home)
      cmd = "ln -s #{test_request.input_file_name} #{problem_home}/test_cases/1/input-1.txt"
      system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
    end
    
    def remove_data_files(problem_home)
      if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
        cmd = "rm #{problem_home}/test_cases/1/*"
        system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
      end
    end
    
    def system_and_raise_when_fail(cmd,msg)
      if !system(cmd)
        raise msg
      end
    end
    
  end
  
  class TestRequestReporter
    def initialize
      @config = Grader::Configuration.get_instance
    end
    
    def report(test_request,test_result_dir)
      save_result(test_request,read_result(test_result_dir))
    end

    def report_error(test_request, msg)
      save_result(test_request, {:running_stat => {:msg => "#{msg}"}})
    end
    
    protected
    def read_result(test_result_dir)
      # TODO:
      cmp_msg_fname = "#{test_result_dir}/compiler_message"
      cmp_file = File.open(cmp_msg_fname)
      cmp_msg = cmp_file.read
      cmp_file.close
      
      result_file_name = "#{test_result_dir}/1/result"

      if File.exists?(result_file_name)
        output_file_name = "#{test_result_dir}/1/output.txt"
        results = File.open("#{test_result_dir}/1/result").readlines
        stat = extract_running_stat(results)

        return {
          :output_file_name => output_file_name,
          :running_stat => stat,
          :comment => "", 
          :cmp_msg => cmp_msg}
      else
        return {
          :running_stat => nil,
          :comment => "Compilation error", 
          :cmp_msg => cmp_msg}
      end<commit_msg>[grader] test_request: fixed error when input file is not found, or input file remains in problem home<commit_after>#
# This part contains various test_request helpers for interfacing
# with Grader::Engine.  There are TestRequestRoomMaker and
# TestRequestReporter.

module Grader

  #
  # A TestRequestRoomMaker is a helper object for Engine
  # - finds grading room: in user_result_dir/(user)/test_request/ ...
  # - prepare problem configuration for grading --- basically it copy
  #   all config files, and copy user's input into the testcase
  #   directory.  First, it finds the template from problem template
  #   directory; if it can't find a template, it'll use the template
  #   from default template.
  class TestRequestRoomMaker
    def initialize
      @config = Grader::Configuration.get_instance
    end
    
    def produce_grading_room(test_request)
      grading_room = grading_room_dir(test_request)
      FileUtils.mkdir_p(grading_room)
      grading_room
    end
    
    def find_problem_home(test_request)
      problem_name = test_request.problem_name

      template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name

      raise "Test Request: error template not found" if !File.exists?(template_dir)
      
      problem_home = problem_home_dir(test_request)
      FileUtils.mkdir_p(problem_home)
      
      copy_problem_template(template_dir,problem_home)
      link_input_file(test_request,problem_home)

      problem_home
    end
    
    def save_source(test_request,source_name)
      dir = self.produce_grading_room(test_request)
      submission = test_request.submission
      f = File.open("#{dir}/#{source_name}","w")
      f.write(submission.source)
      f.close
    end
    
    def clean_up(test_request)
      problem_home = problem_home_dir(test_request)
      remove_data_files(problem_home)
    end
    
    protected
    def grading_room_dir(test_request)
      problem_name = test_request.problem_name
      user = test_request.user
      "#{@config.user_result_dir}" + 
        "/#{user.login}/test_request" +
        "/#{problem_name}/#{test_request.id}"
    end
    
    def problem_home_dir(test_request)
      problem_name = test_request.problem_name
      user = test_request.user
      "#{@config.user_result_dir}" + 
        "/#{user.login}/test_request/#{problem_name}"
    end
    
    def copy_problem_template(template_dir,problem_home)
      cmd = "cp -R #{template_dir}/* #{problem_home}"
      system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
    end
    
    def link_input_file(test_request,problem_home)
      input_fname = "#{test_request.input_file_name}"
      if !File.exists?(input_fname)
        raise "Test Request: input file not found."
      end

      input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
      if File.exists?(input_fname_problem_home)
        FileUtils.rm([input_fname_problem_home], :force => true)
      end

      cmd = "ln -s #{input_fname} #{input_fname_problem_home}" 
      system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
    end
    
    def remove_data_files(problem_home)
      if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
        cmd = "rm #{problem_home}/test_cases/1/*"
        system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
      end
    end
    
    def system_and_raise_when_fail(cmd,msg)
      if !system(cmd)
        raise msg
      end
    end
    
  end
  
  class TestRequestReporter
    def initialize
      @config = Grader::Configuration.get_instance
    end
    
    def report(test_request,test_result_dir)
      save_result(test_request,read_result(test_result_dir))
    end

    def report_error(test_request, msg)
      save_result(test_request, {:running_stat => {
                      :msg => "#{msg}",
                      :running_time => nil,
                      :exit_status => "Some error occured. Program did not run",
                      :memory_usage => nil
                    }})
    end
    
    protected
    def read_result(test_result_dir)
      # TODO:
      cmp_msg_fname = "#{test_result_dir}/compiler_message"
      cmp_file = File.open(cmp_msg_fname)
      cmp_msg = cmp_file.read
      cmp_file.close
      
      result_file_name = "#{test_result_dir}/1/result"

      if File.exists?(result_file_name)
        output_file_name = "#{test_result_dir}/1/output.txt"
        results = File.open("#{test_result_dir}/1/result").readlines
        stat = extract_running_stat(results)

        return {
          :output_file_name => output_file_name,
          :running_stat => stat,
          :comment => "", 
          :cmp_msg => cmp_msg}
      else
        return {
          :running_stat => nil,
          :comment => "Compilation error", 
          :cmp_msg => cmp_msg}
      end
{'fraction_non_alphanumeric': 0.09191741708763453, 'fraction_numerical': 0.0017570832418185812, 'mean_word_length': 2.837758112094395, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, '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': '5494342', 'n_tokens_mistral': 2908, 'n_tokens_neox': 2822, 'n_words': 565}