From 04c54549c51b4aa534feff01c7a6753e72fe4c49 Mon Sep 17 00:00:00 2001 From: Thomas Hille Date: Wed, 22 Feb 2017 14:38:40 +0100 Subject: [PATCH] zwischenstand --- app/models/exercise.rb | 5 +-- app/models/proxy_exercise.rb | 65 +++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/app/models/exercise.rb b/app/models/exercise.rb index dc4181b5..ac4a60a2 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -92,7 +92,7 @@ class Exercise < ActiveRecord::Base (created_at - lag(created_at) OVER (PARTITION BY user_id ORDER BY created_at)) AS working_time FROM submissions - WHERE exercise_id=69) AS foo) AS bar + WHERE exercise_id=#{self.id}) AS foo) AS bar GROUP BY user_id ) AS foo """) @@ -200,7 +200,8 @@ class Exercise < ActiveRecord::Base if user submissions.where(user: user, cause: "assess").where("score IS NOT NULL").order("score DESC").first.score || 0 rescue 0 else - files.teacher_defined_tests.sum(:weight) + 5 + #files.teacher_defined_tests.sum(:weight) end end diff --git a/app/models/proxy_exercise.rb b/app/models/proxy_exercise.rb index f9746c71..9f958e97 100644 --- a/app/models/proxy_exercise.rb +++ b/app/models/proxy_exercise.rb @@ -40,7 +40,45 @@ class ProxyExercise < ActiveRecord::Base end def findMatchingExercise(user) - exercises.shuffle.first + #exercises.shuffle.first + exercisesUserHasAccessed = user.submissions.where(cause: :assess).map{|s| s.exercise}.uniq + tagsUserHasSeen = exercisesUserHasAccessed.map{|ex| ex.tags}.uniq.flatten + puts "exercisesUserHasAccessed #{exercisesUserHasAccessed}" + + + # find execises + potentialRecommendedExercises = [] + exercises.each do |ex| + ## find exercises which have tags the user has already seen + if (ex.tags - tagsUserHasSeen).empty? + potentialRecommendedExercises << ex + end + end + puts "potentialRecommendedExercises: #{potentialRecommendedExercises}" + recommendedExercise = selectBestMatchingExercise(user, exercisesUserHasAccessed, potentialRecommendedExercises) + recommendedExercise + end + + def selectBestMatchingExercise(user, exercisesUserHasAccessed, potentialRecommendedExercises) + topic_knowledge_user_and_max = getUserKnowledgeAndMaxKnowledge(user, exercisesUserHasAccessed) + puts "topic_knowledge_user_and_max: #{topic_knowledge_user_and_max}" + topic_knowledge_user = topic_knowledge_user_and_max[:user_topic_knowledge] + topic_knowledge_max = topic_knowledge_user_and_max[:max_topic_knowledge] + relative_knowledge_improvement = {} + potentialRecommendedExercises.each do |potex| + tags = potex.tags + relative_knowledge_improvement[potex] = 0.0 + tags.each do |tag| + tag_ratio = potex.exercise_tags.where(tag: tag).first.factor / potex.exercise_tags.inject(0){|sum, et| sum += et.factor } + max_topic_knowledge_ratio = potex.expected_difficulty * tag_ratio + old_relative_loss_tag = topic_knowledge_user[tag] / topic_knowledge_max[tag] + new_relative_loss_tag = topic_knowledge_user[tag] / (topic_knowledge_max[tag] + max_topic_knowledge_ratio) + relative_knowledge_improvement[potex] += new_relative_loss_tag - old_relative_loss_tag + end + end + puts "relative improvements #{relative_knowledge_improvement}" + exercise_with_greatest_improvements = relative_knowledge_improvement.max_by{|k,v| v} + exercise_with_greatest_improvements end # [score][quantile] @@ -64,6 +102,8 @@ class ProxyExercise < ActiveRecord::Base Rails.logger.debug("scoring user #{user.id} for exercise #{ex.id}: points_ratio=#{points_ratio} score: 0" ) return 0.0 end + puts points_ratio + puts ex.maximum_score.to_f points_ratio_index = ((scoring_matrix.size - 1) * points_ratio).to_i working_time_user = Time.parse(ex.average_working_time_for_only(user.id) || "00:00:00").seconds_since_midnight quantiles_working_time = ex.getQuantiles(scoring_matrix_quantiles) @@ -90,9 +130,9 @@ class ProxyExercise < ActiveRecord::Base user_score_factor = score(user, ex) ex.tags.each do |t| tag_ratio = ex.exercise_tags.where(tag: t).first.factor / ex.exercise_tags.inject(0){|sum, et| sum += et.factor } - topic_knowledge_ratio = ex.expected_difficulty * tag_ratio - topic_knowledge_loss_user[t] += (1 - user_score_factor) * topic_knowledge_ratio - topic_knowledge_max[t] += topic_knowledge_ratio + max_topic_knowledge_ratio = ex.expected_difficulty * tag_ratio + topic_knowledge_loss_user[t] += (1 - user_score_factor) * max_topic_knowledge_ratio + topic_knowledge_max[t] += max_topic_knowledge_ratio end end relative_loss = {} @@ -102,4 +142,21 @@ class ProxyExercise < ActiveRecord::Base relative_loss end + def getUserKnowledgeAndMaxKnowledge(user, exercises) + # initialize knowledge for each tag with 0 + all_used_tags = exercises.inject(Set.new){|tagset, ex| tagset.merge(ex.tags)} + topic_knowledge_loss_user = all_used_tags.map{|t| [t, 0]}.to_h + topic_knowledge_max = all_used_tags.map{|t| [t, 0]}.to_h + exercises.each do |ex| + user_score_factor = score(user, ex) + ex.tags.each do |t| + tag_ratio = ex.exercise_tags.where(tag: t).first.factor / ex.exercise_tags.inject(0){|sum, et| sum += et.factor } + topic_knowledge_ratio = ex.expected_difficulty * tag_ratio + topic_knowledge_loss_user[t] += (1 - user_score_factor) * topic_knowledge_ratio + topic_knowledge_max[t] += topic_knowledge_ratio + end + end + {user_topic_knowledge: topic_knowledge_loss_user, max_topic_knowledge: topic_knowledge_max} + end + end \ No newline at end of file