Description:
allow ta to set model submission
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r857:aa5ee227f493 - - 4 files changed: 13 inserted, 10 deleted

@@ -1,190 +1,190
1 1 require 'digest/sha1'
2 2 require 'net/pop'
3 3 require 'net/https'
4 4 require 'net/http'
5 5 require 'json'
6 6
7 7 class User < ActiveRecord::Base
8 8
9 9 has_and_belongs_to_many :roles
10 10
11 11 #has_and_belongs_to_many :groups
12 12 has_many :groups_users, class_name: 'GroupUser'
13 13 has_many :groups, :through => :groups_users
14 14
15 15 has_many :test_requests, -> {order(submitted_at: :desc)}
16 16
17 17 has_many :messages, -> { order(created_at: :desc) },
18 18 :class_name => "Message",
19 19 :foreign_key => "sender_id"
20 20
21 21 has_many :replied_messages, -> { order(created_at: :desc) },
22 22 :class_name => "Message",
23 23 :foreign_key => "receiver_id"
24 24
25 25 has_many :logins
26 26
27 27 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
28 28
29 29 belongs_to :site
30 30 belongs_to :country
31 31
32 32 has_and_belongs_to_many :contests, -> { order(:name)}
33 33
34 34 scope :activated_users, -> {where activated: true}
35 35
36 36 validates_presence_of :login
37 37 validates_uniqueness_of :login
38 38 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
39 39 validates_length_of :login, :within => 3..30
40 40
41 41 validates_presence_of :full_name
42 42 validates_length_of :full_name, :minimum => 1
43 43
44 44 validates_presence_of :password, :if => :password_required?
45 45 validates_length_of :password, :within => 4..50, :if => :password_required?
46 46 validates_confirmation_of :password, :if => :password_required?
47 47
48 48 validates_format_of :email,
49 49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
50 50 :if => :email_validation?
51 51 validate :uniqueness_of_email_from_activated_users,
52 52 :if => :email_validation?
53 53 validate :enough_time_interval_between_same_email_registrations,
54 54 :if => :email_validation?
55 55
56 56 # these are for ytopc
57 57 # disable for now
58 58 #validates_presence_of :province
59 59
60 60 attr_accessor :password
61 61
62 62 before_save :encrypt_new_password
63 63 before_save :assign_default_site
64 64 before_save :assign_default_contest
65 65
66 66 # this is for will_paginate
67 67 cattr_reader :per_page
68 68 @@per_page = 50
69 69
70 70 def self.authenticate(login, password)
71 71 user = find_by_login(login)
72 72 if user
73 73 return user if user.authenticated?(password)
74 74 end
75 75 end
76 76
77 77 def authenticated?(password)
78 78 if self.activated
79 79 hashed_password == User.encrypt(password,self.salt)
80 80 else
81 81 false
82 82 end
83 83 end
84 84
85 85 def login_with_name
86 86 "[#{login}] #{full_name}"
87 87 end
88 88
89 89 def admin?
90 90 has_role?('admin')
91 91 end
92 92
93 93 def has_role?(role)
94 - self.roles.where(name: role).count > 0
94 + self.roles.where(name: [role,'admin']).count > 0
95 95 end
96 96
97 97 def email_for_editing
98 98 if self.email==nil
99 99 "(unknown)"
100 100 elsif self.email==''
101 101 "(blank)"
102 102 else
103 103 self.email
104 104 end
105 105 end
106 106
107 107 def email_for_editing=(e)
108 108 self.email=e
109 109 end
110 110
111 111 def alias_for_editing
112 112 if self.alias==nil
113 113 "(unknown)"
114 114 elsif self.alias==''
115 115 "(blank)"
116 116 else
117 117 self.alias
118 118 end
119 119 end
120 120
121 121 def alias_for_editing=(e)
122 122 self.alias=e
123 123 end
124 124
125 125 def activation_key
126 126 if self.hashed_password==nil
127 127 encrypt_new_password
128 128 end
129 129 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
130 130 end
131 131
132 132 def verify_activation_key(key)
133 133 key == activation_key
134 134 end
135 135
136 136 def self.random_password(length=5)
137 137 chars = 'abcdefghjkmnopqrstuvwxyz'
138 138 password = ''
139 139 length.times { password << chars[rand(chars.length - 1)] }
140 140 password
141 141 end
142 142
143 143
144 144 # Contest information
145 145
146 146 def self.find_users_with_no_contest()
147 147 users = User.all
148 148 return users.find_all { |u| u.contests.length == 0 }
149 149 end
150 150
151 151
152 152 def contest_time_left
153 153 if GraderConfiguration.contest_mode?
154 154 return nil if site==nil
155 155 return site.time_left
156 156 elsif GraderConfiguration.indv_contest_mode?
157 157 time_limit = GraderConfiguration.contest_time_limit
158 158 if time_limit == nil
159 159 return nil
160 160 end
161 161 if contest_stat==nil or contest_stat.started_at==nil
162 162 return (Time.now.gmtime + time_limit) - Time.now.gmtime
163 163 else
164 164 finish_time = contest_stat.started_at + time_limit
165 165 current_time = Time.now.gmtime
166 166 if current_time > finish_time
167 167 return 0
168 168 else
169 169 return finish_time - current_time
170 170 end
171 171 end
172 172 else
173 173 return nil
174 174 end
175 175 end
176 176
177 177 def contest_finished?
178 178 if GraderConfiguration.contest_mode?
179 179 return false if site==nil
180 180 return site.finished?
181 181 elsif GraderConfiguration.indv_contest_mode?
182 182 return false if self.contest_stat==nil
183 183 return contest_time_left == 0
184 184 else
185 185 return false
186 186 end
187 187 end
188 188
189 189 def contest_started?
190 190 if GraderConfiguration.indv_contest_mode?
@@ -1,154 +1,156
1 1 :css
2 2 .hof_user { color: orangered; font-style: italic; }
3 3 .hof_language { color: green; font-style: italic; }
4 4 .hof_value { color: deeppink;font-style: italic; }
5 5 .info_param { font-weight: bold;text-align: right; }
6 6 .tooltip {
7 7 font-family: Verdana,sans-serif;
8 8 font-weight: normal;
9 9 text-align: left;
10 10 font-size: 1.0em;
11 11 color: black;
12 12 line-height: 1.1;
13 13 display: none;
14 14 min-width: 20em;
15 15 position: absolute;
16 16 left: 25px;
17 17 bottom: 5px;
18 18 border: 1px solid;
19 19 padding: 5px;
20 20 background-color: #FFF;
21 21 word-wrap: break-word;
22 22 z-index: 9999;
23 23 overflow: auto;
24 24 }
25 25
26 26
27 27 .container-fluid
28 28 .row
29 29 .col-md-8
30 30 .card
31 31 .card-body
32 32 %h2.card-title Submission History
33 33 %canvas#chart{height: '50px'}
34 34
35 35 .col-md-4
36 36 .card
37 37 .card-body
38 38 %h2.card-title General Info
39 39 .row
40 40 .col-sm-6
41 41 Subs
42 42 .col-sm-6
43 43 = @summary[:count]
44 44 .row
45 45 .col-sm-6
46 46 Solved/Attempted User
47 47 .col-sm-6
48 48 #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
49 49 .row
50 50 .col-md-4
51 51 .card
52 52 .card-body
53 53 %h2.card-title Model submission
54 54 %table.table.table-hover
55 55 %thead
56 56 %tr
57 - %th #Sub
57 + %th #Sub (lang)
58 58 %th Author
59 59 %tbody
60 60 - @model_subs.each do |sub|
61 61 %tr
62 - %td= link_to "##{sub.id}", submission_path(sub)
62 + %td
63 + = link_to "##{sub.id}", submission_path(sub)
64 + = "(#{sub.language.pretty_name})"
63 65 %td= sub.user.full_name
64 66 .col-md-8
65 67 - if @best
66 68 .card
67 69 .card-body
68 70 %h2.card-title Top Submissions
69 71 %table.table.table-hover
70 72 %thead
71 73 %tr
72 74 %th Language
73 75 %th Best runtime (ms)
74 76 %th Best memory (kbytes)
75 77 %th Shortest Code (bytes)
76 78 %th First solver
77 79 %tbody
78 80 %tr.bg-warning
79 81 %td
80 82 Overall
81 83 %td
82 84 by #{link_to @best[:runtime][:user], stat_user_path(@best[:runtime][:user_id])}
83 85 %br
84 86 using <span class="text-success">#{@best[:runtime][:lang]}</span>
85 87 %br
86 88 with <span class="text-success">#{@best[:runtime][:value] * 1000} milliseconds</span>
87 89 %br= link_to "#" + @best[:runtime][:sub_id].to_s, submission_path(@best[:runtime][:sub_id])
88 90 %td
89 91 by #{link_to @best[:memory][:user], stat_user_path(@best[:memory][:user_id])}
90 92 %br
91 93 using <span class="text-success">#{@best[:memory][:lang]}</span>
92 94 %br
93 95 with <span class="text-success">#{number_with_delimiter(@best[:memory][:value])} kbytes </span>
94 96 %br= link_to "#" + @best[:memory][:sub_id].to_s, submission_path(@best[:memory][:sub_id])
95 97 %td
96 98 by #{link_to @best[:length][:user], stat_user_path(@best[:length][:user_id])}
97 99 %br
98 100 using <span class="text-success">#{@best[:length][:lang]}</span>
99 101 %br
100 102 with <span class="text-success">#{@best[:length][:value]} bytes</span>
101 103 %br= link_to "#" + @best[:length][:sub_id].to_s, submission_path(@best[:length][:sub_id])
102 104 %td
103 105 - if @best[:first][:user] != '(NULL)'
104 106 #{link_to @best[:first][:user], stat_user_path(@best[:first][:user_id])} is the first solver
105 107 %br
106 108 using <span class="text-success">#{@best[:first][:lang]}</span>
107 109 %br
108 110 on <span class="text-success">#{@best[:first][:value]}</span>
109 111 %br= link_to "#" + @best[:first][:sub_id].to_s, submission_path( @best[:first][:sub_id])
110 112 - else
111 113 no first solver
112 114 - @by_lang.each do |lang,value|
113 115 %tr
114 116 %td= lang
115 117 %td
116 118 = link_to value[:runtime][:user], stat_user_path(value[:runtime][:user_id])
117 119 %br
118 120 = "#{(value[:runtime][:value] * 1000).to_i} @"
119 121 = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id])
120 122 %td
121 123 = link_to value[:memory][:user], stat_user_path( value[:memory][:user_id])
122 124 %br
123 125 = "#{number_with_delimiter(value[:memory][:value])} @"
124 126 = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id])
125 127 %td
126 128 = link_to value[:length][:user], stat_user_path(value[:length][:user_id])
127 129 %br
128 130 = "#{value[:length][:value]} @"
129 131 = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id])
130 132 %td
131 133 - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
132 134 = link_to value[:first][:user], stat_user_path(value[:first][:user_id])
133 135 %br
134 136 = "#{value[:first][:value]} @"
135 137 = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id])
136 138
137 139 %script{src:"https://cdn.jsdelivr.net/npm/chart.js"}
138 140 :javascript
139 141 data = #{@chart_dataset}
140 142 config = {
141 143 type: 'bar',
142 144 data: data,
143 145 options: {
144 146 plugins: {
145 147 legend: {
146 148 display: false
147 149 },
148 150 },
149 151 }
150 152 }
151 153 Chart.defaults.font.size = 15
152 154 //Chart.defaults.font.family = 'Sarabun Light'
153 155 chart = new Chart($('#chart'),config)
154 156
@@ -1,29 +1,30
1 1
2 2 /- if params[:id]
3 3 / %h1 Tasks Hall of Fame
4 4 / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
5 5 /- else
6 6 / %h1 All-Time Hall of Fame
7 7
8 8 .panel.panel-info
9 9 .panel-heading
10 10 Select Task
11 11 .panel-body
12 12 .form-inline
13 13 = select 'report',
14 14 'problem_id',
15 15 @problems.collect {|p| ["[#{p.name}] #{p.full_name}", problem_hof_report_path(p)]},
16 16 {:selected => problem_hof_report_path(@problem)},
17 17 { class: 'select2 form-control' }
18 18 %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: "#report_problem_id"}} Go
19 19
20 20
21 21 - unless params[:id]
22 22 /=render partial: 'all_time_hof'
23 23 Please select a problem.
24 24 - else
25 - %h1 [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name}
26 - -# %h2 Submission History
27 - -# =render partial: 'application/bar_graph', locals: { histogram: @histogram }
25 + %h1
26 + [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name}
27 + - if @current_user.has_role?('ta')
28 + %a{href:stat_problem_path(@problem)} (stat)
28 29 =render partial: 'task_hof'
29 30
@@ -1,128 +1,128
1 1 %h1= "Submission: #{@submission.id}"
2 2
3 3 %textarea#data{style: "display:none;"}
4 4 :preserve
5 5 #{@submission.source}
6 6
7 7 //%div.highlight{:style => "border: 1px solid black;"}
8 8 //=@formatted_code.html_safe
9 9
10 10
11 11 .containter
12 12 .row
13 13 .col-md-7
14 14 %h2 Source Code
15 15 .col-md-5
16 16 %h2 Stat
17 17 .row
18 18 .col-md-7
19 19 %div#editor{ style: "font-size: 14px; height: 400px; border-radius:5px;" }
20 20 :javascript
21 21 e = ace.edit("editor")
22 22 e.setOptions({ maxLines: Infinity })
23 23 e.setValue($("#data").text())
24 24 e.gotoLine(1)
25 25 e.getSession().setMode("#{get_ace_mode(@submission.language)}")
26 26 e.setReadOnly(true)
27 27 .col-md-5
28 28 %table.table.table-striped
29 29 %tr
30 30 %td.text-right
31 31 %strong User
32 32 %td
33 33 - if @current_user.admin? ||@current_user == @submission.user
34 34 - if @submission.user
35 35 = link_to "#{@submission.user.login}", stat_user_path(@submission.user)
36 36 = @submission.user.full_name
37 37 - else
38 38 = "(n/a)"
39 39 - else
40 40 = '-- REDACTED --'
41 41 %tr
42 42 %td.text-right
43 43 %strong Task
44 44 %td
45 45 - if @submission.problem!=nil
46 46 = link_to "[#{@submission.problem.name}]", stat_problem_path(@submission.problem)
47 47 = @submission.problem.full_name
48 48 = link_to_description_if_any "[download] <span class='glyphicon glyphicon-file'></span>".html_safe, @submission.problem
49 49 - else
50 50 = "(n/a)"
51 51 %tr
52 52 %td.text-right
53 53 %strong Tries
54 54 %td= @submission.number
55 55 %tr
56 56 %td.text-right
57 57 %strong Language
58 58 %td= @submission.language.pretty_name
59 59 %tr
60 60 %td.text-right
61 61 %strong Submitted
62 62 %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)})
63 63 %tr
64 64 %td.text-right
65 65 %strong Graded
66 66 - if @submission.graded_at
67 67 %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)})
68 68 - else
69 69 %td -
70 70 %tr
71 71 %td.text-right
72 72 %strong Points
73 73 %td #{@submission.points}/#{@submission.try(:problem).try(:full_score)}
74 74 %tr
75 75 %td.text-right
76 76 %strong Comment
77 77 %td #{@submission.grader_comment}
78 78 %tr
79 79 %td.text-right
80 80 %strong Runtime (s)
81 81 %td #{@submission.max_runtime}
82 82 %tr
83 83 %td.text-right
84 84 %strong Memory (kb)
85 85 %td #{@submission.peak_memory}
86 86 %tr
87 87 %td.text-right
88 88 %strong Compiler result
89 89 %td
90 90 %button.btn.btn-info.btn-xs{type: 'button', data: {toggle: 'modal', target: '#compiler'}}
91 91 view
92 92 %tr
93 93 %td.text-right
94 94 %strong Grading Task Status
95 95 %td
96 96 = @task.status_str if @task
97 - - if session[:admin]
97 + - if @current_user.admin?
98 98 = link_to "rejudge", rejudge_submission_path, data: {remote: true}, class: 'btn btn-info btn-xs'
99 - - if session[:admin]
99 + - if @current_user.has_role?('ta')
100 100 %tr
101 101 %td.text-right
102 102 %strong IP
103 103 %td #{@submission.ip_address}
104 104 %tr
105 105 %td.text-right
106 106 %strong Model solution
107 107 %td
108 108 - if @submission.tag_model?
109 109 YES
110 - - if session[:admin]
110 + - if @current_user.has_role?('ta')
111 111 = link_to "remove model status", set_tag_submission_path(@submission, tag: :default), class: 'btn btn-warning btn-xs'
112 112 - else
113 113 No
114 - - if session[:admin]
114 + - if @current_user.has_role?('ta')
115 115 = link_to "set as model solution", set_tag_submission_path(@submission, tag: :model), class: 'btn btn-success btn-xs'
116 116
117 117
118 118 .modal.fade#compiler{tabindex: -1,role: 'dialog'}
119 119 .modal-dialog.modal-lg{role:'document'}
120 120 .modal-content
121 121 .modal-header
122 122 %button.close{type: 'button', data: {dismissed: :modal}, aria: {label: 'close'}}
123 123 %span{aria: {hidden: 'true'}, data: {dismiss: 'modal'}} &times;
124 124 %h4 Compiler message
125 125 .modal-body
126 126 %pre#compiler_msg= @submission.compiler_message
127 127 .modal-footer
128 128 %button.btn.btn-default{type: 'button', data: {dismiss: 'modal'}} Close
You need to be logged in to leave comments. Login now