Description:
shows test pair download and grade sample test cases
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r381:abc583474e72 - - 9 files changed: 201 inserted, 11 deleted
@@ -0,0 +1,9 | |||||
|
|
1 | + class TestPairAssignment < ActiveRecord::Base | ||
|
|
2 | + belongs_to :problem | ||
|
|
3 | + belongs_to :test_pair | ||
|
|
4 | + belongs_to :user | ||
|
|
5 | + | ||
|
|
6 | + def expired? | ||
|
|
7 | + return created_at + TEST_ASSIGNMENT_EXPIRATION_DURATION < Time.new.gmtime | ||
|
|
8 | + end | ||
|
|
9 | + end |
@@ -0,0 +1,5 | |||||
|
|
1 | + class AddIsPrivateToTestPairs < ActiveRecord::Migration | ||
|
|
2 | + def change | ||
|
|
3 | + add_column :test_pairs, :is_private, :boolean | ||
|
|
4 | + end | ||
|
|
5 | + end |
@@ -0,0 +1,16 | |||||
|
|
1 | + class CreateTestPairAssignments < ActiveRecord::Migration | ||
|
|
2 | + def up | ||
|
|
3 | + create_table :test_pair_assignments do |t| | ||
|
|
4 | + t.integer "user_id" | ||
|
|
5 | + t.integer "problem_id" | ||
|
|
6 | + t.integer "test_pair_id" | ||
|
|
7 | + t.integer "request_number" | ||
|
|
8 | + t.boolean "submitted" | ||
|
|
9 | + t.timestamps | ||
|
|
10 | + end | ||
|
|
11 | + end | ||
|
|
12 | + | ||
|
|
13 | + def down | ||
|
|
14 | + drop_table :test_pair_assignments | ||
|
|
15 | + end | ||
|
|
16 | + end |
@@ -197,27 +197,123 | |||||
|
197 | redirect_to :action => 'list' |
|
197 | redirect_to :action => 'list' |
|
198 | else |
|
198 | else |
|
199 | @contests = user.contests |
|
199 | @contests = user.contests |
|
200 | @user = user |
|
200 | @user = user |
|
201 | end |
|
201 | end |
|
202 | end |
|
202 | end |
|
|
203 | + | ||
|
|
204 | + # thailandoi contests | ||
|
|
205 | + | ||
|
|
206 | + def verifying_testcase | ||
|
|
207 | + problem = Problem.find(params[:id]) | ||
|
|
208 | + if !problem.available | ||
|
|
209 | + flash[:notice] = 'Error: problem is not available' | ||
|
|
210 | + redirect_to :action => 'list' | ||
|
|
211 | + else | ||
|
|
212 | + test_pair = TestPair.get_for(problem, false) | ||
|
|
213 | + send_data(test_pair.input, | ||
|
|
214 | + {:filename => problem.name + '-verifying-input.txt', | ||
|
|
215 | + :type => 'text/plain'}) | ||
|
|
216 | + end | ||
|
|
217 | + end | ||
|
203 |
|
218 | ||
|
|
219 | + def testcase | ||
|
|
220 | + problem = Problem.find(params[:id]) | ||
|
|
221 | + if !problem.available | ||
|
|
222 | + flash[:notice] = 'Error: problem is not available' | ||
|
|
223 | + redirect_to :action => 'list' | ||
|
|
224 | + else | ||
|
|
225 | + test_pair = TestPair.get_for(problem, true) | ||
|
|
226 | + | ||
|
|
227 | + user = User.find(session[:user_id]) | ||
|
|
228 | + assignent = user.get_test_pair_assignment_for(problem) | ||
|
|
229 | + | ||
|
|
230 | + if !assignent | ||
|
|
231 | + assignent = TestPairAssignment.new | ||
|
|
232 | + assignent.user = user | ||
|
|
233 | + assignent.problem = problem | ||
|
|
234 | + assignent.test_pair = test_pair | ||
|
|
235 | + assignent.submitted = false | ||
|
|
236 | + assignent.save | ||
|
|
237 | + end | ||
|
|
238 | + | ||
|
|
239 | + send_data(test_pair.input, | ||
|
|
240 | + {:filename => problem.name + '-input.txt', | ||
|
|
241 | + :type => 'text/plain'}) | ||
|
|
242 | + end | ||
|
|
243 | + end | ||
|
|
244 | + | ||
|
|
245 | + def verifying_submit | ||
|
|
246 | + user = User.find(session[:user_id]) | ||
|
|
247 | + problem_id = params[:id] | ||
|
|
248 | + problem = Problem.find(problem_id) | ||
|
|
249 | + | ||
|
|
250 | + if !problem or !problem.available | ||
|
|
251 | + flash[:notice] = 'Error: problem is not available' | ||
|
|
252 | + redirect_to :action => 'list' and return | ||
|
|
253 | + end | ||
|
|
254 | + | ||
|
|
255 | + test_pair = TestPair.get_for(problem, false) | ||
|
|
256 | + if (params['output_file']) and (params['output_file']!='') | ||
|
|
257 | + output = params['output_file'].read | ||
|
|
258 | + | ||
|
|
259 | + @current_problem = problem | ||
|
|
260 | + @grading_result = grade(output, test_pair.solution) | ||
|
|
261 | + prepare_list_information | ||
|
|
262 | + render :action => 'list' and return | ||
|
|
263 | + else | ||
|
|
264 | + flash[:notice] = 'Error: output file errors' | ||
|
|
265 | + redirect_to :action => 'list' | ||
|
|
266 | + end | ||
|
|
267 | + end | ||
|
|
268 | + | ||
|
204 | protected |
|
269 | protected |
|
205 |
|
270 | ||
|
|
271 | + def grade(output, solution) | ||
|
|
272 | + out_items = output.split | ||
|
|
273 | + sol_items = solution.split | ||
|
|
274 | + res = '' | ||
|
|
275 | + sol_items.length.times do |i| | ||
|
|
276 | + if out_items[i] == sol_items[i] | ||
|
|
277 | + res = res + 'P' | ||
|
|
278 | + else | ||
|
|
279 | + res = res + '-' | ||
|
|
280 | + end | ||
|
|
281 | + end | ||
|
|
282 | + return res | ||
|
|
283 | + end | ||
|
|
284 | + | ||
|
206 | def prepare_announcements(recent=nil) |
|
285 | def prepare_announcements(recent=nil) |
|
207 | if GraderConfiguration.show_tasks_to?(@user) |
|
286 | if GraderConfiguration.show_tasks_to?(@user) |
|
208 | @announcements = Announcement.find_published(true) |
|
287 | @announcements = Announcement.find_published(true) |
|
209 | else |
|
288 | else |
|
210 | @announcements = Announcement.find_published |
|
289 | @announcements = Announcement.find_published |
|
211 | end |
|
290 | end |
|
212 | if recent!=nil |
|
291 | if recent!=nil |
|
213 | recent_id = recent.to_i |
|
292 | recent_id = recent.to_i |
|
214 | @announcements = @announcements.find_all { |a| a.id > recent_id } |
|
293 | @announcements = @announcements.find_all { |a| a.id > recent_id } |
|
215 | end |
|
294 | end |
|
216 | end |
|
295 | end |
|
217 |
|
296 | ||
|
|
297 | + def prepare_timeout_information(problems) | ||
|
|
298 | + @submission_timeouts = {} | ||
|
|
299 | + problems.each do |problem| | ||
|
|
300 | + assignment = @user.get_test_pair_assignment_for(problem) | ||
|
|
301 | + if assignment == nil | ||
|
|
302 | + timeout = nil | ||
|
|
303 | + else | ||
|
|
304 | + if (assignment.expired?) or (assignment.submitted) | ||
|
|
305 | + timeout = 0 | ||
|
|
306 | + else | ||
|
|
307 | + timeout = assignment.created_at + TEST_ASSIGNMENT_EXPIRATION_DURATION - Time.new.gmtime | ||
|
|
308 | + end | ||
|
|
309 | + end | ||
|
|
310 | + @submission_timeouts[problem.id] = timeout | ||
|
|
311 | + end | ||
|
|
312 | + end | ||
|
|
313 | + | ||
|
218 | def prepare_list_information |
|
314 | def prepare_list_information |
|
219 | @user = User.find(session[:user_id]) |
|
315 | @user = User.find(session[:user_id]) |
|
220 | if not GraderConfiguration.multicontests? |
|
316 | if not GraderConfiguration.multicontests? |
|
221 | @problems = @user.available_problems |
|
317 | @problems = @user.available_problems |
|
222 | else |
|
318 | else |
|
223 | @contest_problems = @user.available_problems_group_by_contests |
|
319 | @contest_problems = @user.available_problems_group_by_contests |
@@ -230,12 +326,13 | |||||
|
230 | @prob_submissions[p.id] = { :count => sub.number, :submission => sub } |
|
326 | @prob_submissions[p.id] = { :count => sub.number, :submission => sub } |
|
231 | else |
|
327 | else |
|
232 | @prob_submissions[p.id] = { :count => 0, :submission => nil } |
|
328 | @prob_submissions[p.id] = { :count => 0, :submission => nil } |
|
233 | end |
|
329 | end |
|
234 | end |
|
330 | end |
|
235 | prepare_announcements |
|
331 | prepare_announcements |
|
|
332 | + prepare_timeout_information(@problems) | ||
|
236 | end |
|
333 | end |
|
237 |
|
334 | ||
|
238 | def check_viewability |
|
335 | def check_viewability |
|
239 | @user = User.find(session[:user_id]) |
|
336 | @user = User.find(session[:user_id]) |
|
240 | if (!GraderConfiguration.show_tasks_to?(@user)) and |
|
337 | if (!GraderConfiguration.show_tasks_to?(@user)) and |
|
241 | ((action_name=='submission') or (action_name=='submit')) |
|
338 | ((action_name=='submission') or (action_name=='submit')) |
@@ -1,3 +1,8 | |||||
|
1 | class TestPair < ActiveRecord::Base |
|
1 | class TestPair < ActiveRecord::Base |
|
2 | belongs_to :problem |
|
2 | belongs_to :problem |
|
|
3 | + | ||
|
|
4 | + def self.get_for(problem, is_private) | ||
|
|
5 | + return TestPair.where(:problem_id => problem.id, | ||
|
|
6 | + :is_private => is_private).first | ||
|
|
7 | + end | ||
|
3 | end |
|
8 | end |
@@ -251,12 +251,17 | |||||
|
251 | return problem.available |
|
251 | return problem.available |
|
252 | else |
|
252 | else |
|
253 | return problem_in_user_contests? problem |
|
253 | return problem_in_user_contests? problem |
|
254 | end |
|
254 | end |
|
255 | end |
|
255 | end |
|
256 |
|
256 | ||
|
|
257 | + def get_test_pair_assignment_for(problem) | ||
|
|
258 | + return TestPairAssignment.where(:problem_id => problem.id, | ||
|
|
259 | + :user_id => id).first | ||
|
|
260 | + end | ||
|
|
261 | + | ||
|
257 | protected |
|
262 | protected |
|
258 | def encrypt_new_password |
|
263 | def encrypt_new_password |
|
259 | return if password.blank? |
|
264 | return if password.blank? |
|
260 | self.salt = (10+rand(90)).to_s |
|
265 | self.salt = (10+rand(90)).to_s |
|
261 | self.hashed_password = User.encrypt(self.password,self.salt) |
|
266 | self.hashed_password = User.encrypt(self.password,self.salt) |
|
262 | end |
|
267 | end |
@@ -1,8 +1,51 | |||||
|
1 | - <%= form_tag({:action => 'submit'}, :multipart => true) do %> |
|
1 | + <div class="submitbox"> |
|
2 | - <b>Problem:</b> <%= select 'submission', 'problem_id', |
|
2 | + <b>Problem:</b> <%= select 'submission', 'problem_id', |
|
3 | - [[(t 'main.specified_in_header'),'-1']] + |
|
3 | + [['กรุณาเลือกข้อที่ต้องการส่งหรือทดสอบ','-1']] + |
|
4 | - @problems.collect {|p| [p.full_name, p.id]}, |
|
4 | + @problems.collect {|p| [p.full_name, p.id]}, |
|
5 |
- :selected => '-1' |
|
5 | + { :selected => '-1' }, |
|
6 | - <b>File:</b> <%= file_field_tag 'file' %> |
|
6 | + { :onchange => 'select_click()' } %> |
|
7 | - <%= submit_tag 'Submit' %> |
|
7 | + </div> |
|
|
8 | + | ||
|
|
9 | + <% @problems.each do |problem| %> | ||
|
|
10 | + <div class="submission-submit-divs" id="submission_submit_div_<%= problem.id %>_id" style="displanny: none;"> | ||
|
|
11 | + <div style="border: 1px solid #c0c0c0; padding: 5px; margin: 5px 0 5px 0;"> | ||
|
|
12 | + <b><%= problem.full_name %>: ข้อมูลสำหรับตรวจสอบ</b> (สามารถดาวน์โหลดและส่งกี่ครั้งก็ได้): | ||
|
|
13 | + <%= link_to 'ดาวน์โหลด input', :action => 'verifying_testcase', :id => problem.id %> | ||
|
|
14 | + <% if @current_problem.id == problem.id %> | ||
|
|
15 | + <% if @grading_result %> | ||
|
|
16 | + | <b>ผลการตรวจ:</b> <%= @grading_result %> | ||
|
|
17 | + <% end %> | ||
|
|
18 | + <% end %> | ||
|
|
19 | + <%= form_tag({:controller => 'main', :action => 'verifying_submit', :id => problem.id}, {:method => 'post', :multipart => true}) do %> | ||
|
|
20 | + ส่งคำตอบของข้อมูลสำหรับตรวจสอบ: | ||
|
|
21 | + <%= file_field_tag 'output_file' %> | ||
|
|
22 | + <%= submit_tag 'Submit' %> | ||
|
|
23 | + <% end %> | ||
|
|
24 | + </div> | ||
|
|
25 | + <div style="border: 1px solid #c0c0c0; padding: 5px; margin: 5px 0 5px 0;"> | ||
|
|
26 | + <b><%= problem.full_name %>: ข้อมูลทดสอบจริง</b> (ส่งกี่ครั้งก็ได้ภายในเวลา 5 นาทีหลังดาวน์โหลด): | ||
|
|
27 | + <%= link_to 'ดาวน์โหลด input และเริ่มจับเวลา', { :action => 'testcase', :id => problem.id}, { :onclick => 'return confirm_download()' } %> | ||
|
|
28 | + <span id="submission_time_left_<%= problem.id %>_id"></span> | ||
|
|
29 | + <%= form_tag do %> | ||
|
|
30 | + ข้อมูลส่งออก: <%= file_field_tag 'output_file' %> | ||
|
|
31 | + โปรแกรมคำตอบ: <%= file_field_tag 'source_file' %> | ||
|
|
32 | + <%= submit_tag 'Submit' %> | ||
|
|
33 | + <% end %> | ||
|
|
34 | + </div> | ||
|
|
35 | + </div> | ||
|
8 | <% end %> |
|
36 | <% end %> |
|
|
37 | + <script> | ||
|
|
38 | + function select_click() { | ||
|
|
39 | + $$(".submission-submit-divs").each(function(item) { | ||
|
|
40 | + item.hide(); | ||
|
|
41 | + }); | ||
|
|
42 | + var problem_id = $('submission_problem_id').value; | ||
|
|
43 | + if ( problem_id < 0 ) { | ||
|
|
44 | + return; | ||
|
|
45 | + } | ||
|
|
46 | + $("submission_submit_div_" + problem_id + "_id").show(); | ||
|
|
47 | + } | ||
|
|
48 | + function confirm_download() { | ||
|
|
49 | + return confirm("แน่ใจ?"); | ||
|
|
50 | + } | ||
|
|
51 | + </script> |
@@ -7,15 +7,14 | |||||
|
7 | %span{:class => 'title'} |
|
7 | %span{:class => 'title'} |
|
8 | Announcements |
|
8 | Announcements |
|
9 | #announcementbox-body |
|
9 | #announcementbox-body |
|
10 | = render :partial => 'announcement', :collection => @announcements |
|
10 | = render :partial => 'announcement', :collection => @announcements |
|
11 |
|
11 | ||
|
12 | - if GraderConfiguration.show_submitbox_to?(@user) |
|
12 | - if GraderConfiguration.show_submitbox_to?(@user) |
|
13 | - .submitbox |
|
13 | + = error_messages_for 'submission' |
|
14 | - = error_messages_for 'submission' |
|
14 | + = render :partial => 'submission_box' |
|
15 | - = render :partial => 'submission_box' |
|
||
|
16 |
|
15 | ||
|
17 |
|
16 | ||
|
18 | %hr/ |
|
17 | %hr/ |
|
19 |
|
18 | ||
|
20 | - if (GraderConfiguration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true) |
|
19 | - if (GraderConfiguration.contest_mode?) and (@user.site!=nil) and (@user.site.started!=true) |
|
21 | %p=t 'main.start_soon' |
|
20 | %p=t 'main.start_soon' |
@@ -8,13 +8,13 | |||||
|
8 | # system, you should be using db:schema:load, not running all the migrations |
|
8 | # system, you should be using db:schema:load, not running all the migrations |
|
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations |
|
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations |
|
10 | # you'll amass, the slower it'll run and the greater likelihood for issues). |
|
10 | # you'll amass, the slower it'll run and the greater likelihood for issues). |
|
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 => 201 |
|
14 | + ActiveRecord::Schema.define(:version => 20150128165518) 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" |
|
18 | t.text "body" |
|
18 | t.text "body" |
|
19 | t.boolean "published" |
|
19 | t.boolean "published" |
|
20 | t.datetime "created_at", :null => false |
|
20 | t.datetime "created_at", :null => false |
@@ -175,18 +175,29 | |||||
|
175 | t.integer "submission_id" |
|
175 | t.integer "submission_id" |
|
176 | t.datetime "created_at" |
|
176 | t.datetime "created_at" |
|
177 | t.integer "status" |
|
177 | t.integer "status" |
|
178 | t.datetime "updated_at" |
|
178 | t.datetime "updated_at" |
|
179 | end |
|
179 | end |
|
180 |
|
180 | ||
|
|
181 | + create_table "test_pair_assignments", :force => true do |t| | ||
|
|
182 | + t.integer "user_id" | ||
|
|
183 | + t.integer "problem_id" | ||
|
|
184 | + t.integer "test_pair_id" | ||
|
|
185 | + t.integer "request_number" | ||
|
|
186 | + t.boolean "submitted" | ||
|
|
187 | + t.datetime "created_at", :null => false | ||
|
|
188 | + t.datetime "updated_at", :null => false | ||
|
|
189 | + end | ||
|
|
190 | + | ||
|
181 | create_table "test_pairs", :force => true do |t| |
|
191 | create_table "test_pairs", :force => true do |t| |
|
182 | t.integer "problem_id" |
|
192 | t.integer "problem_id" |
|
183 | t.text "input", :limit => 16777215 |
|
193 | t.text "input", :limit => 16777215 |
|
184 | t.text "solution", :limit => 16777215 |
|
194 | t.text "solution", :limit => 16777215 |
|
185 | t.datetime "created_at", :null => false |
|
195 | t.datetime "created_at", :null => false |
|
186 | t.datetime "updated_at", :null => false |
|
196 | t.datetime "updated_at", :null => false |
|
|
197 | + t.boolean "is_private" | ||
|
187 | end |
|
198 | end |
|
188 |
|
199 | ||
|
189 | create_table "test_requests", :force => true do |t| |
|
200 | create_table "test_requests", :force => true do |t| |
|
190 | t.integer "user_id" |
|
201 | t.integer "user_id" |
|
191 | t.integer "problem_id" |
|
202 | t.integer "problem_id" |
|
192 | t.integer "submission_id" |
|
203 | t.integer "submission_id" |
You need to be logged in to leave comments.
Login now