CreateExamController.class.php 5.93 KB
<?php
/**
 * 自动创建考卷
 * Created by PhpStorm.
 * User: yingcai
 * Date: 2017/8/9
 * Time: 下午3:12
 */

namespace Frontend\Controller\Callback;

use Common\Service\AnswerDetailTempService;
use Common\Service\AnswerTempService;
use Common\Service\PaperService;
use VcySDK\Cron;
use VcySDK\Service;

class CreateExamController extends AbstractController
{
    // 默认生成答卷份数
    const DEFAULT_CREATE_PAPERS = 50;
    // 生成考卷与人数比例
    const PERCENT_PAPERS = 0.4;

    // 默认考卷状态
    const DEFAULT_ANSWER_STATUS = 0;

    // 常规考试
    const NOMAL_TYPE = 1;
    // 非常规类生成考卷份数
    const UN_NOMAL_CREATE_PAPERS = 10;

    // 计划任务最大时间
    const CRON_TIME_MAX = 20;
    // 计划任务最小时间
    const CRON_TIME_MIN = 10;

    /** @var PaperService 试卷信息表 */
    protected $paper_s;
    /** @var AnswerTempService 随机答卷临时表 */
    protected $answer_temp;
    /** @var AnswerDetailTempService 随机答卷详情临时表 */
    protected $answer_temp_detail;

    public function before_action($action = '')
    {
        if (!parent::before_action($action)) {
            return false;
        }

        // 实例化试卷表
        $this->paper_s = new PaperService();
        // 实例化随机答卷临时表
        $this->answer_temp = new AnswerTempService();
        // 实例化随机答卷详情临时表
        $this->answer_temp_detail = new AnswerDetailTempService();

        return true;
    }

    public function Index()
    {
        set_time_limit(0);

        // 获取需要发送的试卷id
        $back = $this->callBackData;
        $ep_id = $back['ep_id'];

        // 非空判断
        if (empty($ep_id)) {

            return true;
        }

        // 获取试卷基本详情
        $paper = $this->paper_s->get($ep_id);
        if (empty($paper)) {

            return true;
        }

        // 是否是随机抽题
        if ($paper['ep_type'] != PaperService::TOPIC_RANDOM) {

            return true;
        }

        $cron_serv = new Cron(Service::instance());

        // 非常规类生成考卷份数
        $papers_count = self::UN_NOMAL_CREATE_PAPERS;

        // 常规考试
        if (self::NOMAL_TYPE == $paper['exam_type']) {
            // 应生成的考卷总份数(即权限范围总人数)
            $exam_papers = $paper['unjoin_count'] + $paper['join_count'];
            // 实际应生成的考卷份数
            $papers_count = round($exam_papers * self::PERCENT_PAPERS);
        }

        // 获取已生成的考卷数量
        $create_exam_papers = $this->answer_temp->count_by_conds(['ep_id' => $ep_id]);

        // 生成的考卷数量已达到上限
        if (($create_exam_papers > $papers_count || ($paper['end_time'] > 0 && $paper['end_time'] <= MILLI_TIME)
                || PaperService::PAPER_STOP == $paper['exam_status']) && !empty($paper['corn_create_exam'])
        ) {
            // 删除计划任务
            $cron_serv->delete($paper['corn_create_exam']);
            // 更新试卷计划任务为空
            $this->paper_s->update($ep_id, ['corn_create_exam' => '']);
            return true;
        }

        // 实际应生成的考卷份数:应生成份数-已有份数
        $create_papers_count = $papers_count - $create_exam_papers;
        // 实际应生成考卷分数大于低限设置
        if ($create_papers_count > self::DEFAULT_CREATE_PAPERS) {
            // 按比例应生成的考卷分数(四舍五入取整)
            $c = round($create_papers_count * self::PERCENT_PAPERS);
        } else { // 实际应生成考卷份数小于等于低限设置
            // 取实际应生成考卷份数
            $c = $create_papers_count;
        }

        for ($i = 0; $i < $c; $i++) {
            // 题库信息
            $bank_topic_data = unserialize($paper['bank_topic_data']);
            //题库ID集合
            $bank_ids = array_column($bank_topic_data, 'eb_id');

            // 选题规则
            $rule_data = [];
            if (!empty($paper['rule'])) {

                $rule_data = unserialize($paper['rule']);
            }
            // 新数据随机抽题
            $snapshot = $this->paper_s->random_rule_topic($bank_ids, $paper['ep_id'], $bank_topic_data, $rule_data);

            // 抽题失败
            if (empty($snapshot)) {

                return true;
            }

            // 组装随机答卷临时表数据
            $data_temp = [
                'ep_id' => $ep_id,
                'answer_status' => self::DEFAULT_ANSWER_STATUS,
            ];
            // 插入随机答卷临时表
            $eat_id = $this->answer_temp->insert($data_temp);

            // 组装随机答卷临时详情表数据
            foreach ($snapshot as &$val) {

                $val['eat_id'] = $eat_id;
                unset($val['eb_id'], $val['domain'], $val['status'], $val['created'], $val['updated'], $val['deleted']);
            }

            // 插入随机答卷临时表
            $this->answer_temp_detail->insert_all($snapshot);
        }

        // 修改计划任务执行时间
        $exam_begin_time = to_second_time($paper['begin_time']);
        // 计算当前距离考试开始时间还有多久
        $m_time = $exam_begin_time - NOW_TIME;
        $minute = $m_time > 0 ? floor($m_time / 60) : 0;

        // 距离考试开始大于20分钟
        if ($minute > self::CRON_TIME_MAX) {

            $params = [
                'crId' => $paper['corn_create_exam'],
                'crCron' => '0 0/20 * * * ?'
            ];
            $cron_serv->update($params);

            // 距离考试考试在10到20分钟之间
        } elseif ($minute > self::CRON_TIME_MIN && $minute <= self::CRON_TIME_MAX) {

            $params = [
                'crId' => $paper['corn_create_exam'],
                'crCron' => '0 0/10 * * * ?'
            ];
            $cron_serv->update($params);
        }

        return true;
    }
}