diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 816099526..257d9fe6e 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -330,9 +330,8 @@ def implement # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedC end user_solved_exercise = @exercise.solved_by?(current_contributor) - count_interventions_today = UserExerciseIntervention.where(user: current_user).where(created_at: Time.zone.now.beginning_of_day..).count - user_got_intervention_in_exercise = UserExerciseIntervention.where(user: current_user, - exercise: @exercise).size >= max_intervention_count_per_exercise + count_interventions_today = current_contributor.user_exercise_interventions.where(created_at: Time.zone.now.beginning_of_day..).count + user_got_intervention_in_exercise = current_contributor.user_exercise_interventions.where(exercise: @exercise).size >= max_intervention_count_per_exercise (user_got_enough_interventions = count_interventions_today >= max_intervention_count_per_day) || user_got_intervention_in_exercise if @embed_options[:disable_interventions] @@ -529,8 +528,7 @@ def external_user_statistics .includes(:exercise, testruns: [:testrun_messages, {file: [:file_type]}], files: [:file_type]) @show_autosaves = params[:show_autosaves] == 'true' || submissions.where.not(cause: 'autosave').none? submissions = submissions.where.not(cause: 'autosave') unless @show_autosaves - interventions = UserExerciseIntervention.where('user_id = ? AND exercise_id = ?', @external_user.id, - @exercise.id) + interventions = @external_user.user_exercise_interventions.where(exercise: @exercise) @all_events = (submissions + interventions).sort_by(&:created_at) @deltas = @all_events.map.with_index do |item, index| delta = item.created_at - @all_events[index - 1].created_at if index.positive? diff --git a/app/models/intervention.rb b/app/models/intervention.rb index 8bdfac936..6d916a6b1 100644 --- a/app/models/intervention.rb +++ b/app/models/intervention.rb @@ -2,12 +2,18 @@ class Intervention < ApplicationRecord has_many :user_exercise_interventions - has_many :users, through: :user_exercise_interventions, source_type: 'ExternalUser' + has_many :external_users, through: :user_exercise_interventions, source: :contributor, source_type: 'ExternalUser' + has_many :internal_users, through: :user_exercise_interventions, source: :contributor, source_type: 'InternalUser' + has_many :programming_groups, through: :user_exercise_interventions, source: :contributor, source_type: 'ProgrammingGroup' def to_s name end + def contributors + @contributors ||= internal_users.distinct + external_users.distinct + programming_groups.distinct + end + def self.create_default_interventions %w[BreakIntervention QuestionIntervention].each do |name| Intervention.find_or_create_by(name:) diff --git a/app/models/user.rb b/app/models/user.rb index ba2dfdd90..35d278512 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -18,7 +18,7 @@ class User < ApplicationRecord has_many :submissions, as: :contributor 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 :user_exercise_interventions, as: :contributor has_many :testruns, as: :user has_many :interventions, through: :user_exercise_interventions has_many :remote_evaluation_mappings, as: :user diff --git a/app/models/user_exercise_intervention.rb b/app/models/user_exercise_intervention.rb index 2048ccf7a..f9836268a 100644 --- a/app/models/user_exercise_intervention.rb +++ b/app/models/user_exercise_intervention.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class UserExerciseIntervention < ApplicationRecord - include Creation + include ContributorCreation belongs_to :intervention belongs_to :exercise end diff --git a/db/migrate/20231208194632_add_index_to_user_exercise_interventions.rb b/db/migrate/20231208194632_add_index_to_user_exercise_interventions.rb new file mode 100644 index 000000000..77f9d806f --- /dev/null +++ b/db/migrate/20231208194632_add_index_to_user_exercise_interventions.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class AddIndexToUserExerciseInterventions < ActiveRecord::Migration[7.1] + def change + up_only do + # We cannot add a foreign key to a table that has rows that violate the constraint. + UserExerciseIntervention.where.not(exercise_id: Exercise.select(:id)).delete_all + UserExerciseIntervention.where.not(intervention_id: Intervention.select(:id)).delete_all + end + + rename_column :user_exercise_interventions, :user_id, :contributor_id + rename_column :user_exercise_interventions, :user_type, :contributor_type + + change_column_null :user_exercise_interventions, :contributor_type, false + change_column_null :user_exercise_interventions, :contributor_id, false + add_index :user_exercise_interventions, %i[contributor_type contributor_id] + + change_column_null :user_exercise_interventions, :exercise_id, false + add_index :user_exercise_interventions, :exercise_id + add_foreign_key :user_exercise_interventions, :exercises + + change_column_null :user_exercise_interventions, :intervention_id, false + add_index :user_exercise_interventions, :intervention_id + add_foreign_key :user_exercise_interventions, :interventions + end + + class Exercise < ActiveRecord::Base; end + class Intervention < ActiveRecord::Base; end + class UserExerciseIntervention < ActiveRecord::Base; end +end diff --git a/db/schema.rb b/db/schema.rb index 50c8ce482..01938a6da 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2023_11_01_222855) do +ActiveRecord::Schema[7.1].define(version: 2023_12_08_194632) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" enable_extension "pgcrypto" @@ -638,14 +638,17 @@ end create_table "user_exercise_interventions", id: :serial, force: :cascade do |t| - t.integer "user_id" - t.string "user_type" - t.integer "exercise_id" - t.integer "intervention_id" + t.integer "contributor_id", null: false + t.string "contributor_type", null: false + t.integer "exercise_id", null: false + t.integer "intervention_id", null: false t.integer "accumulated_worktime_s" t.text "reason" t.datetime "created_at" t.datetime "updated_at" + t.index ["contributor_type", "contributor_id"], name: "idx_on_contributor_type_contributor_id_10a7504bcc" + t.index ["exercise_id"], name: "index_user_exercise_interventions_on_exercise_id" + t.index ["intervention_id"], name: "index_user_exercise_interventions_on_intervention_id" end create_table "user_proxy_exercise_exercises", id: :serial, force: :cascade do |t| @@ -702,4 +705,6 @@ add_foreign_key "testruns", "submissions" add_foreign_key "tips", "file_types" add_foreign_key "user_exercise_feedbacks", "submissions" + add_foreign_key "user_exercise_interventions", "exercises" + add_foreign_key "user_exercise_interventions", "interventions" end