Merge remote-tracking branch 'origin/master' into fix/exercise-anomaly-detection-nil-values
This commit is contained in:
@ -2,7 +2,7 @@ class JunitAdapter < TestingFrameworkAdapter
|
||||
COUNT_REGEXP = /Tests run: (\d+)/
|
||||
FAILURES_REGEXP = /Failures: (\d+)/
|
||||
SUCCESS_REGEXP = /OK \((\d+) test[s]?\)/
|
||||
ASSERTION_ERROR_REGEXP = /java\.lang\.AssertionError:\s(.*)|org\.junit\.ComparisonFailure:\s(.*)/
|
||||
ASSERTION_ERROR_REGEXP = /java\.lang\.AssertionError:?\s(.*?)\tat org.junit|org\.junit\.ComparisonFailure:\s(.*?)\tat org.junit/m
|
||||
|
||||
def self.framework_name
|
||||
'JUnit'
|
||||
|
@ -21,51 +21,57 @@ namespace :detect_exercise_anomalies do
|
||||
WORKING_TIME_CACHE = {}
|
||||
AVERAGE_WORKING_TIME_CACHE = {}
|
||||
|
||||
task :with_at_least, [:number_of_exercises, :number_of_solutions] => :environment do |task, args|
|
||||
task :with_at_least, [:number_of_exercises, :number_of_users] => :environment do |task, args|
|
||||
include TimeHelper
|
||||
|
||||
number_of_exercises = args[:number_of_exercises]
|
||||
number_of_solutions = args[:number_of_solutions]
|
||||
number_of_users = args[:number_of_users]
|
||||
|
||||
puts "Searching for exercise collections with at least #{number_of_exercises} exercises and #{number_of_solutions} users."
|
||||
log "Searching for exercise collections with at least #{number_of_exercises} exercises and #{number_of_users} users."
|
||||
# Get all exercise collections that have at least the specified amount of exercises and at least the specified
|
||||
# number of submissions AND are flagged for anomaly detection
|
||||
collections = get_collections(number_of_exercises, number_of_solutions)
|
||||
puts "Found #{collections.length}."
|
||||
# number of users AND are flagged for anomaly detection
|
||||
collections = get_collections(number_of_exercises, number_of_users)
|
||||
log "Found #{collections.length}."
|
||||
|
||||
collections.each do |collection|
|
||||
puts "\t- #{collection}"
|
||||
log(collection, 1, '- ')
|
||||
anomalies = find_anomalies(collection)
|
||||
|
||||
if anomalies.length > 0 and not collection.user.nil?
|
||||
notify_collection_author(collection, anomalies)
|
||||
if anomalies.length > 0
|
||||
unless collection.user.nil?
|
||||
notify_collection_author(collection, anomalies)
|
||||
end
|
||||
notify_users(collection, anomalies)
|
||||
reset_anomaly_detection_flag(collection)
|
||||
end
|
||||
end
|
||||
puts 'Done.'
|
||||
log 'Done.'
|
||||
end
|
||||
|
||||
def log(message='', indent_level=0, prefix='')
|
||||
puts("\t" * indent_level + "#{prefix}#{message}")
|
||||
end
|
||||
|
||||
def get_collections(number_of_exercises, number_of_solutions)
|
||||
ExerciseCollection
|
||||
.where(:use_anomaly_detection => true)
|
||||
.joins("join exercise_collections_exercises ece on exercise_collections.id = ece.exercise_collection_id
|
||||
.joins("join exercise_collection_items eci on exercise_collections.id = eci.exercise_collection_id
|
||||
join
|
||||
(select e.id
|
||||
from exercises e
|
||||
join submissions s on s.exercise_id = e.id
|
||||
group by e.id
|
||||
having count(s.user_id) > #{ExerciseCollection.sanitize(number_of_solutions)}
|
||||
) as exercises_with_submissions on exercises_with_submissions.id = ece.exercise_id")
|
||||
) as exercises_with_submissions on exercises_with_submissions.id = eci.exercise_id")
|
||||
.group('exercise_collections.id')
|
||||
.having('count(exercises_with_submissions.id) > ?', number_of_exercises)
|
||||
end
|
||||
|
||||
def collect_working_times(collection)
|
||||
working_times = {}
|
||||
collection.exercises.each do |exercise|
|
||||
puts "\t\t> #{exercise.title}"
|
||||
working_times[exercise.id] = get_average_working_time(exercise)
|
||||
collection.exercise_collection_items.order(:position).each do |eci|
|
||||
log(eci.exercise.title, 2, '> ')
|
||||
working_times[eci.exercise.id] = get_average_working_time(eci.exercise)
|
||||
end
|
||||
working_times
|
||||
end
|
||||
@ -98,16 +104,16 @@ namespace :detect_exercise_anomalies do
|
||||
end
|
||||
|
||||
def notify_collection_author(collection, anomalies)
|
||||
puts "\t\tSending E-Mail to author (#{collection.user.displayname} <#{collection.user.email}>)..."
|
||||
log("Sending E-Mail to author (#{collection.user.displayname} <#{collection.user.email}>)...", 2)
|
||||
UserMailer.exercise_anomaly_detected(collection, anomalies).deliver_now
|
||||
end
|
||||
|
||||
def notify_users(collection, anomalies)
|
||||
by_id_and_type = proc { |u| {user_id: u[:user_id], user_type: u[:user_type]} }
|
||||
|
||||
puts "\t\tSending E-Mails to best and worst performing users of each anomaly..."
|
||||
log("Sending E-Mails to best and worst performing users of each anomaly...", 2)
|
||||
anomalies.each do |exercise_id, average_working_time|
|
||||
puts "\t\tAnomaly in exercise #{exercise_id} (avg: #{average_working_time} seconds):"
|
||||
log("Anomaly in exercise #{exercise_id} (avg: #{average_working_time} seconds):", 2)
|
||||
exercise = Exercise.find(exercise_id)
|
||||
users_to_notify = []
|
||||
|
||||
@ -135,7 +141,7 @@ namespace :detect_exercise_anomalies do
|
||||
feedback_link = url_for(action: :new, controller: :user_exercise_feedbacks, exercise_id: exercise.id, host: host)
|
||||
UserMailer.exercise_anomaly_needs_feedback(user, exercise, feedback_link).deliver
|
||||
end
|
||||
puts "\t\tAsked #{users_to_notify.size} users for feedback."
|
||||
log("Asked #{users_to_notify.size} users for feedback.", 2)
|
||||
end
|
||||
end
|
||||
|
||||
@ -159,7 +165,7 @@ namespace :detect_exercise_anomalies do
|
||||
end
|
||||
|
||||
def reset_anomaly_detection_flag(collection)
|
||||
puts "\t\tResetting flag..."
|
||||
log("Resetting flag...", 2)
|
||||
collection.use_anomaly_detection = false
|
||||
collection.save!
|
||||
end
|
||||
|
@ -31,4 +31,18 @@ class UserGroupSeparator
|
||||
:recommended_assignment
|
||||
end
|
||||
end
|
||||
|
||||
def self.getGroupExerciseDescriptionTesting(user)
|
||||
groupById = user.id % 4
|
||||
if groupById == 0
|
||||
:group_a
|
||||
elsif groupById == 1
|
||||
:group_b
|
||||
elsif groupById == 2
|
||||
:group_c
|
||||
else # 3
|
||||
:group_d
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Reference in New Issue
Block a user