Merge pull request #43 from openHPI/statistics

Statistics
This commit is contained in:
rteusner
2016-03-02 17:22:24 +01:00
17 changed files with 73 additions and 24 deletions

View File

@ -17,4 +17,8 @@ class InternalUser < ActiveRecord::Base
activation_token? || reset_password_token?
end
private :password_void?
def teacher?
role == 'teacher'
end
end

4
app/models/testrun.rb Normal file
View File

@ -0,0 +1,4 @@
class Testrun < ActiveRecord::Base
belongs_to :file
belongs_to :submission
end

View File

@ -1,4 +1,4 @@
class ExecutionEnvironmentPolicy < AdminOrAuthorPolicy
class ExecutionEnvironmentPolicy < AdminOnlyPolicy
def author?
@user == @record.author
end

View File

@ -8,7 +8,11 @@ class ExercisePolicy < AdminOrAuthorPolicy
admin?
end
[:clone?, :destroy?, :edit?, :show?, :statistics?, :update?].each do |action|
def show?
@user.internal_user?
end
[:clone?, :destroy?, :edit?, :statistics?, :update?].each do |action|
define_method(action) { admin? || author? || team_member? }
end

View File

@ -1,5 +1,5 @@
class ExternalUserPolicy < AdminOnlyPolicy
def statistics?
admin? || author? || team_member?
admin?
end
end

View File

@ -1,4 +1,4 @@
class FileTypePolicy < AdminOrAuthorPolicy
class FileTypePolicy < AdminOnlyPolicy
def author?
@user == @record.author
end

View File

@ -1,6 +1,6 @@
class TeamPolicy < ApplicationPolicy
[:create?, :index?, :new?].each do |action|
define_method(action) { @user.internal_user? }
define_method(action) { admin? }
end
[:destroy?, :edit?, :show?, :update?].each do |action|

View File

@ -38,14 +38,17 @@ h1 = "#{@exercise} (external user #{@external_user})"
table.table
thead
tr
- ['.time', '.cause', '.score'].each do |title|
- ['.time', '.cause', '.score', '.time_difference'].each do |title|
th.header = t(title)
tbody
- submissions.each do |submission|
- deltas = submissions.map.with_index {|item, index| delta = item.created_at - submissions[index - 1].created_at if index > 0; if delta == nil or delta > 30*60 then 0 else delta end}
- submissions.each_with_index do |submission, index|
tr data-id=submission.id
td.clickable = submission.created_at.strftime("%F %T")
td = submission.cause
td = submission.score
td = Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0
p = t('.addendum')
- else
p = t('.no_data_available')

View File

@ -27,17 +27,17 @@ h1 = Exercise.model_name.human(count: 2)
- @exercises.each do |exercise|
tr data-id=exercise.id
td = exercise.title
td = link_to(exercise.author, exercise.author)
td = link_to(exercise.execution_environment, exercise.execution_environment)
td = link_to_if(policy(exercise.author).show?, exercise.author, exercise.author)
td = link_to_if(policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment)
td = exercise.files.teacher_defined_tests.count
td = exercise.maximum_score
td.public data-value=exercise.public? = symbol_for(exercise.public?)
td = link_to(t('shared.show'), exercise)
td = link_to(t('shared.edit'), edit_exercise_path(exercise))
td = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
td = link_to(t('.clone'), clone_exercise_path(exercise), data: {confirm: t('shared.confirm_destroy')}, method: :post)
td = link_to(t('.implement'), implement_exercise_path(exercise))
td = link_to(t('shared.statistics'), statistics_exercise_path(exercise))
td = link_to(t('shared.show'), exercise) if policy(exercise).show?
td = link_to(t('shared.edit'), edit_exercise_path(exercise)) if policy(exercise).edit?
td = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(exercise).destroy?
td = link_to(t('.clone'), clone_exercise_path(exercise), data: {confirm: t('shared.confirm_destroy')}, method: :post) if policy(exercise).clone?
td = link_to(t('.implement'), implement_exercise_path(exercise)) if policy(exercise).implement?
td = link_to(t('shared.statistics'), statistics_exercise_path(exercise)) if policy(exercise).statistics?
= render('shared/pagination', collection: @exercises)
p = render('shared/new_button', model: Exercise)

View File

@ -4,12 +4,13 @@
h1
= @exercise
- if policy(@exercise).edit?
= render('shared/edit_button', object: @exercise)
= row(label: 'exercise.title', value: @exercise.title)
= row(label: 'exercise.user', value: link_to(@exercise.author, @exercise.author))
= row(label: 'exercise.user', value: link_to_if(policy(@exercise.author).show?, @exercise.author, @exercise.author))
= row(label: 'exercise.description', value: @exercise.description)
= row(label: 'exercise.execution_environment', value: link_to(@exercise.execution_environment, @exercise.execution_environment))
= row(label: 'exercise.execution_environment', value: link_to_if(policy(@exercise.execution_environment).show?, @exercise.execution_environment, @exercise.execution_environment))
= row(label: 'exercise.instructions', value: render_markdown(@exercise.instructions))
= row(label: 'exercise.team', value: @exercise.team ? link_to(@exercise.team, @exercise.team) : nil)
= row(label: 'exercise.maximum_score', value: @exercise.maximum_score)
@ -26,5 +27,6 @@ ul.list-unstyled
.panel-heading
h3.panel-title = file.name_with_extension
.panel-body
- if policy(file).destroy?
.clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm pull-right', data: {confirm: t('shared.confirm_destroy')}, method: :delete)
= render('shared/file', file: file)

View File

@ -22,8 +22,9 @@ h1 = @exercise
tbody
- @exercise.send(symbol).distinct().each do |user|
- if user_statistics[user.id] then us = user_statistics[user.id] else us = {"maximum_score" => nil, "runs" => nil}
- label = current_user.teacher? ? "#{user.name}" : "#{user.name} (#{user.email})"
tr
td = link_to_if symbol==:external_users, "#{user.name} (#{user.email})", {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id}
td = link_to_if symbol==:external_users, label, {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id}
td = us['maximum_score'] or 0
td = us['runs']
td = @exercise.average_working_time_for(user.id) or 0

View File

@ -3,7 +3,7 @@ h1 = t('.title')
- exercises = Exercise.where(:id => @user.submissions.group(:exercise_id).select(:exercise_id).distinct())
.table-responsive
table.table
table.table.table-striped.sortable
thead
tr
- ['.exercise', '.score', '.runs', '.worktime'].each do |title|

View File

@ -1,6 +1,6 @@
= row(label: 'file.name', value: file.name)
= row(label: 'file.path', value: file.path)
= row(label: 'file.file_type', value: link_to(file.file_type, file.file_type))
= row(label: 'file.file_type', value: link_to_if(policy(file).show?, file.file_type, file.file_type))
= row(label: 'file.role', value: file.role? ? t("files.roles.#{file.role}") : '')
= row(label: 'file.hidden', value: file.hidden)
= row(label: 'file.read_only', value: file.read_only)

View File

@ -269,6 +269,8 @@ de:
time: Zeit
cause: Grund
score: Punktzahl
time_difference: 'Arbeitszeit bis hier*'
addendum: '* Differenzen von mehr als 30 Minuten werden ignoriert.'
external_users:
statistics:
title: Statistiken für Externe Benutzer

View File

@ -269,6 +269,8 @@ en:
time: Time
cause: Cause
score: Score
time_difference: 'Working Time until here*'
addendum: '* Deltas longer than 30 minutes are ignored.'
external_users:
statistics:
title: External User Statistics

View File

@ -0,0 +1,13 @@
class CreateTestruns < ActiveRecord::Migration
def change
create_table :testruns do |t|
t.boolean :passed
t.text :output
t.belongs_to :file
t.belongs_to :submission
t.timestamps
end
end
end

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160204111716) do
ActiveRecord::Schema.define(version: 20160302133540) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -91,6 +91,8 @@ ActiveRecord::Schema.define(version: 20160204111716) do
t.boolean "hide_file_tree"
end
add_index "exercises", ["execution_environment_id"], name: "test3", using: :btree
create_table "external_users", force: true do |t|
t.integer "consumer_id"
t.string "email"
@ -200,10 +202,22 @@ ActiveRecord::Schema.define(version: 20160204111716) do
t.string "user_type"
end
add_index "submissions", ["exercise_id"], name: "test1", where: "((user_type)::text = 'ExternalUser'::text)", using: :btree
add_index "submissions", ["exercise_id"], name: "test2", using: :btree
create_table "teams", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "testruns", force: true do |t|
t.boolean "passed"
t.text "output"
t.integer "file_id"
t.integer "submission_id"
t.datetime "created_at"
t.datetime "updated_at"
end
end