diff --git a/app/assets/javascripts/external_users.js b/app/assets/javascripts/external_users.js new file mode 100644 index 00000000..8e4ec52e --- /dev/null +++ b/app/assets/javascripts/external_users.js @@ -0,0 +1,32 @@ +$(function() { + var grid = $('#tag-grid'); + + if ($.isController('external_users') && grid.isPresent()) { + var spinner = $('#loading'); + var noElements = $('#no-elements'); + + var buildTagContainer = function(tag) { + return '\ +
\ +
' + tag.key + '
\ +
\ +
' + tag.value + '%
\ +
\ +
'; + }; + + var jqxhr = $.ajax(window.location.href + '/tag_statistics', { + dataType: 'json', + method: 'GET' + }); + jqxhr.done(function(response) { + spinner.hide(); + if (response.length === 0) { + noElements.show(); + } else { + var elements = response.map(buildTagContainer); + grid.append(elements); + } + }); + } +}); diff --git a/app/assets/stylesheets/base.css.scss b/app/assets/stylesheets/base.css.scss index a0fbd88b..127b36ca 100644 --- a/app/assets/stylesheets/base.css.scss +++ b/app/assets/stylesheets/base.css.scss @@ -59,3 +59,34 @@ span.caret { .markdown { height: 200px; } + +.spinner { + width: 40px; + height: 40px; + background-color: #333; + + margin: 100px auto; + -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out; + animation: sk-rotateplane 1.2s infinite ease-in-out; +} + +@-webkit-keyframes sk-rotateplane { + 0% { -webkit-transform: perspective(120px) } + 50% { -webkit-transform: perspective(120px) rotateY(180deg) } + 100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) } +} + +@keyframes sk-rotateplane { + 0% { + transform: perspective(120px) rotateX(0deg) rotateY(0deg); + -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg) + } + 50% { + transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); + -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) + } + 100% { + transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); + -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); + } +} diff --git a/app/assets/stylesheets/external_users.css.scss b/app/assets/stylesheets/external_users.css.scss new file mode 100644 index 00000000..05bc0b35 --- /dev/null +++ b/app/assets/stylesheets/external_users.css.scss @@ -0,0 +1,16 @@ +#no-elements { + display: none; +} + +#tag-grid { + display: grid; + grid-template-columns: 25% 25% 25% 25%; + grid-column-gap: 10px; + grid-row-gap: 15px; + + .progress { + .progress-bar { + min-width: 2em; + } + } +} diff --git a/app/assets/stylesheets/statistics.css.scss b/app/assets/stylesheets/statistics.css.scss index 2fc9d69d..4dee2b34 100644 --- a/app/assets/stylesheets/statistics.css.scss +++ b/app/assets/stylesheets/statistics.css.scss @@ -120,34 +120,3 @@ tr.highlight { } } } - -.spinner { - width: 40px; - height: 40px; - background-color: #333; - - margin: 100px auto; - -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out; - animation: sk-rotateplane 1.2s infinite ease-in-out; -} - -@-webkit-keyframes sk-rotateplane { - 0% { -webkit-transform: perspective(120px) } - 50% { -webkit-transform: perspective(120px) rotateY(180deg) } - 100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) } -} - -@keyframes sk-rotateplane { - 0% { - transform: perspective(120px) rotateX(0deg) rotateY(0deg); - -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg) - } - 50% { - transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); - -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) - } - 100% { - transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); - -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); - } -} diff --git a/app/controllers/external_users_controller.rb b/app/controllers/external_users_controller.rb index 22d70988..4ef53f6d 100644 --- a/app/controllers/external_users_controller.rb +++ b/app/controllers/external_users_controller.rb @@ -63,4 +63,20 @@ class ExternalUsersController < ApplicationController } end + def tag_statistics + @user = ExternalUser.find(params[:id]) + authorize! + + statistics = [] + tags = ProxyExercise.new().get_user_knowledge_and_max_knowledge(@user, @user.participations.uniq.compact) + tags[:user_topic_knowledge].each_pair do |key, value| + statistics.append({:key => key.name.to_s, :value => (100.0 / tags[:max_topic_knowledge][key] * value).round}) + end + statistics.sort_by! {|item| -item[:value]} + + respond_to do |format| + format.json { render(json: statistics) } + end + end + end diff --git a/app/models/concerns/user.rb b/app/models/concerns/user.rb index 89855062..78299717 100644 --- a/app/models/concerns/user.rb +++ b/app/models/concerns/user.rb @@ -8,6 +8,7 @@ module User has_many :exercises, as: :user has_many :file_types, as: :user has_many :submissions, as: :user + has_many :participations, through: :submissions, source: :exercise, as: :user has_many :user_proxy_exercise_exercises, as: :user has_many :user_exercise_interventions, as: :user has_many :interventions, through: :user_exercise_interventions diff --git a/app/models/proxy_exercise.rb b/app/models/proxy_exercise.rb index 9c84e3ad..3d9197fb 100644 --- a/app/models/proxy_exercise.rb +++ b/app/models/proxy_exercise.rb @@ -214,8 +214,8 @@ class ProxyExercise < ActiveRecord::Base ex.tags.each do |t| tags_counter[t] += 1 tag_diminishing_return_factor = tag_diminishing_return_function(tags_counter[t], all_used_tags_with_count[t]) - tag_ratio = ex.exercise_tags.where(tag: t).first.factor.to_f / ex.exercise_tags.inject(0){|sum, et| sum += et.factor }.to_f - Rails.logger.debug("tag: #{t}, factor: #{ex.exercise_tags.where(tag: t).first.factor}, sumall: #{ex.exercise_tags.inject(0){|sum, et| sum += et.factor }}") + tag_ratio = ex.exercise_tags.where(tag: t).first.factor.to_f / ex.exercise_tags.inject(0){|sum, et| sum + et.factor }.to_f + Rails.logger.debug("tag: #{t}, factor: #{ex.exercise_tags.where(tag: t).first.factor}, sumall: #{ex.exercise_tags.inject(0){|sum, et| sum + et.factor }}") Rails.logger.debug("tag #{t}, count #{tags_counter[t]}, max: #{all_used_tags_with_count[t]}, factor: #{tag_diminishing_return_factor}") Rails.logger.debug("tag_ratio #{tag_ratio}") topic_knowledge_ratio = ex.expected_difficulty * tag_ratio @@ -226,11 +226,10 @@ class ProxyExercise < ActiveRecord::Base end {user_topic_knowledge: topic_knowledge_loss_user, max_topic_knowledge: topic_knowledge_max} end - private :get_user_knowledge_and_max_knowledge def tag_diminishing_return_function(count_tag, total_count_tag) total_count_tag += 1 # bonus exercise comes on top - return 1/(1+(Math::E**(-3/(0.5*total_count_tag)*(count_tag-0.5*total_count_tag)))) + 1 / (1 + (Math::E**(-3 / (0.5 * total_count_tag) * (count_tag - 0.5 * total_count_tag)))) end def select_easiest_exercise(exercises) diff --git a/app/policies/external_user_policy.rb b/app/policies/external_user_policy.rb index 2e11060b..4257fa4b 100644 --- a/app/policies/external_user_policy.rb +++ b/app/policies/external_user_policy.rb @@ -2,4 +2,8 @@ class ExternalUserPolicy < AdminOnlyPolicy def statistics? admin? end + + def tag_statistics? + admin? + end end diff --git a/app/views/external_users/show.html.slim b/app/views/external_users/show.html.slim index 5af691c1..f0028745 100644 --- a/app/views/external_users/show.html.slim +++ b/app/views/external_users/show.html.slim @@ -4,5 +4,12 @@ h1 = @user.name //= row(label: 'external_user.email', value: @user.email) = row(label: 'external_user.consumer', value: link_to(@user.consumer, @user.consumer)) -br -= link_to(t('shared.statistics'), statistics_external_user_path(@user)) +h4 = link_to(t('.exercise_statistics'), statistics_external_user_path(@user)) + +h4 = t('.tag_statistics') +#loading + .spinner + = t('.loading_tag_statistics') +#no-elements + = t('.empty_tag_statistics') +#tag-grid diff --git a/config/locales/de.yml b/config/locales/de.yml index c3f7dc15..eed4d500 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -378,6 +378,11 @@ de: score: Bewertung runs: Abgaben worktime: Arbeitszeit + show: + loading_tag_statistics: "Lade Lernbereichstatistiken" + tag_statistics: "Lernbereichstatistiken" + empty_tag_statistics: "Keine Statistiken verfügbar" + exercise_statistics: "Aufgabenstatistiken" files: roles: main_file: Hauptdatei diff --git a/config/locales/en.yml b/config/locales/en.yml index 494dd163..9fed1190 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -378,6 +378,11 @@ en: score: Score runs: Submissions worktime: Working Time + show: + loading_tag_statistics: "Loading tag statistics..." + tag_statistics: "Tag Statistics" + empty_tag_statistics: "No statistics available" + exercise_statistics: "Exercise Statistics" files: roles: main_file: Main File diff --git a/config/routes.rb b/config/routes.rb index 4ab758d9..6703d8c1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -128,6 +128,9 @@ Rails.application.routes.draw do resources :external_users, only: [:index, :show], concerns: :statistics do resources :exercises, concerns: :statistics + member do + get :tag_statistics + end end namespace :code_ocean do