Description:
added problem import
git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@435 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r204:ffd23bd6817d - - 9 files changed: 265 inserted, 15 deleted
@@ -0,0 +1,20 | |||
|
1 | + - content_for :head do | |
|
2 | + = stylesheet_link_tag 'problems' | |
|
3 | + = javascript_include_tag :defaults | |
|
4 | + | |
|
5 | + %h1 Import problems: successful | |
|
6 | + | |
|
7 | + %p | |
|
8 | + %b Problem: | |
|
9 | + = "#{@problem.full_name} (#{@problem.name})" | |
|
10 | + %br/ | |
|
11 | + Note that the full score has be assigned to the default value, 100. | |
|
12 | + You should change it to the correct full score. | |
|
13 | + | |
|
14 | + %p | |
|
15 | + = link_to '[Back to problem list]', :action => 'list' | |
|
16 | + = link_to '[Import other problems]', :action => 'import' | |
|
17 | + | |
|
18 | + %h3 Import log | |
|
19 | + %pre.import-log | |
|
20 | + = @log |
@@ -0,0 +1,43 | |||
|
1 | + - content_for :head do | |
|
2 | + = stylesheet_link_tag 'problems' | |
|
3 | + = javascript_include_tag :defaults | |
|
4 | + | |
|
5 | + %h1 Import problems | |
|
6 | + | |
|
7 | + %p= link_to '[Back to problem list]', :action => 'list' | |
|
8 | + | |
|
9 | + - if @problem and @problem.errors | |
|
10 | + =error_messages_for 'problem' | |
|
11 | + | |
|
12 | + - form_tag({:action => 'do_import'}, :multipart => true) do | |
|
13 | + .submitbox | |
|
14 | + %table | |
|
15 | + %tr | |
|
16 | + %td Name: | |
|
17 | + %td= text_field_tag 'name' | |
|
18 | + %tr | |
|
19 | + %td Full name: | |
|
20 | + %td | |
|
21 | + = text_field_tag 'full_name' | |
|
22 | + %span{:class => 'help'} Leave blank to use the same value as the name above. | |
|
23 | + %tr | |
|
24 | + %td Testdata file: | |
|
25 | + %td= file_field_tag 'file' | |
|
26 | + %tr | |
|
27 | + %td Time limit: | |
|
28 | + %td | |
|
29 | + = text_field_tag 'time_limit' | |
|
30 | + %span{:class => 'help'} In seconds. Leave blank to use 1 sec. | |
|
31 | + %tr | |
|
32 | + %td Memory limit: | |
|
33 | + %td | |
|
34 | + = text_field_tag 'memory_limit' | |
|
35 | + %span{:class => 'help'} In MB. Leave blank to use 32MB. | |
|
36 | + %tr | |
|
37 | + %td | |
|
38 | + %td= submit_tag 'Import problem' | |
|
39 | + | |
|
40 | + - if @log | |
|
41 | + %h3 Import log | |
|
42 | + %pre.import-log | |
|
43 | + = @log |
@@ -0,0 +1,76 | |||
|
1 | + require 'tmpdir' | |
|
2 | + | |
|
3 | + class TestdataImporter | |
|
4 | + | |
|
5 | + attr :log_msg | |
|
6 | + | |
|
7 | + def import_from_file(problem_name, | |
|
8 | + tempfile, | |
|
9 | + time_limit, | |
|
10 | + memory_limit) | |
|
11 | + | |
|
12 | + dirname = TestdataImporter.extract(problem_name, tempfile) | |
|
13 | + return false if not dirname | |
|
14 | + @log_msg = GraderScript.call_import_problem(problem_name, | |
|
15 | + dirname, | |
|
16 | + time_limit, | |
|
17 | + memory_limit) | |
|
18 | + return true | |
|
19 | + end | |
|
20 | + | |
|
21 | + protected | |
|
22 | + | |
|
23 | + def self.long_ext(filename) | |
|
24 | + i = filename.index('.') | |
|
25 | + len = filename.length | |
|
26 | + return filename.slice(i..len) | |
|
27 | + end | |
|
28 | + | |
|
29 | + def self.extract(problem_name, tempfile) | |
|
30 | + testdata_filename = TestdataImporter.save_testdata_file(problem_name, | |
|
31 | + tempfile) | |
|
32 | + ext = TestdataImporter.long_ext(tempfile.original_filename) | |
|
33 | + | |
|
34 | + extract_dir = File.join(GraderScript.raw_dir, problem_name) | |
|
35 | + begin | |
|
36 | + Dir.mkdir extract_dir | |
|
37 | + rescue Errno::EEXIST | |
|
38 | + end | |
|
39 | + | |
|
40 | + if ext=='.tar.gz' or ext=='.tgz' | |
|
41 | + cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}" | |
|
42 | + elsif ext=='.tar' | |
|
43 | + cmd = "tar -xvf #{testdata_filename} -C #{extract_dir}" | |
|
44 | + elsif ext=='.zip' | |
|
45 | + cmd = "unzip #{testdata_filename} -d #{extract_dir}" | |
|
46 | + else | |
|
47 | + return nil | |
|
48 | + end | |
|
49 | + | |
|
50 | + system(cmd) | |
|
51 | + | |
|
52 | + files = Dir["#{extract_dir}/**/1*.in"] | |
|
53 | + return nil if files.length==0 | |
|
54 | + | |
|
55 | + return File.dirname(files[0]) | |
|
56 | + end | |
|
57 | + | |
|
58 | + def self.save_testdata_file(problem_name, tempfile) | |
|
59 | + ext = TestdataImporter.long_ext(tempfile.original_filename) | |
|
60 | + testdata_filename = File.join(Dir.tmpdir,"#{problem_name}#{ext}") | |
|
61 | + | |
|
62 | + return nil if tempfile=="" | |
|
63 | + | |
|
64 | + if tempfile.instance_of?(Tempfile) | |
|
65 | + tempfile.close | |
|
66 | + FileUtils.move(tempfile.path,testdata_filename) | |
|
67 | + else | |
|
68 | + File.open(testdata_filename, "wb") do |f| | |
|
69 | + f.write(tempfile.read) | |
|
70 | + end | |
|
71 | + end | |
|
72 | + | |
|
73 | + return testdata_filename | |
|
74 | + end | |
|
75 | + | |
|
76 | + end |
@@ -15,6 +15,7 | |||
|
15 | 15 | verify :method => :post, :only => [ :destroy, |
|
16 | 16 | :create, :quick_create, |
|
17 | 17 | :do_manage, |
|
18 | + :do_import, | |
|
18 | 19 | :update ], |
|
19 | 20 | :redirect_to => { :action => :list } |
|
20 | 21 | |
@@ -145,6 +146,20 | |||
|
145 | 146 | redirect_to :action => 'manage' |
|
146 | 147 | end |
|
147 | 148 | |
|
149 | + def import | |
|
150 | + end | |
|
151 | + | |
|
152 | + def do_import | |
|
153 | + @problem, import_log = Problem.new_from_import_form_params(params) | |
|
154 | + | |
|
155 | + if @problem.errors.length != 0 | |
|
156 | + render :action => 'import' and return | |
|
157 | + end | |
|
158 | + | |
|
159 | + @problem.save | |
|
160 | + @log = import_log | |
|
161 | + end | |
|
162 | + | |
|
148 | 163 | ################################## |
|
149 | 164 | protected |
|
150 | 165 |
@@ -9,4 +9,68 | |||
|
9 | 9 | find(:all, :conditions => {:available => true}, :order => "date_added DESC") |
|
10 | 10 | end |
|
11 | 11 | |
|
12 | + def self.new_from_import_form_params(params) | |
|
13 | + problem = Problem.new | |
|
14 | + | |
|
15 | + # form error checking | |
|
16 | + | |
|
17 | + time_limit_s = params[:time_limit] | |
|
18 | + memory_limit_s = params[:memory_limit] | |
|
19 | + | |
|
20 | + time_limit_s = '1' if time_limit_s=='' | |
|
21 | + memory_limit_s = '32' if memory_limit_s=='' | |
|
22 | + | |
|
23 | + time_limit = time_limit_s.to_i | |
|
24 | + memory_limit = memory_limit_s.to_i | |
|
25 | + | |
|
26 | + if time_limit==0 and time_limit_s!='0' | |
|
27 | + problem.errors.add_to_base('Time limit format errors.') | |
|
28 | + elsif time_limit<=0 or time_limit >60 | |
|
29 | + problem.errors.add_to_base('Time limit out of range.') | |
|
12 | 30 | end |
|
31 | + | |
|
32 | + if memory_limit==0 and memory_limit_s!='0' | |
|
33 | + problem.errors.add_to_base('Memory limit format errors.') | |
|
34 | + elsif memory_limit<=0 or memory_limit >512 | |
|
35 | + problem.errors.add_to_base('Memory limit out of range.') | |
|
36 | + end | |
|
37 | + | |
|
38 | + if params[:file]==nil or params[:file]=='' | |
|
39 | + problem.errors.add_to_base('No testdata file.') | |
|
40 | + end | |
|
41 | + | |
|
42 | + file = params[:file] | |
|
43 | + | |
|
44 | + if problem.errors.length!=0 | |
|
45 | + return problem | |
|
46 | + end | |
|
47 | + | |
|
48 | + problem.name = params[:name] | |
|
49 | + if params[:full_name]!='' | |
|
50 | + problem.full_name = params[:full_name] | |
|
51 | + else | |
|
52 | + problem.full_name = params[:name] | |
|
53 | + end | |
|
54 | + | |
|
55 | + if not problem.valid? | |
|
56 | + return problem | |
|
57 | + end | |
|
58 | + | |
|
59 | + importer = TestdataImporter.new | |
|
60 | + | |
|
61 | + if not importer.import_from_file(problem.name, | |
|
62 | + file, | |
|
63 | + time_limit, | |
|
64 | + memory_limit) | |
|
65 | + problem.errors.add_to_base('Import error.') | |
|
66 | + end | |
|
67 | + | |
|
68 | + problem.full_score = 100 | |
|
69 | + problem.date_added = Time.new | |
|
70 | + problem.test_allowed = true | |
|
71 | + problem.output_only = false | |
|
72 | + problem.available = false | |
|
73 | + return problem, importer.log_msg | |
|
74 | + end | |
|
75 | + | |
|
76 | + end |
@@ -8,6 +8,7 | |||
|
8 | 8 | <p> |
|
9 | 9 | <%= link_to '[New problem]', :action => 'new' %> |
|
10 | 10 | <%= link_to '[Manage problems]', :action => 'manage' %> |
|
11 | + <%= link_to '[Import problems]', :action => 'import' %> | |
|
11 | 12 | <%= link_to '[Turn off all problems]', :action => 'turn_all_off' %> |
|
12 | 13 | <%= link_to '[Turn on all problems]', :action => 'turn_all_on' %> |
|
13 | 14 | </p> |
@@ -54,4 +55,4 | |||
|
54 | 55 | |
|
55 | 56 | <br /> |
|
56 | 57 | |
|
57 | - <%= link_to 'New problem', :action => 'new' %> | |
|
58 | + <%= link_to '[New problem]', :action => 'new' %> |
@@ -74,8 +74,10 | |||
|
74 | 74 | # Include your application configuration below |
|
75 | 75 | |
|
76 | 76 | # If you want to manage graders through web interface, set the path to |
|
77 | - # script directory below | |
|
78 | - GRADER_SCRIPT_DIR = '' | |
|
77 | + # the grader directory below. This dir is where raw, ev, ev-exam, | |
|
78 | + # scripts reside. All grader scripts will be in | |
|
79 | + # #{GRADER_ROOT_DIR}/scripts. | |
|
80 | + GRADER_ROOT_DIR = '' | |
|
79 | 81 | |
|
80 | 82 | # These are where inputs and outputs of test requests are stored |
|
81 | 83 | TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input' |
@@ -1,35 +1,58 | |||
|
1 | 1 | module GraderScript |
|
2 | 2 | |
|
3 | 3 | def self.grader_control_enabled? |
|
4 |
- if defined? GRADER_ |
|
|
5 |
- GRADER_ |
|
|
4 | + if defined? GRADER_ROOT_DIR | |
|
5 | + GRADER_ROOT_DIR != '' | |
|
6 | 6 | else |
|
7 | 7 | false |
|
8 | 8 | end |
|
9 | 9 | end |
|
10 | 10 | |
|
11 |
- def self. |
|
|
11 | + def self.raw_dir | |
|
12 | + File.join GRADER_ROOT_DIR, "raw" | |
|
13 | + end | |
|
14 | + | |
|
15 | + def self.call_grader(params) | |
|
12 | 16 | if GraderScript.grader_control_enabled? |
|
13 | - cmd = "#{GRADER_SCRIPT_DIR}/grader stop #{pid}" | |
|
17 | + cmd = File.join(GRADER_ROOT_DIR, "scripts/grader") + " " + params | |
|
14 | 18 | system(cmd) |
|
15 | 19 | end |
|
16 | 20 | end |
|
17 | 21 | |
|
22 | + def self.stop_grader(pid) | |
|
23 | + GraderScript.call_grader "stop #{pid}" | |
|
24 | + end | |
|
25 | + | |
|
18 | 26 | def self.stop_graders(pids) |
|
19 | - if GraderScript.grader_control_enabled? | |
|
20 | 27 |
|
|
21 | - cmd = "#{GRADER_SCRIPT_DIR}/grader stop " + pid_str | |
|
22 | - system(cmd) | |
|
23 | - end | |
|
28 | + GraderScript.call_grader "stop #{pid_str}" | |
|
24 | 29 | end |
|
25 | 30 | |
|
26 | 31 | def self.start_grader(env) |
|
32 | + GraderScript.call_grader "#{env} queue &" | |
|
33 | + GraderScript.call_grader "#{env} test_request &" | |
|
34 | + end | |
|
35 | + | |
|
36 | + def self.call_import_problem(problem_name, | |
|
37 | + problem_dir, | |
|
38 | + time_limit=1, | |
|
39 | + memory_limit=32, | |
|
40 | + checker_name='text') | |
|
27 | 41 | if GraderScript.grader_control_enabled? |
|
28 | - cmd = "#{GRADER_SCRIPT_DIR}/grader #{env} queue &" | |
|
29 | - system(cmd) | |
|
30 | - cmd = "#{GRADER_SCRIPT_DIR}/grader #{env} test_request &" | |
|
31 | - system(cmd) | |
|
42 | + cur_dir = `pwd`.chomp | |
|
43 | + Dir.chdir(GRADER_ROOT_DIR) | |
|
44 | + | |
|
45 | + script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem") | |
|
46 | + cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" + | |
|
47 | + " -t #{time_limit} -m #{memory_limit}" | |
|
48 | + | |
|
49 | + output = `#{cmd}` | |
|
50 | + | |
|
51 | + Dir.chdir(cur_dir) | |
|
52 | + | |
|
53 | + return output | |
|
32 | 54 |
end |
|
55 | + return '' | |
|
33 | 56 | end |
|
34 | 57 | |
|
35 | 58 | end |
You need to be logged in to leave comments.
Login now