Retrieve user statistics in an execution environment for all exercises at once

This commit is contained in:
Maximilian Grundke
2016-01-07 15:42:53 +01:00
parent f195607ba1
commit a508d47e3e
3 changed files with 42 additions and 8 deletions

View File

@ -55,14 +55,47 @@ class ExecutionEnvironmentsController < ApplicationController
"""
end
def user_query
"""
SELECT
id AS exercise_id,
COUNT(DISTINCT user_id) AS users,
AVG(score) AS average_score,
MAX(score) AS maximum_score,
CASE
WHEN MAX(score)=0 THEN 0
ELSE 100 / MAX(score) * AVG(score)
END AS percent_correct,
SUM(submission_count) / COUNT(DISTINCT user_id) AS average_submission_count
FROM
(SELECT e.id,
s.user_id,
MAX(s.score) AS score,
COUNT(s.id) AS submission_count
FROM submissions s
JOIN exercises e ON e.id = s.exercise_id
WHERE e.execution_environment_id = #{@execution_environment.id}
GROUP BY e.id,
s.user_id) AS inner_query
GROUP BY id;
"""
end
def statistics
working_time_statistics = {}
user_statistics = {}
ActiveRecord::Base.connection.execute(working_time_query).each do |tuple|
working_time_statistics[tuple["exercise_id"].to_i] = tuple
end
ActiveRecord::Base.connection.execute(user_query).each do |tuple|
user_statistics[tuple["exercise_id"].to_i] = tuple
end
render locals: {
working_time_statistics: working_time_statistics
working_time_statistics: working_time_statistics,
user_statistics: user_statistics
}
end

View File

@ -34,7 +34,7 @@ class Exercise < ActiveRecord::Base
def average_score
if submissions.exists?(cause: 'submit')
maximum_scores_query = submissions.select('MAX(score) AS maximum_score').where(cause: 'submit').group(:user_id).to_sql.sub('$1', id.to_s)
maximum_scores_query = submissions.select('MAX(score) AS maximum_score').group(:user_id).to_sql.sub('$1', id.to_s)
self.class.connection.execute("SELECT AVG(maximum_score) AS average_score FROM (#{maximum_scores_query}) AS maximum_scores").first['average_score'].to_f
else 0 end
end

View File

@ -8,14 +8,15 @@ h1 = @execution_environment
th.header = t(title)
tbody
- @execution_environment.exercises.each do |exercise|
- average_score = exercise.average_score
- us = user_statistics[exercise.id]
- if not us then us = {"users" => 0, "average_score" => 0.0, "maximum_score" => 0, "percent_correct" => nil, "average_submission_count" => 0}
- wts = working_time_statistics[exercise.id]
- if wts then average_time = wts["average_time"] else 0
tr
td = link_to exercise.title, controller: "exercises", action: "statistics", id: exercise.id
td = exercise.users.distinct.count
td = average_score
td = exercise.maximum_score
td = 100 / exercise.maximum_score * average_score
td = exercise.average_number_of_submissions
td = us["users"]
td = us["average_score"]
td = us["maximum_score"]
td = us["percent_correct"]
td = us["average_submission_count"]
td = average_time