Merge remote-tracking branch 'origin/master' into exercise-anomaly-detection
# Conflicts: # Capfile # Gemfile.lock # db/schema.rb
This commit is contained in:
@ -9,7 +9,7 @@ module SubmissionScoring
|
||||
assessment = assessor.assess(output)
|
||||
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0))
|
||||
testrun_output = passed ? nil : 'message: ' + output[:message].to_s + "\n stdout: " + output[:stdout].to_s + "\n stderr: " + output[:stderr].to_s
|
||||
if !testrun_output.blank?
|
||||
unless testrun_output.blank?
|
||||
submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(testrun_output)
|
||||
@ -47,6 +47,14 @@ module SubmissionScoring
|
||||
end
|
||||
end
|
||||
submission.update(score: score)
|
||||
if submission.normalized_score == 1.0
|
||||
Thread.new do
|
||||
RequestForComment.where(exercise_id: submission.exercise_id, user_id: submission.user_id, user_type: submission.user_type).each{ |rfc|
|
||||
rfc.full_score_reached = true
|
||||
rfc.save
|
||||
}
|
||||
end
|
||||
end
|
||||
outputs
|
||||
end
|
||||
end
|
||||
|
@ -416,6 +416,9 @@ class ExercisesController < ApplicationController
|
||||
flash[:notice] = I18n.t('exercises.submit.full_score_redirect_to_rfc')
|
||||
flash.keep(:notice)
|
||||
|
||||
# increase counter 'times_featured' in rfc
|
||||
rfc.increment!(:times_featured)
|
||||
|
||||
respond_to do |format|
|
||||
format.html {redirect_to(rfc)}
|
||||
format.json {render(json: {redirect: url_for(rfc)})}
|
||||
|
@ -14,46 +14,40 @@ class RequestForCommentsController < ApplicationController
|
||||
def index
|
||||
@search = RequestForComment
|
||||
.last_per_user(2)
|
||||
.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" on comments.file_id = f.id')
|
||||
.group('request_for_comments.id, request_for_comments.user_id, request_for_comments.exercise_id,
|
||||
request_for_comments.file_id, request_for_comments.question, request_for_comments.created_at,
|
||||
request_for_comments.updated_at, request_for_comments.user_type, request_for_comments.solved,
|
||||
request_for_comments.submission_id, request_for_comments.row_number') # ugly, but rails wants it this way
|
||||
.select('request_for_comments.*, max(comments.updated_at) as last_comment')
|
||||
.with_last_activity
|
||||
.search(params[:q])
|
||||
@request_for_comments = @search.result.order('created_at DESC').paginate(page: params[:page], total_entries: @search.result.length)
|
||||
@request_for_comments = @search.result
|
||||
.order('created_at DESC')
|
||||
.paginate(page: params[:page], total_entries: @search.result.length)
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /my_request_for_comments
|
||||
def get_my_comment_requests
|
||||
@search = RequestForComment
|
||||
.with_last_activity
|
||||
.where(user_id: current_user.id)
|
||||
.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" on comments.file_id = f.id')
|
||||
.group('request_for_comments.id')
|
||||
.select('request_for_comments.*, max(comments.updated_at) as last_comment')
|
||||
.search(params[:q])
|
||||
@request_for_comments = @search.result.order('created_at DESC').paginate(page: params[:page])
|
||||
@request_for_comments = @search.result
|
||||
.order('created_at DESC')
|
||||
.paginate(page: params[:page])
|
||||
render 'index'
|
||||
end
|
||||
|
||||
# GET /my_rfc_activity
|
||||
def get_rfcs_with_my_comments
|
||||
@search = RequestForComment
|
||||
.with_last_activity
|
||||
.joins(:comments) # we don't need to outer join here, because we know the user has commented on these
|
||||
.where(comments: {user_id: current_user.id})
|
||||
.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" as c on c.file_id = f.id')
|
||||
.group('request_for_comments.id')
|
||||
.select('request_for_comments.*, max(c.updated_at) as last_comment')
|
||||
.search(params[:q])
|
||||
@request_for_comments = @search.result.order('last_comment DESC').paginate(page: params[:page])
|
||||
@request_for_comments = @search.result
|
||||
.order('last_comment DESC')
|
||||
.paginate(page: params[:page])
|
||||
render 'index'
|
||||
end
|
||||
|
||||
# GET /request_for_comments/1/mark_as_solved
|
||||
def mark_as_solved
|
||||
authorize!
|
||||
@request_for_comment.solved = true
|
||||
@ -66,6 +60,7 @@ class RequestForCommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# POST /request_for_comments/1/set_thank_you_note
|
||||
def set_thank_you_note
|
||||
authorize!
|
||||
@request_for_comment.thank_you_note = params[:note]
|
||||
@ -82,10 +77,6 @@ class RequestForCommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def submit
|
||||
|
||||
end
|
||||
|
||||
# GET /request_for_comments/1
|
||||
# GET /request_for_comments/1.json
|
||||
def show
|
||||
@ -146,10 +137,6 @@ class RequestForCommentsController < ApplicationController
|
||||
authorize!
|
||||
end
|
||||
|
||||
def comment_params
|
||||
params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_request_for_comment
|
||||
@ -162,4 +149,8 @@ class RequestForCommentsController < ApplicationController
|
||||
params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved, :submission_id).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
|
||||
def comment_params
|
||||
params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -202,21 +202,11 @@ class SubmissionsController < ApplicationController
|
||||
tubesock.close
|
||||
end
|
||||
|
||||
def extract_errors
|
||||
if !@message_buffer.blank?
|
||||
@submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(@message_buffer)
|
||||
StructuredError.create_from_template(template, @message_buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def handle_message(message, tubesock, container)
|
||||
@run_output ||= ""
|
||||
@raw_output ||= ''
|
||||
@run_output ||= ''
|
||||
# Handle special commands first
|
||||
if (/^#exit/.match(message))
|
||||
if /^#exit/.match(message)
|
||||
# Just call exit_container on the docker_client.
|
||||
# Do not call kill_socket for the websocket to the client here.
|
||||
# @docker_client.exit_container closes the socket to the container,
|
||||
@ -228,17 +218,17 @@ class SubmissionsController < ApplicationController
|
||||
# Filter out information about run_command, test_command, user or working directory
|
||||
run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename])
|
||||
test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename])
|
||||
if !(/root|workspace|#{run_command}|#{test_command}/.match(message))
|
||||
unless /root|workspace|#{run_command}|#{test_command}/.match(message)
|
||||
parse_message(message, 'stdout', tubesock)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_message(message, output_stream, socket, recursive = true)
|
||||
parsed = '';
|
||||
parsed = ''
|
||||
begin
|
||||
parsed = JSON.parse(message)
|
||||
if(parsed.class == Hash && parsed.key?('cmd'))
|
||||
if parsed.class == Hash and parsed.key?('cmd')
|
||||
socket.send_data message
|
||||
Rails.logger.info('parse_message sent: ' + message)
|
||||
else
|
||||
@ -248,24 +238,24 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
rescue JSON::ParserError => e
|
||||
# Check wether the message contains multiple lines, if true try to parse each line
|
||||
if ((recursive == true) && (message.include? "\n"))
|
||||
if recursive and message.include? "\n"
|
||||
for part in message.split("\n")
|
||||
self.parse_message(part,output_stream,socket,false)
|
||||
end
|
||||
elsif(message.include? "<img")
|
||||
elsif message.include? '<img'
|
||||
#Rails.logger.info('img foung')
|
||||
@buffering = true
|
||||
@buffer = ""
|
||||
@buffer = ''
|
||||
@buffer += message
|
||||
#Rails.logger.info('Starting to buffer')
|
||||
elsif(@buffering && (message.include? "/>"))
|
||||
elsif @buffering and message.include? '/>'
|
||||
@buffer += message
|
||||
parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>@buffer}
|
||||
socket.send_data JSON.dump(parsed)
|
||||
#socket.send_data @buffer
|
||||
@buffering = false
|
||||
#Rails.logger.info('Sent complete buffer')
|
||||
elsif(@buffering)
|
||||
elsif @buffering
|
||||
@buffer += message
|
||||
#Rails.logger.info('Appending to buffer')
|
||||
else
|
||||
@ -275,18 +265,30 @@ class SubmissionsController < ApplicationController
|
||||
Rails.logger.info('parse_message sent: ' + JSON.dump(parsed))
|
||||
end
|
||||
ensure
|
||||
@raw_output += parsed['data'] if parsed.class == Hash and parsed.key? 'data'
|
||||
# save the data that was send to the run_output if there is enough space left. this will be persisted as a testrun with cause "run"
|
||||
@run_output += JSON.dump(parsed) if @run_output.size <= max_run_output_buffer_size
|
||||
end
|
||||
end
|
||||
|
||||
def save_run_output
|
||||
if !@run_output.blank?
|
||||
unless @run_output.blank?
|
||||
@run_output = @run_output[(0..max_run_output_buffer_size-1)] # trim the string to max_message_buffer_size chars
|
||||
Testrun.create(file: @file, cause: 'run', submission: @submission, output: @run_output)
|
||||
end
|
||||
end
|
||||
|
||||
def extract_errors
|
||||
unless @raw_output.blank?
|
||||
@submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(@raw_output)
|
||||
StructuredError.create_from_template(template, @raw_output, @submission)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def score
|
||||
hijack do |tubesock|
|
||||
Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?
|
||||
|
Reference in New Issue
Block a user