Description:
add remove_all in groups consolidate submissions viewing from grader/task
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r680:4ce0b8696d06 - - 9 files changed: 35 inserted, 138 deleted

@@ -1,128 +1,93
1 class GradersController < ApplicationController
1 class GradersController < ApplicationController
2
2
3 - before_filter :admin_authorization, except: [ :submission ]
3 + before_filter :admin_authorization
4 - before_filter(only: [:submission]) {
5 - #check if authenticated
6 - return false unless authenticate
7 -
8 - #admin always has privileged
9 - if @current_user.admin?
10 - return true
11 - end
12 -
13 - if GraderConfiguration["right.user_view_submission"] and Submission.find(params[:id]).problem.available?
14 - return true
15 - else
16 - unauthorized_redirect
17 - return false
18 - end
19 - }
20
4
21 verify :method => :post, :only => ['clear_all',
5 verify :method => :post, :only => ['clear_all',
22 'start_exam',
6 'start_exam',
23 'start_grading',
7 'start_grading',
24 'stop_all',
8 'stop_all',
25 'clear_terminated'],
9 'clear_terminated'],
26 :redirect_to => {:action => 'index'}
10 :redirect_to => {:action => 'index'}
27
11
28 def index
12 def index
29 redirect_to :action => 'list'
13 redirect_to :action => 'list'
30 end
14 end
31
15
32 def list
16 def list
33 @grader_processes = GraderProcess.find_running_graders
17 @grader_processes = GraderProcess.find_running_graders
34 @stalled_processes = GraderProcess.find_stalled_process
18 @stalled_processes = GraderProcess.find_stalled_process
35
19
36 @terminated_processes = GraderProcess.find_terminated_graders
20 @terminated_processes = GraderProcess.find_terminated_graders
37
21
38 @last_task = Task.last
22 @last_task = Task.last
39 @last_test_request = TestRequest.last
23 @last_test_request = TestRequest.last
40 @submission = Submission.order("id desc").limit(20)
24 @submission = Submission.order("id desc").limit(20)
41 @backlog_submission = Submission.where('graded_at is null')
25 @backlog_submission = Submission.where('graded_at is null')
42 end
26 end
43
27
44 def clear
28 def clear
45 grader_proc = GraderProcess.find(params[:id])
29 grader_proc = GraderProcess.find(params[:id])
46 grader_proc.destroy if grader_proc!=nil
30 grader_proc.destroy if grader_proc!=nil
47 redirect_to :action => 'list'
31 redirect_to :action => 'list'
48 end
32 end
49
33
50 def clear_terminated
34 def clear_terminated
51 GraderProcess.find_terminated_graders.each do |p|
35 GraderProcess.find_terminated_graders.each do |p|
52 p.destroy
36 p.destroy
53 end
37 end
54 redirect_to :action => 'list'
38 redirect_to :action => 'list'
55 end
39 end
56
40
57 def clear_all
41 def clear_all
58 GraderProcess.all.each do |p|
42 GraderProcess.all.each do |p|
59 p.destroy
43 p.destroy
60 end
44 end
61 redirect_to :action => 'list'
45 redirect_to :action => 'list'
62 end
46 end
63
47
64 def view
48 def view
65 if params[:type]=='Task'
49 if params[:type]=='Task'
66 redirect_to :action => 'task', :id => params[:id]
50 redirect_to :action => 'task', :id => params[:id]
67 else
51 else
68 redirect_to :action => 'test_request', :id => params[:id]
52 redirect_to :action => 'test_request', :id => params[:id]
69 end
53 end
70 end
54 end
71
55
72 def test_request
56 def test_request
73 @test_request = TestRequest.find(params[:id])
57 @test_request = TestRequest.find(params[:id])
74 end
58 end
75
59
76 def task
60 def task
77 @task = Task.find(params[:id])
61 @task = Task.find(params[:id])
78 end
62 end
79
63
80 - def submission
81 - @submission = Submission.find(params[:id])
82 - formatter = Rouge::Formatters::HTML.new(css_class: 'highlight', line_numbers: true )
83 - lexer = case @submission.language.name
84 - when "c" then Rouge::Lexers::C.new
85 - when "cpp" then Rouge::Lexers::Cpp.new
86 - when "pas" then Rouge::Lexers::Pas.new
87 - when "ruby" then Rouge::Lexers::Ruby.new
88 - when "python" then Rouge::Lexers::Python.new
89 - when "java" then Rouge::Lexers::Java.new
90 - when "php" then Rouge::Lexers::PHP.new
91 - end
92 - @formatted_code = formatter.format(lexer.lex(@submission.source))
93 - @css_style = Rouge::Themes::ThankfulEyes.render(scope: '.highlight')
94 -
95 - user = User.find(session[:user_id])
96 - SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin?
97 -
98 - end
99
64
100 # various grader controls
65 # various grader controls
101
66
102 def stop
67 def stop
103 grader_proc = GraderProcess.find(params[:id])
68 grader_proc = GraderProcess.find(params[:id])
104 GraderScript.stop_grader(grader_proc.pid)
69 GraderScript.stop_grader(grader_proc.pid)
105 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
70 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
106 redirect_to :action => 'list'
71 redirect_to :action => 'list'
107 end
72 end
108
73
109 def stop_all
74 def stop_all
110 GraderScript.stop_graders(GraderProcess.find_running_graders +
75 GraderScript.stop_graders(GraderProcess.find_running_graders +
111 GraderProcess.find_stalled_process)
76 GraderProcess.find_stalled_process)
112 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
77 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
113 redirect_to :action => 'list'
78 redirect_to :action => 'list'
114 end
79 end
115
80
116 def start_grading
81 def start_grading
117 GraderScript.start_grader('grading')
82 GraderScript.start_grader('grading')
118 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
83 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
119 redirect_to :action => 'list'
84 redirect_to :action => 'list'
120 end
85 end
121
86
122 def start_exam
87 def start_exam
123 GraderScript.start_grader('exam')
88 GraderScript.start_grader('exam')
124 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
89 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
125 redirect_to :action => 'list'
90 redirect_to :action => 'list'
126 end
91 end
127
92
128 end
93 end
@@ -1,94 +1,104
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,
3 + :add_user, :remove_user,:remove_all_user,
4 - :add_problem, :remove_problem,
4 + :add_problem, :remove_problem,:remove_all_problem,
5 ]
5 ]
6 before_action :authenticate, :admin_authorization
6 before_action :authenticate, :admin_authorization
7
7
8 # GET /groups
8 # GET /groups
9 def index
9 def index
10 @groups = Group.all
10 @groups = Group.all
11 end
11 end
12
12
13 # GET /groups/1
13 # GET /groups/1
14 def show
14 def show
15 end
15 end
16
16
17 # GET /groups/new
17 # GET /groups/new
18 def new
18 def new
19 @group = Group.new
19 @group = Group.new
20 end
20 end
21
21
22 # GET /groups/1/edit
22 # GET /groups/1/edit
23 def edit
23 def edit
24 end
24 end
25
25
26 # POST /groups
26 # POST /groups
27 def create
27 def create
28 @group = Group.new(group_params)
28 @group = Group.new(group_params)
29
29
30 if @group.save
30 if @group.save
31 redirect_to @group, notice: 'Group was successfully created.'
31 redirect_to @group, notice: 'Group was successfully created.'
32 else
32 else
33 render :new
33 render :new
34 end
34 end
35 end
35 end
36
36
37 # PATCH/PUT /groups/1
37 # PATCH/PUT /groups/1
38 def update
38 def update
39 if @group.update(group_params)
39 if @group.update(group_params)
40 redirect_to @group, notice: 'Group was successfully updated.'
40 redirect_to @group, notice: 'Group was successfully updated.'
41 else
41 else
42 render :edit
42 render :edit
43 end
43 end
44 end
44 end
45
45
46 # DELETE /groups/1
46 # DELETE /groups/1
47 def destroy
47 def destroy
48 @group.destroy
48 @group.destroy
49 redirect_to groups_url, notice: 'Group was successfully destroyed.'
49 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 end
50 end
51
51
52 def remove_user
52 def remove_user
53 user = User.find(params[:user_id])
53 user = User.find(params[:user_id])
54 @group.users.delete(user)
54 @group.users.delete(user)
55 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
55 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
56 end
56 end
57
57
58 + def remove_all_user
59 + @group.users.clear
60 + redirect_to group_path(@group), alert: 'All users removed'
61 + end
62 +
63 + def remove_all_problem
64 + @group.problems.clear
65 + redirect_to group_path(@group), alert: 'All problems removed'
66 + end
67 +
58 def add_user
68 def add_user
59 user = User.find(params[:user_id])
69 user = User.find(params[:user_id])
60 begin
70 begin
61 @group.users << user
71 @group.users << user
62 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
72 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
63 rescue => e
73 rescue => e
64 redirect_to group_path(@group), alert: e.message
74 redirect_to group_path(@group), alert: e.message
65 end
75 end
66 end
76 end
67
77
68 def remove_problem
78 def remove_problem
69 problem = Problem.find(params[:problem_id])
79 problem = Problem.find(params[:problem_id])
70 @group.problems.delete(problem)
80 @group.problems.delete(problem)
71 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
81 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
72 end
82 end
73
83
74 def add_problem
84 def add_problem
75 problem = Problem.find(params[:problem_id])
85 problem = Problem.find(params[:problem_id])
76 begin
86 begin
77 @group.problems << problem
87 @group.problems << problem
78 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
88 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
79 rescue => e
89 rescue => e
80 redirect_to group_path(@group), alert: e.message
90 redirect_to group_path(@group), alert: e.message
81 end
91 end
82 end
92 end
83
93
84 private
94 private
85 # Use callbacks to share common setup or constraints between actions.
95 # Use callbacks to share common setup or constraints between actions.
86 def set_group
96 def set_group
87 @group = Group.find(params[:id])
97 @group = Group.find(params[:id])
88 end
98 end
89
99
90 # Only allow a trusted parameter "white list" through.
100 # Only allow a trusted parameter "white list" through.
91 def group_params
101 def group_params
92 params.require(:group).permit(:name, :description)
102 params.require(:group).permit(:name, :description)
93 end
103 end
94 end
104 end
@@ -1,75 +1,75
1 class TasksController < ApplicationController
1 class TasksController < ApplicationController
2
2
3 before_filter :authenticate, :check_viewability
3 before_filter :authenticate, :check_viewability
4
4
5 def index
5 def index
6 redirect_to :action => 'list'
6 redirect_to :action => 'list'
7 end
7 end
8
8
9 def list
9 def list
10 @problems = @user.available_problems
10 @problems = @user.available_problems
11 end
11 end
12
12
13 # this has contest-wide access control
13 # this has contest-wide access control
14 def view
14 def view
15 base_name = params[:file]
15 base_name = params[:file]
16 base_filename = File.basename("#{base_name}.#{params[:ext]}")
16 base_filename = File.basename("#{base_name}.#{params[:ext]}")
17 filename = "#{Problem.download_file_basedir}/#{base_filename}"
17 filename = "#{Problem.download_file_basedir}/#{base_filename}"
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 - if !problem or !problem.available or !@user.can_view_problem? problem
29 + unless @current_user.can_view_problem? problem
30 redirect_to :action => 'index' and return
30 redirect_to :action => 'index' and return
31 end
31 end
32
32
33 base_name = params[:file]
33 base_name = params[:file]
34 base_filename = File.basename("#{base_name}.#{params[:ext]}")
34 base_filename = File.basename("#{base_name}.#{params[:ext]}")
35 filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
35 filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}"
36 puts "SENDING: #{filename}"
36 puts "SENDING: #{filename}"
37
37
38 if !FileTest.exists?(filename)
38 if !FileTest.exists?(filename)
39 redirect_to :action => 'index' and return
39 redirect_to :action => 'index' and return
40 end
40 end
41
41
42 puts "SENDING: #{filename}"
42 puts "SENDING: #{filename}"
43
43
44 send_file_to_user(filename, base_filename)
44 send_file_to_user(filename, base_filename)
45 end
45 end
46
46
47 protected
47 protected
48
48
49 def send_file_to_user(filename, base_filename)
49 def send_file_to_user(filename, base_filename)
50 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
50 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
51 response.headers['Content-Type'] = "application/force-download"
51 response.headers['Content-Type'] = "application/force-download"
52 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
52 response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\""
53 response.headers["X-Sendfile"] = filename
53 response.headers["X-Sendfile"] = filename
54 response.headers['Content-length'] = File.size(filename)
54 response.headers['Content-length'] = File.size(filename)
55 render :nothing => true
55 render :nothing => true
56 else
56 else
57 if params[:ext]=='pdf'
57 if params[:ext]=='pdf'
58 content_type = 'application/pdf'
58 content_type = 'application/pdf'
59 else
59 else
60 content_type = 'application/octet-stream'
60 content_type = 'application/octet-stream'
61 end
61 end
62
62
63 send_file filename, :stream => false, :disposition => 'inline', :filename => base_filename, :type => content_type
63 send_file filename, :stream => false, :disposition => 'inline', :filename => base_filename, :type => content_type
64 end
64 end
65 end
65 end
66
66
67 def check_viewability
67 def check_viewability
68 @user = User.find(session[:user_id])
68 @user = User.find(session[:user_id])
69 if @user==nil or !GraderConfiguration.show_tasks_to?(@user)
69 if @user==nil or !GraderConfiguration.show_tasks_to?(@user)
70 redirect_to :controller => 'main', :action => 'list'
70 redirect_to :controller => 'main', :action => 'list'
71 return false
71 return false
72 end
72 end
73 end
73 end
74
74
75 end
75 end
@@ -1,419 +1,416
1 require 'digest/sha1'
1 require 'digest/sha1'
2 require 'net/pop'
2 require 'net/pop'
3 require 'net/https'
3 require 'net/https'
4 require 'net/http'
4 require 'net/http'
5 require 'json'
5 require 'json'
6
6
7 class User < ActiveRecord::Base
7 class User < ActiveRecord::Base
8
8
9 has_and_belongs_to_many :roles
9 has_and_belongs_to_many :roles
10
10
11 #has_and_belongs_to_many :groups
11 #has_and_belongs_to_many :groups
12 has_many :groups_users, class_name: GroupUser
12 has_many :groups_users, class_name: GroupUser
13 has_many :groups, :through => :groups_users
13 has_many :groups, :through => :groups_users
14
14
15 has_many :test_requests, -> {order(submitted_at: DESC)}
15 has_many :test_requests, -> {order(submitted_at: DESC)}
16
16
17 has_many :messages, -> { order(created_at: DESC) },
17 has_many :messages, -> { order(created_at: DESC) },
18 :class_name => "Message",
18 :class_name => "Message",
19 :foreign_key => "sender_id"
19 :foreign_key => "sender_id"
20
20
21 has_many :replied_messages, -> { order(created_at: DESC) },
21 has_many :replied_messages, -> { order(created_at: DESC) },
22 :class_name => "Message",
22 :class_name => "Message",
23 :foreign_key => "receiver_id"
23 :foreign_key => "receiver_id"
24
24
25 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
25 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
26
26
27 belongs_to :site
27 belongs_to :site
28 belongs_to :country
28 belongs_to :country
29
29
30 has_and_belongs_to_many :contests, -> { order(:name); uniq}
30 has_and_belongs_to_many :contests, -> { order(:name); uniq}
31
31
32 scope :activated_users, -> {where activated: true}
32 scope :activated_users, -> {where activated: true}
33
33
34 validates_presence_of :login
34 validates_presence_of :login
35 validates_uniqueness_of :login
35 validates_uniqueness_of :login
36 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
36 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
37 validates_length_of :login, :within => 3..30
37 validates_length_of :login, :within => 3..30
38
38
39 validates_presence_of :full_name
39 validates_presence_of :full_name
40 validates_length_of :full_name, :minimum => 1
40 validates_length_of :full_name, :minimum => 1
41
41
42 validates_presence_of :password, :if => :password_required?
42 validates_presence_of :password, :if => :password_required?
43 validates_length_of :password, :within => 4..20, :if => :password_required?
43 validates_length_of :password, :within => 4..20, :if => :password_required?
44 validates_confirmation_of :password, :if => :password_required?
44 validates_confirmation_of :password, :if => :password_required?
45
45
46 validates_format_of :email,
46 validates_format_of :email,
47 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
47 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
48 :if => :email_validation?
48 :if => :email_validation?
49 validate :uniqueness_of_email_from_activated_users,
49 validate :uniqueness_of_email_from_activated_users,
50 :if => :email_validation?
50 :if => :email_validation?
51 validate :enough_time_interval_between_same_email_registrations,
51 validate :enough_time_interval_between_same_email_registrations,
52 :if => :email_validation?
52 :if => :email_validation?
53
53
54 # these are for ytopc
54 # these are for ytopc
55 # disable for now
55 # disable for now
56 #validates_presence_of :province
56 #validates_presence_of :province
57
57
58 attr_accessor :password
58 attr_accessor :password
59
59
60 before_save :encrypt_new_password
60 before_save :encrypt_new_password
61 before_save :assign_default_site
61 before_save :assign_default_site
62 before_save :assign_default_contest
62 before_save :assign_default_contest
63
63
64 # this is for will_paginate
64 # this is for will_paginate
65 cattr_reader :per_page
65 cattr_reader :per_page
66 @@per_page = 50
66 @@per_page = 50
67
67
68 def self.authenticate(login, password)
68 def self.authenticate(login, password)
69 user = find_by_login(login)
69 user = find_by_login(login)
70 if user
70 if user
71 return user if user.authenticated?(password)
71 return user if user.authenticated?(password)
72 if user.authenticated_by_cucas?(password) or user.authenticated_by_pop3?(password)
72 if user.authenticated_by_cucas?(password) or user.authenticated_by_pop3?(password)
73 user.password = password
73 user.password = password
74 user.save
74 user.save
75 return user
75 return user
76 end
76 end
77 end
77 end
78 end
78 end
79
79
80 def authenticated?(password)
80 def authenticated?(password)
81 if self.activated
81 if self.activated
82 hashed_password == User.encrypt(password,self.salt)
82 hashed_password == User.encrypt(password,self.salt)
83 else
83 else
84 false
84 false
85 end
85 end
86 end
86 end
87
87
88 def authenticated_by_pop3?(password)
88 def authenticated_by_pop3?(password)
89 Net::POP3.enable_ssl
89 Net::POP3.enable_ssl
90 pop = Net::POP3.new('pops.it.chula.ac.th')
90 pop = Net::POP3.new('pops.it.chula.ac.th')
91 authen = true
91 authen = true
92 begin
92 begin
93 pop.start(login, password)
93 pop.start(login, password)
94 pop.finish
94 pop.finish
95 return true
95 return true
96 rescue
96 rescue
97 return false
97 return false
98 end
98 end
99 end
99 end
100
100
101 def authenticated_by_cucas?(password)
101 def authenticated_by_cucas?(password)
102 url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
102 url = URI.parse('https://www.cas.chula.ac.th/cas/api/?q=studentAuthenticate')
103 appid = '41508763e340d5858c00f8c1a0f5a2bb'
103 appid = '41508763e340d5858c00f8c1a0f5a2bb'
104 appsecret ='d9cbb5863091dbe186fded85722a1e31'
104 appsecret ='d9cbb5863091dbe186fded85722a1e31'
105 post_args = {
105 post_args = {
106 'appid' => appid,
106 'appid' => appid,
107 'appsecret' => appsecret,
107 'appsecret' => appsecret,
108 'username' => login,
108 'username' => login,
109 'password' => password
109 'password' => password
110 }
110 }
111
111
112 #simple call
112 #simple call
113 begin
113 begin
114 http = Net::HTTP.new('www.cas.chula.ac.th', 443)
114 http = Net::HTTP.new('www.cas.chula.ac.th', 443)
115 http.use_ssl = true
115 http.use_ssl = true
116 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
116 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
117 result = [ ]
117 result = [ ]
118 http.start do |http|
118 http.start do |http|
119 req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
119 req = Net::HTTP::Post.new('/cas/api/?q=studentAuthenticate')
120 param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
120 param = "appid=#{appid}&appsecret=#{appsecret}&username=#{login}&password=#{password}"
121 resp = http.request(req,param)
121 resp = http.request(req,param)
122 result = JSON.parse resp.body
122 result = JSON.parse resp.body
123 end
123 end
124 return true if result["type"] == "beanStudent"
124 return true if result["type"] == "beanStudent"
125 rescue => e
125 rescue => e
126 return false
126 return false
127 end
127 end
128 return false
128 return false
129 end
129 end
130
130
131 def admin?
131 def admin?
132 self.roles.detect {|r| r.name == 'admin' }
132 self.roles.detect {|r| r.name == 'admin' }
133 end
133 end
134
134
135 def email_for_editing
135 def email_for_editing
136 if self.email==nil
136 if self.email==nil
137 "(unknown)"
137 "(unknown)"
138 elsif self.email==''
138 elsif self.email==''
139 "(blank)"
139 "(blank)"
140 else
140 else
141 self.email
141 self.email
142 end
142 end
143 end
143 end
144
144
145 def email_for_editing=(e)
145 def email_for_editing=(e)
146 self.email=e
146 self.email=e
147 end
147 end
148
148
149 def alias_for_editing
149 def alias_for_editing
150 if self.alias==nil
150 if self.alias==nil
151 "(unknown)"
151 "(unknown)"
152 elsif self.alias==''
152 elsif self.alias==''
153 "(blank)"
153 "(blank)"
154 else
154 else
155 self.alias
155 self.alias
156 end
156 end
157 end
157 end
158
158
159 def alias_for_editing=(e)
159 def alias_for_editing=(e)
160 self.alias=e
160 self.alias=e
161 end
161 end
162
162
163 def activation_key
163 def activation_key
164 if self.hashed_password==nil
164 if self.hashed_password==nil
165 encrypt_new_password
165 encrypt_new_password
166 end
166 end
167 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
167 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
168 end
168 end
169
169
170 def verify_activation_key(key)
170 def verify_activation_key(key)
171 key == activation_key
171 key == activation_key
172 end
172 end
173
173
174 def self.random_password(length=5)
174 def self.random_password(length=5)
175 chars = 'abcdefghjkmnopqrstuvwxyz'
175 chars = 'abcdefghjkmnopqrstuvwxyz'
176 password = ''
176 password = ''
177 length.times { password << chars[rand(chars.length - 1)] }
177 length.times { password << chars[rand(chars.length - 1)] }
178 password
178 password
179 end
179 end
180
180
181 def self.find_non_admin_with_prefix(prefix='')
181 def self.find_non_admin_with_prefix(prefix='')
182 users = User.all
182 users = User.all
183 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
183 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
184 end
184 end
185
185
186 # Contest information
186 # Contest information
187
187
188 def self.find_users_with_no_contest()
188 def self.find_users_with_no_contest()
189 users = User.all
189 users = User.all
190 return users.find_all { |u| u.contests.length == 0 }
190 return users.find_all { |u| u.contests.length == 0 }
191 end
191 end
192
192
193
193
194 def contest_time_left
194 def contest_time_left
195 if GraderConfiguration.contest_mode?
195 if GraderConfiguration.contest_mode?
196 return nil if site==nil
196 return nil if site==nil
197 return site.time_left
197 return site.time_left
198 elsif GraderConfiguration.indv_contest_mode?
198 elsif GraderConfiguration.indv_contest_mode?
199 time_limit = GraderConfiguration.contest_time_limit
199 time_limit = GraderConfiguration.contest_time_limit
200 if time_limit == nil
200 if time_limit == nil
201 return nil
201 return nil
202 end
202 end
203 if contest_stat==nil or contest_stat.started_at==nil
203 if contest_stat==nil or contest_stat.started_at==nil
204 return (Time.now.gmtime + time_limit) - Time.now.gmtime
204 return (Time.now.gmtime + time_limit) - Time.now.gmtime
205 else
205 else
206 finish_time = contest_stat.started_at + time_limit
206 finish_time = contest_stat.started_at + time_limit
207 current_time = Time.now.gmtime
207 current_time = Time.now.gmtime
208 if current_time > finish_time
208 if current_time > finish_time
209 return 0
209 return 0
210 else
210 else
211 return finish_time - current_time
211 return finish_time - current_time
212 end
212 end
213 end
213 end
214 else
214 else
215 return nil
215 return nil
216 end
216 end
217 end
217 end
218
218
219 def contest_finished?
219 def contest_finished?
220 if GraderConfiguration.contest_mode?
220 if GraderConfiguration.contest_mode?
221 return false if site==nil
221 return false if site==nil
222 return site.finished?
222 return site.finished?
223 elsif GraderConfiguration.indv_contest_mode?
223 elsif GraderConfiguration.indv_contest_mode?
224 return false if self.contest_stat(true)==nil
224 return false if self.contest_stat(true)==nil
225 return contest_time_left == 0
225 return contest_time_left == 0
226 else
226 else
227 return false
227 return false
228 end
228 end
229 end
229 end
230
230
231 def contest_started?
231 def contest_started?
232 if GraderConfiguration.indv_contest_mode?
232 if GraderConfiguration.indv_contest_mode?
233 stat = self.contest_stat
233 stat = self.contest_stat
234 return ((stat != nil) and (stat.started_at != nil))
234 return ((stat != nil) and (stat.started_at != nil))
235 elsif GraderConfiguration.contest_mode?
235 elsif GraderConfiguration.contest_mode?
236 return true if site==nil
236 return true if site==nil
237 return site.started
237 return site.started
238 else
238 else
239 return true
239 return true
240 end
240 end
241 end
241 end
242
242
243 def update_start_time
243 def update_start_time
244 stat = self.contest_stat
244 stat = self.contest_stat
245 if stat.nil? or stat.started_at.nil?
245 if stat.nil? or stat.started_at.nil?
246 stat ||= UserContestStat.new(:user => self)
246 stat ||= UserContestStat.new(:user => self)
247 stat.started_at = Time.now.gmtime
247 stat.started_at = Time.now.gmtime
248 stat.save
248 stat.save
249 end
249 end
250 end
250 end
251
251
252 def problem_in_user_contests?(problem)
252 def problem_in_user_contests?(problem)
253 problem_contests = problem.contests.all
253 problem_contests = problem.contests.all
254
254
255 if problem_contests.length == 0 # this is public contest
255 if problem_contests.length == 0 # this is public contest
256 return true
256 return true
257 end
257 end
258
258
259 contests.each do |contest|
259 contests.each do |contest|
260 if problem_contests.find {|c| c.id == contest.id }
260 if problem_contests.find {|c| c.id == contest.id }
261 return true
261 return true
262 end
262 end
263 end
263 end
264 return false
264 return false
265 end
265 end
266
266
267 def available_problems_group_by_contests
267 def available_problems_group_by_contests
268 contest_problems = []
268 contest_problems = []
269 pin = {}
269 pin = {}
270 contests.enabled.each do |contest|
270 contests.enabled.each do |contest|
271 available_problems = contest.problems.available
271 available_problems = contest.problems.available
272 contest_problems << {
272 contest_problems << {
273 :contest => contest,
273 :contest => contest,
274 :problems => available_problems
274 :problems => available_problems
275 }
275 }
276 available_problems.each {|p| pin[p.id] = true}
276 available_problems.each {|p| pin[p.id] = true}
277 end
277 end
278 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
278 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
279 contest_problems << {
279 contest_problems << {
280 :contest => nil,
280 :contest => nil,
281 :problems => other_avaiable_problems
281 :problems => other_avaiable_problems
282 }
282 }
283 return contest_problems
283 return contest_problems
284 end
284 end
285
285
286 def solve_all_available_problems?
286 def solve_all_available_problems?
287 available_problems.each do |p|
287 available_problems.each do |p|
288 u = self
288 u = self
289 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
289 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
290 return false if !p or !sub or sub.points < p.full_score
290 return false if !p or !sub or sub.points < p.full_score
291 end
291 end
292 return true
292 return true
293 end
293 end
294
294
295 def available_problems
295 def available_problems
296 if not GraderConfiguration.multicontests?
296 if not GraderConfiguration.multicontests?
297 if GraderConfiguration.use_problem_group?
297 if GraderConfiguration.use_problem_group?
298 return available_problems_in_group
298 return available_problems_in_group
299 else
299 else
300 return Problem.available_problems
300 return Problem.available_problems
301 end
301 end
302 else
302 else
303 contest_problems = []
303 contest_problems = []
304 pin = {}
304 pin = {}
305 contests.enabled.each do |contest|
305 contests.enabled.each do |contest|
306 contest.problems.available.each do |problem|
306 contest.problems.available.each do |problem|
307 if not pin.has_key? problem.id
307 if not pin.has_key? problem.id
308 contest_problems << problem
308 contest_problems << problem
309 end
309 end
310 pin[problem.id] = true
310 pin[problem.id] = true
311 end
311 end
312 end
312 end
313 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
313 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
314 return contest_problems + other_avaiable_problems
314 return contest_problems + other_avaiable_problems
315 end
315 end
316 end
316 end
317
317
318 def available_problems_in_group
318 def available_problems_in_group
319 problem = []
319 problem = []
320 self.groups.each do |group|
320 self.groups.each do |group|
321 group.problems.where(available: true).each { |p| problem << p }
321 group.problems.where(available: true).each { |p| problem << p }
322 end
322 end
323 problem.uniq!
323 problem.uniq!
324 if problem
324 if problem
325 problem.sort! do |a,b|
325 problem.sort! do |a,b|
326 case
326 case
327 when a.date_added < b.date_added
327 when a.date_added < b.date_added
328 1
328 1
329 when a.date_added > b.date_added
329 when a.date_added > b.date_added
330 -1
330 -1
331 else
331 else
332 a.name <=> b.name
332 a.name <=> b.name
333 end
333 end
334 end
334 end
335 return problem
335 return problem
336 else
336 else
337 return []
337 return []
338 end
338 end
339 end
339 end
340
340
341 def can_view_problem?(problem)
341 def can_view_problem?(problem)
342 - if not GraderConfiguration.multicontests?
342 + return true if admin?
343 - return problem.available
343 + return available_problems.include? problem
344 - else
345 - return problem_in_user_contests? problem
346 - end
347 end
344 end
348
345
349 def self.clear_last_login
346 def self.clear_last_login
350 User.update_all(:last_ip => nil)
347 User.update_all(:last_ip => nil)
351 end
348 end
352
349
353 protected
350 protected
354 def encrypt_new_password
351 def encrypt_new_password
355 return if password.blank?
352 return if password.blank?
356 self.salt = (10+rand(90)).to_s
353 self.salt = (10+rand(90)).to_s
357 self.hashed_password = User.encrypt(self.password,self.salt)
354 self.hashed_password = User.encrypt(self.password,self.salt)
358 end
355 end
359
356
360 def assign_default_site
357 def assign_default_site
361 # have to catch error when migrating (because self.site is not available).
358 # have to catch error when migrating (because self.site is not available).
362 begin
359 begin
363 if self.site==nil
360 if self.site==nil
364 self.site = Site.find_by_name('default')
361 self.site = Site.find_by_name('default')
365 if self.site==nil
362 if self.site==nil
366 self.site = Site.find(1) # when 'default has be renamed'
363 self.site = Site.find(1) # when 'default has be renamed'
367 end
364 end
368 end
365 end
369 rescue
366 rescue
370 end
367 end
371 end
368 end
372
369
373 def assign_default_contest
370 def assign_default_contest
374 # have to catch error when migrating (because self.site is not available).
371 # have to catch error when migrating (because self.site is not available).
375 begin
372 begin
376 if self.contests.length == 0
373 if self.contests.length == 0
377 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
374 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
378 if default_contest
375 if default_contest
379 self.contests = [default_contest]
376 self.contests = [default_contest]
380 end
377 end
381 end
378 end
382 rescue
379 rescue
383 end
380 end
384 end
381 end
385
382
386 def password_required?
383 def password_required?
387 self.hashed_password.blank? || !self.password.blank?
384 self.hashed_password.blank? || !self.password.blank?
388 end
385 end
389
386
390 def self.encrypt(string,salt)
387 def self.encrypt(string,salt)
391 Digest::SHA1.hexdigest(salt + string)
388 Digest::SHA1.hexdigest(salt + string)
392 end
389 end
393
390
394 def uniqueness_of_email_from_activated_users
391 def uniqueness_of_email_from_activated_users
395 user = User.activated_users.find_by_email(self.email)
392 user = User.activated_users.find_by_email(self.email)
396 if user and (user.login != self.login)
393 if user and (user.login != self.login)
397 self.errors.add(:base,"Email has already been taken")
394 self.errors.add(:base,"Email has already been taken")
398 end
395 end
399 end
396 end
400
397
401 def enough_time_interval_between_same_email_registrations
398 def enough_time_interval_between_same_email_registrations
402 return if !self.new_record?
399 return if !self.new_record?
403 return if self.activated
400 return if self.activated
404 open_user = User.find_by_email(self.email,
401 open_user = User.find_by_email(self.email,
405 :order => 'created_at DESC')
402 :order => 'created_at DESC')
406 if open_user and open_user.created_at and
403 if open_user and open_user.created_at and
407 (open_user.created_at > Time.now.gmtime - 5.minutes)
404 (open_user.created_at > Time.now.gmtime - 5.minutes)
408 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
405 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
409 end
406 end
410 end
407 end
411
408
412 def email_validation?
409 def email_validation?
413 begin
410 begin
414 return VALIDATE_USER_EMAILS
411 return VALIDATE_USER_EMAILS
415 rescue
412 rescue
416 return false
413 return false
417 end
414 end
418 end
415 end
419 end
416 end
@@ -1,15 +1,15
1 %h1= "Task: #{@task.id}"
1 %h1= "Task: #{@task.id}"
2
2
3 %p
3 %p
4 User:
4 User:
5 = "#{@task.submission.user.login}"
5 = "#{@task.submission.user.login}"
6 %br/
6 %br/
7 Status:
7 Status:
8 = "#{@task.status_str} (at #{format_short_time(@task.updated_at)})"
8 = "#{@task.status_str} (at #{format_short_time(@task.updated_at)})"
9 %br/
9 %br/
10 = "Submission: #{@task.submission_id}"
10 = "Submission: #{@task.submission_id}"
11 - if @task.submission !=nil
11 - if @task.submission !=nil
12 - = link_to '[view submission]', :action => 'submission', :id => @task.submission.id
12 + = link_to '[view submission]', submission_path( @task.submission.id )
13 %br/
13 %br/
14 = "Submitted at: #{format_short_time(@task.created_at)}"
14 = "Submitted at: #{format_short_time(@task.created_at)}"
15 %br/
15 %br/
@@ -1,72 +1,73
1 %p
1 %p
2 %b Name:
2 %b Name:
3 = @group.name
3 = @group.name
4 %p
4 %p
5 %b Description:
5 %b Description:
6 = @group.description
6 = @group.description
7
7
8 %br
8 %br
9 = link_to 'Edit', edit_group_path(@group)
9 = link_to 'Edit', edit_group_path(@group)
10 \|
10 \|
11 = link_to 'Back', groups_path
11 = link_to 'Back', groups_path
12
12
13 .row
13 .row
14 - %h1 Group details
14 + .col-md-12
15 + %h1 Group details
15 .row
16 .row
16 .col-md-6
17 .col-md-6
17 .panel.panel-default
18 .panel.panel-default
18 .panel-heading
19 .panel-heading
19 .panel-title Users in this group
20 .panel-title Users in this group
20 .panel-body
21 .panel-body
21 =form_tag add_user_group_path(@group), class: 'form-inline' do
22 =form_tag add_user_group_path(@group), class: 'form-inline' do
22 .form-group
23 .form-group
23 =label_tag :user_id, "User"
24 =label_tag :user_id, "User"
24 =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2'
25 =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2'
25 =submit_tag "Add",class: 'btn btn-primary'
26 =submit_tag "Add",class: 'btn btn-primary'
26
27
27
28
28 %table.table.table-hover
29 %table.table.table-hover
29 %thead
30 %thead
30 %tr
31 %tr
31 %th Login
32 %th Login
32 %th Full name
33 %th Full name
33 %th Remark
34 %th Remark
34 - %th
35 + %th= link_to 'Remove All', remove_all_user_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL USERS from group?" }, class: 'btn btn-danger btn-sm'
35
36
36 %tbody
37 %tbody
37 - @group.users.each do |user|
38 - @group.users.each do |user|
38 %tr
39 %tr
39 %td= user.login
40 %td= user.login
40 %td= user.full_name
41 %td= user.full_name
41 %td= user.remark
42 %td= user.remark
42 - %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger'
43 + %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger btn-sm'
43 .col-md-6
44 .col-md-6
44 .panel.panel-default
45 .panel.panel-default
45 .panel-heading
46 .panel-heading
46 .panel-title Problems
47 .panel-title Problems
47 .panel-body
48 .panel-body
48
49
49 =form_tag add_problem_group_path(@group), class: 'form-inline' do
50 =form_tag add_problem_group_path(@group), class: 'form-inline' do
50 .form-group
51 .form-group
51 =label_tag :problem_id, "Problem"
52 =label_tag :problem_id, "Problem"
52 =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2'
53 =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2'
53 =submit_tag "Add",class: 'btn btn-primary'
54 =submit_tag "Add",class: 'btn btn-primary'
54
55
55
56
56 %table.table.table-hover
57 %table.table.table-hover
57 %thead
58 %thead
58 %tr
59 %tr
59 %th name
60 %th name
60 %th Full name
61 %th Full name
61 %th Full score
62 %th Full score
62 - %th
63 + %th= link_to 'Remove All', remove_all_problem_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL PROBLEMS from group?" }, class: 'btn btn-danger btn-sm'
63
64
64 %tbody
65 %tbody
65 - @group.problems.each do |problem|
66 - @group.problems.each do |problem|
66 %tr
67 %tr
67 %td= problem.name
68 %td= problem.name
68 %td= problem.full_name
69 %td= problem.full_name
69 %td= problem.full_score
70 %td= problem.full_score
70 - %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger'
71 + %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger btn-sm'
71
72
72
73
@@ -1,54 +1,60
1 - content_for :head do
1 - content_for :head do
2 = stylesheet_link_tag 'problems'
2 = stylesheet_link_tag 'problems'
3 %h1 Problems
3 %h1 Problems
4 %p
4 %p
5 = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-success btn-sm'
5 = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-success btn-sm'
6 = link_to 'New problem', new_problem_path, class: 'btn btn-success btn-sm'
6 = link_to 'New problem', new_problem_path, class: 'btn btn-success btn-sm'
7 = link_to 'Bulk Manage', { action: 'manage'}, class: 'btn btn-info btn-sm'
7 = link_to 'Bulk Manage', { action: 'manage'}, class: 'btn btn-info btn-sm'
8 = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm'
8 = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm'
9 = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm'
9 = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm'
10 .submitbox
10 .submitbox
11 = form_tag :action => 'quick_create' do
11 = form_tag :action => 'quick_create' do
12 %b Quick New:
12 %b Quick New:
13 %label{:for => "problem_name"} Name
13 %label{:for => "problem_name"} Name
14 = text_field 'problem', 'name'
14 = text_field 'problem', 'name'
15 |
15 |
16 %label{:for => "problem_full_name"} Full name
16 %label{:for => "problem_full_name"} Full name
17 = text_field 'problem', 'full_name'
17 = text_field 'problem', 'full_name'
18 = submit_tag "Create"
18 = submit_tag "Create"
19 %table.table.table-condense.table-hover
19 %table.table.table-condense.table-hover
20 %thead
20 %thead
21 %th Name
21 %th Name
22 %th Full name
22 %th Full name
23 %th.text-right Full score
23 %th.text-right Full score
24 + %th
25 + Submit
26 + %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Admin can always submit to any problem' } [?]
24 %th Date added
27 %th Date added
25 %th.text-center
28 %th.text-center
26 Avail?
29 Avail?
27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
30 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
28 %th.text-center
31 %th.text-center
29 View Data?
32 View Data?
30 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
33 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
31 %th.text-center
34 %th.text-center
32 Test?
35 Test?
33 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
36 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
34 - if GraderConfiguration.multicontests?
37 - if GraderConfiguration.multicontests?
35 %th Contests
38 %th Contests
36 - for problem in @problems
39 - for problem in @problems
37 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
40 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
38 - @problem=problem
41 - @problem=problem
39 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
42 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
40 - %td= problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
43 + %td
44 + = problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
45 + = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
41 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
46 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
47 + %td= link_to "Submit", direct_edit_problem_submissions_path(problem), class: 'btn btn-xs btn-primary'
42 %td= problem.date_added
48 %td= problem.date_added
43 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
49 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
44 %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
50 %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
45 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
51 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
46 - if GraderConfiguration.multicontests?
52 - if GraderConfiguration.multicontests?
47 %td
53 %td
48 = problem.contests.collect { |c| c.name }.join(', ')
54 = problem.contests.collect { |c| c.name }.join(', ')
49 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
55 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
50 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
56 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
51 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
57 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
52 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
58 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
53 %br/
59 %br/
54 = link_to '[New problem]', :action => 'new'
60 = link_to '[New problem]', :action => 'new'
@@ -1,108 +1,113
1 CafeGrader::Application.routes.draw do
1 CafeGrader::Application.routes.draw do
2 get "sources/direct_edit"
2 get "sources/direct_edit"
3
3
4 root :to => 'main#login'
4 root :to => 'main#login'
5
5
6 #logins
6 #logins
7 get 'login/login', to: 'login#login'
7 get 'login/login', to: 'login#login'
8
8
9 resources :contests
9 resources :contests
10
10
11 resources :sites
11 resources :sites
12
12
13 resources :announcements do
13 resources :announcements do
14 member do
14 member do
15 get 'toggle','toggle_front'
15 get 'toggle','toggle_front'
16 end
16 end
17 end
17 end
18
18
19 resources :problems do
19 resources :problems do
20 member do
20 member do
21 get 'toggle'
21 get 'toggle'
22 get 'toggle_test'
22 get 'toggle_test'
23 get 'toggle_view_testcase'
23 get 'toggle_view_testcase'
24 get 'stat'
24 get 'stat'
25 end
25 end
26 collection do
26 collection do
27 get 'turn_all_off'
27 get 'turn_all_off'
28 get 'turn_all_on'
28 get 'turn_all_on'
29 get 'import'
29 get 'import'
30 get 'manage'
30 get 'manage'
31 end
31 end
32 end
32 end
33
33
34 resources :groups do
34 resources :groups do
35 member do
35 member do
36 post 'add_user', to: 'groups#add_user', as: 'add_user'
36 post 'add_user', to: 'groups#add_user', as: 'add_user'
37 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
37 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
38 + delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
38 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
39 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
39 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
40 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
41 + delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
42 + end
43 + collection do
44 +
40 end
45 end
41 end
46 end
42
47
43 resources :testcases, only: [] do
48 resources :testcases, only: [] do
44 member do
49 member do
45 get 'download_input'
50 get 'download_input'
46 get 'download_sol'
51 get 'download_sol'
47 end
52 end
48 collection do
53 collection do
49 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
54 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
50 end
55 end
51 end
56 end
52
57
53 resources :grader_configuration, controller: 'configurations'
58 resources :grader_configuration, controller: 'configurations'
54
59
55 resources :users do
60 resources :users do
56 member do
61 member do
57 get 'toggle_activate', 'toggle_enable'
62 get 'toggle_activate', 'toggle_enable'
58 get 'stat'
63 get 'stat'
59 end
64 end
60 end
65 end
61
66
62 resources :submissions do
67 resources :submissions do
63 member do
68 member do
64 get 'download'
69 get 'download'
65 get 'compiler_msg'
70 get 'compiler_msg'
66 get 'rejudge'
71 get 'rejudge'
67 end
72 end
68 collection do
73 collection do
69 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
74 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
70 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
75 get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
71 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
76 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
72 end
77 end
73 end
78 end
74
79
75
80
76
81
77 #main
82 #main
78 get "main/list"
83 get "main/list"
79 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
84 get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
80
85
81 #user admin
86 #user admin
82 get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
87 get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
83 post 'user_admin', to: 'user_admin#create'
88 post 'user_admin', to: 'user_admin#create'
84 delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
89 delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
85
90
86 #report
91 #report
87 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
92 get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
88 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
93 get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
89 get "report/login"
94 get "report/login"
90 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
95 get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
91 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
96 post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
92
97
93
98
94 #
99 #
95 get 'tasks/view/:file.:ext' => 'tasks#view'
100 get 'tasks/view/:file.:ext' => 'tasks#view'
96 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
101 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
97 get 'heartbeat/:id/edit' => 'heartbeat#edit'
102 get 'heartbeat/:id/edit' => 'heartbeat#edit'
98
103
99 #grader
104 #grader
100 get 'graders/list', to: 'graders#list', as: 'grader_list'
105 get 'graders/list', to: 'graders#list', as: 'grader_list'
101
106
102
107
103 # See how all your routes lay out with "rake routes"
108 # See how all your routes lay out with "rake routes"
104
109
105 # This is a legacy wild controller route that's not recommended for RESTful applications.
110 # This is a legacy wild controller route that's not recommended for RESTful applications.
106 # Note: This route will make all actions in every controller accessible via GET requests.
111 # Note: This route will make all actions in every controller accessible via GET requests.
107 match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
112 match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
108 end
113 end
deleted file
You need to be logged in to leave comments. Login now