From b20d13f86675cd99d53e9a29eba48689306ef08e Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 29 Oct 2015 10:15:40 +0100 Subject: [PATCH 001/106] Add statistics for exercises per user --- .gitignore | 1 + app/views/exercises/statistics.html.slim | 15 +++++++++++++++ config/locales/de.yml | 4 ++++ config/locales/en.yml | 4 ++++ 4 files changed, 24 insertions(+) diff --git a/.gitignore b/.gitignore index 4e183355..89d0de42 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ /rubocop.html /tmp /vagrant/ +/.vagrant *.sublime-* /.idea /.vagrant diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index 77ab091d..c044004a 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -7,3 +7,18 @@ h1 = @exercise = row(label: '.average_score') do p == @exercise.average_score ? t('shared.out_of', maximum_value: @exercise.maximum_score, value: @exercise.average_score.round(2)) : empty p = progress_bar(@exercise.average_percentage) + +.table-responsive + table.table + thead + tr + - ['.user', '.score', '.runs', '.worktime'].each do |title| + th.header = t(title) + tbody + - @exercise.users.each do |user| + tr + - submissions = @exercise.submissions.where('user_id=?', user.id) + td = "#{user.name} (#{user.email})" + td = submissions.maximum('score') + td = submissions.count('id') + td = "#{((submissions.maximum('created_at') - submissions.minimum('created_at')) / 60).round(2)} min" diff --git a/config/locales/de.yml b/config/locales/de.yml index aaedd678..871decd9 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -239,6 +239,10 @@ de: intermediate_submissions: Intermediäre Abgaben participants: Bearbeitende Nutzer users: '%{count} verschiedene Nutzer' + user: 'Nutzer' + score: 'Punktzahl' + runs: 'Versuche' + worktime: 'Arbeitszeit' submit: failure: Beim Übermitteln Ihrer Punktzahl ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut. files: diff --git a/config/locales/en.yml b/config/locales/en.yml index 5baed464..7c28ae29 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -239,6 +239,10 @@ en: intermediate_submissions: Intermediate Submissions participants: Participating Users users: '%{count} distinct users' + user: 'User' + score: 'Score' + runs: 'Runs' + worktime: 'Worktime' submit: failure: An error occured while transmitting your score. Please try again later. files: From 22da25be60312de478850c77fcc449008c68f6c5 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 29 Oct 2015 10:45:43 +0100 Subject: [PATCH 002/106] Output time in readable format --- app/views/exercises/statistics.html.slim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index c044004a..d76f7b61 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -21,4 +21,5 @@ h1 = @exercise td = "#{user.name} (#{user.email})" td = submissions.maximum('score') td = submissions.count('id') - td = "#{((submissions.maximum('created_at') - submissions.minimum('created_at')) / 60).round(2)} min" + - seconds = submissions.maximum('created_at') - submissions.minimum('created_at') + td = "#{distance_of_time_in_words(seconds)} (#{seconds})" From 78422647fe40b007b3942cd142b9936193c4b0a8 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 29 Oct 2015 14:19:31 +0100 Subject: [PATCH 003/106] Add execution environment statistics --- Gemfile.lock | 3 --- .../execution_environments_controller.rb | 5 +++- app/policies/execution_environment_policy.rb | 2 +- .../execution_environments/index.html.slim | 3 ++- .../statistics.html.slim | 23 +++++++++++++++++++ config/locales/de.yml | 5 ++++ config/locales/en.yml | 13 +++++++---- config/routes.rb | 1 + .../execution_environments_controller_spec.rb | 8 +++++++ 9 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 app/views/execution_environments/statistics.html.slim diff --git a/Gemfile.lock b/Gemfile.lock index d27789ea..0492a3e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -392,6 +392,3 @@ DEPENDENCIES uglifier (>= 1.3.0) web-console (~> 2.0) will_paginate (~> 3.0) - -BUNDLED WITH - 1.10.6 diff --git a/app/controllers/execution_environments_controller.rb b/app/controllers/execution_environments_controller.rb index 5e69f8fc..574aaed7 100644 --- a/app/controllers/execution_environments_controller.rb +++ b/app/controllers/execution_environments_controller.rb @@ -2,7 +2,7 @@ class ExecutionEnvironmentsController < ApplicationController include CommonBehavior before_action :set_docker_images, only: [:create, :edit, :new, :update] - before_action :set_execution_environment, only: MEMBER_ACTIONS + [:execute_command, :shell] + before_action :set_execution_environment, only: MEMBER_ACTIONS + [:execute_command, :shell, :statistics] before_action :set_testing_framework_adapters, only: [:create, :edit, :new, :update] def authorize! @@ -28,6 +28,9 @@ class ExecutionEnvironmentsController < ApplicationController render(json: @docker_client.execute_arbitrary_command(params[:command])) end + def statistics + end + def execution_environment_params params[:execution_environment].permit(:docker_image, :exposed_ports, :editor_mode, :file_extension, :file_type_id, :help, :indent_size, :memory_limit, :name, :network_enabled, :permitted_execution_time, :pool_size, :run_command, :test_command, :testing_framework).merge(user_id: current_user.id, user_type: current_user.class.name) end diff --git a/app/policies/execution_environment_policy.rb b/app/policies/execution_environment_policy.rb index 3766f714..bccc9a07 100644 --- a/app/policies/execution_environment_policy.rb +++ b/app/policies/execution_environment_policy.rb @@ -4,7 +4,7 @@ class ExecutionEnvironmentPolicy < AdminOrAuthorPolicy end private :author? - [:execute_command?, :shell?].each do |action| + [:execute_command?, :shell?, :statistics?].each do |action| define_method(action) { admin? || author? } end end diff --git a/app/views/execution_environments/index.html.slim b/app/views/execution_environments/index.html.slim index 7ed2cebb..0ccb880c 100644 --- a/app/views/execution_environments/index.html.slim +++ b/app/views/execution_environments/index.html.slim @@ -9,7 +9,7 @@ h1 = ExecutionEnvironment.model_name.human(count: 2) th = t('activerecord.attributes.execution_environment.memory_limit') th = t('activerecord.attributes.execution_environment.network_enabled') th = t('activerecord.attributes.execution_environment.permitted_execution_time') - th colspan=4 = t('shared.actions') + th colspan=5 = t('shared.actions') th colspan=2 = t('shared.resources') tbody - @execution_environments.each do |execution_environment| @@ -23,6 +23,7 @@ h1 = ExecutionEnvironment.model_name.human(count: 2) td = link_to(t('shared.edit'), edit_execution_environment_path(execution_environment)) td = link_to(t('shared.destroy'), execution_environment, data: {confirm: t('shared.confirm_destroy')}, method: :delete) td = link_to(t('.shell'), shell_execution_environment_path(execution_environment)) + td = link_to(t('shared.statistics'), statistics_execution_environment_path(execution_environment)) td = link_to(t('activerecord.models.error.other'), execution_environment_errors_path(execution_environment.id)) td = link_to(t('activerecord.models.hint.other'), execution_environment_hints_path(execution_environment.id)) diff --git a/app/views/execution_environments/statistics.html.slim b/app/views/execution_environments/statistics.html.slim new file mode 100644 index 00000000..111c6d29 --- /dev/null +++ b/app/views/execution_environments/statistics.html.slim @@ -0,0 +1,23 @@ +h1 = @execution_environment + +.table-responsive + table.table + thead + tr + - ['.exercise', '.score', '.runs', '.worktime'].each do |title| + th.header = t(title) + tbody + - @execution_environment.exercises.each do |exercise| + tr + - submissions = exercise.submissions + td = exercise.title + td = submissions.average(:score) + td = submissions.count() + - minima = submissions.group(:user_id).minimum(:created_at) + - maxima = submissions.group(:user_id).maximum(:created_at) + - result = 0 + - results = {} + - maxima.each {|key, value| results[key] = value - minima[key]} + - results.values.map {|value| result += value} + - result /= results.size if results.size > 0 + td = distance_of_time_in_words(result) diff --git a/config/locales/de.yml b/config/locales/de.yml index 9716a9a0..12b3df92 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -167,6 +167,11 @@ de: shell: command: Befehl headline: Shell + statistics: + exercise: Übung + score: Durchschnittliche Punktzahl + runs: Durchschnittliche Anzahl von Versuchen + worktime: Durchschnittliche Arbeitszeit exercises: editor: confirm_start_over: Wollen Sie wirklich von vorne anfangen? diff --git a/config/locales/en.yml b/config/locales/en.yml index 164082df..771d5a00 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -167,6 +167,11 @@ en: shell: command: Command headline: Shell + statistics: + exercise: Exercise + score: Average Score + runs: Average Number of Runs + worktime: Average Worktime exercises: editor: confirm_start_over: Do you really want to start over? @@ -239,10 +244,10 @@ en: intermediate_submissions: Intermediate Submissions participants: Participating Users users: '%{count} distinct users' - user: 'User' - score: 'Score' - runs: 'Runs' - worktime: 'Worktime' + user: User + score: Score + runs: Runs + worktime: Worktime submit: failure: An error occured while transmitting your score. Please try again later. files: diff --git a/config/routes.rb b/config/routes.rb index 1616d9b8..7bb17297 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,6 +26,7 @@ Rails.application.routes.draw do member do get :shell post 'shell', as: :execute_command, to: :execute_command + get :statistics end resources :errors, only: [:create, :index, :show] diff --git a/spec/controllers/execution_environments_controller_spec.rb b/spec/controllers/execution_environments_controller_spec.rb index 331c3ec7..2abf59ef 100644 --- a/spec/controllers/execution_environments_controller_spec.rb +++ b/spec/controllers/execution_environments_controller_spec.rb @@ -130,6 +130,14 @@ describe ExecutionEnvironmentsController do expect_template(:shell) end + describe 'GET #statistics' do + before(:each) { get :statistics, id: execution_environment.id } + + expect_assigns(execution_environment: :execution_environment) + expect_status(200) + expect_template(:statistics) + end + describe 'GET #show' do before(:each) { get :show, id: execution_environment.id } From c5dd1e712b84b10b515e07170f9e52f4ee5add3e Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 29 Oct 2015 14:21:26 +0100 Subject: [PATCH 004/106] Fix users being shown multiple times --- app/views/exercises/statistics.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index d76f7b61..3af02b10 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -15,7 +15,7 @@ h1 = @exercise - ['.user', '.score', '.runs', '.worktime'].each do |title| th.header = t(title) tbody - - @exercise.users.each do |user| + - @exercise.users.distinct().each do |user| tr - submissions = @exercise.submissions.where('user_id=?', user.id) td = "#{user.name} (#{user.email})" From c41818e3247c123ef594e34397308aecf4fb935d Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 29 Oct 2015 15:08:02 +0100 Subject: [PATCH 005/106] Push statistics features to model --- app/models/exercise.rb | 9 +++++++-- .../execution_environments/statistics.html.slim | 14 +++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 152d79bf..b6ff3bd1 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -23,14 +23,19 @@ class Exercise < ActiveRecord::Base validates :token, presence: true, uniqueness: true def average_percentage - (average_score/ maximum_score * 100).round if average_score + (average_score / maximum_score * 100).round if average_score end 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) self.class.connection.execute("SELECT AVG(maximum_score) AS average_score FROM (#{maximum_scores_query}) AS maximum_scores").first['average_score'].to_f - end + else 0 end + end + + def average_working_time + working_time_query = submissions.select('MAX(created_at) - MIN(created_at) AS time').group(:user_id).to_sql.sub('$1', id.to_s) + self.class.connection.execute("SELECT AVG(time) AS average_time FROM (#{working_time_query}) AS working_times").first['average_time'] end def duplicate(attributes = {}) diff --git a/app/views/execution_environments/statistics.html.slim b/app/views/execution_environments/statistics.html.slim index 111c6d29..38112c4f 100644 --- a/app/views/execution_environments/statistics.html.slim +++ b/app/views/execution_environments/statistics.html.slim @@ -9,15 +9,7 @@ h1 = @execution_environment tbody - @execution_environment.exercises.each do |exercise| tr - - submissions = exercise.submissions td = exercise.title - td = submissions.average(:score) - td = submissions.count() - - minima = submissions.group(:user_id).minimum(:created_at) - - maxima = submissions.group(:user_id).maximum(:created_at) - - result = 0 - - results = {} - - maxima.each {|key, value| results[key] = value - minima[key]} - - results.values.map {|value| result += value} - - result /= results.size if results.size > 0 - td = distance_of_time_in_words(result) + td = exercise.average_score + td = exercise.submissions.count() + td = exercise.average_working_time From 7baff6ddaf568493d6b66ce32ae61827c456e49a Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Sun, 1 Nov 2015 14:47:52 +0100 Subject: [PATCH 006/106] Group statistics per user type --- app/models/exercise.rb | 6 ++++- app/views/exercises/statistics.html.slim | 30 +++++++++++++----------- config/locales/de.yml | 10 ++++---- config/locales/en.yml | 2 ++ 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index b6ff3bd1..91a9c2b2 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -11,7 +11,10 @@ class Exercise < ActiveRecord::Base belongs_to :execution_environment has_many :submissions belongs_to :team - has_many :users, source_type: ExternalUser, through: :submissions + + has_many :external_users, source: :user, source_type: ExternalUser, through: :submissions + has_many :internal_users, source: :user, source_type: InternalUser, through: :submissions + alias_method :users, :external_users scope :with_submissions, -> { where('id IN (SELECT exercise_id FROM submissions)') } @@ -22,6 +25,7 @@ class Exercise < ActiveRecord::Base validates :title, presence: true validates :token, presence: true, uniqueness: true + def average_percentage (average_score / maximum_score * 100).round if average_score end diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index 3af02b10..99e6ead2 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -8,18 +8,20 @@ h1 = @exercise p == @exercise.average_score ? t('shared.out_of', maximum_value: @exercise.maximum_score, value: @exercise.average_score.round(2)) : empty p = progress_bar(@exercise.average_percentage) -.table-responsive - table.table - thead - tr - - ['.user', '.score', '.runs', '.worktime'].each do |title| - th.header = t(title) - tbody - - @exercise.users.distinct().each do |user| +- Hash[:internal_users => t('.internal_users'), :external_users => t('.external_users')].each_pair do |symbol, label| + strong = label + .table-responsive + table.table + thead tr - - submissions = @exercise.submissions.where('user_id=?', user.id) - td = "#{user.name} (#{user.email})" - td = submissions.maximum('score') - td = submissions.count('id') - - seconds = submissions.maximum('created_at') - submissions.minimum('created_at') - td = "#{distance_of_time_in_words(seconds)} (#{seconds})" + - ['.user', '.score', '.runs', '.worktime'].each do |title| + th.header = t(title) + tbody + - @exercise.send(symbol).distinct().each do |user| + tr + - submissions = @exercise.submissions.where('user_id=?', user.id) + td = "#{user.name} (#{user.email})" + td = submissions.maximum('score') + td = submissions.count('id') + - seconds = submissions.maximum('created_at') - submissions.minimum('created_at') + td = "#{distance_of_time_in_words(seconds)} (#{seconds})" diff --git a/config/locales/de.yml b/config/locales/de.yml index 12b3df92..d445aa40 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -244,10 +244,12 @@ de: intermediate_submissions: Intermediäre Abgaben participants: Bearbeitende Nutzer users: '%{count} verschiedene Nutzer' - user: 'Nutzer' - score: 'Punktzahl' - runs: 'Versuche' - worktime: 'Arbeitszeit' + user: Nutzer + score: Punktzahl + runs: Versuche + worktime: Arbeitszeit + internal_users: Interne Nutzer + external_user: Externe Nutzer submit: failure: Beim Übermitteln Ihrer Punktzahl ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut. files: diff --git a/config/locales/en.yml b/config/locales/en.yml index 771d5a00..07d5b6b5 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -248,6 +248,8 @@ en: score: Score runs: Runs worktime: Worktime + internal_users: Internal Users + external_users: External Users submit: failure: An error occured while transmitting your score. Please try again later. files: From baed5bcc038b5b36950b564b453da1eaf87e6638 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Sun, 1 Nov 2015 15:54:01 +0100 Subject: [PATCH 007/106] Add first draft of cleansed average working time --- app/models/exercise.rb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 91a9c2b2..3546c7e7 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -38,8 +38,23 @@ class Exercise < ActiveRecord::Base end def average_working_time - working_time_query = submissions.select('MAX(created_at) - MIN(created_at) AS time').group(:user_id).to_sql.sub('$1', id.to_s) - self.class.connection.execute("SELECT AVG(time) AS average_time FROM (#{working_time_query}) AS working_times").first['average_time'] + self.class.connection.execute(""" + SELECT avg(working_time) as average_time + FROM + (SELECT user_id, + sum(working_time_new) AS working_time + FROM + (SELECT user_id, + CASE WHEN working_time >= '0:30:00' THEN '0' ELSE working_time END AS working_time_new + FROM + (SELECT user_id, + id, + (created_at - lag(created_at) over (PARTITION BY user_id + ORDER BY id)) AS working_time + FROM submissions + WHERE exercise_id=#{id}) AS foo) AS bar + GROUP BY user_id) AS baz; + """).first['average_time'] end def duplicate(attributes = {}) From d4031c363fd5006bbefa66a091d7560efeb71b48 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 5 Nov 2015 10:57:07 +0100 Subject: [PATCH 008/106] Fix number of runs --- app/models/exercise.rb | 5 +++++ app/views/execution_environments/statistics.html.slim | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 3546c7e7..e7dba16d 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -37,6 +37,11 @@ class Exercise < ActiveRecord::Base else 0 end end + def average_number_of_submissions + user_count = internal_users.distinct.count + external_users.distinct.count + return user_count == 0 ? 0 : submissions.count() / user_count.to_f() + end + def average_working_time self.class.connection.execute(""" SELECT avg(working_time) as average_time diff --git a/app/views/execution_environments/statistics.html.slim b/app/views/execution_environments/statistics.html.slim index 38112c4f..ae2bf4f8 100644 --- a/app/views/execution_environments/statistics.html.slim +++ b/app/views/execution_environments/statistics.html.slim @@ -11,5 +11,5 @@ h1 = @execution_environment tr td = exercise.title td = exercise.average_score - td = exercise.submissions.count() + td = exercise.average_number_of_submissions td = exercise.average_working_time From f3acc426ac4fa2292d6e6085e632d223e714e478 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 5 Nov 2015 11:17:45 +0100 Subject: [PATCH 009/106] Refactor average worktime and add it to exercise statistics per user --- app/models/exercise.rb | 39 ++++++++++++++++-------- app/views/exercises/statistics.html.slim | 3 +- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index e7dba16d..192c4513 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -42,26 +42,39 @@ class Exercise < ActiveRecord::Base return user_count == 0 ? 0 : submissions.count() / user_count.to_f() end + def user_working_time_query + """ + SELECT user_id, + sum(working_time_new) AS working_time + FROM + (SELECT user_id, + CASE WHEN working_time >= '0:30:00' THEN '0' ELSE working_time END AS working_time_new + FROM + (SELECT user_id, + id, + (created_at - lag(created_at) over (PARTITION BY user_id + ORDER BY id)) AS working_time + FROM submissions + WHERE exercise_id=#{id}) AS foo) AS bar + GROUP BY user_id + """ + end + def average_working_time self.class.connection.execute(""" SELECT avg(working_time) as average_time FROM - (SELECT user_id, - sum(working_time_new) AS working_time - FROM - (SELECT user_id, - CASE WHEN working_time >= '0:30:00' THEN '0' ELSE working_time END AS working_time_new - FROM - (SELECT user_id, - id, - (created_at - lag(created_at) over (PARTITION BY user_id - ORDER BY id)) AS working_time - FROM submissions - WHERE exercise_id=#{id}) AS foo) AS bar - GROUP BY user_id) AS baz; + (#{user_working_time_query}) AS baz; """).first['average_time'] end + def average_working_time_for(user_id) + self.class.connection.execute(""" + #{user_working_time_query} + HAVING user_id = #{user_id} + """).first['working_time'] + end + def duplicate(attributes = {}) exercise = dup exercise.attributes = attributes diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index 99e6ead2..f4a9dde5 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -23,5 +23,4 @@ h1 = @exercise td = "#{user.name} (#{user.email})" td = submissions.maximum('score') td = submissions.count('id') - - seconds = submissions.maximum('created_at') - submissions.minimum('created_at') - td = "#{distance_of_time_in_words(seconds)} (#{seconds})" + td = @exercise.average_working_time_for(user.id) or 0 From 0ba30c10ddb2aae313c727f30b209794384bad1f Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 5 Nov 2015 11:26:30 +0100 Subject: [PATCH 010/106] Use default value for missing scores --- app/views/exercises/statistics.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index f4a9dde5..f2e4e784 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -21,6 +21,6 @@ h1 = @exercise tr - submissions = @exercise.submissions.where('user_id=?', user.id) td = "#{user.name} (#{user.email})" - td = submissions.maximum('score') + td = submissions.maximum('score') or 0 td = submissions.count('id') td = @exercise.average_working_time_for(user.id) or 0 From be87f939c63e0b7cae14189f7edae5531d5da589 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Sat, 7 Nov 2015 15:57:32 +0100 Subject: [PATCH 011/106] Add support for comments on multiple files per exercise --- app/views/request_for_comments/show.html.erb | 76 ++++++++++---------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index 7894d66f..d1f5591f 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -2,9 +2,15 @@

<%= Exercise.find(@request_for_comment.exercise_id) %>

<% - - user = @request_for_comment.user - + user = @request_for_comment.user + submission_id = ActiveRecord::Base.connection.execute("select id from submissions + where exercise_id = + #{@request_for_comment.exercise_id} AND + user_id = #{@request_for_comment.user_id} AND + '#{@request_for_comment.created_at}' > created_at + order by created_at desc + limit 1").first['id'].to_i + submission = Submission.find(submission_id) %> <%= user %> | <%= @request_for_comment.requested_at %>

@@ -13,36 +19,34 @@ -
<%= CodeOcean::File.find(@request_for_comment.file_id).content %> -
+<% submission.files.each do |file| %> + <%= (file.path or "") + "/" + file.name + file.file_type.file_extension %> +
<%= file.content %> +
+<% end %>