From 8680714720837eea5b58d1cfc26d4fbed8b479e7 Mon Sep 17 00:00:00 2001
From: cxt <853663049@qq.com>
Date: Fri, 3 Jan 2020 11:57:58 +0800
Subject: [PATCH] =?UTF-8?q?=E8=AF=95=E5=8D=B7=E7=9A=84=E7=BC=96=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../examination_banks_controller.rb           | 27 ++----
 .../examination_items_controller.rb           | 84 +++++++++++++++++++
 app/models/examination_item.rb                | 18 ++++
 .../examination_items/save_item_service.rb    | 50 +++++++++++
 config/routes.rb                              | 12 +++
 5 files changed, 173 insertions(+), 18 deletions(-)
 create mode 100644 app/controllers/examination_items_controller.rb
 create mode 100644 app/services/examination_items/save_item_service.rb

diff --git a/app/controllers/examination_banks_controller.rb b/app/controllers/examination_banks_controller.rb
index e5e9ca4ca..96767c21b 100644
--- a/app/controllers/examination_banks_controller.rb
+++ b/app/controllers/examination_banks_controller.rb
@@ -28,34 +28,25 @@ class ExaminationBanksController < ApplicationController
       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)
-          new_item.save!
-          item.increment!(:quotes)
-
-          if item.item_type == "PROGRAM"
-            new_hack = item.container.fork
-            new_item.update_attributes!(container: new_hack)
-          else
-            new_item.examination_item_analysis.create!(analysis: item.analysis)
-            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
+          new_item = ExaminationItem.new
+          new_item.new_item(item, exam, basket.score, basket.position)
         end
       end
 
       current_user.item_baskets.destroy_all
     end
     render_ok
+  rescue ApplicationService::Error => ex
+    render_error(ex.message)
   end
 
-  def edit
-
-  end
+  def edit; end
 
   def update
-
+    ExaminationBanks::SaveExaminationBankService.call(@exam, form_params)
+    render_ok
+  rescue ApplicationService::Error => ex
+    render_error(ex.message)
   end
 
   def destroy
diff --git a/app/controllers/examination_items_controller.rb b/app/controllers/examination_items_controller.rb
new file mode 100644
index 000000000..ee7a27c59
--- /dev/null
+++ b/app/controllers/examination_items_controller.rb
@@ -0,0 +1,84 @@
+class ExaminationItemsController < ApplicationController
+  before_action :require_login
+  before_action :validate_score, only: [:set_score, :batch_set_score]
+  before_action :find_exam, only: [:create, :batch_set_score, :delete_item_type]
+  before_action :find_item, except: [:create, :batch_set_score, :delete_item_type]
+  before_action :edit_auth
+
+  def create
+    ExaminationItems::SaveItemService.call(current_user, create_params, @exam)
+    render_ok
+  rescue ApplicationService::Error => ex
+    render_error(ex.message)
+  end
+
+  def destroy
+    ActiveRecord::Base.transaction do
+      @exam.examination_items.where(item_type: @item.item_type).where("position > #{@item.position}").update_all("position = position -1")
+      @item.destroy!
+    end
+    render_ok
+  end
+
+  def delete_item_type
+    items = @exam.examination_items.where(item_type: params[:item_type])
+    items.destroy_all
+    render_ok
+  end
+
+  def set_score
+    @item.update_attributes!(score: params[:score])
+    @questions_score = @exam.examination_items.where(item_type: @item.item_type).pluck(:score).sum
+    @all_score = @exam.examination_items.pluck(:score).sum
+    render_ok({questions_score: @questions_score, all_score: @all_score})
+  end
+
+  def batch_set_score
+    @exam.examination_items.where(item_type: params[:item_type]).update_all(score: params[:score])
+    @questions_score = @exam.examination_items.where(item_type: params[:item_type]).pluck(:score).sum
+    @all_score = @exam.examination_items.pluck(:score).sum
+    render_ok({questions_score: @questions_score, all_score: @all_score})
+  end
+
+  def adjust_position
+    same_items = @exam.examination_items.where(item_type: @item.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 > @item.position
+        same_items.where("position > #{@item.position} and position <= #{params[:position].to_i}").update_all("position=position-1")
+        @item.update_attributes!(position: params[:position])
+      elsif params[:position].to_i < @item.position
+        same_items.where("position < #{@item.position} and position >= #{params[:position].to_i}").update_all("position=position+1")
+        @item.update_attributes!(position: params[:position])
+      else
+        return normal_status(-1, "排序无变化")
+      end
+    end
+    render_ok
+  end
+
+  private
+
+  def find_exam
+    @exam = ExaminationBank.find_by!(id: params[:exam_id])
+  end
+
+  def create_params
+    params.permit(item_ids: [])
+  end
+
+  def find_item
+    @item = ExaminationItem.find_by!(id: params[:id])
+    @exam = @item.examination_bank
+  end
+
+  def validate_score
+    tip_exception("分值不能为空") unless params[:score].present?
+    tip_exception("分值需大于0") unless params[:score].to_f > 0
+  end
+
+  def edit_auth
+    current_user.admin_or_business? || @exam.user == current_user
+  end
+end
\ No newline at end of file
diff --git a/app/models/examination_item.rb b/app/models/examination_item.rb
index 0cc515cae..bfd1d6376 100644
--- a/app/models/examination_item.rb
+++ b/app/models/examination_item.rb
@@ -24,4 +24,22 @@ class ExaminationItem < ApplicationRecord
     0
   end
 
+  # 题库复制
+  def new_item item, exam, score, position
+    attributes = {examination_bank: exam, item_bank: item, name: item.name, item_type: item.item_type,
+                  difficulty: item.difficulty, score: score, position: position}
+    self.update!(attributes)
+    item.increment!(:quotes)
+
+    if item.item_type == "PROGRAM"
+      new_hack = item.container.fork
+      self.update!(container: new_hack)
+    else
+      ExaminationItemAnalysis.create!(analysis: item.analysis, examination_item_id: self.id)
+      item.item_choices.each do |choice|
+        examination_item_choices << ExaminationItemChoice.new(choice_text: choice.choice_text, is_answer: choice.is_answer)
+      end
+    end
+  end
+
 end
diff --git a/app/services/examination_items/save_item_service.rb b/app/services/examination_items/save_item_service.rb
new file mode 100644
index 000000000..34d5262a8
--- /dev/null
+++ b/app/services/examination_items/save_item_service.rb
@@ -0,0 +1,50 @@
+class ExaminationItems::SaveItemService < ApplicationService
+  attr_reader :user, :params, :exam
+
+  def initialize(user, params, exam)
+    @user = user
+    @params = params
+    @exam = exam
+  end
+
+  def call
+    raise("请选择试题") if params[:item_ids].blank?
+
+    # 只能选用公共题库或是自己的题库
+    items = ItemBank.where(public: 1).or(ItemBank.where(user_id: user.id))
+
+    # 已选到过试题篮的不重复选用
+    item_ids = params[:item_ids] - exam.examination_items.pluck(:item_bank_id)
+    items.where(id: item_ids).each do |item|
+      ActiveRecord::Base.transaction do
+        item_score = item_score item.item_type
+        item_position = item_position item.item_type
+        new_item = ExaminationItem.new
+        new_item.new_item(item, exam, item_score, item_position)
+      end
+    end
+  end
+
+  private
+
+  def item_score item_type
+    if exam.examination_items.where(item_type: item_type).last.present?
+      score = exam.examination_items.where(item_type: item_type).last.score
+    else
+      score =
+        case item_type
+        when "SINGLE", "MULTIPLE", "JUDGMENT"
+          5
+        when "PROGRAM"
+          10
+        else
+          5
+        end
+    end
+    score
+  end
+
+  def item_position item_type
+    exam.examination_items.where(item_type: item_type).last&.position.to_i + 1
+  end
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 77ffdfc2c..2409a8883 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -83,6 +83,18 @@ Rails.application.routes.draw do
       end
     end
 
+    resources :examination_items do
+      collection do
+        delete :delete_item_type
+        post :batch_set_score
+      end
+
+      member do
+        post :set_score
+        post :adjust_position
+      end
+    end
+
     resources :hacks, path: :problems,  param: :identifier do
       collection do
         get :unpulished_list