Description:
import original files git-svn-id: http://theory.cpe.ku.ac.th/grader/cli/trunk/scripts@12 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

r0:5402b79c9e92 - - 12 files changed: 845 inserted, 0 deleted

@@ -0,0 +1,14
1 +
2 + PROBLEMS_DIR = "/home/jittat/grader/ev"
3 +
4 + USER_RESULT_DIR = "/home/jittat/grader/result"
5 +
6 + TALKATIVE = true
7 +
8 + def report_comment(comment)
9 + if comment.chomp =~ /^P+$/ # all P's
10 + 'passed'
11 + else
12 + 'failed'
13 + end
14 + end
@@ -0,0 +1,10
1 +
2 + PROBLEMS_DIR = "/home/jittat/grader/ev"
3 +
4 + USER_RESULT_DIR = "/home/jittat/grader/result"
5 +
6 + TALKATIVE = true
7 +
8 + def report_comment(comment)
9 + comment.chomp
10 + end
@@ -0,0 +1,6
1 +
2 + # Rails app directory
3 + RAILS_APP_DIR = "/home/jittat/web_grader"
4 +
5 + # load the required environment file
6 + require "env_#{GRADER_ENV}.rb"
@@ -0,0 +1,109
1 + #!/usr/bin/ruby
2 +
3 + def talk(str)
4 + if TALKATIVE
5 + puts str
6 + end
7 + end
8 +
9 + def execute(command, error_message="")
10 + if not system(command)
11 + puts "ERROR: #{error_message}"
12 + exit(127)
13 + end
14 + end
15 +
16 + def save_source(submission,dir,fname)
17 + f = File.open("#{dir}/#{fname}","w")
18 + f.write(submission.source)
19 + f.close
20 + end
21 +
22 + def call_judge(problem_home,language,problem_out_dir,fname)
23 + ENV['PROBLEM_HOME'] = problem_home
24 + Dir.chdir problem_out_dir
25 + cmd = "#{problem_home}/script/judge #{language} #{fname}"
26 + # puts "CMD: #{cmd}"
27 + system(cmd)
28 + end
29 +
30 + def read_result(test_result_dir)
31 + cmp_msg_fname = "#{test_result_dir}/compiler_message"
32 + cmp_msg = File.open(cmp_msg_fname).read
33 +
34 + result_fname = "#{test_result_dir}/result"
35 + comment_fname = "#{test_result_dir}/comment"
36 + if FileTest.exist?(result_fname)
37 + result = File.open(result_fname).readline.to_i
38 + comment = File.open(comment_fname).readline.chomp
39 + return {:points => result,
40 + :comment => comment,
41 + :cmp_msg => cmp_msg}
42 + else
43 + return {:points => 0,
44 + :comment => 'compile error',
45 + :cmp_msg => cmp_msg}
46 + end
47 + end
48 +
49 + def save_result(submission,result)
50 + submission.graded_at = Time.now
51 + submission.points = result[:points]
52 + submission.grader_comment = report_comment(result[:comment])
53 + submission.compiler_message = result[:cmp_msg]
54 + submission.save
55 + end
56 +
57 + def grade(submission_id)
58 + sub = Submission.find(submission_id)
59 + user = sub.user
60 + problem = sub.problem
61 +
62 + language = sub.language.name
63 + lang_ext = sub.language.ext
64 + # FIX THIS
65 + talk 'some hack on language'
66 + if language == 'cpp'
67 + language = 'c++'
68 + end
69 +
70 + user_dir = "#{USER_RESULT_DIR}/#{user.login}"
71 + Dir.mkdir(user_dir) if !FileTest.exist?(user_dir)
72 +
73 + problem_out_dir = "#{user_dir}/#{problem.name}"
74 + Dir.mkdir(problem_out_dir) if !FileTest.exist?(problem_out_dir)
75 +
76 + problem_home = "#{PROBLEMS_DIR}/#{problem.name}"
77 + source_name = "#{problem.name}.#{lang_ext}"
78 +
79 + save_source(sub,problem_out_dir,source_name)
80 + call_judge(problem_home,language,problem_out_dir,source_name)
81 + save_result(sub,read_result("#{problem_out_dir}/test-result"))
82 + end
83 +
84 + # reading environment
85 + GRADER_ENV = 'exam'
86 + if ARGV.length > 1
87 + GRADER_ENV = ARGV[1]
88 + end
89 + require "environment.rb"
90 +
91 + #main program
92 +
93 + talk 'Reading rails environment'
94 +
95 + RAILS_ENV = 'development'
96 + require RAILS_APP_DIR + '/config/environment'
97 +
98 + current_dir = `pwd`
99 +
100 + talk 'Grader queue'
101 + task = Task.find(:first, :order => 'created_at')
102 + if task!=nil
103 + grade(task.submission_id)
104 + task.destroy
105 + else
106 + puts "No job"
107 + end
108 +
109 +
@@ -0,0 +1,89
1 + #!/usr/bin/ruby
2 +
3 + # import_problem:
4 + # * creates a directory for a problem in the current directory,
5 + # * copy standard scripts
6 + # * copy testdata in the old format and create standard testcase config file
7 +
8 + require 'erb'
9 +
10 + def input_filename(dir,i)
11 + "#{dir}/input-#{i}.txt"
12 + end
13 +
14 + def answer_filename(dir,i)
15 + "#{dir}/answer-#{i}.txt"
16 + end
17 +
18 + def copy_testcase(importing_test_dir,dir,i)
19 + system("cp #{importing_test_dir}/#{i}.in #{input_filename(dir,i)}")
20 + system("cp #{importing_test_dir}/#{i}.sol #{answer_filename(dir,i)}")
21 + end
22 +
23 + def process_options(options)
24 + i = 3
25 + while i<ARGV.length
26 + if ARGV[i]=='-t'
27 + options[:time_limit] = ARGV[i+1].to_i if ARGV.length>i+1
28 + i += 1
29 + end
30 + if ARGV[i]=='-m'
31 + options[:mem_limit] = ARGV[i+1].to_i if ARGV.length>i+1
32 + i += 1
33 + end
34 + i += 1
35 + end
36 + end
37 +
38 + GRADER_DIR = "/home/jittat/grader/grader_ng"
39 +
40 + # print usage
41 + if ARGV.length < 3
42 + puts "using: import_task problem importing_testcase_dir number_of_testcase [options]"
43 + exit(127)
44 + end
45 +
46 + # processing arguments
47 + problem = ARGV[0]
48 + testcase_dir = ARGV[1]
49 + num_testcases = ARGV[2].to_i
50 +
51 + options = {:time_limit => 1, :mem_limit => 16}
52 + process_options(options)
53 +
54 + # start working
55 + puts "creating directories"
56 +
57 + system("mkdir #{problem}")
58 + system("mkdir #{problem}/script")
59 + system("mkdir #{problem}/test_cases")
60 + system("cp #{GRADER_DIR}/std-script/* #{problem}/script")
61 +
62 + puts "copying testcases"
63 +
64 + 1.upto(num_testcases) do |i|
65 + system("mkdir #{problem}/test_cases/#{i}")
66 + copy_testcase("#{testcase_dir}","#{problem}/test_cases/#{i}",i)
67 + end
68 +
69 +
70 + # generating all_tests.cfg
71 + puts "generating testcase config file"
72 +
73 + template = %q{
74 + problem do
75 + num_tests <%= num_testcases %>
76 + full_score <%= num_testcases*10 %>
77 + time_limit_each <%= options[:time_limit] %>
78 + mem_limit_each <%= options[:mem_limit] %>
79 + score_each 10
80 + end
81 + }
82 +
83 + all_test_cfg = ERB.new(template)
84 +
85 + cfg_file = File.open("#{problem}/test_cases/all_test.cfg","w")
86 + cfg_file.puts all_test_cfg.result
87 + cfg_file.close
88 +
89 + puts "done"
new file 100755
binary diff hidden
@@ -0,0 +1,59
1 + #!/usr/bin/ruby
2 +
3 + problem_home = ENV['PROBLEM_HOME']
4 + require "#{problem_home}/script/test_dsl.rb"
5 +
6 + if ARGV.length < 2
7 + puts "Usage: check <language> <test-number> [<output-file>]"
8 + exit(0)
9 + end
10 +
11 + language = ARGV[0]
12 + test_num = ARGV[1].to_i
13 + if ARGV.length >= 3
14 + output_file_name = ARGV[2]
15 + else
16 + output_file_name = "output.txt"
17 + end
18 +
19 + load "#{problem_home}/test_cases/all_tests.cfg"
20 + problem = Problem.get_instance
21 +
22 + output_file = File.new(output_file_name, "r")
23 + answer_file = File.new("#{problem_home}/test_cases/#{test_num}/answer-#{test_num}.txt")
24 + result_file = File.new("check_result", "w")
25 +
26 + output_file_content = output_file.read
27 + answer_file_content = answer_file.read
28 +
29 + report_correct = lambda {
30 + result_file.write "Correct\n"
31 + result_file.write problem.get_score(test_num)
32 + result_file.write "\n"
33 + result_file.close
34 + exit(0)
35 + }
36 +
37 + report_wrong = lambda {
38 + result_file.write "Incorrect\n"
39 + result_file.write "0\n"
40 + result_file.close
41 + exit(0)
42 + }
43 +
44 + ##################
45 + # Your code here #
46 + ##################
47 + num_pattern = /^[0-9]*/
48 + if (output_file_content =~ num_pattern) == nil
49 + report_wrong.call
50 + end
51 +
52 + output_i = output_file_content.to_i
53 + answer_i = answer_file_content.to_i
54 +
55 + if output_i == answer_i
56 + report_correct.call
57 + else
58 + report_wrong.call
59 + end
@@ -0,0 +1,102
1 + #!/bin/sh
2 +
3 + ##############################
4 + #
5 + # Standard Compile Script
6 + #
7 + # Supported compilers:
8 + # gcc, g++, and gpc.
9 + #
10 + ##############################
11 +
12 + export C_COMPILER=/usr/bin/gcc
13 + export CPLUSPLUS_COMPILER=/usr/bin/g++
14 + export PASCAL_COMPILER=/usr/bin/gpc
15 +
16 + export C_OPTIONS="-O2 -Wall"
17 + export CPLUSPLUS_OPTIONS="-O2 -Wall"
18 + export PASCAL_OPTIONS="-O2 -Wall"
19 +
20 + # Check for the correct number of arguments. Otherwise, print usage.
21 + if [ $# -eq 0 -o $# -gt 4 ]
22 + then
23 + echo "Usage: $0 <language> [<source-file>] [<output-file>] [<message-file>]"
24 + echo
25 + echo "<source-file> is defaulted to \"source\"."
26 + echo "<output-file> is defaulted to \"a.out\"."
27 + echo "<message-file> is defaulted to \"compiler_message\"."
28 + echo
29 + exit 127
30 + fi
31 +
32 + # Retrieve the arguments.
33 + if [ $# -ge 1 ]
34 + then
35 + export PROG_LANG=$1
36 + echo "programming language: ${PROG_LANG}"
37 + fi
38 +
39 + if [ $# -ge 2 ]
40 + then
41 + export SOURCE_FILE=$2
42 + else
43 + export SOURCE_FILE=source
44 + fi
45 + echo " source file: $SOURCE_FILE"
46 +
47 + if [ $# -ge 3 ]
48 + then
49 + export OUTPUT_FILE=$3
50 + else
51 + export OUTPUT_FILE=a.out
52 + fi
53 + echo " output file: $OUTPUT_FILE"
54 +
55 + if [ $# -eq 4 ]
56 + then
57 + export MESSAGE_FILE=$4
58 + else
59 + export MESSAGE_FILE=compiler_message
60 + fi
61 + echo " message file: $MESSAGE_FILE"
62 +
63 + echo
64 +
65 + # Remove any remaining output files or message files.
66 + rm -Rf $OUTPUT_FILE
67 + rm -Rf $MESSAGE_FILE
68 +
69 + # Check if the source file exists before attempt compiling.
70 + if [ ! -f $SOURCE_FILE ]
71 + then
72 + echo "ERROR: The source file does not exist!"
73 + echo "ERROR: The source file did not exist." > $MESSAGE_FILE
74 + exit 127
75 + fi
76 +
77 + # Compile.
78 + if [ $PROG_LANG = "c" ]
79 + then
80 + $C_COMPILER $C_OPTIONS -o $OUTPUT_FILE $SOURCE_FILE 2>$MESSAGE_FILE
81 + elif [ $PROG_LANG = "c++" ]
82 + then
83 + $CPLUSPLUS_COMPILER $CPLUSPLUS_OPTIONS -o $OUTPUT_FILE $SOURCE_FILE 2>$MESSAGE_FILE
84 + elif [ $PROG_LANG = "pascal" ]
85 + then
86 + $PASCAL_COMPILER $PASCAL_OPTIONS -o $OUTPUT_FILE $SOURCE_FILE 2>$MESSAGE_FILE
87 + else
88 + echo "ERROR: Invalid language specified!"
89 + echo "ERROR: Invalid language specified!" > $MESSAGE_FILE
90 + exit 127
91 + fi
92 +
93 + # Report success or failure.
94 + if [ -f $OUTPUT_FILE ]
95 + then
96 + echo "Compilation was successful!"
97 + else
98 + echo "ERROR: Something was wrong during the compilation!"
99 + echo "Dumping compiler message:"
100 + echo
101 + cat $MESSAGE_FILE
102 + fi No newline at end of file
@@ -0,0 +1,65
1 + #!/usr/bin/ruby
2 +
3 + def char_comment(comment)
4 + if comment =~ /[iI]ncorrect/
5 + '-'
6 + elsif comment =~ /[Cc]orrect/
7 + 'P'
8 + elsif comment =~ /[Tt]ime/
9 + 'T'
10 + else
11 + '?'
12 + end
13 + end
14 +
15 + problem_home = ENV['PROBLEM_HOME']
16 + require "#{problem_home}/script/test_dsl.rb"
17 + load "#{problem_home}/test_cases/all_tests.cfg"
18 + problem = Problem.get_instance
19 +
20 + if problem.well_formed? == false
21 + puts "The problem specification is not well formed."
22 + exit(127)
23 + end
24 +
25 + all_score = 0
26 + all_comment = ''
27 + (1..(problem.runs.length-1)).each do |k|
28 + run = problem.runs[k]
29 + run_score = 0
30 + run_comment = ''
31 + run.tests.each do |test_num|
32 + result_file_name = "#{test_num}/result"
33 + if not File.exists?(result_file_name)
34 + puts "Cannot find the file #{test_num}/result!"
35 + exit(127)
36 + end
37 +
38 + result_file = File.new(result_file_name, "r")
39 + result_file_lines = result_file.readlines
40 + run_score = run_score + result_file_lines[1].to_i
41 + run_comment += char_comment(result_file_lines[0])
42 + result_file.close
43 + end
44 +
45 + run_result_file = File.new("result-#{k}", "w")
46 + run_result_file.write run_score
47 + run_result_file.write "\n"
48 + run_result_file.close
49 +
50 + run_comment_file = File.new("comment-#{k}", "w")
51 + run_comment_file.write "#{run_comment}\n"
52 + run_comment_file.close
53 +
54 + all_score = all_score + run_score
55 + all_comment += run_comment
56 + end
57 +
58 + result_file = File.new("result", "w")
59 + result_file.write all_score
60 + result_file.write "\n"
61 + result_file.close
62 +
63 + comment_file = File.new("comment", "w")
64 + comment_file.write "#{all_comment}\n"
65 + comment_file.close
@@ -0,0 +1,114
1 + #!/usr/bin/ruby
2 +
3 + problem_home = ENV['PROBLEM_HOME']
4 +
5 + def execute(command, error_message="")
6 + if not system(command)
7 + puts "ERROR: #{error_message}"
8 + exit(127)
9 + end
10 + end
11 +
12 + # ARGV[0] --- language
13 + # ARGV[1] --- program source file
14 + # ARGV[2] --- test result directory
15 + # ARGV[3] --- sandbox directory
16 +
17 + if ARGV.length < 2 || ARGV.length > 4
18 + puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
19 + puts " <sandbox-directory> is defaulted to ./sandbox"
20 + puts " <test-result-directory> is defaulted to ./test-result"
21 + puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
22 + exit(127)
23 + end
24 +
25 + language = ARGV[0]
26 + if language != "c" && language != "c++" && language != "pascal"
27 + puts "You specified a language that is not supported."
28 + exit(127)
29 + end
30 +
31 + source_file = ARGV[1]
32 + if File.exist?(source_file) == false
33 + puts "The source file does not exist."
34 + exit(127)
35 + end
36 +
37 + puts "Making test result and sandbox directories..."
38 +
39 + current_dir = `pwd`
40 + current_dir.strip!
41 +
42 + if ARGV.length >= 3
43 + test_result_dir = ARGV[2]
44 + else
45 + test_result_dir = "#{current_dir}/test-result"
46 + end
47 + puts "Test result directory: #{test_result_dir}"
48 + system("rm -Rf #{test_result_dir}")
49 + execute("mkdir #{test_result_dir}", "Cannot make directory #{test_result_dir}.")
50 +
51 + if ARGV.length >= 4
52 + sandbox_dir = ARGV[3]
53 + else
54 + sandbox_dir = "#{current_dir}/sandbox"
55 + end
56 + puts "Sandbox directory: #{sandbox_dir}"
57 + system("rm -Rf #{sandbox_dir}")
58 + execute("mkdir #{sandbox_dir}", "Cannot make directory #{sandbox_dir}")
59 +
60 + # Compile
61 + puts
62 + puts "Compiling..."
63 + execute("cp #{source_file} #{sandbox_dir}", "Cannot copy the source file to #{sandbox_dir}")
64 + begin
65 + Dir.chdir sandbox_dir
66 + rescue
67 + puts "ERROR: Cannot change directory to #{sandbox_dir}."
68 + exit(127)
69 + end
70 + execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
71 + compile_message = `cat compiler_message`
72 + compile_message.strip!
73 + execute("mv compiler_message #{test_result_dir}", "Cannot move the compiler message to #{test_result_dir}.")
74 + if compile_message != ""
75 + puts "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
76 + exit(127)
77 + else
78 + execute("mv a.out #{test_result_dir}", "Cannot move the compiled program to #{test_result_dir}")
79 + system("rm -Rf #{sandbox_dir}/*")
80 + end
81 +
82 + require "#{problem_home}/script/test_dsl.rb"
83 + load "#{problem_home}/test_cases/all_tests.cfg"
84 + problem = Problem.get_instance
85 +
86 + if problem.well_formed? == false
87 + puts "The problem specification is not well formed."
88 + exit(127)
89 + end
90 +
91 + # Doing the testing.
92 + (1..(problem.num_tests)).each do |test_num|
93 + puts
94 + execute("cp #{test_result_dir}/a.out #{sandbox_dir}", "Cannot copy the compiled program into #{sandbox_dir}")
95 + execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
96 + execute("mkdir #{test_result_dir}/#{test_num}", "Cannot create directory #{test_result_dir}/#{test_num}")
97 + execute("mv #{sandbox_dir}/result #{test_result_dir}/#{test_num}", "Cannot copy the result file into #{test_result_dir}/#{test_num}")
98 + execute("mv #{sandbox_dir}/comment #{test_result_dir}/#{test_num}", "Cannot copy the comment file into #{test_result_dir}/#{test_num}")
99 + execute("rm -Rf #{sandbox_dir}/*", "Cannot clear #{sandbox_dir}")
100 + end
101 +
102 + # Grade
103 + puts
104 + puts "Grading..."
105 + begin
106 + Dir.chdir test_result_dir
107 + rescue
108 + puts "ERROR: Cannot change directory to #{test_result_dir}."
109 + exit(127)
110 + end
111 + execute("#{problem_home}/script/grade", "An error occured during grading!")
112 +
113 + puts
114 + puts "All done!"
@@ -0,0 +1,99
1 + #!/usr/bin/ruby
2 +
3 + if ARGV.length < 2 || ARGV.length > 3
4 + puts "Usage: run <language> <test-num> [<program-name>]"
5 + exit(127)
6 + end
7 +
8 + language = ARGV[0]
9 + test_num = ARGV[1].to_i
10 + if ARGV.length > 2
11 + program_name = ARGV[2]
12 + else
13 + program_name = "a.out"
14 + end
15 +
16 + problem_home = ENV['PROBLEM_HOME']
17 + require "#{problem_home}/script/test_dsl.rb"
18 + load "#{problem_home}/test_cases/all_tests.cfg"
19 + problem = Problem.get_instance
20 +
21 + if problem.well_formed? == false
22 + puts "The problem specification is not well formed."
23 + exit(127)
24 + end
25 +
26 + # Check if the test number is okay.
27 + if test_num <= 0 || test_num > problem.num_tests
28 + puts "You have specified a wrong test number."
29 + exit(127)
30 + end
31 +
32 + #####################################
33 + # Set the relavant file names here. #
34 + #####################################
35 +
36 + input_file_name = "#{problem_home}/test_cases/#{test_num}/input-#{test_num}.txt"
37 +
38 + #####################################
39 +
40 + time_limit = problem.get_time_limit test_num
41 + mem_limit = problem.get_mem_limit(test_num) * 1024
42 +
43 + # Copy the input file.
44 + #`cp #{problem_home}/test_cases/#{test_num}/#{input_file_name} .`
45 +
46 + # Run the program.
47 + run_command = "/usr/bin/time -f \"%E\" 2>run_result #{problem_home}/script/box -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
48 + puts "Running test #{test_num}..."
49 + puts run_command
50 + puts
51 + system(run_command)
52 +
53 + # Create the result file.
54 + result_file = File.new("result", "w")
55 + comment_file = File.new("comment", "w")
56 +
57 + # Check if the program actually produced any output.
58 + run_result_file = File.new("run_result", "r")
59 + run_result = run_result_file.readlines
60 + run_result_file.close
61 + time_elapsed = run_result[run_result.length-1]
62 +
63 + report = lambda{ |status, points, comment|
64 + result_file.write status.strip
65 + result_file.write "\n"
66 + result_file.write points.to_s.strip
67 + result_file.write "\n"
68 + result_file.write time_elapsed.strip
69 + result_file.write "\n"
70 + result_file.close
71 + `rm run_result`
72 + `rm output.txt`
73 +
74 + comment_file.write comment
75 + comment_file.close
76 +
77 + puts
78 + puts "Done!"
79 + exit(0)
80 + }
81 +
82 + if run_result[0][0,2] != "OK"
83 + puts "There was a runtime error."
84 + report.call(run_result[0], 0, "No comment.\n")
85 + end
86 +
87 + # Run 'check' to evaluate the output.
88 + #puts "There was no runtime error. Proceed to checking the output."
89 + check_command = "#{problem_home}/script/check #{language} #{test_num}"
90 + puts "Checking the output..."
91 + puts check_command
92 + if not system(check_command)
93 + exit(127)
94 + end
95 +
96 + check_file = File.new("check_result", "r")
97 + check_file_lines = check_file.readlines
98 +
99 + report.call(check_file_lines[0], check_file_lines[1], "No comment.\n")
@@ -0,0 +1,178
1 + class DSLNode
2 + def DSLNode.scalar_attr(*names)
3 + names.each do |name|
4 + define_method name do |*a|
5 + if a.length == 0
6 + instance_variable_get( "@#{name}" )
7 + else
8 + instance_variable_set( "@#{name}", a[0] )
9 + end
10 + end
11 + end
12 + end
13 +
14 + def DSLNode.array_attr(*names)
15 + names.each do |name|
16 + define_method name do |*a|
17 + if a.length == 0
18 + instance_variable_get( "@#{name}" )
19 + else
20 + instance_variable_set( "@#{name}", a )
21 + end
22 + end
23 + end
24 + end
25 + end
26 +
27 + class Problem < DSLNode
28 + def initialize
29 + @runs = []
30 + @tests = []
31 + end
32 +
33 + def Problem.getter(name, plural_name, each_name)
34 + eval "def get_#{name}(index) \n \
35 + if defined?(@tests) and @tests[index] != nil \n \
36 + if @tests[index].#{name} != nil \n \
37 + return @tests[index].#{name} \n \
38 + end \n \
39 + end \n \
40 + \n \
41 + (1..@runs.length-1).each do |i| \n \
42 + run = @runs[i] \n \
43 + k = run.tests.index(index) \n \
44 + if k == nil \n \
45 + next \n \
46 + end \n \
47 + \n \
48 + if run.#{plural_name} != nil && run.#{plural_name}[k] != nil \n \
49 + return run.#{plural_name}[k] \n \
50 + end \n \
51 + \n \
52 + if run.#{each_name} != nil \n \
53 + return run.#{each_name} \n \
54 + end \n \
55 + end \n \
56 + \n \
57 + if @#{each_name} != nil \n \
58 + return @#{each_name} \n \
59 + else \n \
60 + raise 'The problem is malformed (possibly in more than one way)!' \n \
61 + end \n \
62 + end"
63 + end
64 +
65 + scalar_attr :num_tests, :full_score, :score_each, :time_limit_each, :mem_limit_each
66 + array_attr :runs, :tests
67 + getter "score", "scores", "score_each"
68 + getter "mem_limit", "mem_limits", "mem_limit_each"
69 + getter "time_limit", "time_limits", "time_limit_each"
70 +
71 + def run(index, &block)
72 + new_run = Run.new
73 + new_run.instance_eval &block
74 + @runs[index] = new_run
75 + end
76 +
77 + def test(index, &block)
78 + new_test = Test.new
79 + new_test.instance_eval &block
80 + @tests[index] = new_test
81 + end
82 +
83 + def read_test(index)
84 + filename = ENV['PROBLEM_HOME'] + "/test_cases/#{index}/test.cfg"
85 + if File.exists?(filename)
86 + @tests[index] ||= Test.new
87 + content = File.read(filename)
88 + @tests[index].instance_eval content
89 + end
90 + end
91 +
92 + def Problem.set_instance(prob)
93 + @instance = prob
94 + end
95 +
96 + def Problem.get_instance
97 + return @instance
98 + end
99 +
100 + def well_formed?
101 + # Check if run 1 to run @runs.length are present.
102 + (1..(@runs.length-1)).each do |i|
103 + if @runs[i] == nil
104 + puts "run #{i} is not present"
105 + return false
106 + end
107 + end
108 +
109 + # Check if all tests are in one and only one run.
110 + test_present = []
111 + (1..(@num_tests)).each do |i|
112 + test_present[i] = false
113 + end
114 + (1..(@runs.length-1)).each do |j|
115 + run = @runs[j]
116 + run.tests.each do |t|
117 + if test_present[t] == false
118 + test_present[t] = true
119 + else
120 + puts "test #{t} is present in more than one run"
121 + return false
122 + end
123 + end
124 + end
125 + (1..(@num_tests)).each do |i|
126 + if test_present[i] == false
127 + puts "test #{i} is not present"
128 + return false
129 + end
130 + end
131 +
132 + # Check if we can find the score, mem limit, and time limit for all tests.
133 + (1..(@num_tests)).each do |i|
134 + begin
135 + get_score i
136 + rescue
137 + puts "cannot get score for test #{i}"
138 + return false
139 + end
140 +
141 + begin
142 + get_mem_limit i
143 + rescue
144 + puts "cannot get mem limit for test #{i}"
145 + return false
146 + end
147 +
148 + begin
149 + get_time_limit i
150 + rescue
151 + puts "cannot get time limit for test #{i}"
152 + return false
153 + end
154 + end
155 +
156 + return true
157 + end
158 + end
159 +
160 + class Run < DSLNode
161 + scalar_attr :score_each, :time_limit_each, :mem_limit_each
162 + array_attr :tests, :scores, :time_limits, :mem_limits
163 + end
164 +
165 + class Test < DSLNode
166 + scalar_attr :score, :time_limit, :mem_limit
167 + end
168 +
169 + def problem(&blk)
170 + prob = Problem.new
171 + prob.instance_eval &blk
172 + Problem.set_instance prob
173 + p = Problem.get_instance
174 + (1..(p.num_tests)).each do |i|
175 + p.read_test i
176 + end
177 + p.well_formed?
178 + end
You need to be logged in to leave comments. Login now