diff --git a/app/controllers/examination_banks_controller.rb b/app/controllers/examination_banks_controller.rb new file mode 100644 index 000000000..9d5732fdc --- /dev/null +++ b/app/controllers/examination_banks_controller.rb @@ -0,0 +1,51 @@ +class ExaminationBanksController < ApplicationController + before_action :require_login + + def index + exams = ExaminationBankQuery.call(params) + @exams_count = exams.size + @exams = paginate exams.includes(:user, :examination_items) + end + + def show + + end + + def create + ActiveRecord::Base.transaction do + exam = ExaminationBank.new(user: current_user) + # 保存试卷基础信息 + exam = ExaminationBanks::SaveExaminationBankService.call(exam, form_params) + + # 将试题篮中的试题发送到试卷,试卷的题目与试题独立 + current_user.item_baskets.includes(:item_bank).each do |basket| + item = basket.item_bank + if item.present? + new_item = ExaminationItem.new(examination_bank: exam, item_bank: item, name: item.name, item_type: item.item_type, + difficulty: item.difficulty, score: basket.score, position: basket.position) + if new_item.save! + item.increment!(:quotes) + if item.item_choices.present? + item.item_choices.each do |choice| + new_item.examination_item_choices << ExaminationItemChoice.new(choice_text: choice.choice_text, is_answer: choice.is_answer) + end + end + end + end + end + + current_user.item_baskets.destroy_all + end + render_ok + end + + def edit + + end + + private + + def form_params + params.permit(:discipline_id, :sub_discipline_id, :difficulty, :name, :duration, tag_discipline_id: []) + end +end \ No newline at end of file diff --git a/app/controllers/item_baskets_controller.rb b/app/controllers/item_baskets_controller.rb index fc2af2849..21203346b 100644 --- a/app/controllers/item_baskets_controller.rb +++ b/app/controllers/item_baskets_controller.rb @@ -1,5 +1,7 @@ class ItemBasketsController < ApplicationController before_action :require_login + before_action :validate_score, only: [:set_score, :batch_set_score] + helper_method :current_basket def index @item_baskets = current_user.item_baskets @@ -41,9 +43,48 @@ class ItemBasketsController < ApplicationController render_ok end + def set_score + current_basket.update_attributes!(score: params[:score]) + @questions_score = current_user.item_baskets.where(item_type: current_basket.item_type).pluck(:score).sum + @all_score = current_user.item_baskets.pluck(:score).sum + end + + def batch_set_score + current_user.item_baskets.where(item_type: params[:item_type]).update_all(score: params[:score]) + @questions_score = current_user.item_baskets.where(item_type: params[:item_type]).pluck(:score).sum + @all_score = current_user.item_baskets.pluck(:score).sum + end + + def adjust_position + same_items = current_user.item_baskets.where(item_type: current_basket.item_type) + max_position = same_items.size + tip_exception("position超出范围") unless params[:position].present? && params[:position].to_i <= max_position && params[:position].to_i >= 1 + ActiveRecord::Base.transaction do + if params[:position].to_i > current_basket.position + same_items.where("position > #{current_basket.position} and position <= #{params[:position].to_i}").update_all("position=position-1") + current_basket.update_attributes!(position: params[:position]) + elsif params[:position].to_i < current_basket.position + same_items.where("position < #{current_basket.position} and position >= #{params[:position].to_i}").update_all("position=position+1") + current_basket.update_attributes!(position: params[:position]) + else + return normal_status(-1, "排序无变化") + end + end + render_ok + end + private def create_params params.permit(item_ids: []) end + + def current_basket + @_current_basket = current_user.item_baskets.find_by!(id: params[:id]) + end + + def validate_score + tip_exception("分值不能为空") unless params[:score].present? + tip_exception("分值需大于0") unless params[:score].to_f > 0 + end end \ No newline at end of file diff --git a/app/forms/examination_banks/save_exam_form.rb b/app/forms/examination_banks/save_exam_form.rb new file mode 100644 index 000000000..1835baa82 --- /dev/null +++ b/app/forms/examination_banks/save_exam_form.rb @@ -0,0 +1,12 @@ +class ExaminationBanks::SaveExamForm + include ActiveModel::Model + + attr_accessor :discipline_id, :sub_discipline_id, :difficulty, :name, :duration, :tag_discipline_id + + validates :discipline_id, presence: true + validates :sub_discipline_id, presence: true + validates :difficulty, presence: true, inclusion: {in: 1..3}, numericality: { only_integer: true } + validates :name, presence: true, length: { maximum: 60 } + validates :duration, numericality: { only_integer: true, greater_than: 0 } + +end \ No newline at end of file diff --git a/app/models/examination_bank.rb b/app/models/examination_bank.rb new file mode 100644 index 000000000..9df13ccd3 --- /dev/null +++ b/app/models/examination_bank.rb @@ -0,0 +1,17 @@ +class ExaminationBank < ApplicationRecord + belongs_to :user + belongs_to :sub_discipline + + has_many :tag_discipline_containers, as: :container, dependent: :destroy + has_many :tag_disciplines, through: :tag_discipline_containers + + has_many :examination_items, dependent: :destroy + + def question_count + examination_items.size + end + + def total_score + examination_items.pluck(:score).sum + end +end diff --git a/app/models/examination_item.rb b/app/models/examination_item.rb new file mode 100644 index 000000000..b9da32ab5 --- /dev/null +++ b/app/models/examination_item.rb @@ -0,0 +1,6 @@ +class ExaminationItem < ApplicationRecord + belongs_to :examination_bank, touch: true + belongs_to :item_bank, optional: true + + has_many :examination_item_choices, dependent: :destroy +end diff --git a/app/models/examination_item_choice.rb b/app/models/examination_item_choice.rb new file mode 100644 index 000000000..2bc35e0b1 --- /dev/null +++ b/app/models/examination_item_choice.rb @@ -0,0 +1,3 @@ +class ExaminationItemChoice < ApplicationRecord + belongs_to :examination_item +end diff --git a/app/queries/examination_bank_query.rb b/app/queries/examination_bank_query.rb new file mode 100644 index 000000000..c4cb7dee3 --- /dev/null +++ b/app/queries/examination_bank_query.rb @@ -0,0 +1,32 @@ +class ExaminationBankQuery < ApplicationQuery + include CustomSortable + attr_reader :params + + sort_columns :updated_at, default_by: :updated_at, default_direction: :desc, default_table: 'examination_banks' + + def initialize(params) + @params = params + end + + def call + if params[:public].to_i == 1 + exams = ExaminationBank.where(public: 1) + elsif params[:public].to_i == 0 + exams = ExaminationBank.where(user_id: User.current.id) + end + + if params[:tag_discipline_id].present? + exams = exams.joins(:tag_discipline_containers).where(tag_discipline_containers: {tag_discipline_id: params[:tag_discipline_id]}) + elsif params[:sub_discipline_id].present? + exams = exams.where(sub_discipline_id: params[:sub_discipline_id]) + elsif params[:discipline_id].present? + exams = exams.joins(:sub_discipline).where(sub_disciplines: {discipline_id: params[:discipline_id]}) + end + + exams = exams.where(difficulty: params[:difficulty].to_i) if params[:difficulty].present? + + exams = exams.where("name like ?", "%#{params[:keyword].strip}%") if params[:keyword].present? + + custom_sort(exams, params[:sort_by], params[:sort_direction]) + end +end \ No newline at end of file diff --git a/app/services/examination_banks/save_examination_bank_service.rb b/app/services/examination_banks/save_examination_bank_service.rb new file mode 100644 index 000000000..ab13e2412 --- /dev/null +++ b/app/services/examination_banks/save_examination_bank_service.rb @@ -0,0 +1,30 @@ +class ExaminationBanks::SaveExaminationBankService < ApplicationService + attr_reader :exam, :params + + def initialize(exam, params) + @exam = exam + @params = params + end + + def call + ExaminationBanks::SaveExamForm.new(params).validate! + + exam.name = params[:name].to_s.strip + exam.difficulty = params[:difficulty] + exam.duration = params[:duration] + exam.sub_discipline_id = params[:sub_discipline_id] + exam.save! + + # 知识点的创建 + new_tag_discipline_ids = params[:tag_discipline_id] || [] + old_tag_discipline_ids = exam.tag_discipline_containers.pluck(:tag_discipline_id) + delete_tag_discipline_ids = old_tag_discipline_ids - new_tag_discipline_ids + create_tag_discipline_ids = new_tag_discipline_ids - old_tag_discipline_ids + exam.tag_discipline_containers.where(tag_discipline_id: delete_tag_discipline_ids).destroy_all + create_tag_discipline_ids.each do |tag_id| + exam.tag_discipline_containers << TagDisciplineContainer.new(tag_discipline_id: tag_id) + end + + exam + end +end \ No newline at end of file diff --git a/app/services/item_banks/save_item_service.rb b/app/services/item_banks/save_item_service.rb index 0ae25661a..764a4812d 100644 --- a/app/services/item_banks/save_item_service.rb +++ b/app/services/item_banks/save_item_service.rb @@ -15,7 +15,7 @@ class ItemBanks::SaveItemService < ApplicationService item.item_type = params[:item_type] if new_record item.difficulty = params[:difficulty] item.sub_discipline_id = params[:sub_discipline_id] - item.name = params[:name].strip + item.name = params[:name].to_s.strip item.save! analysis = item.item_analysis || ItemAnalysis.new(item_bank_id: item.id) diff --git a/app/views/examination_banks/index.json.jbuilder b/app/views/examination_banks/index.json.jbuilder new file mode 100644 index 000000000..75bd006fe --- /dev/null +++ b/app/views/examination_banks/index.json.jbuilder @@ -0,0 +1,11 @@ +json.exams @exams.each do |exam| + json.(exam, :id, :name, :difficulty, :quotes) + json.question_count exam.question_count + json.total_score exam.total_score + json.update_time exam.updated_at&.strftime("%Y-%m-%d %H:%M") + json.author do + json.login exam.user&.login + json.name exam.user&.full_name + end +end +json.exam_count @exams_count \ No newline at end of file diff --git a/app/views/item_baskets/batch_set_score.json.jbuilder b/app/views/item_baskets/batch_set_score.json.jbuilder new file mode 100644 index 000000000..28dd1b653 --- /dev/null +++ b/app/views/item_baskets/batch_set_score.json.jbuilder @@ -0,0 +1,3 @@ +json.status 0 +json.questions_score @questions_score +json.all_score @all_score \ No newline at end of file diff --git a/app/views/item_baskets/set_score.json.jbuilder b/app/views/item_baskets/set_score.json.jbuilder new file mode 100644 index 000000000..28dd1b653 --- /dev/null +++ b/app/views/item_baskets/set_score.json.jbuilder @@ -0,0 +1,3 @@ +json.status 0 +json.questions_score @questions_score +json.all_score @all_score \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 3e5550528..c36d78741 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -66,9 +66,18 @@ Rails.application.routes.draw do collection do get :basket_list delete :delete_item_type + post :batch_set_score + end + + member do + post :set_score + post :adjust_position end end - + + resources :examination_banks do + + end resources :hacks, path: :problems, param: :identifier do collection do diff --git a/db/migrate/20191227023000_create_examination_banks.rb b/db/migrate/20191227023000_create_examination_banks.rb new file mode 100644 index 000000000..fdc123be6 --- /dev/null +++ b/db/migrate/20191227023000_create_examination_banks.rb @@ -0,0 +1,15 @@ +class CreateExaminationBanks < ActiveRecord::Migration[5.2] + def change + create_table :examination_banks do |t| + t.string :name + t.integer :difficulty, default: 1 + t.references :user, index: true + t.boolean :public, default: 0 + t.integer :quotes, default: 0 + t.references :sub_discipline, index: true + t.integer :duration + + t.timestamps + end + end +end diff --git a/db/migrate/20191227024334_create_examination_items.rb b/db/migrate/20191227024334_create_examination_items.rb new file mode 100644 index 000000000..c96fd2435 --- /dev/null +++ b/db/migrate/20191227024334_create_examination_items.rb @@ -0,0 +1,15 @@ +class CreateExaminationItems < ActiveRecord::Migration[5.2] + def change + create_table :examination_items do |t| + t.references :examination_bank, index: true + t.references :item_bank, index: true + t.string :name + t.integer :item_type, default: 0 + t.integer :difficulty, default: 1 + t.float :score, default: 0 + t.integer :position, default: 0 + + t.timestamps + end + end +end diff --git a/db/migrate/20191227024638_create_examination_item_choices.rb b/db/migrate/20191227024638_create_examination_item_choices.rb new file mode 100644 index 000000000..3976a30d9 --- /dev/null +++ b/db/migrate/20191227024638_create_examination_item_choices.rb @@ -0,0 +1,11 @@ +class CreateExaminationItemChoices < ActiveRecord::Migration[5.2] + def change + create_table :examination_item_choices do |t| + t.references :examination_item, index: true + t.text :choice_text + t.boolean :is_answer, default: 0 + + t.timestamps + end + end +end diff --git a/spec/models/examination_bank_spec.rb b/spec/models/examination_bank_spec.rb new file mode 100644 index 000000000..28e5878e2 --- /dev/null +++ b/spec/models/examination_bank_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ExaminationBank, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/examination_item_choice_spec.rb b/spec/models/examination_item_choice_spec.rb new file mode 100644 index 000000000..0907fd09e --- /dev/null +++ b/spec/models/examination_item_choice_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ExaminationItemChoice, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/examination_item_spec.rb b/spec/models/examination_item_spec.rb new file mode 100644 index 000000000..b824896df --- /dev/null +++ b/spec/models/examination_item_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe ExaminationItem, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end