Description:
- after submission, redirecto to edit_submission_path - add more info to submission status - fix bug #20 and #21
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r696:0b7243db68e6 - - 11 files changed: 33 inserted, 23 deleted

@@ -76,49 +76,49
76 @submission.source_filename = "live_edit.#{language.ext}"
76 @submission.source_filename = "live_edit.#{language.ext}"
77 @submission.language = language
77 @submission.language = language
78 end
78 end
79
79
80 @submission.submitted_at = Time.new.gmtime
80 @submission.submitted_at = Time.new.gmtime
81 @submission.ip_address = request.remote_ip
81 @submission.ip_address = request.remote_ip
82
82
83 if GraderConfiguration.time_limit_mode? and user.contest_finished?
83 if GraderConfiguration.time_limit_mode? and user.contest_finished?
84 @submission.errors.add(:base,"The contest is over.")
84 @submission.errors.add(:base,"The contest is over.")
85 prepare_list_information
85 prepare_list_information
86 render :action => 'list' and return
86 render :action => 'list' and return
87 end
87 end
88
88
89 if @submission.valid?(@current_user)
89 if @submission.valid?(@current_user)
90 if @submission.save == false
90 if @submission.save == false
91 flash[:notice] = 'Error saving your submission'
91 flash[:notice] = 'Error saving your submission'
92 elsif Task.create(:submission_id => @submission.id,
92 elsif Task.create(:submission_id => @submission.id,
93 :status => Task::STATUS_INQUEUE) == false
93 :status => Task::STATUS_INQUEUE) == false
94 flash[:notice] = 'Error adding your submission to task queue'
94 flash[:notice] = 'Error adding your submission to task queue'
95 end
95 end
96 else
96 else
97 prepare_list_information
97 prepare_list_information
98 render :action => 'list' and return
98 render :action => 'list' and return
99 end
99 end
100 - redirect_to :action => 'list'
100 + redirect_to edit_submission_path(@submission)
101 end
101 end
102
102
103 def source
103 def source
104 submission = Submission.find(params[:id])
104 submission = Submission.find(params[:id])
105 if ((submission.user_id == session[:user_id]) and
105 if ((submission.user_id == session[:user_id]) and
106 (submission.problem != nil) and
106 (submission.problem != nil) and
107 (submission.problem.available))
107 (submission.problem.available))
108 send_data(submission.source,
108 send_data(submission.source,
109 {:filename => submission.download_filename,
109 {:filename => submission.download_filename,
110 :type => 'text/plain'})
110 :type => 'text/plain'})
111 else
111 else
112 flash[:notice] = 'Error viewing source'
112 flash[:notice] = 'Error viewing source'
113 redirect_to :action => 'list'
113 redirect_to :action => 'list'
114 end
114 end
115 end
115 end
116
116
117 def compiler_msg
117 def compiler_msg
118 @submission = Submission.find(params[:id])
118 @submission = Submission.find(params[:id])
119 if @submission.user_id == session[:user_id]
119 if @submission.user_id == session[:user_id]
120 render :action => 'compiler_msg', :layout => 'empty'
120 render :action => 'compiler_msg', :layout => 'empty'
121 else
121 else
122 flash[:notice] = 'Error viewing source'
122 flash[:notice] = 'Error viewing source'
123 redirect_to :action => 'list'
123 redirect_to :action => 'list'
124 end
124 end
@@ -31,48 +31,50
31 end
31 end
32
32
33 def show_max_score
33 def show_max_score
34 #process parameters
34 #process parameters
35 #problems
35 #problems
36 @problems = []
36 @problems = []
37 if params[:problem_id]
37 if params[:problem_id]
38 params[:problem_id].each do |id|
38 params[:problem_id].each do |id|
39 next unless id.strip != ""
39 next unless id.strip != ""
40 pid = Problem.find_by_id(id.to_i)
40 pid = Problem.find_by_id(id.to_i)
41 @problems << pid if pid
41 @problems << pid if pid
42 end
42 end
43 end
43 end
44
44
45 #users
45 #users
46 @users = if params[:user] == "all" then
46 @users = if params[:user] == "all" then
47 User.includes(:contests).includes(:contest_stat)
47 User.includes(:contests).includes(:contest_stat)
48 else
48 else
49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
50 end
50 end
51
51
52 #set up range from param
52 #set up range from param
53 @since_id = params.fetch(:from_id, 0).to_i
53 @since_id = params.fetch(:from_id, 0).to_i
54 @until_id = params.fetch(:to_id, 0).to_i
54 @until_id = params.fetch(:to_id, 0).to_i
55 + @since_id = nil if @since_id == 0
56 + @until_id = nil if @until_id == 0
55
57
56 #calculate the routine
58 #calculate the routine
57 @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
59 @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
58
60
59 #rencer accordingly
61 #rencer accordingly
60 if params[:button] == 'download' then
62 if params[:button] == 'download' then
61 csv = gen_csv_from_scorearray(@scorearray,@problems)
63 csv = gen_csv_from_scorearray(@scorearray,@problems)
62 send_data csv, filename: 'max_score.csv'
64 send_data csv, filename: 'max_score.csv'
63 else
65 else
64 #render template: 'user_admin/user_stat'
66 #render template: 'user_admin/user_stat'
65 render 'max_score'
67 render 'max_score'
66 end
68 end
67
69
68 end
70 end
69
71
70 def score
72 def score
71 if params[:commit] == 'download csv'
73 if params[:commit] == 'download csv'
72 @problems = Problem.all
74 @problems = Problem.all
73 else
75 else
74 @problems = Problem.available_problems
76 @problems = Problem.available_problems
75 end
77 end
76 @users = User.includes(:contests, :contest_stat).where(enabled: true)
78 @users = User.includes(:contests, :contest_stat).where(enabled: true)
77 @scorearray = Array.new
79 @scorearray = Array.new
78 @users.each do |u|
80 @users.each do |u|
@@ -64,63 +64,66
64 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
64 append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index'
65 end
65 end
66
66
67 if GraderConfiguration['right.user_hall_of_fame']
67 if GraderConfiguration['right.user_hall_of_fame']
68 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
68 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
69 end
69 end
70 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
70 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
71
71
72 if GraderConfiguration['system.user_setting_enabled']
72 if GraderConfiguration['system.user_setting_enabled']
73 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
73 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
74 end
74 end
75 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
75 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
76
76
77 menu_items.html_safe
77 menu_items.html_safe
78 end
78 end
79
79
80 def append_to(option,label, controller, action)
80 def append_to(option,label, controller, action)
81 option << ' ' if option!=''
81 option << ' ' if option!=''
82 option << link_to_unless_current(label,
82 option << link_to_unless_current(label,
83 :controller => controller,
83 :controller => controller,
84 :action => action)
84 :action => action)
85 end
85 end
86
86
87 def format_short_time(time)
87 def format_short_time(time)
88 - now = Time.now.gmtime
88 + now = Time.zone.now
89 st = ''
89 st = ''
90 - if (time.yday != now.yday) or
90 + if (time.yday != now.yday) or (time.year != now.year)
91 - (time.year != now.year)
91 + st = time.strftime("%d/%m/%y ")
92 - st = time.strftime("%x ")
93 end
92 end
94 st + time.strftime("%X")
93 st + time.strftime("%X")
95 end
94 end
96
95
97 def format_short_duration(duration)
96 def format_short_duration(duration)
98 return '' if duration==nil
97 return '' if duration==nil
99 d = duration.to_f
98 d = duration.to_f
100 return Time.at(d).gmtime.strftime("%X")
99 return Time.at(d).gmtime.strftime("%X")
101 end
100 end
102
101
102 + def format_full_time_ago(time)
103 + st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')'
104 + end
105 +
103 def read_textfile(fname,max_size=2048)
106 def read_textfile(fname,max_size=2048)
104 begin
107 begin
105 File.open(fname).read(max_size)
108 File.open(fname).read(max_size)
106 rescue
109 rescue
107 nil
110 nil
108 end
111 end
109 end
112 end
110
113
111 def toggle_button(on,toggle_url,id, option={})
114 def toggle_button(on,toggle_url,id, option={})
112 btn_size = option[:size] || 'btn-xs'
115 btn_size = option[:size] || 'btn-xs'
113 link_to (on ? "Yes" : "No"), toggle_url,
116 link_to (on ? "Yes" : "No"), toggle_url,
114 {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
117 {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
115 id: id,
118 id: id,
116 data: {remote: true, method: 'get'}}
119 data: {remote: true, method: 'get'}}
117 end
120 end
118
121
119 def get_ace_mode(language)
122 def get_ace_mode(language)
120 # return ace mode string from Language
123 # return ace mode string from Language
121
124
122 case language.pretty_name
125 case language.pretty_name
123 when 'Pascal'
126 when 'Pascal'
124 'ace/mode/pascal'
127 'ace/mode/pascal'
125 when 'C++','C'
128 when 'C++','C'
126 'ace/mode/c_cpp'
129 'ace/mode/c_cpp'
@@ -13,50 +13,50
13 validate :must_have_valid_problem
13 validate :must_have_valid_problem
14 validate :must_specify_language
14 validate :must_specify_language
15
15
16 has_one :task
16 has_one :task
17
17
18 before_save :assign_latest_number_if_new_recond
18 before_save :assign_latest_number_if_new_recond
19
19
20 def self.find_last_by_user_and_problem(user_id, problem_id)
20 def self.find_last_by_user_and_problem(user_id, problem_id)
21 where("user_id = ? AND problem_id = ?",user_id,problem_id).last
21 where("user_id = ? AND problem_id = ?",user_id,problem_id).last
22 end
22 end
23
23
24 def self.find_all_last_by_problem(problem_id)
24 def self.find_all_last_by_problem(problem_id)
25 # need to put in SQL command, maybe there's a better way
25 # need to put in SQL command, maybe there's a better way
26 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
26 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
27 "WHERE id = " +
27 "WHERE id = " +
28 "(SELECT MAX(id) FROM submissions AS subs " +
28 "(SELECT MAX(id) FROM submissions AS subs " +
29 "WHERE subs.user_id = submissions.user_id AND " +
29 "WHERE subs.user_id = submissions.user_id AND " +
30 "problem_id = " + problem_id.to_s + " " +
30 "problem_id = " + problem_id.to_s + " " +
31 "GROUP BY user_id) " +
31 "GROUP BY user_id) " +
32 "ORDER BY user_id")
32 "ORDER BY user_id")
33 end
33 end
34
34
35 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
35 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
36 records = Submission.where(problem_id: problem_id,user_id: user_id)
36 records = Submission.where(problem_id: problem_id,user_id: user_id)
37 - records = records.where('id >= ?',since_id) if since_id > 0
37 + records = records.where('id >= ?',since_id) if since_id and since_id > 0
38 - records = records.where('id <= ?',until_id) if until_id > 0
38 + records = records.where('id <= ?',until_id) if until_id and until_id > 0
39 records.all
39 records.all
40 end
40 end
41
41
42 def self.find_last_for_all_available_problems(user_id)
42 def self.find_last_for_all_available_problems(user_id)
43 submissions = Array.new
43 submissions = Array.new
44 problems = Problem.available_problems
44 problems = Problem.available_problems
45 problems.each do |problem|
45 problems.each do |problem|
46 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
46 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
47 submissions << sub if sub!=nil
47 submissions << sub if sub!=nil
48 end
48 end
49 submissions
49 submissions
50 end
50 end
51
51
52 def self.find_by_user_problem_number(user_id, problem_id, number)
52 def self.find_by_user_problem_number(user_id, problem_id, number)
53 where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first
53 where("user_id = ? AND problem_id = ? AND number = ?",user_id,problem_id,number).first
54 end
54 end
55
55
56 def self.find_all_by_user_problem(user_id, problem_id)
56 def self.find_all_by_user_problem(user_id, problem_id)
57 where("user_id = ? AND problem_id = ?",user_id,problem_id)
57 where("user_id = ? AND problem_id = ?",user_id,problem_id)
58 end
58 end
59
59
60 def download_filename
60 def download_filename
61 if self.problem.output_only
61 if self.problem.output_only
62 return self.source_filename
62 return self.source_filename
@@ -1,26 +1,28
1 -
2 - if submission.nil?
1 - if submission.nil?
3 = "-"
2 = "-"
4 - else
3 - else
4 + %strong= "Submission ID:"
5 + = submission.id
6 + %br
5 - unless submission.graded_at
7 - unless submission.graded_at
6 - = t 'main.submitted_at'
8 + %strong= t 'main.submitted_at:'
7 - = format_short_time(submission.submitted_at.localtime)
9 + = format_full_time_ago(submission.submitted_at.localtime)
8 - else
10 - else
9 - %strong= t 'main.graded_at'
11 + %strong= t 'main.graded_at:'
10 - = "#{format_short_time(submission.graded_at.localtime)} "
12 + = format_full_time_ago(submission.graded_at.localtime)
11 %br
13 %br
12 - if GraderConfiguration['ui.show_score']
14 - if GraderConfiguration['ui.show_score']
13 %strong=t 'main.score'
15 %strong=t 'main.score'
14 = "#{(submission.points*100/submission.problem.full_score).to_i} "
16 = "#{(submission.points*100/submission.problem.full_score).to_i} "
15 = " ["
17 = " ["
16 %tt
18 %tt
17 = submission.grader_comment
19 = submission.grader_comment
18 = "]"
20 = "]"
19 %br
21 %br
20 - %strong View:
22 + %strong View:
21 - - if GraderConfiguration.show_grading_result
23 + - if GraderConfiguration.show_grading_result
22 - = link_to '[detailed result]', :action => 'result', :id => submission.id
24 + = link_to '[detailed result]', :action => 'result', :id => submission.id
23 - = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'}
25 + = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'} if submission.graded_at
24 = link_to "#{t 'main.src_link'}", download_submission_path(submission.id), class: 'btn btn-xs btn-info'
26 = link_to "#{t 'main.src_link'}", download_submission_path(submission.id), class: 'btn btn-xs btn-info'
25 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
27 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
26
28
@@ -12,38 +12,38
12 = label_tag :problem_id, "Problems"
12 = label_tag :problem_id, "Problems"
13 = select_tag 'problem_id[]',
13 = select_tag 'problem_id[]',
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
14 options_for_select(Problem.all.collect {|p| ["[#{p.name}] #{p.full_name}", p.id]},params[:problem_id]),
15 { class: 'select2 form-control', multiple: "true" }
15 { class: 'select2 form-control', multiple: "true" }
16 .col-md-4
16 .col-md-4
17 .panel.panel-primary
17 .panel.panel-primary
18 .panel-heading
18 .panel-heading
19 Submission range
19 Submission range
20 .panel-body
20 .panel-body
21 %p
21 %p
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
22 Input minimum and maximum range of submission ID that should be included. A blank value for min and max means -1 and infinity, respectively.
23 .form-group
23 .form-group
24 = label_tag :from, "Min"
24 = label_tag :from, "Min"
25 = text_field_tag 'from_id', @since_id, class: "form-control"
25 = text_field_tag 'from_id', @since_id, class: "form-control"
26 .form-group
26 .form-group
27 = label_tag :from, "Max"
27 = label_tag :from, "Max"
28 = text_field_tag 'to_id', @until_id, class: "form-control"
28 = text_field_tag 'to_id', @until_id, class: "form-control"
29 .col-md-4
29 .col-md-4
30 .panel.panel-primary
30 .panel.panel-primary
31 .panel-heading
31 .panel-heading
32 Users
32 Users
33 .panel-body
33 .panel-body
34 .radio
34 .radio
35 %label
35 %label
36 - = radio_button_tag 'users', 'all', true
36 + = radio_button_tag 'users', 'all', (params[:users] == "all")
37 All users
37 All users
38 .radio
38 .radio
39 %label
39 %label
40 - = radio_button_tag 'users', 'enabled'
40 + = radio_button_tag 'users', 'enabled', (params[:users] == "enabled")
41 Only enabled users
41 Only enabled users
42 .row
42 .row
43 .col-md-12
43 .col-md-12
44 = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
44 = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
45 = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
45 = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
46
46
47 - if @scorearray
47 - if @scorearray
48 %h2 Result
48 %h2 Result
49 =render "score_table"
49 =render "score_table"
@@ -6,49 +6,49
6 .row
6 .row
7 .col-md-12
7 .col-md-12
8 .alert.alert-info
8 .alert.alert-info
9 Write your code in the following box, choose language, and click submit button when finished
9 Write your code in the following box, choose language, and click submit button when finished
10 .row
10 .row
11 .col-md-8
11 .col-md-8
12 %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'}
12 %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'}
13 .col-md-4
13 .col-md-4
14 - # submission form
14 - # submission form
15 = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
15 = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do
16
16
17 = hidden_field_tag 'editor_text', @source
17 = hidden_field_tag 'editor_text', @source
18 = hidden_field_tag 'submission[problem_id]', @problem.id
18 = hidden_field_tag 'submission[problem_id]', @problem.id
19 .form-group
19 .form-group
20 = label_tag "Task:"
20 = label_tag "Task:"
21 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
21 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
22
22
23 .form-group
23 .form-group
24 = label_tag 'Language'
24 = label_tag 'Language'
25 = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px"
25 = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px"
26 .form-group
26 .form-group
27 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
27 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
28 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
28 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
29 - # latest submission status
29 - # latest submission status
30 - .panel.panel-info
30 + .panel{class: (@submission && @submission.graded_at) ? "panel-info" : "panel-warning"}
31 .panel-heading
31 .panel-heading
32 Latest Submission Status
32 Latest Submission Status
33 = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission
33 = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission
34 .panel-body
34 .panel-body
35 - if @submission
35 - if @submission
36 = render :partial => 'submission_short',
36 = render :partial => 'submission_short',
37 :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
37 :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
38 .row
38 .row
39 .col-md-12
39 .col-md-12
40 %h2 Console
40 %h2 Console
41 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
41 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
42
42
43 :javascript
43 :javascript
44 $(document).ready(function() {
44 $(document).ready(function() {
45 e = ace.edit("editor")
45 e = ace.edit("editor")
46 e.setValue($("#text_sourcecode").val());
46 e.setValue($("#text_sourcecode").val());
47 e.gotoLine(1);
47 e.gotoLine(1);
48 $("#language_id").trigger('change');
48 $("#language_id").trigger('change');
49 brython();
49 brython();
50 });
50 });
51
51
52
52
53 %script#__main__{type:'text/python3'}
53 %script#__main__{type:'text/python3'}
54 :plain
54 :plain
@@ -44,29 +44,29
44
44
45 # Use SQL instead of Active Record's schema dumper when creating the database.
45 # Use SQL instead of Active Record's schema dumper when creating the database.
46 # This is necessary if your schema can't be completely dumped by the schema dumper,
46 # This is necessary if your schema can't be completely dumped by the schema dumper,
47 # like if you have constraints or database-specific column types
47 # like if you have constraints or database-specific column types
48 # config.active_record.schema_format = :sql
48 # config.active_record.schema_format = :sql
49
49
50 # Enable the asset pipeline
50 # Enable the asset pipeline
51 config.assets.enabled = true
51 config.assets.enabled = true
52
52
53 # Version of your assets, change this if you want to expire all your assets
53 # Version of your assets, change this if you want to expire all your assets
54 config.assets.version = '1.0'
54 config.assets.version = '1.0'
55
55
56 # ---------------- IMPORTANT ----------------------
56 # ---------------- IMPORTANT ----------------------
57 # If we deploy the app into a subdir name "grader", be sure to do "rake assets:precompile RAILS_RELATIVE_URL_ROOT=/grader"
57 # If we deploy the app into a subdir name "grader", be sure to do "rake assets:precompile RAILS_RELATIVE_URL_ROOT=/grader"
58 # moreover, using the following line instead also known to works
58 # moreover, using the following line instead also known to works
59 #config.action_controller.relative_url_root = '/grader'
59 #config.action_controller.relative_url_root = '/grader'
60
60
61 #font path
61 #font path
62 config.assets.paths << "#{Rails}/vendor/assets/fonts"
62 config.assets.paths << "#{Rails}/vendor/assets/fonts"
63
63
64 config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
64 config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
65 config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
65 config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
66 %w( announcements submissions configurations contests contest_management graders heartbeat
66 %w( announcements submissions configurations contests contest_management graders heartbeat
67 login main messages problems report site sites sources tasks
67 login main messages problems report site sites sources tasks
68 - test user_admin users ).each do |controller|
68 + test user_admin users testcases).each do |controller|
69 config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
69 config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
70 end
70 end
71 end
71 end
72 end
72 end
@@ -1,23 +1,23
1 # Be sure to restart your server when you modify this file.
1 # Be sure to restart your server when you modify this file.
2
2
3 # Version of your assets, change this if you want to expire all your assets.
3 # Version of your assets, change this if you want to expire all your assets.
4 Rails.application.config.assets.version = '1.0'
4 Rails.application.config.assets.version = '1.0'
5
5
6 # Add additional assets to the asset load path.
6 # Add additional assets to the asset load path.
7 # Rails.application.config.assets.paths << Emoji.images_path
7 # Rails.application.config.assets.paths << Emoji.images_path
8 # Add Yarn node_modules folder to the asset load path.
8 # Add Yarn node_modules folder to the asset load path.
9 Rails.application.config.assets.paths << Rails.root.join('node_modules')
9 Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 Rails.application.config.assets.paths << Rails.root.join('vendor/assets/fonts')
10 Rails.application.config.assets.paths << Rails.root.join('vendor/assets/fonts')
11
11
12 # Precompile additional assets.
12 # Precompile additional assets.
13 # application.js, application.css, and all non-JS/CSS in the app/assets
13 # application.js, application.css, and all non-JS/CSS in the app/assets
14 # folder are already added.
14 # folder are already added.
15 # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 # Rails.application.config.assets.precompile += %w( admin.js admin.css )
16
16
17 Rails.application.config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
17 Rails.application.config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
18 Rails.application.config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
18 Rails.application.config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
19 %w( announcements submissions configurations contests contest_management graders heartbeat
19 %w( announcements submissions configurations contests contest_management graders heartbeat
20 login main messages problems report site sites sources tasks groups
20 login main messages problems report site sites sources tasks groups
21 - test user_admin users tags).each do |controller|
21 + test user_admin users tags testcases).each do |controller|
22 Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
22 Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
23 end
23 end
@@ -12,48 +12,49
12 File.join GRADER_ROOT_DIR, "raw"
12 File.join GRADER_ROOT_DIR, "raw"
13 end
13 end
14
14
15 def self.call_grader(params)
15 def self.call_grader(params)
16 if GraderScript.grader_control_enabled?
16 if GraderScript.grader_control_enabled?
17 cmd = File.join(GRADER_ROOT_DIR, "scripts/grader") + " " + params
17 cmd = File.join(GRADER_ROOT_DIR, "scripts/grader") + " " + params
18 system(cmd)
18 system(cmd)
19 end
19 end
20 end
20 end
21
21
22 def self.stop_grader(pid)
22 def self.stop_grader(pid)
23 GraderScript.call_grader "stop #{pid}"
23 GraderScript.call_grader "stop #{pid}"
24 end
24 end
25
25
26 def self.stop_graders(pids)
26 def self.stop_graders(pids)
27 pid_str = (pids.map { |process| process.pid.to_s }).join ' '
27 pid_str = (pids.map { |process| process.pid.to_s }).join ' '
28 GraderScript.call_grader "stop #{pid_str}"
28 GraderScript.call_grader "stop #{pid_str}"
29 end
29 end
30
30
31 def self.start_grader(env)
31 def self.start_grader(env)
32 GraderScript.call_grader "#{env} queue --err-log &"
32 GraderScript.call_grader "#{env} queue --err-log &"
33 GraderScript.call_grader "#{env} test_request -err-log &"
33 GraderScript.call_grader "#{env} test_request -err-log &"
34 end
34 end
35
35
36 + #call the import problem script
36 def self.call_import_problem(problem_name,
37 def self.call_import_problem(problem_name,
37 problem_dir,
38 problem_dir,
38 time_limit=1,
39 time_limit=1,
39 memory_limit=32,
40 memory_limit=32,
40 checker_name='text')
41 checker_name='text')
41 if GraderScript.grader_control_enabled?
42 if GraderScript.grader_control_enabled?
42 cur_dir = `pwd`.chomp
43 cur_dir = `pwd`.chomp
43 Dir.chdir(GRADER_ROOT_DIR)
44 Dir.chdir(GRADER_ROOT_DIR)
44
45
45 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
46 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
46 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
47 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
47 " -t #{time_limit} -m #{memory_limit}"
48 " -t #{time_limit} -m #{memory_limit}"
48
49
49 output = `#{cmd}`
50 output = `#{cmd}`
50
51
51 Dir.chdir(cur_dir)
52 Dir.chdir(cur_dir)
52
53
53 return "import CMD: #{cmd}\n" + output
54 return "import CMD: #{cmd}\n" + output
54 end
55 end
55 return ''
56 return ''
56 end
57 end
57
58
58 def self.call_import_testcase(problem_name)
59 def self.call_import_testcase(problem_name)
59 if GraderScript.grader_control_enabled?
60 if GraderScript.grader_control_enabled?
@@ -1,78 +1,80
1 require 'tmpdir'
1 require 'tmpdir'
2
2
3 class TestdataImporter
3 class TestdataImporter
4
4
5 attr :log_msg
5 attr :log_msg
6
6
7 def initialize(problem)
7 def initialize(problem)
8 @problem = problem
8 @problem = problem
9 end
9 end
10
10
11 - def import_from_file(tempfile,
11 + #Create or update problem according to the parameter
12 - time_limit,
12 + def import_from_file(tempfile,
13 + time_limit,
13 memory_limit,
14 memory_limit,
14 checker_name='text',
15 checker_name='text',
15 import_to_db=false)
16 import_to_db=false)
16
17
17 dirname = extract(tempfile)
18 dirname = extract(tempfile)
18 return false if not dirname
19 return false if not dirname
19 if not import_to_db
20 if not import_to_db
20 @log_msg = GraderScript.call_import_problem(@problem.name,
21 @log_msg = GraderScript.call_import_problem(@problem.name,
21 dirname,
22 dirname,
22 time_limit,
23 time_limit,
23 memory_limit,
24 memory_limit,
24 checker_name)
25 checker_name)
25 else
26 else
26 # Import test data to test pairs.
27 # Import test data to test pairs.
27
28
28 @problem.test_pairs.clear
29 @problem.test_pairs.clear
29 if import_test_pairs(dirname)
30 if import_test_pairs(dirname)
30 test_pair_count = TestPair.count :conditions => "problem_id = #{@problem.id}"
31 test_pair_count = TestPair.count :conditions => "problem_id = #{@problem.id}"
31 @log_msg = "Importing test pair successful. (#{test_pair_count} test pairs imported)"
32 @log_msg = "Importing test pair successful. (#{test_pair_count} test pairs imported)"
32 else
33 else
33 @log_msg = "Importing test pair failed. (0 test pairs imported)"
34 @log_msg = "Importing test pair failed. (0 test pairs imported)"
34 end
35 end
35 end
36 end
36
37
37 @log_msg << import_problem_description(dirname)
38 @log_msg << import_problem_description(dirname)
38 @log_msg << import_problem_pdf(dirname)
39 @log_msg << import_problem_pdf(dirname)
39 @log_msg << import_full_score(dirname)
40 @log_msg << import_full_score(dirname)
40
41
41 #import test data
42 #import test data
42 @log_msg << GraderScript.call_import_testcase(@problem.name)
43 @log_msg << GraderScript.call_import_testcase(@problem.name)
43
44
44 return true
45 return true
45 end
46 end
46
47
47 protected
48 protected
48
49
49 def self.long_ext(filename)
50 def self.long_ext(filename)
50 i = filename.index('.')
51 i = filename.index('.')
51 len = filename.length
52 len = filename.length
52 return filename.slice(i..len)
53 return filename.slice(i..len)
53 end
54 end
54
55
56 + # extract an archive file located at +tempfile+ to the +raw_dir+
55 def extract(tempfile)
57 def extract(tempfile)
56 testdata_filename = save_testdata_file(tempfile)
58 testdata_filename = save_testdata_file(tempfile)
57 ext = TestdataImporter.long_ext(tempfile.original_filename)
59 ext = TestdataImporter.long_ext(tempfile.original_filename)
58
60
59 extract_dir = File.join(GraderScript.raw_dir, @problem.name)
61 extract_dir = File.join(GraderScript.raw_dir, @problem.name)
60 if File.exists? extract_dir
62 if File.exists? extract_dir
61 backup_count = 0
63 backup_count = 0
62 begin
64 begin
63 backup_count += 1
65 backup_count += 1
64 backup_dirname = "#{extract_dir}.backup.#{backup_count}"
66 backup_dirname = "#{extract_dir}.backup.#{backup_count}"
65 end while File.exists? backup_dirname
67 end while File.exists? backup_dirname
66 File.rename(extract_dir, backup_dirname)
68 File.rename(extract_dir, backup_dirname)
67 end
69 end
68 Dir.mkdir extract_dir
70 Dir.mkdir extract_dir
69
71
70 if ext=='.tar.gz' or ext=='.tgz'
72 if ext=='.tar.gz' or ext=='.tgz'
71 cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}"
73 cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}"
72 elsif ext=='.tar'
74 elsif ext=='.tar'
73 cmd = "tar -xvf #{testdata_filename} -C #{extract_dir}"
75 cmd = "tar -xvf #{testdata_filename} -C #{extract_dir}"
74 elsif ext=='.zip'
76 elsif ext=='.zip'
75 cmd = "unzip -o #{testdata_filename} -d #{extract_dir}"
77 cmd = "unzip -o #{testdata_filename} -d #{extract_dir}"
76 else
78 else
77 return nil
79 return nil
78 end
80 end
You need to be logged in to leave comments. Login now