Description:
fixed test run scoring bug: now it takes the minimum of each test case's score git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@273 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r66:c03ebf30fb10 - - 4 files changed: 17 inserted, 16 deleted

@@ -1,127 +1,129
1 #
1 #
2 # This part contains various test_request helpers for interfacing
2 # This part contains various test_request helpers for interfacing
3 # with Grader::Engine. There are TestRequestRoomMaker and
3 # with Grader::Engine. There are TestRequestRoomMaker and
4 # TestRequestReporter.
4 # TestRequestReporter.
5
5
6 module Grader
6 module Grader
7
7
8 #
8 #
9 # A TestRequestRoomMaker is a helper object for Engine
9 # A TestRequestRoomMaker is a helper object for Engine
10 # - finds grading room: in user_result_dir/(user)/test_request/ ...
10 # - finds grading room: in user_result_dir/(user)/test_request/ ...
11 # - prepare problem configuration for grading --- basically it copy
11 # - prepare problem configuration for grading --- basically it copy
12 # all config files, and copy user's input into the testcase
12 # all config files, and copy user's input into the testcase
13 # directory. First, it finds the template from problem template
13 # directory. First, it finds the template from problem template
14 # directory; if it can't find a template, it'll use the template
14 # directory; if it can't find a template, it'll use the template
15 # from default template.
15 # from default template.
16 class TestRequestRoomMaker
16 class TestRequestRoomMaker
17 def initialize
17 def initialize
18 @config = Grader::Configuration.get_instance
18 @config = Grader::Configuration.get_instance
19 end
19 end
20
20
21 def produce_grading_room(test_request)
21 def produce_grading_room(test_request)
22 grading_room = grading_room_dir(test_request)
22 grading_room = grading_room_dir(test_request)
23 FileUtils.mkdir_p(grading_room)
23 FileUtils.mkdir_p(grading_room)
24
24
25 #
25 #
26 # Also copy additional submitted file to this directory as well.
26 # Also copy additional submitted file to this directory as well.
27 # The program would see this file only if it is copied
27 # The program would see this file only if it is copied
28 # to the sandbox directory later. The run script should do it.
28 # to the sandbox directory later. The run script should do it.
29 #
29 #
30 + if FileTest.exists?("#{test_request.input_file_name}.files")
30 cmd = "cp #{test_request.input_file_name}.files/* #{grading_room}"
31 cmd = "cp #{test_request.input_file_name}.files/* #{grading_room}"
31 system(cmd)
32 system(cmd)
33 + end
32
34
33 grading_room
35 grading_room
34 end
36 end
35
37
36 def find_problem_home(test_request)
38 def find_problem_home(test_request)
37 problem_name = test_request.problem_name
39 problem_name = test_request.problem_name
38
40
39 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
41 template_dir = "#{@config.test_request_problem_templates_dir}/" + problem_name
40
42
41 raise "Test Request: error template not found" if !File.exists?(template_dir)
43 raise "Test Request: error template not found" if !File.exists?(template_dir)
42
44
43 problem_home = problem_home_dir(test_request)
45 problem_home = problem_home_dir(test_request)
44 FileUtils.mkdir_p(problem_home)
46 FileUtils.mkdir_p(problem_home)
45
47
46 copy_problem_template(template_dir,problem_home)
48 copy_problem_template(template_dir,problem_home)
47 link_input_file(test_request,problem_home)
49 link_input_file(test_request,problem_home)
48
50
49 problem_home
51 problem_home
50 end
52 end
51
53
52 def save_source(test_request,source_name)
54 def save_source(test_request,source_name)
53 dir = self.produce_grading_room(test_request)
55 dir = self.produce_grading_room(test_request)
54 submission = test_request.submission
56 submission = test_request.submission
55 f = File.open("#{dir}/#{source_name}","w")
57 f = File.open("#{dir}/#{source_name}","w")
56 f.write(submission.source)
58 f.write(submission.source)
57 f.close
59 f.close
58 end
60 end
59
61
60 def clean_up(test_request)
62 def clean_up(test_request)
61 problem_home = problem_home_dir(test_request)
63 problem_home = problem_home_dir(test_request)
62 remove_data_files(problem_home)
64 remove_data_files(problem_home)
63 end
65 end
64
66
65 protected
67 protected
66 def grading_room_dir(test_request)
68 def grading_room_dir(test_request)
67 problem_name = test_request.problem_name
69 problem_name = test_request.problem_name
68 user = test_request.user
70 user = test_request.user
69 grading_room = "#{@config.user_result_dir}" +
71 grading_room = "#{@config.user_result_dir}" +
70 "/#{user.login}/test_request" +
72 "/#{user.login}/test_request" +
71 "/#{problem_name}/#{test_request.id}"
73 "/#{problem_name}/#{test_request.id}"
72 grading_room
74 grading_room
73 end
75 end
74
76
75 def problem_home_dir(test_request)
77 def problem_home_dir(test_request)
76 problem_name = test_request.problem_name
78 problem_name = test_request.problem_name
77 user = test_request.user
79 user = test_request.user
78 "#{@config.user_result_dir}" +
80 "#{@config.user_result_dir}" +
79 "/#{user.login}/test_request/#{problem_name}"
81 "/#{user.login}/test_request/#{problem_name}"
80 end
82 end
81
83
82 def copy_problem_template(template_dir,problem_home)
84 def copy_problem_template(template_dir,problem_home)
83 cmd = "cp -R #{template_dir}/* #{problem_home}"
85 cmd = "cp -R #{template_dir}/* #{problem_home}"
84 system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
86 system_and_raise_when_fail(cmd,"Test Request: cannot copy problem template")
85 end
87 end
86
88
87 def link_input_file(test_request,problem_home)
89 def link_input_file(test_request,problem_home)
88 input_fname = "#{test_request.input_file_name}"
90 input_fname = "#{test_request.input_file_name}"
89 if !File.exists?(input_fname)
91 if !File.exists?(input_fname)
90 raise "Test Request: input file not found."
92 raise "Test Request: input file not found."
91 end
93 end
92
94
93 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
95 input_fname_problem_home = "#{problem_home}/test_cases/1/input-1.txt"
94 if File.exists?(input_fname_problem_home)
96 if File.exists?(input_fname_problem_home)
95 FileUtils.rm([input_fname_problem_home], :force => true)
97 FileUtils.rm([input_fname_problem_home], :force => true)
96 end
98 end
97
99
98 cmd = "ln -s #{input_fname} #{input_fname_problem_home}"
100 cmd = "ln -s #{input_fname} #{input_fname_problem_home}"
99 system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
101 system_and_raise_when_fail(cmd,"Test Request: cannot link input file")
100 end
102 end
101
103
102 def remove_data_files(problem_home)
104 def remove_data_files(problem_home)
103 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
105 if File.exists?("#{problem_home}/test_cases/1/input-1.txt")
104 cmd = "rm #{problem_home}/test_cases/1/*"
106 cmd = "rm #{problem_home}/test_cases/1/*"
105 system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
107 system_and_raise_when_fail(cmd,"Test Request: cannot remove data files")
106 end
108 end
107 end
109 end
108
110
109 def system_and_raise_when_fail(cmd,msg)
111 def system_and_raise_when_fail(cmd,msg)
110 if !system(cmd)
112 if !system(cmd)
111 raise msg
113 raise msg
112 end
114 end
113 end
115 end
114
116
115 end
117 end
116
118
117 class TestRequestReporter
119 class TestRequestReporter
118 def initialize
120 def initialize
119 @config = Grader::Configuration.get_instance
121 @config = Grader::Configuration.get_instance
120 end
122 end
121
123
122 def report(test_request,test_result_dir)
124 def report(test_request,test_result_dir)
123 save_result(test_request,read_result(test_result_dir))
125 save_result(test_request,read_result(test_result_dir))
124 end
126 end
125
127
126 def report_error(test_request, msg)
128 def report_error(test_request, msg)
127 save_result(test_request, {:running_stat => {
129 save_result(test_request, {:running_stat => {
@@ -1,108 +1,106
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 CORRECT_MARK = 'P'
3 CORRECT_MARK = 'P'
4 INCORRECT_MARK = '-'
4 INCORRECT_MARK = '-'
5 TIMEOUT_MARK = 'T'
5 TIMEOUT_MARK = 'T'
6 RUN_ERROR_MARK = 'x'
6 RUN_ERROR_MARK = 'x'
7
7
8 def log(str='')
8 def log(str='')
9 if ENV['TALKATIVE']!=nil
9 if ENV['TALKATIVE']!=nil
10 puts str
10 puts str
11 end
11 end
12 if ENV['GRADER_LOGGING']!=nil
12 if ENV['GRADER_LOGGING']!=nil
13 log_fname = ENV['GRADER_LOGGING']
13 log_fname = ENV['GRADER_LOGGING']
14 fp = File.open(log_fname,"a")
14 fp = File.open(log_fname,"a")
15 fp.puts("grade: #{Time.new.strftime("%H:%M")} #{str}")
15 fp.puts("grade: #{Time.new.strftime("%H:%M")} #{str}")
16 fp.close
16 fp.close
17 end
17 end
18 end
18 end
19
19
20 def char_comment(comment)
20 def char_comment(comment)
21 if comment =~ /[Ii]ncorrect/
21 if comment =~ /[Ii]ncorrect/
22 INCORRECT_MARK
22 INCORRECT_MARK
23 elsif comment =~ /[Cc]orrect/
23 elsif comment =~ /[Cc]orrect/
24 CORRECT_MARK
24 CORRECT_MARK
25 elsif comment =~ /[Tt]ime/
25 elsif comment =~ /[Tt]ime/
26 TIMEOUT_MARK
26 TIMEOUT_MARK
27 elsif res = /^[Cc]omment:(.*)$/.match(comment)
27 elsif res = /^[Cc]omment:(.*)$/.match(comment)
28 res[1]
28 res[1]
29 else
29 else
30 RUN_ERROR_MARK # these are run time errors
30 RUN_ERROR_MARK # these are run time errors
31 end
31 end
32 end
32 end
33
33
34 problem_home = ENV['PROBLEM_HOME']
34 problem_home = ENV['PROBLEM_HOME']
35 require "#{problem_home}/script/test_dsl.rb"
35 require "#{problem_home}/script/test_dsl.rb"
36 load "#{problem_home}/test_cases/all_tests.cfg"
36 load "#{problem_home}/test_cases/all_tests.cfg"
37 problem = Problem.get_instance
37 problem = Problem.get_instance
38
38
39 if problem.well_formed? == false
39 if problem.well_formed? == false
40 log "The problem specification is not well formed."
40 log "The problem specification is not well formed."
41 exit(127)
41 exit(127)
42 end
42 end
43
43
44 all_score = 0
44 all_score = 0
45 all_comment = ''
45 all_comment = ''
46 (1..(problem.runs.length-1)).each do |k|
46 (1..(problem.runs.length-1)).each do |k|
47 log "grade run #{k}"
47 log "grade run #{k}"
48 run = problem.runs[k]
48 run = problem.runs[k]
49 - run_score = 0
49 + run_score = nil
50 run_comment = ''
50 run_comment = ''
51 run_comment_short = ''
51 run_comment_short = ''
52 run.tests.each do |test_num|
52 run.tests.each do |test_num|
53 result_file_name = "#{test_num}/result"
53 result_file_name = "#{test_num}/result"
54 if not File.exists?(result_file_name)
54 if not File.exists?(result_file_name)
55 run_comment += "result file for test #{test_num} not found\n"
55 run_comment += "result file for test #{test_num} not found\n"
56 run_comment_short += RUN_ERROR_MARK
56 run_comment_short += RUN_ERROR_MARK
57 log "Cannot find the file #{test_num}/result!"
57 log "Cannot find the file #{test_num}/result!"
58 else
58 else
59 result_file = File.new(result_file_name, "r")
59 result_file = File.new(result_file_name, "r")
60 result_file_lines = result_file.readlines
60 result_file_lines = result_file.readlines
61 if result_file_lines.length>=2
61 if result_file_lines.length>=2
62 - run_score = run_score + result_file_lines[1].to_i
62 + current_run_score = result_file_lines[1].to_i
63 run_comment += result_file_lines[0]
63 run_comment += result_file_lines[0]
64 run_comment_short += char_comment(result_file_lines[0].chomp)
64 run_comment_short += char_comment(result_file_lines[0].chomp)
65 else
65 else
66 + current_run_score = 0
66 run_comment += "result file for test #{test_num} error\n"
67 run_comment += "result file for test #{test_num} error\n"
67 run_comment_short += RUN_ERROR_MARK
68 run_comment_short += RUN_ERROR_MARK
68 log "Error in #{test_num}/result!"
69 log "Error in #{test_num}/result!"
69 end
70 end
71 +
72 + # the score of this run should be the minimum of the score for
73 + # each test case
74 + if (run_score==nil) or (run_score>current_run_score)
75 + run_score = current_run_score
76 + end
70 result_file.close
77 result_file.close
71 end
78 end
72 end
79 end
73
80
74 - # find total score for this run
75 - run_total_score = 0
76 - problem = Problem.get_instance
77 - run.tests.each { |test_num| run_total_score += problem.get_score(test_num) }
78 -
79 - if run_total_score!=run_score # fail in some test cases, fail the run
80 - run_score = 0
81 - end
82 -
83 run_result_file = File.new("result-#{k}", "w")
81 run_result_file = File.new("result-#{k}", "w")
84 run_result_file.write run_score
82 run_result_file.write run_score
85 run_result_file.write "\n"
83 run_result_file.write "\n"
86 run_result_file.close
84 run_result_file.close
87
85
88 run_comment_file = File.new("comment-#{k}", "w")
86 run_comment_file = File.new("comment-#{k}", "w")
89 run_comment_file.write "#{run_comment}\n"
87 run_comment_file.write "#{run_comment}\n"
90 run_comment_file.close
88 run_comment_file.close
91
89
92 all_score = all_score + run_score
90 all_score = all_score + run_score
93
91
94 # append comment for test run with many test cases
92 # append comment for test run with many test cases
95 if run.tests.length > 1
93 if run.tests.length > 1
96 run_comment_short = '[' + run_comment_short + ']'
94 run_comment_short = '[' + run_comment_short + ']'
97 end
95 end
98 all_comment += run_comment_short
96 all_comment += run_comment_short
99 end
97 end
100
98
101 result_file = File.new("result", "w")
99 result_file = File.new("result", "w")
102 result_file.write all_score
100 result_file.write all_score
103 result_file.write "\n"
101 result_file.write "\n"
104 result_file.close
102 result_file.close
105
103
106 comment_file = File.new("comment", "w")
104 comment_file = File.new("comment", "w")
107 comment_file.write "#{all_comment}\n"
105 comment_file.write "#{all_comment}\n"
108 comment_file.close
106 comment_file.close
@@ -1,20 +1,20
1 problem do
1 problem do
2 num_tests <%= num_testcases %>
2 num_tests <%= num_testcases %>
3 full_score <%= num_testruns*10 %>
3 full_score <%= num_testruns*10 %>
4 time_limit_each <%= options[:time_limit] %>
4 time_limit_each <%= options[:time_limit] %>
5 mem_limit_each <%= options[:mem_limit] %>
5 mem_limit_each <%= options[:mem_limit] %>
6 score_each 10
6 score_each 10
7
7
8 <% tr_num = 0 %>
8 <% tr_num = 0 %>
9 <% testrun_info.each do |testrun| %>
9 <% testrun_info.each do |testrun| %>
10 <% tr_num += 1 %>
10 <% tr_num += 1 %>
11 run <%= tr_num %> do
11 run <%= tr_num %> do
12 tests <%= (testrun.collect {|testcase| testcase[0]}).join(", ") %>
12 tests <%= (testrun.collect {|testcase| testcase[0]}).join(", ") %>
13 <% if testrun.length==1 %>
13 <% if testrun.length==1 %>
14 scores 10
14 scores 10
15 <% else %>
15 <% else %>
16 - scores 10 <% (testrun.length-1).times do %>,0 <% end %>
16 + scores 10 <% (testrun.length-1).times do %>,10 <% end %>
17 <% end %>
17 <% end %>
18 end
18 end
19 <% end %>
19 <% end %>
20 end
20 end
@@ -1,39 +1,40
1 problem do
1 problem do
2 num_tests 10
2 num_tests 10
3 full_score 135
3 full_score 135
4 time_limit_each 1
4 time_limit_each 1
5 mem_limit_each 11
5 mem_limit_each 11
6 score_each 10
6 score_each 10
7
7
8 run 1 do
8 run 1 do
9 tests 1, 2
9 tests 1, 2
10 - scores 10, 20
10 + scores 30, 30
11 time_limits 1, 2
11 time_limits 1, 2
12 mem_limits 5, 6
12 mem_limits 5, 6
13 end
13 end
14
14
15 run 2 do
15 run 2 do
16 tests 3, 4, 5, 6, 7
16 tests 3, 4, 5, 6, 7
17 - score_each 10
17 + score_each 50
18 time_limit_each 3
18 time_limit_each 3
19 mem_limit_each 3
19 mem_limit_each 3
20 end
20 end
21
21
22 run 3 do
22 run 3 do
23 tests 8, 9, 10
23 tests 8, 9, 10
24 end
24 end
25
25
26 test 8 do
26 test 8 do
27 - score 30
27 + score 55
28 time_limit 3
28 time_limit 3
29 mem_limit 10
29 mem_limit 10
30 end
30 end
31
31
32 test 9 do
32 test 9 do
33 - score 15
33 + score 55
34 end
34 end
35
35
36 test 10 do
36 test 10 do
37 + score 55
37 time_limit 1
38 time_limit 1
38 end
39 end
39 end
40 end
You need to be logged in to leave comments. Login now