From c006bc3dc82f344248363824391688d068901e14 Mon Sep 17 00:00:00 2001 From: Karol Date: Thu, 29 Aug 2019 18:31:32 +0200 Subject: [PATCH] wip exercise to task implementation --- app/assets/javascripts/codeharbor_link.js | 3 - app/controllers/exercises_controller.rb | 34 +++-- .../convert_exercise_to_task.rb | 129 ++++++++++++++++++ .../convert_task_to_exercise.rb | 2 +- app/services/proforma_service/export_task.rb | 15 ++ 5 files changed, 166 insertions(+), 17 deletions(-) create mode 100644 app/services/proforma_service/convert_exercise_to_task.rb create mode 100644 app/services/proforma_service/export_task.rb diff --git a/app/assets/javascripts/codeharbor_link.js b/app/assets/javascripts/codeharbor_link.js index bf8c74e1..7ada3756 100644 --- a/app/assets/javascripts/codeharbor_link.js +++ b/app/assets/javascripts/codeharbor_link.js @@ -21,17 +21,14 @@ $(document).on('turbolinks:load', function() { }); var generateUUID = (function () { // Public Domain/MIT - // var d = getDate(); return replace('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'); }); var generateRandomHex32 = (function () { - // var d = getDate(); return replace(Array(32).join('x')); }); - $('.generate-client-id').on('click', function () { $('.client-id').val(generateUUID()); }); diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 33e06fa9..b285454d 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -107,6 +107,19 @@ class ExercisesController < ApplicationController @feedbacks = @exercise.user_exercise_feedbacks.paginate(page: params[:page]) end + def push_proforma_xml + codeharbor_link = CodeharborLink.find(params[:account_link]) + oauth2_client = OAuth2::Client.new(codeharbor_link.client_id, codeharbor_link.client_secret, url: codeharbor_link.push_url, ssl: {verify: false}) + oauth2token = codeharbor_link[:oauth2token] + token = OAuth2::AccessToken.from_hash(oauth2_client, access_token: oauth2token) + + # xml_generator = Proforma::XmlGenerator.new + xml_document = xml_generator.generate_xml(@exercise) + request = token.post(codeharbor_link.push_url, body: xml_document, headers: {'Content-Type' => 'text/xml'}) + puts request + redirect_to @exercise, notice: t('exercises.push_proforma_xml.notice', link: codeharbor_link.push_url) + end + def import_proforma_xml tempfile = Tempfile.new('codeharbor_import.zip') tempfile.write request.body.read.force_encoding('UTF-8') @@ -122,22 +135,17 @@ class ExercisesController < ApplicationController end def user_for_oauth2_request - authorizationHeader = request.headers['Authorization'] - if authorizationHeader == nil - raise ({status: 401, message: 'No Authorization header'}) - end + authorization_header = request.headers['Authorization'] + raise(status: 401, message: 'No Authorization header') if authorization_header.nil? - oauth2Token = authorizationHeader.split(' ')[1] - if oauth2Token == nil || oauth2Token.size == 0 - raise ({status: 401, message: 'No token in Authorization header'}) - end + oauth2_token = authorization_header.split(' ')[1] + raise(status: 401, message: 'No token in Authorization header') if oauth2_token.nil? || oauth2_token.size.zero? - user = user_by_codeharbor_token(oauth2Token) - if user == nil - raise ({status: 401, message: 'Unknown OAuth2 token'}) - end + user = user_by_codeharbor_token(oauth2_token) - return user + raise(status: 401, message: 'Unknown OAuth2 token') if user.nil? + + user end private :user_for_oauth2_request diff --git a/app/services/proforma_service/convert_exercise_to_task.rb b/app/services/proforma_service/convert_exercise_to_task.rb new file mode 100644 index 00000000..11c4b36c --- /dev/null +++ b/app/services/proforma_service/convert_exercise_to_task.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +require 'mimemagic' + +module ProformaService + class ConvertExerciseToTask < ServiceBase + def initialize(exercise: nil) + @exercise = exercise + end + + def execute + create_task + end + + private + + def create_task + Proforma::Task.new( + { + title: @exercise.title, + description: @exercise.description, + internal_description: @exercise.instructions, + + # proglang: proglang, + files: task_files, + # tests: tests, + # uuid: @exercise.uuid, + # parent_uuid: parent_uuid, + # language: primary_description.language, + # model_solutions: model_solutions + }.compact + ) + end + + def parent_uuid + @exercise.clone_relations.first&.origin&.uuid + end + + def primary_description + @exercise.descriptions.select(&:primary?).first + end + + def proglang + {name: @exercise.execution_environment.language, version: @exercise.execution_environment.version} + end + + def model_solutions + @exercise.exercise_files.filter { |file| file.role == 'Reference Implementation' }.map do |file| + Proforma::ModelSolution.new( + id: "ms-#{file.id}", + files: [ + Proforma::TaskFile.new( + id: file.id, + content: file.content, + filename: file.full_file_name, + used_by_grader: false, + usage_by_lms: 'display', + visible: 'delayed', + binary: false, + internal_description: file.role + ) + ] + ) + end + end + + def tests + @exercise.tests.map do |test| + Proforma::Test.new( + id: test.id, + title: test.exercise_file.name, + files: test_file(test.exercise_file), + meta_data: { + 'feedback-message' => test.feedback_message, + 'testing-framework' => test.testing_framework&.name, + 'testing-framework-version' => test.testing_framework&.version + }.compact + ) + end + end + + def test_file(file) + [Proforma::TaskFile.new( + id: file.id, + content: file.content, + filename: file.full_file_name, + used_by_grader: true, + visible: file.hidden ? 'no' : 'yes', + binary: false, + internal_description: file.role || 'Teacher-defined Test' + )] + end + + def task_files + @exercise.files + .filter { |file| !file.role.in? %w[reference_implementation teacher_defined_test] }.map do |file| + task_file(file) + end + end + + def task_file(file) + Proforma::TaskFile.new( + { + id: file.id, + filename: file.path.present? && file.path != '.' ? ::File.join(file.path, file.name_with_extension) : file.name_with_extension, + usage_by_lms: file.read_only ? 'display' : 'edit', + visible: file.hidden ? 'no' : 'yes', + internal_description: file.role || 'regular_file' + }.tap do |params| + if file.native_file.present? + file = ::File.new(file.native_file.file.path, 'r') + params[:content] = file.read + params[:used_by_grader] = false + params[:binary] = true + params[:mimetype] = MimeMagic.by_magic(file).type + else + params[:content] = file.content + params[:used_by_grader] = true + params[:binary] = false + end + end + ) + end + + def attachment_content(file) + Paperclip.io_adapters.for(file.attachment).read + end + end +end diff --git a/app/services/proforma_service/convert_task_to_exercise.rb b/app/services/proforma_service/convert_task_to_exercise.rb index ddeb9030..75af90a8 100644 --- a/app/services/proforma_service/convert_task_to_exercise.rb +++ b/app/services/proforma_service/convert_task_to_exercise.rb @@ -53,7 +53,7 @@ module ProformaService hidden: file.visible == 'no', name: File.basename(file.filename, '.*'), read_only: file.usage_by_lms != 'edit', - role: file.internal_description.underscore.gsub(' ', '_'), + role: file.internal_description, path: File.dirname(file.filename) }.tap do |params| if file.binary diff --git a/app/services/proforma_service/export_task.rb b/app/services/proforma_service/export_task.rb new file mode 100644 index 00000000..72679e23 --- /dev/null +++ b/app/services/proforma_service/export_task.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module ProformaService + class ExportTask < ServiceBase + def initialize(exercise: nil) + @exercise = exercise + end + + def execute + @task = ConvertExerciseToTask.call(exercise: @exercise) + exporter = Proforma::Exporter.new(@task) + exporter.perform + end + end +end