# # 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}"}) 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 = format_running_stat(results) return { :output_file_name => output_file_name, :running_stat => stat, :comment => "", :cmp_msg => cmp_msg} else return { :running_stat => "", :comment => "Compilation error", :cmp_msg => cmp_msg} end end def format_running_stat(results) running_time_line = results[-1] run_stat = "" if !(/[Cc]orrect/.match(results[0])) run_stat = results[0].chomp end if res = /r(.*)u(.*)s/.match(running_time_line) seconds = (res[1].to_f + res[2].to_f) time_stat = "Time used: #{seconds} sec." else time_stat = "Time used: n/a sec." end return "#{run_stat}#{time_stat}" end def save_result(test_request,result) if result[:output_file_name]!=nil test_request.output_file_name = link_output_file(test_request, result[:output_file_name]) end test_request.graded_at = Time.now test_request.compiler_message = (result[:cmp_msg] or '') test_request.grader_comment = (result[:comment] or '') test_request.running_stat = (result[:running_stat] or '') test_request.save end protected def link_output_file(test_request, fname) target_file_name = random_output_file_name(test_request.user, test_request.problem) FileUtils.mkdir_p(File.dirname(target_file_name)) cmd = "ln -s #{fname} #{target_file_name}" if !system(cmd) raise "TestRequestReporter: cannot move output file" end return target_file_name end def random_output_file_name(user,problem) problem_name = TestRequest.name_of(problem) begin tmpname = "#{@config.test_request_output_base_dir}" + "/#{user.login}/#{problem_name}/#{rand(10000)}" end while File.exists?(tmpname) tmpname end end end