From 2679f5fa562af814b3d125981b779cacb6b82d7f Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Fri, 20 Jan 2023 20:56:20 +0100 Subject: [PATCH] Allow random selection for ProxyExercise --- app/controllers/proxy_exercises_controller.rb | 2 +- app/models/proxy_exercise.rb | 30 ++++++++++++++----- app/views/proxy_exercises/_form.html.slim | 3 ++ app/views/proxy_exercises/show.html.slim | 1 + config/locales/de.yml | 4 +++ config/locales/en.yml | 4 +++ ...0185807_add_algorithm_to_proxy_exercise.rb | 7 +++++ db/schema.rb | 3 +- spec/factories/proxy_exercise.rb | 1 + 9 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20230120185807_add_algorithm_to_proxy_exercise.rb diff --git a/app/controllers/proxy_exercises_controller.rb b/app/controllers/proxy_exercises_controller.rb index 473ae0fe..cd0c42ee 100644 --- a/app/controllers/proxy_exercises_controller.rb +++ b/app/controllers/proxy_exercises_controller.rb @@ -42,7 +42,7 @@ class ProxyExercisesController < ApplicationController def proxy_exercise_params if params[:proxy_exercise].present? - params[:proxy_exercise].permit(:description, :title, :public, exercise_ids: []).merge(user_id: current_user.id, + params[:proxy_exercise].permit(:description, :title, :algorithm, :public, exercise_ids: []).merge(user_id: current_user.id, user_type: current_user.class.name) end end diff --git a/app/models/proxy_exercise.rb b/app/models/proxy_exercise.rb index d576d57c..7850ddab 100644 --- a/app/models/proxy_exercise.rb +++ b/app/models/proxy_exercise.rb @@ -4,6 +4,11 @@ class ProxyExercise < ApplicationRecord include Creation include DefaultValues + enum algorithm: { + best_match: 0, + random: 1, + }, _default: :write, _prefix: true + after_initialize :generate_token after_initialize :set_reason after_initialize :set_default_values @@ -47,16 +52,25 @@ class ProxyExercise < ApplicationRecord Rails.logger.debug { "retrieved assigned exercise for user #{user.id}: Exercise #{assigned_user_proxy_exercise.exercise}" } assigned_user_proxy_exercise.exercise else - Rails.logger.debug { "find new matching exercise for user #{user.id}" } matching_exercise = - begin - find_matching_exercise(user) - rescue StandardError => e # fallback - Rails.logger.error("finding matching exercise failed. Fall back to random exercise! Error: #{$ERROR_INFO}") - @reason[:reason] = 'fallback because of error' - @reason[:error] = "#{$ERROR_INFO}:\n\t#{e.backtrace.join("\n\t")}" - exercises.where('expected_difficulty > 1').sample # difficulty should be > 1 to prevent dummy exercise from being chosen. + case algorithm + when 'best_match' + Rails.logger.debug { "find new matching exercise for user #{user.id}" } + begin + find_matching_exercise(user) + rescue StandardError => e # fallback + Rails.logger.error("finding matching exercise failed. Fall back to random exercise! Error: #{$ERROR_INFO}") + @reason[:reason] = 'fallback because of error' + @reason[:error] = "#{$ERROR_INFO}:\n\t#{e.backtrace.join("\n\t")}" + exercises.where('expected_difficulty > 1').sample # difficulty should be > 1 to prevent dummy exercise from being chosen. + end + when 'random' + @reason[:reason] = 'random exercise requested' + exercises.sample + else + raise "Unknown algorithm #{algorithm}" end + user.user_proxy_exercise_exercises << UserProxyExerciseExercise.create(user:, exercise: matching_exercise, proxy_exercise: self, reason: @reason.to_json) matching_exercise diff --git a/app/views/proxy_exercises/_form.html.slim b/app/views/proxy_exercises/_form.html.slim index 3b63229e..b390f3a1 100644 --- a/app/views/proxy_exercises/_form.html.slim +++ b/app/views/proxy_exercises/_form.html.slim @@ -6,6 +6,9 @@ .mb-3 = f.label(:description, class: 'form-label') = f.pagedown :description, input_html: { preview: true, rows: 10 } + .mb-3 + = f.label(:algorithm, class: 'form-label') + = f.collection_select(:algorithm, ProxyExercise.algorithms.map { |algorithm, _id| [t("activerecord.attributes.proxy_exercise.algorithm_type.#{algorithm}"), algorithm] }, :second, :first, {}, class: 'form-control form-control-sm') .form-check.mb-3 label.form-check-label = f.check_box(:public, class: 'form-check-input') diff --git a/app/views/proxy_exercises/show.html.slim b/app/views/proxy_exercises/show.html.slim index 892ef4c6..e740bbe0 100644 --- a/app/views/proxy_exercises/show.html.slim +++ b/app/views/proxy_exercises/show.html.slim @@ -5,6 +5,7 @@ h1 = row(label: 'exercise.title', value: @proxy_exercise.title) = row(label: 'exercise.user', value: link_to_if(policy(@proxy_exercise.author).show?, @proxy_exercise.author, @proxy_exercise.author)) = row(label: 'proxy_exercise.files_count', value: @exercises.count) += row(label: 'proxy_exercise.algorithm', value: t("activerecord.attributes.proxy_exercise.algorithm_type.#{@proxy_exercise.algorithm}")) = row(label: 'exercise.public', value: @proxy_exercise.public?) = row(label: 'exercise.description', value: @proxy_exercise.description) = row(label: 'exercise.embedding_parameters', class: 'mb-4') do diff --git a/config/locales/de.yml b/config/locales/de.yml index 747017a0..b8ffdf25 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -54,6 +54,10 @@ de: proxy_exercise: title: Title files_count: Anzahl der Aufgaben + algorithm: Algorithmus + algorithm_type: + best_match: Beste Übereinstimmung + random: Zufällige Aufgabe external_user: consumer: Konsument email: E-Mail diff --git a/config/locales/en.yml b/config/locales/en.yml index d1f50f7b..9345245a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -54,6 +54,10 @@ en: proxy_exercise: title: Title files_count: Exercises Count + algorithm: Algorithm + algorithm_type: + best_match: Best Match + random: Random Exercise external_user: consumer: Consumer email: Email diff --git a/db/migrate/20230120185807_add_algorithm_to_proxy_exercise.rb b/db/migrate/20230120185807_add_algorithm_to_proxy_exercise.rb new file mode 100644 index 00000000..ea69747b --- /dev/null +++ b/db/migrate/20230120185807_add_algorithm_to_proxy_exercise.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddAlgorithmToProxyExercise < ActiveRecord::Migration[7.0] + def change + add_column :proxy_exercises, :algorithm, :integer, limit: 1, null: false, default: 0, comment: 'Used as enum in Rails' + end +end diff --git a/db/schema.rb b/db/schema.rb index 32fd3c5a..de6e7ea5 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.0].define(version: 2022_12_06_221333) do +ActiveRecord::Schema[7.0].define(version: 2023_01_20_185807) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" enable_extension "pgcrypto" @@ -358,6 +358,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_12_06_221333) do t.string "user_type" t.bigint "user_id" t.boolean "public", default: false, null: false + t.integer "algorithm", limit: 2, default: 0, null: false, comment: "Used as enum in Rails" t.index ["user_type", "user_id"], name: "index_proxy_exercises_on_user_type_and_user_id" end diff --git a/spec/factories/proxy_exercise.rb b/spec/factories/proxy_exercise.rb index cefe808d..853837a7 100644 --- a/spec/factories/proxy_exercise.rb +++ b/spec/factories/proxy_exercise.rb @@ -5,5 +5,6 @@ FactoryBot.define do created_by_teacher token { 'dummytoken' } title { 'Dummy' } + algorithm { 'best_match' } end end