Description:
saves submitted output, checks time outs; updated submission front-end flows
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r383:31aa87b1b1e9 - - 8 files changed: 116 inserted, 20 deleted
@@ -0,0 +1,5 | |||||
|
|
1 | + class AddOutputToSubmissions < ActiveRecord::Migration | ||
|
|
2 | + def change | ||
|
|
3 | + add_column :submissions, :output, :text | ||
|
|
4 | + end | ||
|
|
5 | + end |
@@ -1,7 +1,9 | |||||
|
1 | var TOIContest = { |
|
1 | var TOIContest = { |
|
2 | NO_TIMEOUT: -1, |
|
2 | NO_TIMEOUT: -1, |
|
|
3 | + SUBMISSION_TIMEOUT: 300, | ||
|
3 |
|
4 | ||
|
4 | timeOuts: {}, |
|
5 | timeOuts: {}, |
|
|
6 | + timeStarted: 0, | ||
|
5 |
|
7 | ||
|
6 | problemSelectClick: function() { |
|
8 | problemSelectClick: function() { |
|
7 | $$(".submission-submit-divs").each(function(item) { |
|
9 | $$(".submission-submit-divs").each(function(item) { |
@@ -14,8 +16,18 | |||||
|
14 | $("submission_submit_div_" + problem_id + "_id").show(); |
|
16 | $("submission_submit_div_" + problem_id + "_id").show(); |
|
15 | }, |
|
17 | }, |
|
16 |
|
18 | ||
|
17 | - confirmDownload: function() { |
|
19 | + confirmDownload: function(pid) { |
|
18 | - return confirm("แน่ใจ?"); |
|
20 | + result = confirm("คุณแน่ใจที่จะส่งข้อนี้หรือไม่?\nเมื่อคุณดาวน์โหลดข้อมูลชุดทดสอบแล้ว คุณจะต้องส่งข้อมูลส่งออกและโปรแกรมภายในเวลา 5 นาที"); |
|
|
21 | + if ( result ) { | ||
|
|
22 | + if ( TOIContest.timeOuts[ pid ] == TOIContest.NO_TIMEOUT ) { | ||
|
|
23 | + TOIContest.refreshTimeOuts(); | ||
|
|
24 | + | ||
|
|
25 | + TOIContest.timeOuts[ pid ] = TOIContest.SUBMISSION_TIMEOUT; | ||
|
|
26 | + | ||
|
|
27 | + TOIContest.refreshTimeOutMessages(); | ||
|
|
28 | + } | ||
|
|
29 | + } | ||
|
|
30 | + return result; | ||
|
19 | }, |
|
31 | }, |
|
20 |
|
32 | ||
|
21 | refreshTimeOutMessages: function() { |
|
33 | refreshTimeOutMessages: function() { |
@@ -26,12 +38,40 | |||||
|
26 | var minLeft = parseInt(timeOut / 60); |
|
38 | var minLeft = parseInt(timeOut / 60); |
|
27 | var secLeft = parseInt(timeOut % 60); |
|
39 | var secLeft = parseInt(timeOut % 60); |
|
28 | $('submission_time_left_' + pid + '_id').innerHTML = '| <b>เหลือเวลาอีก ' + minLeft + ':' + secLeft + ' นาที</b>'; |
|
40 | $('submission_time_left_' + pid + '_id').innerHTML = '| <b>เหลือเวลาอีก ' + minLeft + ':' + secLeft + ' นาที</b>'; |
|
|
41 | + $('submission_form_'+ pid + '_id').show(); | ||
|
29 | } else { |
|
42 | } else { |
|
30 | $('submission_time_left_' + pid + '_id').innerHTML = '| <b>หมดเวลาส่ง</a>'; |
|
43 | $('submission_time_left_' + pid + '_id').innerHTML = '| <b>หมดเวลาส่ง</a>'; |
|
31 | $('submission_form_'+ pid + '_id').hide(); |
|
44 | $('submission_form_'+ pid + '_id').hide(); |
|
32 | } |
|
45 | } |
|
|
46 | + } else { | ||
|
|
47 | + $('submission_form_'+ pid + '_id').hide(); | ||
|
33 | } |
|
48 | } |
|
34 | } |
|
49 | } |
|
35 | - } |
|
50 | + }, |
|
|
51 | + | ||
|
|
52 | + refreshTimeOuts: function() { | ||
|
|
53 | + if ( TOIContest.timeStarted == 0 ) { | ||
|
|
54 | + TOIContest.timeStarted = (new Date()).getTime(); | ||
|
|
55 | + } | ||
|
|
56 | + | ||
|
|
57 | + var timeElapsed = ((new Date()).getTime() - TOIContest.timeStarted)/1000; | ||
|
|
58 | + for ( var pid in TOIContest.timeOuts ) { | ||
|
|
59 | + var timeOut = TOIContest.timeOuts[ pid ]; | ||
|
|
60 | + if ( timeOut > timeElapsed ) { | ||
|
|
61 | + TOIContest.timeOuts[ pid ] -= timeElapsed; | ||
|
|
62 | + } else if ( timeOut > 0 ) { | ||
|
|
63 | + TOIContest.timeOuts[ pid ] = 0; | ||
|
|
64 | + } | ||
|
|
65 | + } | ||
|
|
66 | + }, | ||
|
|
67 | + | ||
|
|
68 | + registerRefreshEvent: function() { | ||
|
|
69 | + TOIContest.timeStarted = (new Date()).getTime(); | ||
|
|
70 | + setTimeout(function () { | ||
|
|
71 | + TOIContest.refreshTimeOuts(); | ||
|
|
72 | + TOIContest.refreshTimeOutMessages(); | ||
|
|
73 | + TOIContest.registerRefreshEvent(); | ||
|
|
74 | + }, 1000); | ||
|
|
75 | + }, | ||
|
36 | }; |
|
76 | }; |
|
37 |
|
77 |
@@ -1,3 +1,4 | |||||
|
|
1 | + # coding: utf-8 | ||
|
1 | class MainController < ApplicationController |
|
2 | class MainController < ApplicationController |
|
2 |
|
3 | ||
|
3 | before_filter :authenticate, :except => [:index, :login] |
|
4 | before_filter :authenticate, :except => [:index, :login] |
@@ -48,6 +49,10 | |||||
|
48 | end |
|
49 | end |
|
49 |
|
50 | ||
|
50 | def list |
|
51 | def list |
|
|
52 | + if session[:current_problem_id] | ||
|
|
53 | + @current_problem = Problem.find(session[:current_problem_id]) | ||
|
|
54 | + session[:current_problem_id] = nil | ||
|
|
55 | + end | ||
|
51 | prepare_list_information |
|
56 | prepare_list_information |
|
52 | end |
|
57 | end |
|
53 |
|
58 | ||
@@ -59,13 +64,35 | |||||
|
59 | user = User.find(session[:user_id]) |
|
64 | user = User.find(session[:user_id]) |
|
60 |
|
65 | ||
|
61 | @submission = Submission.new |
|
66 | @submission = Submission.new |
|
62 |
- @ |
|
67 | + @current_problem = Problem.find(params[:submission][:problem_id]) |
|
|
68 | + | ||
|
|
69 | + if !@current_problem | ||
|
|
70 | + flash[:notice] = 'Error: คุณยังไม่ได้ระบุข้อที่ต้องการส่ง' | ||
|
|
71 | + redirect_to :action => 'list' | ||
|
|
72 | + end | ||
|
|
73 | + | ||
|
|
74 | + assignment = user.get_test_pair_assignment_for(@current_problem) | ||
|
|
75 | + if !assignment | ||
|
|
76 | + flash[:notice] = 'Error: คุณยังไม่ได้ดาวน์โหลดข้อมูลทดสอบ' | ||
|
|
77 | + prepare_list_information | ||
|
|
78 | + render :action => 'list' and return | ||
|
|
79 | + end | ||
|
|
80 | + if assignment.expired? | ||
|
|
81 | + flash[:notice] = 'Error: หมดเวลาส่งสำหรับข้อนี้' | ||
|
|
82 | + prepare_list_information | ||
|
|
83 | + render :action => 'list' and return | ||
|
|
84 | + end | ||
|
|
85 | + | ||
|
|
86 | + @submission.problem = @current_problem | ||
|
63 | @submission.user = user |
|
87 | @submission.user = user |
|
64 | @submission.language_id = 0 |
|
88 | @submission.language_id = 0 |
|
65 | if (params['file']) and (params['file']!='') |
|
89 | if (params['file']) and (params['file']!='') |
|
66 | @submission.source = params['file'].read |
|
90 | @submission.source = params['file'].read |
|
67 | @submission.source_filename = params['file'].original_filename |
|
91 | @submission.source_filename = params['file'].original_filename |
|
68 | end |
|
92 | end |
|
|
93 | + if (params['output_file']) and (params['output_file']!='') | ||
|
|
94 | + @submission.output = params['output_file'].read | ||
|
|
95 | + end | ||
|
69 | @submission.submitted_at = Time.new.gmtime |
|
96 | @submission.submitted_at = Time.new.gmtime |
|
70 |
|
97 | ||
|
71 | if GraderConfiguration.time_limit_mode? and user.contest_finished? |
|
98 | if GraderConfiguration.time_limit_mode? and user.contest_finished? |
@@ -80,11 +107,17 | |||||
|
80 | elsif Task.create(:submission_id => @submission.id, |
|
107 | elsif Task.create(:submission_id => @submission.id, |
|
81 | :status => Task::STATUS_INQUEUE) == false |
|
108 | :status => Task::STATUS_INQUEUE) == false |
|
82 | flash[:notice] = 'Error adding your submission to task queue' |
|
109 | flash[:notice] = 'Error adding your submission to task queue' |
|
|
110 | + else | ||
|
|
111 | + flash[:notice] = 'จัดเก็บคำตอบและโปรแกรมที่คุณส่งเรียบร้อย' | ||
|
83 | end |
|
112 | end |
|
84 | else |
|
113 | else |
|
85 | prepare_list_information |
|
114 | prepare_list_information |
|
86 | render :action => 'list' and return |
|
115 | render :action => 'list' and return |
|
87 | end |
|
116 | end |
|
|
117 | + | ||
|
|
118 | + if @current_problem | ||
|
|
119 | + session[:current_problem_id] = @current_problem.id | ||
|
|
120 | + end | ||
|
88 | redirect_to :action => 'list' |
|
121 | redirect_to :action => 'list' |
|
89 | end |
|
122 | end |
|
90 |
|
123 | ||
@@ -225,15 +258,11 | |||||
|
225 | test_pair = TestPair.get_for(problem, true) |
|
258 | test_pair = TestPair.get_for(problem, true) |
|
226 |
|
259 | ||
|
227 | user = User.find(session[:user_id]) |
|
260 | user = User.find(session[:user_id]) |
|
228 | - assignent = user.get_test_pair_assignment_for(problem) |
|
261 | + assignment = user.get_test_pair_assignment_for(problem) |
|
229 |
|
262 | ||
|
230 | - if !assignent |
|
263 | + if !assignment |
|
231 |
- assignent = TestPairAssignment. |
|
264 | + assignment = TestPairAssignment.create_for(user, problem, test_pair) |
|
232 |
- assignent. |
|
265 | + assignment.save |
|
233 | - assignent.problem = problem |
|
||
|
234 | - assignent.test_pair = test_pair |
|
||
|
235 | - assignent.submitted = false |
|
||
|
236 | - assignent.save |
|
||
|
237 | end |
|
266 | end |
|
238 |
|
267 | ||
|
239 | send_data(test_pair.input, |
|
268 | send_data(test_pair.input, |
@@ -252,17 +281,18 | |||||
|
252 | redirect_to :action => 'list' and return |
|
281 | redirect_to :action => 'list' and return |
|
253 | end |
|
282 | end |
|
254 |
|
283 | ||
|
|
284 | + @current_problem = problem | ||
|
255 | test_pair = TestPair.get_for(problem, false) |
|
285 | test_pair = TestPair.get_for(problem, false) |
|
256 | if (params['output_file']) and (params['output_file']!='') |
|
286 | if (params['output_file']) and (params['output_file']!='') |
|
257 | output = params['output_file'].read |
|
287 | output = params['output_file'].read |
|
258 |
|
288 | ||
|
259 | - @current_problem = problem |
|
||
|
260 | @grading_result = grade(output, test_pair.solution) |
|
289 | @grading_result = grade(output, test_pair.solution) |
|
261 | prepare_list_information |
|
290 | prepare_list_information |
|
262 | render :action => 'list' and return |
|
291 | render :action => 'list' and return |
|
263 | else |
|
292 | else |
|
264 | flash[:notice] = 'Error: output file errors' |
|
293 | flash[:notice] = 'Error: output file errors' |
|
265 | - redirect_to :action => 'list' |
|
294 | + prepare_list_information |
|
|
295 | + render :action => 'list' and return | ||
|
266 | end |
|
296 | end |
|
267 | end |
|
297 | end |
|
268 |
|
298 |
@@ -10,6 +10,11 | |||||
|
10 | validates_presence_of :source |
|
10 | validates_presence_of :source |
|
11 | validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long' |
|
11 | validates_length_of :source, :maximum => 100_000, :allow_blank => true, :message => 'too long' |
|
12 | validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short' |
|
12 | validates_length_of :source, :minimum => 1, :allow_blank => true, :message => 'too short' |
|
|
13 | + | ||
|
|
14 | + validates_presence_of :output | ||
|
|
15 | + validates_length_of :output, :maximum => 100_000, :allow_blank => true, :message => 'too long' | ||
|
|
16 | + validates_length_of :output, :minimum => 1, :allow_blank => true, :message => 'too short' | ||
|
|
17 | + | ||
|
13 | validate :must_have_valid_problem |
|
18 | validate :must_have_valid_problem |
|
14 | validate :must_specify_language |
|
19 | validate :must_specify_language |
|
15 |
|
20 |
@@ -6,4 +6,14 | |||||
|
6 | def expired? |
|
6 | def expired? |
|
7 | return created_at + TEST_ASSIGNMENT_EXPIRATION_DURATION < Time.new.gmtime |
|
7 | return created_at + TEST_ASSIGNMENT_EXPIRATION_DURATION < Time.new.gmtime |
|
8 | end |
|
8 | end |
|
|
9 | + | ||
|
|
10 | + def self.create_for(user, problem, test_pair) | ||
|
|
11 | + assignment = TestPairAssignment.new | ||
|
|
12 | + assignment.user = user | ||
|
|
13 | + assignment.problem = problem | ||
|
|
14 | + assignment.test_pair = test_pair | ||
|
|
15 | + assignment.submitted = false | ||
|
|
16 | + assignment.save | ||
|
|
17 | + return assignment | ||
|
|
18 | + end | ||
|
9 | end |
|
19 | end |
@@ -1,13 +1,14 | |||||
|
|
1 | + <% selected_problem_id = @current_problem ? @current_problem.id : -1 %> | ||
|
1 | <div class="submitbox"> |
|
2 | <div class="submitbox"> |
|
2 | <b>Problem:</b> <%= select 'submission', 'problem_id', |
|
3 | <b>Problem:</b> <%= select 'submission', 'problem_id', |
|
3 | [['กรุณาเลือกข้อที่ต้องการส่งหรือทดสอบ','-1']] + |
|
4 | [['กรุณาเลือกข้อที่ต้องการส่งหรือทดสอบ','-1']] + |
|
4 | @problems.collect {|p| [p.full_name, p.id]}, |
|
5 | @problems.collect {|p| [p.full_name, p.id]}, |
|
5 |
- { :selected => |
|
6 | + { :selected => selected_problem_id }, |
|
6 | { :onchange => 'TOIContest.problemSelectClick()' } %> |
|
7 | { :onchange => 'TOIContest.problemSelectClick()' } %> |
|
7 | </div> |
|
8 | </div> |
|
8 |
|
9 | ||
|
9 | <% @problems.each do |problem| %> |
|
10 | <% @problems.each do |problem| %> |
|
10 |
- <div class="submission-submit-divs" id="submission_submit_div_<%= problem.id %>_id" style="displa |
|
11 | + <div class="submission-submit-divs" id="submission_submit_div_<%= problem.id %>_id" style="display: none;"> |
|
11 | <div style="border: 1px solid #c0c0c0; padding: 5px; margin: 5px 0 5px 0;"> |
|
12 | <div style="border: 1px solid #c0c0c0; padding: 5px; margin: 5px 0 5px 0;"> |
|
12 | <b><%= problem.full_name %>: ข้อมูลสำหรับตรวจสอบ</b> (สามารถดาวน์โหลดและส่งกี่ครั้งก็ได้,ไม่มีคะแนน): |
|
13 | <b><%= problem.full_name %>: ข้อมูลสำหรับตรวจสอบ</b> (สามารถดาวน์โหลดและส่งกี่ครั้งก็ได้,ไม่มีคะแนน): |
|
13 | <%= link_to 'ดาวน์โหลด input', :action => 'verifying_testcase', :id => problem.id %> |
|
14 | <%= link_to 'ดาวน์โหลด input', :action => 'verifying_testcase', :id => problem.id %> |
@@ -24,11 +25,12 | |||||
|
24 | </div> |
|
25 | </div> |
|
25 | <div style="border: 1px solid #c0c0c0; padding: 5px; margin: 5px 0 5px 0;"> |
|
26 | <div style="border: 1px solid #c0c0c0; padding: 5px; margin: 5px 0 5px 0;"> |
|
26 | <b><%= problem.full_name %>: ข้อมูลทดสอบจริง</b> (ส่งกี่ครั้งก็ได้ภายในเวลา 5 นาทีหลังดาวน์โหลด): |
|
27 | <b><%= problem.full_name %>: ข้อมูลทดสอบจริง</b> (ส่งกี่ครั้งก็ได้ภายในเวลา 5 นาทีหลังดาวน์โหลด): |
|
27 |
- <%= link_to 'ดาวน์โหลด input และเริ่มจับเวลา', { :action => 'testcase', :id => problem.id}, { :onclick => |
|
28 | + <%= link_to 'ดาวน์โหลด input และเริ่มจับเวลา', { :action => 'testcase', :id => problem.id}, { :onclick => "return TOIContest.confirmDownload(#{problem.id})" } %> |
|
28 | <span id="submission_time_left_<%= problem.id %>_id"></span> |
|
29 | <span id="submission_time_left_<%= problem.id %>_id"></span> |
|
29 |
- <%= form_tag({:controller => 'main', :action => 'submit' |
|
30 | + <%= form_tag({:controller => 'main', :action => 'submit'}, {:method => 'post', :multipart => true, :id => "submission_form_#{problem.id}_id" }) do %> |
|
|
31 | + <%= hidden_field_tag 'submission[problem_id]', problem.id %> | ||
|
30 | ข้อมูลส่งออก: <%= file_field_tag 'output_file' %> |
|
32 | ข้อมูลส่งออก: <%= file_field_tag 'output_file' %> |
|
31 |
- โปรแกรมคำตอบ: <%= file_field_tag ' |
|
33 | + โปรแกรมคำตอบ: <%= file_field_tag 'file' %> |
|
32 | <%= submit_tag 'Submit' %> |
|
34 | <%= submit_tag 'Submit' %> |
|
33 | <% end %> |
|
35 | <% end %> |
|
34 | </div> |
|
36 | </div> |
@@ -49,6 +49,8 | |||||
|
49 | = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';" |
|
49 | = "Announcement.refreshUrl = '#{url_for :controller => 'main', :action => 'announcements'}';" |
|
50 | Announcement.registerRefreshEventTimer(); |
|
50 | Announcement.registerRefreshEventTimer(); |
|
51 |
|
51 | ||
|
|
52 | + TOIContest.problemSelectClick() | ||
|
|
53 | + | ||
|
52 | TOIContest.timeOuts = {}; |
|
54 | TOIContest.timeOuts = {}; |
|
53 | - @problems.each do |p| |
|
55 | - @problems.each do |p| |
|
54 | - if (@submission_timeouts.has_key? p.id) and (@submission_timeouts[p.id] != nil) |
|
56 | - if (@submission_timeouts.has_key? p.id) and (@submission_timeouts[p.id] != nil) |
@@ -57,3 +59,4 | |||||
|
57 | = "TOIContest.timeOuts[#{p.id}] = TOIContest.NO_TIMEOUT;" |
|
59 | = "TOIContest.timeOuts[#{p.id}] = TOIContest.NO_TIMEOUT;" |
|
58 |
|
60 | ||
|
59 | TOIContest.refreshTimeOutMessages(); |
|
61 | TOIContest.refreshTimeOutMessages(); |
|
|
62 | + TOIContest.registerRefreshEvent(); |
@@ -11,7 +11,7 | |||||
|
11 | # |
|
11 | # |
|
12 | # It's strongly recommended to check this file into your version control system. |
|
12 | # It's strongly recommended to check this file into your version control system. |
|
13 |
|
13 | ||
|
14 |
- ActiveRecord::Schema.define(:version => 2015012 |
|
14 | + ActiveRecord::Schema.define(:version => 20150129021221) do |
|
15 |
|
15 | ||
|
16 | create_table "announcements", :force => true do |t| |
|
16 | create_table "announcements", :force => true do |t| |
|
17 | t.string "author" |
|
17 | t.string "author" |
@@ -166,6 +166,7 | |||||
|
166 | t.text "grader_comment" |
|
166 | t.text "grader_comment" |
|
167 | t.integer "number" |
|
167 | t.integer "number" |
|
168 | t.string "source_filename" |
|
168 | t.string "source_filename" |
|
|
169 | + t.text "output" | ||
|
169 | end |
|
170 | end |
|
170 |
|
171 | ||
|
171 | add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true |
|
172 | add_index "submissions", ["user_id", "problem_id", "number"], :name => "index_submissions_on_user_id_and_problem_id_and_number", :unique => true |
You need to be logged in to leave comments.
Login now