app/controllers/course/assessment/question/programming_controller.rb
# frozen_string_literal: true
class Course::Assessment::Question::ProgrammingController < Course::Assessment::Question::Controller
include Course::Assessment::Question::KoditsuQuestionConcern
build_and_authorize_new_question :programming_question,
class: Course::Assessment::Question::Programming, only: [:new, :create]
load_and_authorize_resource :programming_question,
class: 'Course::Assessment::Question::Programming',
through: :assessment, parent: false,
except: [:new, :create, :generate, :codaveri_languages]
before_action :load_question_assessment, only: [:edit, :update, :update_question_setting]
before_action :set_attributes_for_programming_question, except: [:generate, :codaveri_languages]
def new
respond_to do |format|
format.json { format_test_cases }
end
end
def create
@programming_question.package_type = programming_question_params.key?(:file) ? :zip_upload : :online_editor
process_package
is_course_koditsu_enabled = current_course.component_enabled?(Course::KoditsuPlatformComponent)
if @programming_question.save
load_question_assessment
create_question_in_koditsu if is_course_koditsu_enabled && @assessment.is_koditsu_enabled
render_success_json true
else
render_failure_json
end
end
def edit
respond_to do |format|
format.json do
@meta = programming_package_service.extract_meta if @programming_question.edit_online?
format_test_cases
end
end
end
def update
result = @programming_question.class.transaction do
@question_assessment.skill_ids = programming_question_params[:question_assessment].
try(:[], :skill_ids)
@programming_question.assign_attributes(programming_question_params.
except(:question_assessment))
process_package
raise ActiveRecord::Rollback unless @programming_question.save
@question = @programming_question.acting_as
@question.update!(is_synced_with_koditsu: false)
is_course_koditsu_enabled = current_course.component_enabled?(Course::KoditsuPlatformComponent)
edit_koditsu_question if is_course_koditsu_enabled && @assessment.is_koditsu_enabled
true
end
if result
render_success_json false
else
render_failure_json
end
end
def codaveri_languages
render json: {
languages: Coursemology::Polyglot::Language.
where(enabled: true).
order(weight: :desc).
filter_map do |language|
if CodaveriAsyncApiService.language_valid_for_codaveri?(language)
{
id: language.id,
name: language.name,
disabled: !language.enabled,
editorMode: language.ace_mode
}
end
end
}, status: :ok
end
def generate # rubocop:disable Metrics/AbcSize
language = Coursemology::Polyglot::Language.where(id: params[:language_id]).first
unless CodaveriAsyncApiService.language_valid_for_codaveri?(language)
render json: {
success: false,
message: 'Language not supported'
}, status: :bad_request
end
generation_service = Course::Assessment::Question::CodaveriProblemGenerationService.new(
@assessment,
params[:custom_prompt],
# TODO: move these declarations (polyglot_language_name and _version) to polyglot repo
language.name.split[0].downcase,
language.name.split[1],
params[:difficulty]
)
generated_problem = generation_service.codaveri_generate_problem
render json: generated_problem, status: :ok
end
def update_question_setting
if @programming_question.update(programming_question_setting_params)
head :ok
else
error = @programming_question.errors.full_messages.to_sentence
render json: { errors: error }, status: :bad_request
end
end
def destroy
koditsu_question_id = @programming_question.acting_as.koditsu_question_id
success = @programming_question.class.transaction do
raise ActiveRecord::Rollback unless @programming_question.destroy
is_course_koditsu_enabled = current_course.component_enabled?(Course::KoditsuPlatformComponent)
if is_course_koditsu_enabled && @assessment.is_koditsu_enabled
@assessment.update!(is_synced_with_koditsu: false)
remove_question_from_assessment_in_koditsu(koditsu_question_id)
delete_koditsu_question(koditsu_question_id)
end
true
end
if success
head :ok
else
error = @programming_question.errors.full_messages.to_sentence
render json: { errors: error }, status: :bad_request
end
end
private
def format_test_cases
@public_test_cases = []
@private_test_cases = []
@evaluation_test_cases = []
@programming_question.test_cases.each do |test_case|
@public_test_cases << test_case if test_case.public_test?
@private_test_cases << test_case if test_case.private_test?
@evaluation_test_cases << test_case if test_case.evaluation_test?
end
end
def set_attributes_for_programming_question
@programming_question.max_time_limit = current_course.programming_max_time_limit
end
def programming_question_params
params.require(:question_programming).permit(
:title, :description, :staff_only_comments, :maximum_grade,
:language_id, :memory_limit, :time_limit, :attempt_limit,
:live_feedback_enabled, :live_feedback_custom_prompt,
:is_low_priority, :is_codaveri, *attachment_params,
question_assessment: { skill_ids: [] }
)
end
def programming_question_setting_params
params.require(:question_programming).permit(:is_codaveri, :live_feedback_enabled)
end
def render_success_json(redirect_to_edit)
render partial: 'response', locals: { redirect_to_edit: redirect_to_edit }
end
def render_failure_json
render json: { errors: @programming_question.errors.full_messages.to_sentence }, status: :bad_request
end
def process_package
return unless @programming_question.edit_online?
programming_package_service(params).generate_package
@meta = programming_package_service(params).extract_meta
@programming_question.multiple_file_submission = @meta[:data]['submit_as_file'] || false
end
def programming_package_service(params = nil)
@service ||= Course::Assessment::Question::Programming::ProgrammingPackageService.new(
@programming_question, params
)
end
def load_question_assessment
@question_assessment = load_question_assessment_for(@programming_question)
end
end