Description:
merge
Commit status:
[Not Reviewed]
References:
merge java
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r701:f26733606a76 - - 21 files changed: 132 inserted, 57 deleted

@@ -88,25 +88,25
88 88
89 89 if @submission.valid?(@current_user)
90 90 if @submission.save == false
91 91 flash[:notice] = 'Error saving your submission'
92 92 elsif Task.create(:submission_id => @submission.id,
93 93 :status => Task::STATUS_INQUEUE) == false
94 94 flash[:notice] = 'Error adding your submission to task queue'
95 95 end
96 96 else
97 97 prepare_list_information
98 98 render :action => 'list' and return
99 99 end
100 - redirect_to :action => 'list'
100 + redirect_to edit_submission_path(@submission)
101 101 end
102 102
103 103 def source
104 104 submission = Submission.find(params[:id])
105 105 if ((submission.user_id == session[:user_id]) and
106 106 (submission.problem != nil) and
107 107 (submission.problem.available))
108 108 send_data(submission.source,
109 109 {:filename => submission.download_filename,
110 110 :type => 'text/plain'})
111 111 else
112 112 flash[:notice] = 'Error viewing source'
@@ -156,25 +156,25
156 156 problem.available = true
157 157 problem.save
158 158 end
159 159 redirect_to action: :index
160 160 end
161 161
162 162 def stat
163 163 @problem = Problem.find(params[:id])
164 164 unless @problem.available or session[:admin]
165 165 redirect_to :controller => 'main', :action => 'list'
166 166 return
167 167 end
168 - @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
168 + @submissions = Submission.includes(:user).includes(:language).where(problem_id: params[:id]).order(:user_id,:id)
169 169
170 170 #stat summary
171 171 range =65
172 172 @histogram = { data: Array.new(range,0), summary: {} }
173 173 user = Hash.new(0)
174 174 @submissions.find_each do |sub|
175 175 d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60
176 176 @histogram[:data][d.to_i] += 1 if d < range
177 177 user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max
178 178 end
179 179 @histogram[:summary][:max] = [@histogram[:data].max,1].max
180 180
@@ -200,24 +200,28
200 200 ok = []
201 201 failed = []
202 202 get_problems_from_params.each do |p|
203 203 begin
204 204 group.problems << p
205 205 ok << p.full_name
206 206 rescue => e
207 207 failed << p.full_name
208 208 end
209 209 end
210 210 flash[:success] = "The following problems are added to the group #{group.name}: " + ok.join(', ') if ok.count > 0
211 211 flash[:alert] = "The following problems are already in the group #{group.name}: " + failed.join(', ') if failed.count > 0
212 + elsif params.has_key? 'add_tags'
213 + get_problems_from_params.each do |p|
214 + p.tag_ids += params[:tag_ids]
215 + end
212 216 end
213 217
214 218 redirect_to :action => 'manage'
215 219 end
216 220
217 221 def import
218 222 @allow_test_pair_import = allow_test_pair_import?
219 223 end
220 224
221 225 def do_import
222 226 old_problem = Problem.find_by_name(params[:name])
223 227 if !allow_test_pair_import? and params.has_key? :import_to_db
@@ -291,16 +295,16
291 295 problems << Problem.find(id)
292 296 end
293 297 end
294 298 problems
295 299 end
296 300
297 301 def get_problems_stat
298 302 end
299 303
300 304 private
301 305
302 306 def problem_params
303 - params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description)
307 + params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description, tag_ids:[])
304 308 end
305 309
306 310 end
@@ -43,24 +43,26
43 43 end
44 44
45 45 #users
46 46 @users = if params[:user] == "all" then
47 47 User.includes(:contests).includes(:contest_stat)
48 48 else
49 49 User.includes(:contests).includes(:contest_stat).where(enabled: true)
50 50 end
51 51
52 52 #set up range from param
53 53 @since_id = params.fetch(:from_id, 0).to_i
54 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 58 #calculate the routine
57 59 @scorearray = calculate_max_score(@problems, @users, @since_id, @until_id)
58 60
59 61 #rencer accordingly
60 62 if params[:button] == 'download' then
61 63 csv = gen_csv_from_scorearray(@scorearray,@problems)
62 64 send_data csv, filename: 'max_score.csv'
63 65 else
64 66 #render template: 'user_admin/user_stat'
65 67 render 'max_score'
66 68 end
@@ -32,24 +32,26
32 32
33 33 # PATCH/PUT /tags/1
34 34 def update
35 35 if @tag.update(tag_params)
36 36 redirect_to @tag, notice: 'Tag was successfully updated.'
37 37 else
38 38 render :edit
39 39 end
40 40 end
41 41
42 42 # DELETE /tags/1
43 43 def destroy
44 + #remove any association
45 + ProblemTag.where(tag_id: @tag.id).destroy_all
44 46 @tag.destroy
45 47 redirect_to tags_url, notice: 'Tag was successfully destroyed.'
46 48 end
47 49
48 50 private
49 51 # Use callbacks to share common setup or constraints between actions.
50 52 def set_tag
51 53 @tag = Tag.find(params[:id])
52 54 end
53 55
54 56 # Only allow a trusted parameter "white list" through.
55 57 def tag_params
@@ -76,39 +76,42
76 76
77 77 menu_items.html_safe
78 78 end
79 79
80 80 def append_to(option,label, controller, action)
81 81 option << ' ' if option!=''
82 82 option << link_to_unless_current(label,
83 83 :controller => controller,
84 84 :action => action)
85 85 end
86 86
87 87 def format_short_time(time)
88 - now = Time.now.gmtime
88 + now = Time.zone.now
89 89 st = ''
90 - if (time.yday != now.yday) or
91 - (time.year != now.year)
92 - st = time.strftime("%x ")
90 + if (time.yday != now.yday) or (time.year != now.year)
91 + st = time.strftime("%d/%m/%y ")
93 92 end
94 93 st + time.strftime("%X")
95 94 end
96 95
97 96 def format_short_duration(duration)
98 97 return '' if duration==nil
99 98 d = duration.to_f
100 99 return Time.at(d).gmtime.strftime("%X")
101 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 106 def read_textfile(fname,max_size=2048)
104 107 begin
105 108 File.open(fname).read(max_size)
106 109 rescue
107 110 nil
108 111 end
109 112 end
110 113
111 114 def toggle_button(on,toggle_url,id, option={})
112 115 btn_size = option[:size] || 'btn-xs'
113 116 link_to (on ? "Yes" : "No"), toggle_url,
114 117 {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
@@ -25,26 +25,26
25 25 # need to put in SQL command, maybe there's a better way
26 26 Submission.includes(:user).find_by_sql("SELECT * FROM submissions " +
27 27 "WHERE id = " +
28 28 "(SELECT MAX(id) FROM submissions AS subs " +
29 29 "WHERE subs.user_id = submissions.user_id AND " +
30 30 "problem_id = " + problem_id.to_s + " " +
31 31 "GROUP BY user_id) " +
32 32 "ORDER BY user_id")
33 33 end
34 34
35 35 def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id)
36 36 records = Submission.where(problem_id: problem_id,user_id: user_id)
37 - records = records.where('id >= ?',since_id) if since_id > 0
38 - records = records.where('id <= ?',until_id) if until_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 and until_id > 0
39 39 records.all
40 40 end
41 41
42 42 def self.find_last_for_all_available_problems(user_id)
43 43 submissions = Array.new
44 44 problems = Problem.available_problems
45 45 problems.each do |problem|
46 46 sub = Submission.find_last_by_user_and_problem(user_id, problem.id)
47 47 submissions << sub if sub!=nil
48 48 end
49 49 submissions
50 50 end
@@ -1,26 +1,28
1 -
2 1 - if submission.nil?
3 2 = "-"
4 3 - else
4 + %strong= "Submission ID:"
5 + = submission.id
6 + %br
5 7 - unless submission.graded_at
6 - = t 'main.submitted_at'
7 - = format_short_time(submission.submitted_at.localtime)
8 + %strong= t 'main.submitted_at:'
9 + = format_full_time_ago(submission.submitted_at.localtime)
8 10 - else
9 - %strong= t 'main.graded_at'
10 - = "#{format_short_time(submission.graded_at.localtime)} "
11 + %strong= t 'main.graded_at:'
12 + = format_full_time_ago(submission.graded_at.localtime)
11 13 %br
12 14 - if GraderConfiguration['ui.show_score']
13 15 %strong=t 'main.score'
14 16 = "#{(submission.points*100/submission.problem.full_score).to_i} "
15 17 = " ["
16 18 %tt
17 19 = submission.grader_comment
18 20 = "]"
19 21 %br
20 - %strong View:
21 - - if GraderConfiguration.show_grading_result
22 - = 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'}
22 + %strong View:
23 + - if GraderConfiguration.show_grading_result
24 + = link_to '[detailed result]', :action => 'result', :id => submission.id
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 26 = link_to "#{t 'main.src_link'}", download_submission_path(submission.id), class: 'btn btn-xs btn-info'
25 27 = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info'
26 28
@@ -37,24 +37,25
37 37 :javascript
38 38 $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'});
39 39 / admin section
40 40 - if (@current_user!=nil) and (session[:admin])
41 41 / management
42 42 %li.dropdown
43 43 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
44 44 Manage
45 45 %span.caret
46 46 %ul.dropdown-menu
47 47 = add_menu( 'Announcements', 'announcements', 'index')
48 48 = add_menu( 'Problems', 'problems', 'index')
49 + = add_menu( 'Tags', 'tags', 'index')
49 50 = add_menu( 'Users', 'user_admin', 'index')
50 51 = add_menu( 'User Groups', 'groups', 'index')
51 52 = add_menu( 'Graders', 'graders', 'list')
52 53 = add_menu( 'Message ', 'messages', 'console')
53 54 %li.divider{role: 'separator'}
54 55 = add_menu( 'System config', 'configurations', 'index')
55 56 %li.divider{role: 'separator'}
56 57 = add_menu( 'Sites', 'sites', 'index')
57 58 = add_menu( 'Contests', 'contest_management', 'index')
58 59 / report
59 60 %li.dropdown
60 61 %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
@@ -3,24 +3,27
3 3 .form-group
4 4 %label{:for => "problem_name"} Name
5 5 = text_field 'problem', 'name', class: 'form-control'
6 6 %small
7 7 Do not directly edit the problem name, unless you know what you are doing. If you want to change the name, use the name change button in the problem management menu instead.
8 8 .form-group
9 9 %label{:for => "problem_full_name"} Full name
10 10 = text_field 'problem', 'full_name', class: 'form-control'
11 11 .form-group
12 12 %label{:for => "problem_full_score"} Full score
13 13 = text_field 'problem', 'full_score', class: 'form-control'
14 14 .form-group
15 + %label{:for => "problem_full_score"} Tags
16 + = collection_select(:problem, :tag_ids, Tag.all, :id, :name, {}, {multiple: true, class: 'form-control select2'})
17 + .form-group
15 18 %label{:for => "problem_date_added"} Date added
16 19 = date_select 'problem', 'date_added', class: 'form-control'
17 20 - # TODO: these should be put in model Problem, but I can't think of
18 21 - # nice default values for them. These values look fine only
19 22 - # in this case (of lazily adding new problems).
20 23 - @problem.available = true if @problem!=nil and @problem.available==nil
21 24 - @problem.test_allowed = true if @problem!=nil and @problem.test_allowed==nil
22 25 - @problem.output_only = false if @problem!=nil and @problem.output_only==nil
23 26 .checkbox
24 27 %label{:for => "problem_available"}
25 28 = check_box :problem, :available
26 29 Available?
@@ -12,47 +12,52
12 12 %b Quick New:
13 13 %label{:for => "problem_name"} Name
14 14 = text_field 'problem', 'name'
15 15 |
16 16 %label{:for => "problem_full_name"} Full name
17 17 = text_field 'problem', 'full_name'
18 18 = submit_tag "Create"
19 19 %table.table.table-condense.table-hover
20 20 %thead
21 21 %th Name
22 22 %th Full name
23 23 %th.text-right Full score
24 + %th Tags
24 25 %th
25 26 Submit
26 27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Admin can always submit to any problem' } [?]
27 28 %th Date added
28 29 %th.text-center
29 30 Avail?
30 31 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
31 32 %th.text-center
32 33 View Data?
33 34 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
34 35 %th.text-center
35 36 Test?
36 37 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
37 38 - if GraderConfiguration.multicontests?
38 39 %th Contests
39 40 - for problem in @problems
40 41 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
41 42 - @problem=problem
42 43 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
43 44 %td
44 45 = problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
45 46 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
46 47 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
48 + %td
49 + - problem.tags.each do |t|
50 + - #%button.btn.btn-default.btn-xs= t.name
51 + %span.label.label-default= t.name
47 52 %td= link_to "Submit", direct_edit_problem_submissions_path(problem,@current_user.id), class: 'btn btn-xs btn-primary'
48 53 %td= problem.date_added
49 54 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
50 55 %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
51 56 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
52 57 - if GraderConfiguration.multicontests?
53 58 %td
54 59 = problem.contests.collect { |c| c.name }.join(', ')
55 60 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
56 61 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
57 62 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
58 63 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
@@ -40,68 +40,79
40 40
41 41 = form_tag :action=>'do_manage' do
42 42 .panel.panel-primary
43 43 .panel-heading
44 44 Action
45 45 .panel-body
46 46 .submit-box
47 47 What do you want to do to the selected problem?
48 48 %br/
49 49 (You can shift-click to select a range of problems)
50 50 %ul.form-inline
51 51 %li
52 - Change date added to
52 + Change "Date added" to
53 53 .input-group.date
54 54 = text_field_tag :date_added, class: 'form-control'
55 55 %span.input-group-addon
56 56 %span.glyphicon.glyphicon-calendar
57 57 -# = select_date Date.current, :prefix => 'date_added'
58 58 &nbsp;&nbsp;&nbsp;
59 59 = submit_tag 'Change', :name => 'change_date_added', class: 'btn btn-primary btn-sm'
60 60 %li
61 - Set available to
61 + Set "Available" to
62 62 = submit_tag 'True', :name => 'enable_problem', class: 'btn btn-primary btn-sm'
63 63 = submit_tag 'False', :name => 'disable_problem', class: 'btn btn-primary btn-sm'
64 64
65 65 - if GraderConfiguration.multicontests?
66 66 %li
67 - Add to
67 + Add selected problems to contest
68 68 = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
69 69 = submit_tag 'Add', :name => 'add_to_contest', class: 'btn btn-primary btn-sm'
70 70 %li
71 - Add problems to group
71 + Add selected problems to user group
72 72 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
73 - = submit_tag 'Add', name: 'add_group', class: 'btn btn-default'
74 -
73 + = submit_tag 'Add', name: 'add_group', class: 'btn btn-primary'
74 + %li
75 + Add the following tags to the selected problems
76 + = select_tag "tag_ids", options_from_collection_for_select( Tag.all, 'id','name'), id: 'tags_name',class: 'select2', multiple: true, data: {placeholder: 'Select tags by clicking', width: "200px"}
77 + = submit_tag 'Add', name: 'add_tags', class: 'btn btn-primary'
75 78
76 - %table.table.table-hover
77 - %tr{style: "text-align: left;"}
78 - %th= check_box_tag 'select_all'
79 - %th Name
80 - %th Full name
81 - %th Available
82 - %th Date added
83 - - if GraderConfiguration.multicontests?
84 - %th Contests
79 + %table.table.table-hover.datatable
80 + %thead
81 + %tr{style: "text-align: left;"}
82 + %th= check_box_tag 'select_all'
83 + %th Name
84 + %th Full name
85 + %th Tags
86 + %th Available
87 + %th Date added
88 + - if GraderConfiguration.multicontests?
89 + %th Contests
85 90
86 - - num = 0
87 - - for problem in @problems
88 - - num += 1
89 - %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
90 - %td= check_box_tag "prob-#{problem.id}-#{num}"
91 - %td= problem.name
92 - %td= problem.full_name
93 - %td= problem.available
94 - %td= problem.date_added
95 - - if GraderConfiguration.multicontests?
91 + %tbody
92 + - num = 0
93 + - for problem in @problems
94 + - num += 1
95 + %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
96 + %td= check_box_tag "prob-#{problem.id}-#{num}"
97 + %td= problem.name
98 + %td= problem.full_name
96 99 %td
97 - - problem.contests.each do |contest|
98 - = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
100 + - problem.tags.each do |t|
101 + %span.label.label-default= t.name
102 + %td= problem.available
103 + %td= problem.date_added
104 + - if GraderConfiguration.multicontests?
105 + %td
106 + - problem.contests.each do |contest|
107 + = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
99 108
100 109 :javascript
101 110 $('.input-group.date').datetimepicker({
102 111 format: 'DD/MMM/YYYY',
103 112 showTodayButton: true,
104 113 widgetPositioning: {horizontal: 'auto', vertical: 'bottom'},
105 114
106 115 });
107 -
116 + $('.datatable').DataTable({
117 + paging: false
118 + });
@@ -23,35 +23,37
23 23 %h2 Submissions Count
24 24 = render partial: 'application/bar_graph', locals: { histogram: @histogram }
25 25
26 26 %h2 Submissions
27 27 - if @submissions and @submissions.count > 0
28 28 %table#main_table.table.table-condensed.table-striped
29 29 %thead
30 30 %tr
31 31 %th ID
32 32 %th Login
33 33 %th Name
34 34 %th Submitted_at
35 + %th language
35 36 %th Points
36 37 %th comment
37 38 %th IP
38 39 %tbody
39 40 - row_odd,curr = true,''
40 41 - @submissions.each do |sub|
41 42 - next unless sub.user
42 43 - row_odd,curr = !row_odd, sub.user if curr != sub.user
43 44 %tr
44 45 %td= link_to sub.id, submission_path(sub)
45 46 %td= link_to sub.user.login, stat_user_path(sub.user)
46 47 %td= sub.user.full_name
47 48 %td{data: {order: sub.submitted_at}}= time_ago_in_words(sub.submitted_at) + " ago"
49 + %td= sub.language.name
48 50 %td= sub.points
49 51 %td.fix-width= sub.grader_comment
50 52 %td= sub.ip_address
51 53 - else
52 54 No submission
53 55
54 56 :javascript
55 57 $("#main_table").DataTable({
56 58 paging: false
57 59 });
@@ -3,32 +3,67
3 3 %tr
4 4 %th Login
5 5 %th Name
6 6 / %th Activated?
7 7 / %th Logged_in
8 8 / %th Contest(s)
9 9 %th Remark
10 10 - @problems.each do |p|
11 11 %th.text-right= p.name.gsub('_',' ')
12 12 %th.text-right Total
13 13 %th.text-right Passed
14 14 %tbody
15 + - sum = Array.new(@scorearray[0].count,0)
16 + - nonzero = Array.new(@scorearray[0].count,0)
17 + - full = Array.new(@scorearray[0].count,0)
15 18 - @scorearray.each do |sc|
16 19 %tr
17 20 - total,num_passed = 0,0
18 21 - sc.each_index do |i|
19 22 - if i == 0
20 23 %td= link_to sc[i].login, stat_user_path(sc[i])
21 24 %td= sc[i].full_name
22 25 / %td= sc[i].activated
23 26 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
24 27 / %td= sc[i].contests.collect {|c| c.name}.join(', ')
25 28 %td= sc[i].remark
26 29 - else
27 30 %td.text-right= sc[i][0]
28 31 - total += sc[i][0]
29 32 - num_passed += 1 if sc[i][1]
33 + - sum[i] += sc[i][0]
34 + - nonzero[i] += 1 if sc[i][0] > 0
35 + - full[i] += 1 if sc[i][1]
30 36 %td.text-right= total
31 37 %td.text-right= num_passed
38 + %tfoot
39 + %tr
40 + %td Summation
41 + %td
42 + %td
43 + - sum.each.with_index do |s,i|
44 + - next if i == 0
45 + %td.text-right= number_with_delimiter(s)
46 + %td
47 + %td
48 + %tr
49 + %td partial solver
50 + %td
51 + %td
52 + - nonzero.each.with_index do |s,i|
53 + - next if i == 0
54 + %td.text-right= number_with_delimiter(s)
55 + %td
56 + %td
57 + %tr
58 + %td Full solver
59 + %td
60 + %td
61 + - full.each.with_index do |s,i|
62 + - next if i == 0
63 + %td.text-right= number_with_delimiter(s)
64 + %td
65 + %td
66 +
32 67
33 68 :javascript
34 69 $.bootstrapSortable(true,'reversed')
@@ -24,26 +24,26
24 24 = label_tag :from, "Min"
25 25 = text_field_tag 'from_id', @since_id, class: "form-control"
26 26 .form-group
27 27 = label_tag :from, "Max"
28 28 = text_field_tag 'to_id', @until_id, class: "form-control"
29 29 .col-md-4
30 30 .panel.panel-primary
31 31 .panel-heading
32 32 Users
33 33 .panel-body
34 34 .radio
35 35 %label
36 - = radio_button_tag 'users', 'all', true
36 + = radio_button_tag 'users', 'all', (params[:users] == "all")
37 37 All users
38 38 .radio
39 39 %label
40 - = radio_button_tag 'users', 'enabled'
40 + = radio_button_tag 'users', 'enabled', (params[:users] == "enabled")
41 41 Only enabled users
42 42 .row
43 43 .col-md-12
44 44 = button_tag 'Show', class: "btn btn-primary btn-large", value: "show"
45 45 = button_tag 'Download CSV', class: "btn btn-primary btn-large", value: "download"
46 46
47 47 - if @scorearray
48 48 %h2 Result
49 49 =render "score_table"
@@ -22,14 +22,15
22 22 .actions
23 23 = f.submit "Update", class: 'btn btn-primary'
24 24 .col-md-8
25 25
26 26 = link_to 'Show', @site
27 27 |
28 28 = link_to 'Back', sites_path
29 29
30 30
31 31 :javascript
32 32 $('.input-group.date').datetimepicker({
33 33 format: 'DD/MMM/YYYY HH:mm',
34 + showTodayButton: true,
34 35 });
35 36
@@ -18,32 +18,33
18 18 = hidden_field_tag 'submission[problem_id]', @problem.id
19 19 .form-group
20 20 = label_tag "Task:"
21 21 = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true
22 22
23 23 .form-group
24 24 = label_tag 'Language'
25 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 26 .form-group
27 27 = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit',
28 28 data: {confirm: "Submitting this source code for task #{@problem.long_name}?"}
29 29 - # latest submission status
30 - .panel.panel-info
30 + .panel{class: (@submission && @submission.graded_at) ? "panel-info" : "panel-warning"}
31 31 .panel-heading
32 32 Latest Submission Status
33 33 = link_to "Refresh",get_latest_submission_status_submissions_path(@submission.user,@problem), class: "btn btn-default btn-sm", remote: true if @submission
34 34 .panel-body
35 - - if @submission
36 - = render :partial => 'submission_short',
37 - :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
35 + %div#latest_status
36 + - if @submission
37 + = render :partial => 'submission_short',
38 + :locals => {submission: @submission, problem_name: @problem.name, problem_id: @problem.id }
38 39 .row
39 40 .col-md-12
40 41 %h2 Console
41 42 %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20}
42 43
43 44 :javascript
44 45 $(document).ready(function() {
45 46 e = ace.edit("editor")
46 47 e.setValue($("#text_sourcecode").val());
47 48 e.gotoLine(1);
48 49 $("#language_id").trigger('change');
49 50 brython();
@@ -1,2 +1,2
1 1 :plain
2 - $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}")
2 + $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name, problem_id: @problem.id}})}")
@@ -56,17 +56,17
56 56 # ---------------- IMPORTANT ----------------------
57 57 # If we deploy the app into a subdir name "grader", be sure to do "rake assets:precompile RAILS_RELATIVE_URL_ROOT=/grader"
58 58 # moreover, using the following line instead also known to works
59 59 #config.action_controller.relative_url_root = '/grader'
60 60
61 61 #font path
62 62 config.assets.paths << "#{Rails}/vendor/assets/fonts"
63 63
64 64 config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
65 65 config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
66 66 %w( announcements submissions configurations contests contest_management graders heartbeat
67 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 69 config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
70 70 end
71 71 end
72 72 end
@@ -9,15 +9,15
9 9 Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 10 Rails.application.config.assets.paths << Rails.root.join('vendor/assets/fonts')
11 11
12 12 # Precompile additional assets.
13 13 # application.js, application.css, and all non-JS/CSS in the app/assets
14 14 # folder are already added.
15 15 # Rails.application.config.assets.precompile += %w( admin.js admin.css )
16 16
17 17 Rails.application.config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js']
18 18 Rails.application.config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
19 19 %w( announcements submissions configurations contests contest_management graders heartbeat
20 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 22 Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
23 23 end
@@ -24,24 +24,25
24 24 end
25 25
26 26 def self.stop_graders(pids)
27 27 pid_str = (pids.map { |process| process.pid.to_s }).join ' '
28 28 GraderScript.call_grader "stop #{pid_str}"
29 29 end
30 30
31 31 def self.start_grader(env)
32 32 GraderScript.call_grader "#{env} queue --err-log &"
33 33 GraderScript.call_grader "#{env} test_request -err-log &"
34 34 end
35 35
36 + #call the import problem script
36 37 def self.call_import_problem(problem_name,
37 38 problem_dir,
38 39 time_limit=1,
39 40 memory_limit=32,
40 41 checker_name='text')
41 42 if GraderScript.grader_control_enabled?
42 43 cur_dir = `pwd`.chomp
43 44 Dir.chdir(GRADER_ROOT_DIR)
44 45
45 46 script_name = File.join(GRADER_ROOT_DIR, "scripts/import_problem")
46 47 cmd = "#{script_name} #{problem_name} #{problem_dir} #{checker_name}" +
47 48 " -t #{time_limit} -m #{memory_limit}"
@@ -1,24 +1,25
1 1 require 'tmpdir'
2 2
3 3 class TestdataImporter
4 4
5 5 attr :log_msg
6 6
7 7 def initialize(problem)
8 8 @problem = problem
9 9 end
10 10
11 - def import_from_file(tempfile,
12 - time_limit,
11 + #Create or update problem according to the parameter
12 + def import_from_file(tempfile,
13 + time_limit,
13 14 memory_limit,
14 15 checker_name='text',
15 16 import_to_db=false)
16 17
17 18 dirname = extract(tempfile)
18 19 return false if not dirname
19 20 if not import_to_db
20 21 @log_msg = GraderScript.call_import_problem(@problem.name,
21 22 dirname,
22 23 time_limit,
23 24 memory_limit,
24 25 checker_name)
@@ -43,24 +44,25
43 44
44 45 return true
45 46 end
46 47
47 48 protected
48 49
49 50 def self.long_ext(filename)
50 51 i = filename.index('.')
51 52 len = filename.length
52 53 return filename.slice(i..len)
53 54 end
54 55
56 + # extract an archive file located at +tempfile+ to the +raw_dir+
55 57 def extract(tempfile)
56 58 testdata_filename = save_testdata_file(tempfile)
57 59 ext = TestdataImporter.long_ext(tempfile.original_filename)
58 60
59 61 extract_dir = File.join(GraderScript.raw_dir, @problem.name)
60 62 if File.exists? extract_dir
61 63 backup_count = 0
62 64 begin
63 65 backup_count += 1
64 66 backup_dirname = "#{extract_dir}.backup.#{backup_count}"
65 67 end while File.exists? backup_dirname
66 68 File.rename(extract_dir, backup_dirname)
You need to be logged in to leave comments. Login now