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

r834:825a2986c8ea - - 19 files changed: 140 inserted, 89 deleted

@@ -0,0 +1,8
1 + = render partial: 'toggle_button',
2 + locals: {button_id: "#group-enabled-#{@group.id}",button_on: @group.enabled }
3 + :plain
4 + r = $("#group-#{@group.id}");
5 + r.removeClass('success');
6 + r.removeClass('danger');
7 + r.addClass("#{@group.enabled? ? 'success' : 'danger'}");
8 +
@@ -0,0 +1,5
1 + class AddEnabledToGroup < ActiveRecord::Migration[5.2]
2 + def change
3 + add_column :groups, :enabled, :boolean, default: true
4 + end
5 + end
@@ -143,25 +143,26
143 return true if user==nil || user.site == nil
143 return true if user==nil || user.site == nil
144 if user.contest_finished?
144 if user.contest_finished?
145 flash[:notice] = 'Error: the contest you are participating is over.'
145 flash[:notice] = 'Error: the contest you are participating is over.'
146 redirect_to :back
146 redirect_to :back
147 return false
147 return false
148 end
148 end
149 return true
149 return true
150 end
150 end
151
151
152 def is_request_ip_allowed?
152 def is_request_ip_allowed?
153 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
153 unless GraderConfiguration[WHITELIST_IGNORE_CONF_KEY]
154 user_ip = IPAddr.new(request.remote_ip)
154 user_ip = IPAddr.new(request.remote_ip)
155 + allowed = GraderConfiguration[WHITELIST_IP_CONF_KEY] || ''
155
156
156 - GraderConfiguration[WHITELIST_IP_CONF_KEY].delete(' ').split(',').each do |ips|
157 + allowed.delete(' ').split(',').each do |ips|
157 allow_ips = IPAddr.new(ips)
158 allow_ips = IPAddr.new(ips)
158 if allow_ips.include?(user_ip)
159 if allow_ips.include?(user_ip)
159 return true
160 return true
160 end
161 end
161 end
162 end
162 return false
163 return false
163 end
164 end
164 return true
165 return true
165 end
166 end
166
167
167 end
168 end
@@ -1,16 +1,17
1 class GroupsController < ApplicationController
1 class GroupsController < ApplicationController
2 before_action :set_group, only: [:show, :edit, :update, :destroy,
2 before_action :set_group, only: [:show, :edit, :update, :destroy,
3 :add_user, :remove_user,:remove_all_user,
3 :add_user, :remove_user,:remove_all_user,
4 :add_problem, :remove_problem,:remove_all_problem,
4 :add_problem, :remove_problem,:remove_all_problem,
5 + :toggle,
5 ]
6 ]
6 before_action :admin_authorization
7 before_action :admin_authorization
7
8
8 # GET /groups
9 # GET /groups
9 def index
10 def index
10 @groups = Group.all
11 @groups = Group.all
11 end
12 end
12
13
13 # GET /groups/1
14 # GET /groups/1
14 def show
15 def show
15 end
16 end
16
17
@@ -40,24 +41,29
40 redirect_to @group, notice: 'Group was successfully updated.'
41 redirect_to @group, notice: 'Group was successfully updated.'
41 else
42 else
42 render :edit
43 render :edit
43 end
44 end
44 end
45 end
45
46
46 # DELETE /groups/1
47 # DELETE /groups/1
47 def destroy
48 def destroy
48 @group.destroy
49 @group.destroy
49 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 end
51 end
51
52
53 + def toggle
54 + @group.enabled = @group.enabled? ? false : true
55 + @group.save
56 + end
57 +
52 def remove_user
58 def remove_user
53 user = User.find(params[:user_id])
59 user = User.find(params[:user_id])
54 @group.users.delete(user)
60 @group.users.delete(user)
55 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
61 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
56 end
62 end
57
63
58 def remove_all_user
64 def remove_all_user
59 @group.users.clear
65 @group.users.clear
60 redirect_to group_path(@group), alert: 'All users removed'
66 redirect_to group_path(@group), alert: 'All users removed'
61 end
67 end
62
68
63 def remove_all_problem
69 def remove_all_problem
@@ -90,15 +96,15
90 redirect_to group_path(@group), alert: e.message
96 redirect_to group_path(@group), alert: e.message
91 end
97 end
92 end
98 end
93
99
94 private
100 private
95 # Use callbacks to share common setup or constraints between actions.
101 # Use callbacks to share common setup or constraints between actions.
96 def set_group
102 def set_group
97 @group = Group.find(params[:id])
103 @group = Group.find(params[:id])
98 end
104 end
99
105
100 # Only allow a trusted parameter "white list" through.
106 # Only allow a trusted parameter "white list" through.
101 def group_params
107 def group_params
102 - params.require(:group).permit(:name, :description)
108 + params.require(:group).permit(:name, :description, :enabled)
103 end
109 end
104 end
110 end
@@ -7,26 +7,26
7 # GET /submissions.json
7 # GET /submissions.json
8 # Show problem selection and user's submission of that problem
8 # Show problem selection and user's submission of that problem
9 def index
9 def index
10 @user = @current_user
10 @user = @current_user
11 @problems = @user.available_problems
11 @problems = @user.available_problems
12
12
13 if params[:problem_id]==nil
13 if params[:problem_id]==nil
14 @problem = nil
14 @problem = nil
15 @submissions = nil
15 @submissions = nil
16 else
16 else
17 @problem = Problem.find_by_id(params[:problem_id])
17 @problem = Problem.find_by_id(params[:problem_id])
18 if (@problem == nil) or (not @problem.available)
18 if (@problem == nil) or (not @problem.available)
19 - redirect_to main_list_path
19 + redirect_to list_main_path
20 - flash[:notice] = 'Error: submissions for that problem are not viewable.'
20 + flash[:error] = 'Authorization error: You have no right to view submissions for this problem'
21 return
21 return
22 end
22 end
23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
23 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id).order(id: :desc)
24 end
24 end
25 end
25 end
26
26
27 # GET /submissions/1
27 # GET /submissions/1
28 # GET /submissions/1.json
28 # GET /submissions/1.json
29 def show
29 def show
30 @submission = Submission.find(params[:id])
30 @submission = Submission.find(params[:id])
31
31
32 #log the viewing
32 #log the viewing
@@ -18,35 +18,37
18
18
19 if !FileTest.exists?(filename)
19 if !FileTest.exists?(filename)
20 redirect_to :action => 'index' and return
20 redirect_to :action => 'index' and return
21 end
21 end
22
22
23 send_file_to_user(filename, base_filename)
23 send_file_to_user(filename, base_filename)
24 end
24 end
25
25
26 # this has problem-level access control
26 # this has problem-level access control
27 def download
27 def download
28 problem = Problem.find(params[:id])
28 problem = Problem.find(params[:id])
29 unless @current_user.can_view_problem? problem
29 unless @current_user.can_view_problem? problem
30 - flash[:notice] = 'You are not authorized to access this file'
30 + flash[:error] = 'You are not authorized to access this file'
31 - redirect_to :action => 'index' and return
31 + redirect_to list_main_path
32 + return
32 end
33 end
33
34
34 base_name = params[:file]
35 base_name = params[:file]
35 base_filename = File.basename("#{base_name}.#{params[:ext]}")
36 base_filename = File.basename("#{base_name}.#{params[:ext]}")
36 filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
37 filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
37
38
38 if !FileTest.exists?(filename)
39 if !FileTest.exists?(filename)
39 flash[:notice] = 'File does not exists'
40 flash[:notice] = 'File does not exists'
40 - redirect_to :action => 'index' and return
41 + redirect_to list_main_path
42 + return
41 end
43 end
42
44
43 send_file_to_user(filename, base_filename)
45 send_file_to_user(filename, base_filename)
44 end
46 end
45
47
46 protected
48 protected
47
49
48 def send_file_to_user(filename, base_filename)
50 def send_file_to_user(filename, base_filename)
49 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
51 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
50 response.headers['Content-Type'] = "application/force-download"
52 response.headers['Content-Type'] = "application/force-download"
51 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
53 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
52 response.headers["X-Sendfile"] = filename
54 response.headers["X-Sendfile"] = filename
@@ -56,55 +56,65
56 redirect_to action: 'index', page: params[:page]
56 redirect_to action: 'index', page: params[:page]
57 end
57 end
58
58
59 def create_from_list
59 def create_from_list
60 lines = params[:user_list]
60 lines = params[:user_list]
61
61
62 note = []
62 note = []
63 error_note = []
63 error_note = []
64 error_msg = nil
64 error_msg = nil
65 ok_user = []
65 ok_user = []
66
66
67 lines.split("\n").each do |line|
67 lines.split("\n").each do |line|
68 - items = line.chomp.split(',')
68 + #split with large limit, this will cause consecutive ',' to be result in a blank
69 + items = line.chomp.split(',',1000)
69 if items.length>=2
70 if items.length>=2
70 login = items[0]
71 login = items[0]
71 full_name = items[1]
72 full_name = items[1]
72 remark =''
73 remark =''
73 user_alias = ''
74 user_alias = ''
74
75
75 added_random_password = false
76 added_random_password = false
76 - if items.length >= 3 and items[2].chomp(" ").length > 0;
77 + added_password = false
78 + if items.length >= 3
79 + if items[2].chomp(" ").length > 0
77 password = items[2].chomp(" ")
80 password = items[2].chomp(" ")
81 + added_password = true
82 + end
78 else
83 else
79 password = random_password
84 password = random_password
80 added_random_password=true;
85 added_random_password=true;
81 end
86 end
82
87
83 if items.length>= 4 and items[3].chomp(" ").length > 0;
88 if items.length>= 4 and items[3].chomp(" ").length > 0;
84 user_alias = items[3].chomp(" ")
89 user_alias = items[3].chomp(" ")
85 else
90 else
86 user_alias = login
91 user_alias = login
87 end
92 end
88
93
94 +
95 + has_remark = false
89 if items.length>=5
96 if items.length>=5
90 remark = items[4].strip;
97 remark = items[4].strip;
98 + has_remark = true
91 end
99 end
92
100
93 user = User.find_by_login(login)
101 user = User.find_by_login(login)
94 if (user)
102 if (user)
95 user.full_name = full_name
103 user.full_name = full_name
96 - user.password = password
104 + user.remark = remark if has_remark
97 - user.remark = remark
105 + user.password = password if added_password || added_random_password
98 else
106 else
107 + #create a random password if none are given
108 + password = random_password unless password
99 user = User.new({:login => login,
109 user = User.new({:login => login,
100 :full_name => full_name,
110 :full_name => full_name,
101 :password => password,
111 :password => password,
102 :password_confirmation => password,
112 :password_confirmation => password,
103 :alias => user_alias,
113 :alias => user_alias,
104 :remark => remark})
114 :remark => remark})
105 end
115 end
106 user.activated = true
116 user.activated = true
107
117
108 if user.save
118 if user.save
109 if added_random_password
119 if added_random_password
110 note << "'#{login}' (+)"
120 note << "'#{login}' (+)"
@@ -104,26 +104,27
104 end
104 end
105
105
106 def read_textfile(fname,max_size=2048)
106 def read_textfile(fname,max_size=2048)
107 begin
107 begin
108 File.open(fname).read(max_size)
108 File.open(fname).read(max_size)
109 rescue
109 rescue
110 nil
110 nil
111 end
111 end
112 end
112 end
113
113
114 def toggle_button(on,toggle_url,id, option={})
114 def toggle_button(on,toggle_url,id, option={})
115 btn_size = option[:size] || 'btn-xs'
115 btn_size = option[:size] || 'btn-xs'
116 + btn_block = option[:block] || 'btn-block'
116 link_to (on ? "Yes" : "No"), toggle_url,
117 link_to (on ? "Yes" : "No"), toggle_url,
117 - {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 + {class: "btn #{btn_block} #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 id: id,
119 id: id,
119 data: {remote: true, method: 'get'}}
120 data: {remote: true, method: 'get'}}
120 end
121 end
121
122
122 def get_ace_mode(language)
123 def get_ace_mode(language)
123 # return ace mode string from Language
124 # return ace mode string from Language
124
125
125 case language.pretty_name
126 case language.pretty_name
126 when 'Pascal'
127 when 'Pascal'
127 'ace/mode/pascal'
128 'ace/mode/pascal'
128 when 'C++','C'
129 when 'C++','C'
129 'ace/mode/c_cpp'
130 'ace/mode/c_cpp'
@@ -172,27 +173,24
172 end
173 end
173
174
174 contest_name = GraderConfiguration['contest.name']
175 contest_name = GraderConfiguration['contest.name']
175
176
176 #
177 #
177 # build real title bar
178 # build real title bar
178 result = <<TITLEBAR
179 result = <<TITLEBAR
179 <div class="title">
180 <div class="title">
180 <table>
181 <table>
181 #{header}
182 #{header}
182 <tr>
183 <tr>
183 <td class="left-col">
184 <td class="left-col">
184 - #{user.full_name}<br/>
185 - #{t 'title_bar.current_time'} #{format_short_time(Time.zone.now)}
186 - #{time_left}
187 <br/>
185 <br/>
188 </td>
186 </td>
189 <td class="right-col">#{contest_name}</td>
187 <td class="right-col">#{contest_name}</td>
190 </tr>
188 </tr>
191 </table>
189 </table>
192 </div>
190 </div>
193 TITLEBAR
191 TITLEBAR
194 result.html_safe
192 result.html_safe
195 end
193 end
196
194
197 def markdown(text)
195 def markdown(text)
198 markdown = RDiscount.new(text)
196 markdown = RDiscount.new(text)
@@ -1,20 +1,14
1 module MainHelper
1 module MainHelper
2
2
3 - def link_to_description_if_any(name, problem, options={})
3 + def link_to_description_if_any(name, problem)
4 if !problem.url.blank?
4 if !problem.url.blank?
5 - return link_to name, problem.url, options
5 + return link_to name, problem.url
6 elsif !problem.description_filename.blank?
6 elsif !problem.description_filename.blank?
7 - #build a link to a problem (via task controller)
8 basename, ext = problem.description_filename.split('.')
7 basename, ext = problem.description_filename.split('.')
9 - options[:controller] = 'tasks'
8 + return link_to name, download_task_path(problem.id,basename,ext), target: '_blank'
10 - options[:action] = 'download'
11 - options[:id] = problem.id
12 - options[:file] = basename
13 - options[:ext] = ext
14 - return link_to name, options
15 else
9 else
16 return ''
10 return ''
17 end
11 end
18 end
12 end
19
13
20 end
14 end
@@ -145,24 +145,24
145 end
145 end
146 end
146 end
147
147
148 def must_have_valid_problem
148 def must_have_valid_problem
149 return if self.source==nil
149 return if self.source==nil
150 if self.problem==nil
150 if self.problem==nil
151 errors.add('problem',"must be specified.")
151 errors.add('problem',"must be specified.")
152 else
152 else
153 #admin always have right
153 #admin always have right
154 return if self.user.admin?
154 return if self.user.admin?
155
155
156 #check if user has the right to submit the problem
156 #check if user has the right to submit the problem
157 - errors.add('problem',"must be valid.") if (!self.user.available_problems.include?(self.problem)) and (self.new_record?)
157 + errors[:base] << "Authorization error: you have no right to submit to this problem" if (!self.user.available_problems.include?(self.problem)) and (self.new_record?)
158 end
158 end
159 end
159 end
160
160
161 # callbacks
161 # callbacks
162 def assign_latest_number_if_new_recond
162 def assign_latest_number_if_new_recond
163 return if !self.new_record?
163 return if !self.new_record?
164 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
164 latest = Submission.find_last_by_user_and_problem(self.user_id, self.problem_id)
165 self.number = (latest==nil) ? 1 : latest.number + 1;
165 self.number = (latest==nil) ? 1 : latest.number + 1;
166 end
166 end
167
167
168 end
168 end
@@ -307,47 +307,50
307 contest.problems.available.each do |problem|
307 contest.problems.available.each do |problem|
308 if not pin.has_key? problem.id
308 if not pin.has_key? problem.id
309 contest_problems << problem
309 contest_problems << problem
310 end
310 end
311 pin[problem.id] = true
311 pin[problem.id] = true
312 end
312 end
313 end
313 end
314 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
314 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
315 return contest_problems + other_avaiable_problems
315 return contest_problems + other_avaiable_problems
316 end
316 end
317 end
317 end
318
318
319 + # new feature, get list of available problem in all enabled group that the user belongs to
319 def available_problems_in_group
320 def available_problems_in_group
320 problem = []
321 problem = []
321 - self.groups.each do |group|
322 + self.groups.where(enabled: true).each do |group|
322 group.problems.where(available: true).each { |p| problem << p }
323 group.problems.where(available: true).each { |p| problem << p }
323 end
324 end
324 problem.uniq!
325 problem.uniq!
325 if problem
326 if problem
326 problem.sort! do |a,b|
327 problem.sort! do |a,b|
327 case
328 case
328 when a.date_added < b.date_added
329 when a.date_added < b.date_added
329 1
330 1
330 when a.date_added > b.date_added
331 when a.date_added > b.date_added
331 -1
332 -1
332 else
333 else
333 a.name <=> b.name
334 a.name <=> b.name
334 end
335 end
335 end
336 end
336 return problem
337 return problem
337 else
338 else
338 return []
339 return []
339 end
340 end
340 end
341 end
341
342
343 + #check if the user has the right to view that problem
344 + #this also consider group based problem policy
342 def can_view_problem?(problem)
345 def can_view_problem?(problem)
343 return true if admin?
346 return true if admin?
344 return available_problems.include? problem
347 return available_problems.include? problem
345 end
348 end
346
349
347 def self.clear_last_login
350 def self.clear_last_login
348 User.update_all(:last_ip => nil)
351 User.update_all(:last_ip => nil)
349 end
352 end
350
353
351 protected
354 protected
352 def encrypt_new_password
355 def encrypt_new_password
353 return if password.blank?
356 return if password.blank?
@@ -1,25 +1,25
1
1
2 %tr
2 %tr
3 %td{:align => "center"}
3 %td{:align => "center"}
4 = submission.number
4 = submission.number
5 %td.text-right
5 %td.text-right
6 = link_to "##{submission.id}", submission_path(submission.id)
6 = link_to "##{submission.id}", submission_path(submission.id)
7 %td
7 %td
8 = l submission.submitted_at, format: :long
8 = l submission.submitted_at, format: :long
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
10 %td
10 %td
11 = submission.source_filename
11 = submission.source_filename
12 = " (#{submission.language.pretty_name}) "
12 = " (#{submission.language.pretty_name}) "
13 - = link_to('[load]',{:action => 'source', :id => submission.id})
13 + = link_to '[load]', download_submission_path(submission)
14 %td
14 %td
15 - if submission.graded_at
15 - if submission.graded_at
16 = "Graded at #{format_short_time(submission.graded_at)}."
16 = "Graded at #{format_short_time(submission.graded_at)}."
17 %br/
17 %br/
18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
19 = " ["
19 = " ["
20 %tt
20 %tt
21 = submission.grader_comment
21 = submission.grader_comment
22 = "]"
22 = "]"
23 %td
23 %td
24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
25 %td
25 %td
@@ -1,16 +1,27
1 = form_for @group do |f|
1 = form_for @group do |f|
2 - if @group.errors.any?
2 - if @group.errors.any?
3 #error_explanation
3 #error_explanation
4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
5 %ul
5 %ul
6 - @group.errors.full_messages.each do |msg|
6 - @group.errors.full_messages.each do |msg|
7 %li= msg
7 %li= msg
8 -
8 + .row
9 + .col-md-6
9 .form-group.field
10 .form-group.field
10 = f.label :name
11 = f.label :name
11 = f.text_field :name, class: 'form-control'
12 = f.text_field :name, class: 'form-control'
13 + .row
14 + .col-md-6
12 .form-group.field
15 .form-group.field
13 = f.label :description
16 = f.label :description
14 = f.text_field :description, class: 'form-control'
17 = f.text_field :description, class: 'form-control'
18 + .row
19 + .col-md-6
20 + .checkbox
21 + = f.label :enabled do
22 + = f.check_box :enabled
23 + Enabled
24 + .row
25 + .col-md-6
15 .form-group.actions
26 .form-group.actions
16 = f.submit 'Save', class: 'btn btn-primary'
27 = f.submit 'Save', class: 'btn btn-primary'
@@ -1,22 +1,24
1 %h1 Groups
1 %h1 Groups
2
2
3 %p
3 %p
4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
5 %table.table.table-hover
5 %table.table.table-hover
6 %thead
6 %thead
7 %tr
7 %tr
8 %th Name
8 %th Name
9 %th Description
9 %th Description
10 + %th Enabled?
10 %th
11 %th
11 %th
12 %th
12
13
13 %tbody
14 %tbody
14 - @groups.each do |group|
15 - @groups.each do |group|
15 - %tr
16 + %tr{:class => "#{(group.enabled?) ? "success" : "danger"}", id: "group-#{group.id}"}
16 %td= group.name
17 %td= group.name
17 %td= group.description
18 %td= group.description
19 + %td= toggle_button(group.enabled?, toggle_group_path(group), "group-enabled-#{group.id}", size: ' ', block: ' ')
18 %td= link_to 'View', group, class: 'btn btn-default'
20 %td= link_to 'View', group, class: 'btn btn-default'
19 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
21 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
20
22
21 %br
23 %br
22
24
@@ -34,14 +34,14
34 %td{:width => '300px'}
34 %td{:width => '300px'}
35 %tt <tt>/*<br/>LANG: C++<br/>TASK: mobiles<br/>*/</tt>
35 %tt <tt>/*<br/>LANG: C++<br/>TASK: mobiles<br/>*/</tt>
36
36
37 %p
37 %p
38 =raw t 'help.example_pas'
38 =raw t 'help.example_pas'
39
39
40 %table{:border => '1'}
40 %table{:border => '1'}
41 %tr
41 %tr
42 %td{:width => '300px'}
42 %td{:width => '300px'}
43 %tt <tt>{<br/>LANG: Pascal<br/>TASK: mobiles<br/>}</tt>
43 %tt <tt>{<br/>LANG: Pascal<br/>TASK: mobiles<br/>}</tt>
44
44
45 %p
45 %p
46 - = raw(t('help.ask_questions_at_messages',:message_link_name => (t 'menu.messages'),:url => url_for(:controller => 'messages', :action => 'list')))
46 + = raw(t('help.ask_questions_at_messages',:message_link_name => (t 'menu.messages'),url: messages_path ))
47
47
@@ -33,24 +33,25
33 - if @submission.user
33 - if @submission.user
34 = link_to "#{@submission.user.login}", stat_user_path(@submission.user)
34 = link_to "#{@submission.user.login}", stat_user_path(@submission.user)
35 = @submission.user.full_name
35 = @submission.user.full_name
36 - else
36 - else
37 = "(n/a)"
37 = "(n/a)"
38 %tr
38 %tr
39 %td.text-right
39 %td.text-right
40 %strong Task
40 %strong Task
41 %td
41 %td
42 - if @submission.problem!=nil
42 - if @submission.problem!=nil
43 = link_to "[#{@submission.problem.name}]", stat_problem_path(@submission.problem)
43 = link_to "[#{@submission.problem.name}]", stat_problem_path(@submission.problem)
44 = @submission.problem.full_name
44 = @submission.problem.full_name
45 + = link_to_description_if_any "[download] <span class='glyphicon glyphicon-file'></span>".html_safe, @submission.problem
45 - else
46 - else
46 = "(n/a)"
47 = "(n/a)"
47 %tr
48 %tr
48 %td.text-right
49 %td.text-right
49 %strong Tries
50 %strong Tries
50 %td= @submission.number
51 %td= @submission.number
51 %tr
52 %tr
52 %td.text-right
53 %td.text-right
53 %strong Language
54 %strong Language
54 %td= @submission.language.pretty_name
55 %td= @submission.language.pretty_name
55 %tr
56 %tr
56 %td.text-right
57 %td.text-right
@@ -17,24 +17,33
17 %tt passwd, alias
17 %tt passwd, alias
18 and
18 and
19 %tt remark
19 %tt remark
20 is optional.
20 is optional.
21 %li
21 %li
22 When
22 When
23 %tt passwd
23 %tt passwd
24 or
24 or
25 %tt alias
25 %tt alias
26 is empty, the original value will be used instead.
26 is empty, the original value will be used instead.
27 %li
27 %li
28 If the users with the same user_id already exists, existing information will be overwritten.
28 If the users with the same user_id already exists, existing information will be overwritten.
29 + Example:
30 + %ol
31 + %li
32 + %pre user1,Somchai Jaidee
33 + will create (or update) a user with login "user1" and setting the fullname to "Somchai Jaidee", also setting a random password.
34 + %li
35 + %pre user1,Somchai Jaidee,
36 + will create (or update) a user with login "user1" and and setting the fullname "Somchai Jaidee". No change is made to the password unless this is a new user. If this is a new user, a random password will be generated.
37 +
29
38
30 .row
39 .row
31 .col-md-6
40 .col-md-6
32 = form_tag :action => 'create_from_list' do
41 = form_tag :action => 'create_from_list' do
33 .form-group
42 .form-group
34 = submit_tag 'Create following users',class: 'btn btn-success'
43 = submit_tag 'Create following users',class: 'btn btn-success'
35 .form-group
44 .form-group
36 .div.checkbox
45 .div.checkbox
37 %label
46 %label
38 = check_box_tag :add_to_group
47 = check_box_tag :add_to_group
39 Also add these users to the following group
48 Also add these users to the following group
40 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
49 = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
@@ -45,24 +45,25
45 post 'do_import'
45 post 'do_import'
46 end
46 end
47 end
47 end
48
48
49 resources :groups do
49 resources :groups do
50 member do
50 member do
51 post 'add_user', to: 'groups#add_user', as: 'add_user'
51 post 'add_user', to: 'groups#add_user', as: 'add_user'
52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
57 + get 'toggle'
57 end
58 end
58 collection do
59 collection do
59
60
60 end
61 end
61 end
62 end
62
63
63 resources :testcases, only: [] do
64 resources :testcases, only: [] do
64 member do
65 member do
65 get 'download_input'
66 get 'download_input'
66 get 'download_sol'
67 get 'download_sol'
67 end
68 end
68 collection do
69 collection do
@@ -83,25 +84,24
83 end
84 end
84 collection do
85 collection do
85 get 'profile'
86 get 'profile'
86 post 'chg_passwd'
87 post 'chg_passwd'
87 end
88 end
88 end
89 end
89
90
90 resources :submissions do
91 resources :submissions do
91 member do
92 member do
92 get 'download'
93 get 'download'
93 get 'compiler_msg'
94 get 'compiler_msg'
94 get 'rejudge'
95 get 'rejudge'
95 - get 'source'
96 end
96 end
97 collection do
97 collection do
98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
101 end
101 end
102 end
102 end
103
103
104
104
105 #user admin
105 #user admin
106 resources :user_admin do
106 resources :user_admin do
107 collection do
107 collection do
@@ -168,25 +168,25
168 get 'help'
168 get 'help'
169 post 'submit'
169 post 'submit'
170 end
170 end
171 #main
171 #main
172 #get "main/list"
172 #get "main/list"
173 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
173 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
174 #post 'main/submit', to: 'main#submit'
174 #post 'main/submit', to: 'main#submit'
175 #get 'main/announcements', to: 'main#announcements'
175 #get 'main/announcements', to: 'main#announcements'
176
176
177
177
178 #
178 #
179 get 'tasks/view/:file.:ext' => 'tasks#view'
179 get 'tasks/view/:file.:ext' => 'tasks#view'
180 - get 'tasks/download/:id/:file.:ext' => 'tasks#download'
180 + get 'tasks/download/:id/:file.:ext' => 'tasks#download', as: 'download_task'
181 get 'heartbeat/:id/edit' => 'heartbeat#edit'
181 get 'heartbeat/:id/edit' => 'heartbeat#edit'
182
182
183 #grader
183 #grader
184 get 'graders/list', to: 'graders#list', as: 'grader_list'
184 get 'graders/list', to: 'graders#list', as: 'grader_list'
185 namespace :graders do
185 namespace :graders do
186 get 'task/:id/:type', action: 'task', as: 'task'
186 get 'task/:id/:type', action: 'task', as: 'task'
187 get 'view/:id/:type', action: 'view', as: 'view'
187 get 'view/:id/:type', action: 'view', as: 'view'
188 get 'clear/:id', action: 'clear', as: 'clear'
188 get 'clear/:id', action: 'clear', as: 'clear'
189 get 'stop'
189 get 'stop'
190 get 'stop_all'
190 get 'stop_all'
191 get 'clear_all'
191 get 'clear_all'
192 get 'clear_terminated'
192 get 'clear_terminated'
@@ -1,211 +1,212
1 # This file is auto-generated from the current state of the database. Instead
1 # This file is auto-generated from the current state of the database. Instead
2 # of editing this file, please use the migrations feature of Active Record to
2 # of editing this file, please use the migrations feature of Active Record to
3 # incrementally modify your database, and then regenerate this schema definition.
3 # incrementally modify your database, and then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your
5 # Note that this schema.rb definition is the authoritative source for your
6 # database schema. If you need to create the application database on another
6 # database schema. If you need to create the application database on another
7 # system, you should be using db:schema:load, not running all the migrations
7 # system, you should be using db:schema:load, not running all the migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 #
10 #
11 # It's strongly recommended that you check this file into your version control system.
11 # It's strongly recommended that you check this file into your version control system.
12
12
13 - ActiveRecord::Schema.define(version: 2018_06_12_102327) do
13 + ActiveRecord::Schema.define(version: 2020_08_13_083020) do
14
14
15 - create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
15 + create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
16 t.string "author"
16 t.string "author"
17 t.text "body"
17 t.text "body"
18 t.boolean "published"
18 t.boolean "published"
19 - t.datetime "created_at"
19 + t.datetime "created_at", null: false
20 - t.datetime "updated_at"
20 + t.datetime "updated_at", null: false
21 t.boolean "frontpage", default: false
21 t.boolean "frontpage", default: false
22 t.boolean "contest_only", default: false
22 t.boolean "contest_only", default: false
23 t.string "title"
23 t.string "title"
24 t.string "notes"
24 t.string "notes"
25 end
25 end
26
26
27 - create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
27 + create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
28 t.string "title"
28 t.string "title"
29 t.boolean "enabled"
29 t.boolean "enabled"
30 - t.datetime "created_at"
30 + t.datetime "created_at", null: false
31 - t.datetime "updated_at"
31 + t.datetime "updated_at", null: false
32 t.string "name"
32 t.string "name"
33 end
33 end
34
34
35 - create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
35 + create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
36 t.integer "contest_id"
36 t.integer "contest_id"
37 t.integer "problem_id"
37 t.integer "problem_id"
38 end
38 end
39
39
40 - create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
40 + create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
41 t.integer "contest_id"
41 t.integer "contest_id"
42 t.integer "user_id"
42 t.integer "user_id"
43 end
43 end
44
44
45 - create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
45 + create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
46 t.string "name"
46 t.string "name"
47 - t.datetime "created_at"
47 + t.datetime "created_at", null: false
48 - t.datetime "updated_at"
48 + t.datetime "updated_at", null: false
49 end
49 end
50
50
51 - create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
51 + create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
52 t.text "body"
52 t.text "body"
53 t.boolean "markdowned"
53 t.boolean "markdowned"
54 - t.datetime "created_at"
54 + t.datetime "created_at", null: false
55 - t.datetime "updated_at"
55 + t.datetime "updated_at", null: false
56 end
56 end
57
57
58 - create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
58 + create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
59 t.string "key"
59 t.string "key"
60 t.string "value_type"
60 t.string "value_type"
61 t.string "value"
61 t.string "value"
62 - t.datetime "created_at"
62 + t.datetime "created_at", null: false
63 - t.datetime "updated_at"
63 + t.datetime "updated_at", null: false
64 t.text "description"
64 t.text "description"
65 end
65 end
66
66
67 - create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
67 + create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
68 t.string "host"
68 t.string "host"
69 t.integer "pid"
69 t.integer "pid"
70 t.string "mode"
70 t.string "mode"
71 t.boolean "active"
71 t.boolean "active"
72 - t.datetime "created_at"
72 + t.datetime "created_at", null: false
73 - t.datetime "updated_at"
73 + t.datetime "updated_at", null: false
74 t.integer "task_id"
74 t.integer "task_id"
75 t.string "task_type"
75 t.string "task_type"
76 t.boolean "terminated"
76 t.boolean "terminated"
77 - t.index ["host", "pid"], name: "index_grader_processes_on_host_and_pid"
77 + t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid"
78 end
78 end
79
79
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 t.string "name"
81 t.string "name"
82 t.string "description"
82 t.string "description"
83 + t.boolean "enabled", default: true
83 end
84 end
84
85
85 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 t.integer "problem_id", null: false
87 t.integer "problem_id", null: false
87 t.integer "group_id", null: false
88 t.integer "group_id", null: false
88 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 end
90 end
90
91
91 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 t.integer "group_id", null: false
93 t.integer "group_id", null: false
93 t.integer "user_id", null: false
94 t.integer "user_id", null: false
94 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 end
96 end
96
97
97 - create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
98 + create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
98 t.integer "user_id"
99 t.integer "user_id"
99 t.string "ip_address"
100 t.string "ip_address"
100 - t.datetime "created_at"
101 + t.datetime "created_at", null: false
101 - t.datetime "updated_at"
102 + t.datetime "updated_at", null: false
102 t.string "status"
103 t.string "status"
103 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 end
105 end
105
106
106 - create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
107 + create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
107 t.string "name", limit: 10
108 t.string "name", limit: 10
108 t.string "pretty_name"
109 t.string "pretty_name"
109 t.string "ext", limit: 10
110 t.string "ext", limit: 10
110 t.string "common_ext"
111 t.string "common_ext"
111 end
112 end
112
113
113 - create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
114 + create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
114 t.integer "user_id"
115 t.integer "user_id"
115 t.string "ip_address"
116 t.string "ip_address"
116 - t.datetime "created_at"
117 + t.datetime "created_at", null: false
117 - t.datetime "updated_at"
118 + t.datetime "updated_at", null: false
118 end
119 end
119
120
120 - create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
121 + create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
121 t.integer "sender_id"
122 t.integer "sender_id"
122 t.integer "receiver_id"
123 t.integer "receiver_id"
123 t.integer "replying_message_id"
124 t.integer "replying_message_id"
124 t.text "body"
125 t.text "body"
125 t.boolean "replied"
126 t.boolean "replied"
126 - t.datetime "created_at"
127 + t.datetime "created_at", null: false
127 - t.datetime "updated_at"
128 + t.datetime "updated_at", null: false
128 end
129 end
129
130
130 - create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
131 + create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
131 t.string "name", limit: 30
132 t.string "name", limit: 30
132 t.string "full_name"
133 t.string "full_name"
133 t.integer "full_score"
134 t.integer "full_score"
134 t.date "date_added"
135 t.date "date_added"
135 t.boolean "available"
136 t.boolean "available"
136 t.string "url"
137 t.string "url"
137 t.integer "description_id"
138 t.integer "description_id"
138 t.boolean "test_allowed"
139 t.boolean "test_allowed"
139 t.boolean "output_only"
140 t.boolean "output_only"
140 t.string "description_filename"
141 t.string "description_filename"
141 t.boolean "view_testcase"
142 t.boolean "view_testcase"
142 end
143 end
143
144
144 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
145 create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
145 t.integer "problem_id"
146 t.integer "problem_id"
146 t.integer "tag_id"
147 t.integer "tag_id"
147 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
148 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
148 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
149 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
149 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
150 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
150 end
151 end
151
152
152 - create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
153 + create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
153 t.string "name"
154 t.string "name"
154 t.string "controller"
155 t.string "controller"
155 t.string "action"
156 t.string "action"
156 end
157 end
157
158
158 - create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
159 + create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
159 t.integer "right_id"
160 t.integer "right_id"
160 t.integer "role_id"
161 t.integer "role_id"
161 t.index ["role_id"], name: "index_rights_roles_on_role_id"
162 t.index ["role_id"], name: "index_rights_roles_on_role_id"
162 end
163 end
163
164
164 - create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
165 + create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
165 t.string "name"
166 t.string "name"
166 end
167 end
167
168
168 - create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
169 + create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
169 t.integer "role_id"
170 t.integer "role_id"
170 t.integer "user_id"
171 t.integer "user_id"
171 t.index ["user_id"], name: "index_roles_users_on_user_id"
172 t.index ["user_id"], name: "index_roles_users_on_user_id"
172 end
173 end
173
174
174 - create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
175 + create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
175 t.string "session_id"
176 t.string "session_id"
176 t.text "data"
177 t.text "data"
177 t.datetime "updated_at"
178 t.datetime "updated_at"
178 t.index ["session_id"], name: "index_sessions_on_session_id"
179 t.index ["session_id"], name: "index_sessions_on_session_id"
179 t.index ["updated_at"], name: "index_sessions_on_updated_at"
180 t.index ["updated_at"], name: "index_sessions_on_updated_at"
180 end
181 end
181
182
182 - create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
183 + create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
183 t.string "name"
184 t.string "name"
184 t.boolean "started"
185 t.boolean "started"
185 t.datetime "start_time"
186 t.datetime "start_time"
186 - t.datetime "created_at"
187 + t.datetime "created_at", null: false
187 - t.datetime "updated_at"
188 + t.datetime "updated_at", null: false
188 t.integer "country_id"
189 t.integer "country_id"
189 t.string "password"
190 t.string "password"
190 end
191 end
191
192
192 - create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
193 + create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
193 t.integer "user_id"
194 t.integer "user_id"
194 t.integer "submission_id"
195 t.integer "submission_id"
195 - t.datetime "created_at"
196 + t.datetime "created_at", null: false
196 - t.datetime "updated_at"
197 + t.datetime "updated_at", null: false
197 end
198 end
198
199
199 - create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
200 + create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
200 t.integer "user_id"
201 t.integer "user_id"
201 t.integer "problem_id"
202 t.integer "problem_id"
202 t.integer "language_id"
203 t.integer "language_id"
203 t.text "source", limit: 16777215
204 t.text "source", limit: 16777215
204 t.binary "binary"
205 t.binary "binary"
205 t.datetime "submitted_at"
206 t.datetime "submitted_at"
206 t.datetime "compiled_at"
207 t.datetime "compiled_at"
207 t.text "compiler_message"
208 t.text "compiler_message"
208 t.datetime "graded_at"
209 t.datetime "graded_at"
209 t.integer "points"
210 t.integer "points"
210 t.text "grader_comment"
211 t.text "grader_comment"
211 t.integer "number"
212 t.integer "number"
@@ -217,91 +218,91
217 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
218 t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true
218 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
219 t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id"
219 end
220 end
220
221
221 create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
222 create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
222 t.string "name", null: false
223 t.string "name", null: false
223 t.text "description"
224 t.text "description"
224 t.boolean "public"
225 t.boolean "public"
225 t.datetime "created_at", null: false
226 t.datetime "created_at", null: false
226 t.datetime "updated_at", null: false
227 t.datetime "updated_at", null: false
227 end
228 end
228
229
229 - create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
230 + create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
230 t.integer "submission_id"
231 t.integer "submission_id"
231 t.datetime "created_at"
232 t.datetime "created_at"
232 t.integer "status"
233 t.integer "status"
233 t.datetime "updated_at"
234 t.datetime "updated_at"
234 t.index ["submission_id"], name: "index_tasks_on_submission_id"
235 t.index ["submission_id"], name: "index_tasks_on_submission_id"
235 end
236 end
236
237
237 - create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
238 + create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
238 t.integer "problem_id"
239 t.integer "problem_id"
239 t.text "input", limit: 16777215
240 t.text "input", limit: 16777215
240 t.text "solution", limit: 16777215
241 t.text "solution", limit: 16777215
241 - t.datetime "created_at"
242 + t.datetime "created_at", null: false
242 - t.datetime "updated_at"
243 + t.datetime "updated_at", null: false
243 end
244 end
244
245
245 - create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
246 + create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
246 t.integer "user_id"
247 t.integer "user_id"
247 t.integer "problem_id"
248 t.integer "problem_id"
248 t.integer "submission_id"
249 t.integer "submission_id"
249 t.string "input_file_name"
250 t.string "input_file_name"
250 t.string "output_file_name"
251 t.string "output_file_name"
251 t.string "running_stat"
252 t.string "running_stat"
252 t.integer "status"
253 t.integer "status"
253 - t.datetime "updated_at"
254 + t.datetime "updated_at", null: false
254 t.datetime "submitted_at"
255 t.datetime "submitted_at"
255 t.datetime "compiled_at"
256 t.datetime "compiled_at"
256 t.text "compiler_message"
257 t.text "compiler_message"
257 t.datetime "graded_at"
258 t.datetime "graded_at"
258 t.string "grader_comment"
259 t.string "grader_comment"
259 - t.datetime "created_at"
260 + t.datetime "created_at", null: false
260 t.float "running_time"
261 t.float "running_time"
261 t.string "exit_status"
262 t.string "exit_status"
262 t.integer "memory_usage"
263 t.integer "memory_usage"
263 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
264 t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id"
264 end
265 end
265
266
266 create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
267 create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
267 t.integer "problem_id"
268 t.integer "problem_id"
268 t.integer "num"
269 t.integer "num"
269 t.integer "group"
270 t.integer "group"
270 t.integer "score"
271 t.integer "score"
271 t.text "input", limit: 4294967295
272 t.text "input", limit: 4294967295
272 t.text "sol", limit: 4294967295
273 t.text "sol", limit: 4294967295
273 t.datetime "created_at"
274 t.datetime "created_at"
274 t.datetime "updated_at"
275 t.datetime "updated_at"
275 t.index ["problem_id"], name: "index_testcases_on_problem_id"
276 t.index ["problem_id"], name: "index_testcases_on_problem_id"
276 end
277 end
277
278
278 - create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
279 + create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
279 t.integer "user_id"
280 t.integer "user_id"
280 t.datetime "started_at"
281 t.datetime "started_at"
281 - t.datetime "created_at"
282 + t.datetime "created_at", null: false
282 - t.datetime "updated_at"
283 + t.datetime "updated_at", null: false
283 t.boolean "forced_logout"
284 t.boolean "forced_logout"
284 end
285 end
285
286
286 - create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
287 + create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t|
287 t.string "login", limit: 50
288 t.string "login", limit: 50
288 t.string "full_name"
289 t.string "full_name"
289 t.string "hashed_password"
290 t.string "hashed_password"
290 t.string "salt", limit: 5
291 t.string "salt", limit: 5
291 t.string "alias"
292 t.string "alias"
292 t.string "email"
293 t.string "email"
293 t.integer "site_id"
294 t.integer "site_id"
294 t.integer "country_id"
295 t.integer "country_id"
295 t.boolean "activated", default: false
296 t.boolean "activated", default: false
296 t.datetime "created_at"
297 t.datetime "created_at"
297 t.datetime "updated_at"
298 t.datetime "updated_at"
298 - t.string "section"
299 t.boolean "enabled", default: true
299 t.boolean "enabled", default: true
300 t.string "remark"
300 t.string "remark"
301 t.string "last_ip"
301 t.string "last_ip"
302 + t.string "section"
302 t.index ["login"], name: "index_users_on_login", unique: true
303 t.index ["login"], name: "index_users_on_login", unique: true
303 end
304 end
304
305
305 add_foreign_key "problems_tags", "problems"
306 add_foreign_key "problems_tags", "problems"
306 add_foreign_key "problems_tags", "tags"
307 add_foreign_key "problems_tags", "tags"
307 end
308 end
You need to be logged in to leave comments. Login now