|
|
#!/usr/bin/ruby
|
|
|
|
|
|
def talk(str)
|
|
|
if TALKATIVE
|
|
|
puts str
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def execute(command, error_message="")
|
|
|
if not system(command)
|
|
|
puts "ERROR: #{error_message}"
|
|
|
exit(127)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def save_source(submission,dir,fname)
|
|
|
f = File.open("#{dir}/#{fname}","w")
|
|
|
f.write(submission.source)
|
|
|
f.close
|
|
|
end
|
|
|
|
|
|
def call_judge(problem_home,language,problem_out_dir,fname)
|
|
|
ENV['PROBLEM_HOME'] = problem_home
|
|
|
|
|
|
puts problem_out_dir
|
|
|
Dir.chdir problem_out_dir
|
|
|
cmd = "#{problem_home}/script/judge #{language} #{fname}"
|
|
|
# puts "CMD: #{cmd}"
|
|
|
system(cmd)
|
|
|
end
|
|
|
|
|
|
def read_result(test_result_dir)
|
|
|
cmp_msg_fname = "#{test_result_dir}/compiler_message"
|
|
|
cmp_file = File.open(cmp_msg_fname)
|
|
|
cmp_msg = cmp_file.read
|
|
|
cmp_file.close
|
|
|
|
|
|
result_fname = "#{test_result_dir}/result"
|
|
|
comment_fname = "#{test_result_dir}/comment"
|
|
|
if FileTest.exist?(result_fname)
|
|
|
result_file = File.open(result_fname)
|
|
|
result = result_file.readline.to_i
|
|
|
result_file.close
|
|
|
|
|
|
comment_file = File.open(comment_fname)
|
|
|
comment = comment_file.readline.chomp
|
|
|
comment_file.close
|
|
|
|
|
|
return {:points => result,
|
|
|
:comment => comment,
|
|
|
:cmp_msg => cmp_msg}
|
|
|
else
|
|
|
return {:points => 0,
|
|
|
:comment => 'compile error',
|
|
|
:cmp_msg => cmp_msg}
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def save_result(submission,result)
|
|
|
problem = Problem.find(submission.problem_id)
|
|
|
submission.graded_at = Time.now
|
|
|
submission.points = result[:points]
|
|
|
if submission.points == problem.full_score
|
|
|
submission.grader_comment = 'PASSED: ' + report_comment(result[:comment])
|
|
|
else
|
|
|
submission.grader_comment = 'FAILED: ' + report_comment(result[:comment])
|
|
|
end
|
|
|
submission.compiler_message = result[:cmp_msg]
|
|
|
submission.save
|
|
|
end
|
|
|
|
|
|
def copy_script(problem_home)
|
|
|
script_dir = "#{problem_home}/script"
|
|
|
std_script_dir = File.dirname(__FILE__) + '/std-script'
|
|
|
scripts = Dir[std_script_dir + '/*']
|
|
|
|
|
|
copied = []
|
|
|
|
|
|
scripts.each do |s|
|
|
|
fname = File.basename(s)
|
|
|
if !FileTest.exist?("#{script_dir}/#{fname}")
|
|
|
copied << fname
|
|
|
system("cp #{s} #{script_dir}")
|
|
|
end
|
|
|
end
|
|
|
|
|
|
return copied
|
|
|
end
|
|
|
|
|
|
def clear_script(log,problem_home)
|
|
|
log.each do |s|
|
|
|
system("rm #{problem_home}/script/#{s}")
|
|
|
end
|
|
|
end
|
|
|
|
|
|
def grade(submission_id)
|
|
|
current_dir = `pwd`.chomp
|
|
|
|
|
|
sub = Submission.find(submission_id)
|
|
|
user = sub.user
|
|
|
problem = sub.problem
|
|
|
|
|
|
language = sub.language.name
|
|
|
lang_ext = sub.language.ext
|
|
|
# FIX THIS
|
|
|
talk 'some hack on language'
|
|
|
if language == 'cpp'
|
|
|
language = 'c++'
|
|
|
end
|
|
|
|
|
|
user_dir = "#{USER_RESULT_DIR}/#{user.login}"
|
|
|
Dir.mkdir(user_dir) if !FileTest.exist?(user_dir)
|
|
|
|
|
|
problem_out_dir = "#{user_dir}/#{problem.name}"
|
|
|
Dir.mkdir(problem_out_dir) if !FileTest.exist?(problem_out_dir)
|
|
|
|
|
|
problem_home = "#{PROBLEMS_DIR}/#{problem.name}"
|
|
|
source_name = "#{problem.name}.#{lang_ext}"
|
|
|
|
|
|
save_source(sub,problem_out_dir,source_name)
|
|
|
|
|
|
copy_log = copy_script(problem_home)
|
|
|
|
|
|
call_judge(problem_home,language,problem_out_dir,source_name)
|
|
|
save_result(sub,read_result("#{problem_out_dir}/test-result"))
|
|
|
|
|
|
clear_script(copy_log,problem_home)
|
|
|
|
|
|
Dir.chdir(current_dir)
|
|
|
end
|
|
|
|
|
|
def stop_grader
|
|
|
File.open(File.dirname(__FILE__) + '/stop','w').close
|
|
|
end
|
|
|
|
|
|
def check_stopfile
|
|
|
FileTest.exist?(File.dirname(__FILE__) + '/stop')
|
|
|
end
|
|
|
|
|
|
def clear_stopfile
|
|
|
system("rm " + File.dirname(__FILE__) + '/stop')
|
|
|
end
|
|
|
|
|
|
#########################################
|
|
|
# main program
|
|
|
#########################################
|
|
|
|
|
|
# reading environment and options
|
|
|
if (ARGV.length >= 1) and (ARGV[0]=='stop')
|
|
|
stop_grader
|
|
|
puts "stop file created"
|
|
|
exit(0)
|
|
|
end
|
|
|
|
|
|
if check_stopfile
|
|
|
puts "stop file exists"
|
|
|
clear_stopfile
|
|
|
exit(0)
|
|
|
end
|
|
|
|
|
|
grader_mode = 'queue'
|
|
|
if ARGV.length >= 1
|
|
|
GRADER_ENV = ARGV[0]
|
|
|
if ARGV.length >=2
|
|
|
grader_mode = ARGV[1]
|
|
|
end
|
|
|
else
|
|
|
GRADER_ENV = 'exam'
|
|
|
end
|
|
|
|
|
|
puts "environment: #{GRADER_ENV}"
|
|
|
require File.dirname(__FILE__) + "/environment.rb"
|
|
|
|
|
|
#main program
|
|
|
talk 'Reading rails environment'
|
|
|
|
|
|
RAILS_ENV = 'development'
|
|
|
require RAILS_APP_DIR + '/config/environment'
|
|
|
|
|
|
case grader_mode
|
|
|
when "queue"
|
|
|
talk 'Grader queue'
|
|
|
while true
|
|
|
if check_stopfile # created by calling grader stop
|
|
|
clear_stopfile
|
|
|
puts "stopped"
|
|
|
exit(0)
|
|
|
end
|
|
|
|
|
|
task = Task.find(:first, :order => 'created_at')
|
|
|
if task!=nil
|
|
|
grade(task.submission_id)
|
|
|
task.destroy
|
|
|
else
|
|
|
sleep(1)
|
|
|
end
|
|
|
end
|
|
|
|
|
|
when "prob"
|
|
|
prob = Problem.find_by_name(ARGV[2])
|
|
|
if prob==nil
|
|
|
puts "cannot find problem: #{ARGV[2]}"
|
|
|
exit(0)
|
|
|
end
|
|
|
users = User.find(:all)
|
|
|
users.each do |u|
|
|
|
puts "user: #{u.login}"
|
|
|
last_sub = Submission.find(:first,
|
|
|
:conditions => "user_id = #{u.id} and " +
|
|
|
"problem_id = #{prob.id}",
|
|
|
:order => 'submitted_at DESC')
|
|
|
if last_sub!=nil
|
|
|
grade(last_sub.id)
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|