ScoreAnalysisController.class.php 8.74 KB
<?php
/**
 * 【考试中心-后台】试卷考试成绩人数分布接口
 * ScoreAnalysisController.class.php
 * @author : wanghuan
 * @date   : 2017-07-17
 * @version: $Id$
 */

namespace Apicp\Controller\Answer;

use Common\Common\User;
use Common\Common\Department;
use Common\Service\PaperService;
use Common\Service\RightService;
use Common\Service\AnswerService;

class ScoreAnalysisController extends AbstractController
{
    // 最大区间数
    const AVGNUM_MAX = 10;
    // 最小区间数
    const AVGNUM_MIN = 9;

    /** @var PaperService */
    protected $paper_serv;
    /** @var RightService */
    protected $right_serv;
    /** @var AnswerService */
    protected $answer_serv;

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

        // 初始化User
        $this->user = User::instance();
        // 实例化试卷service
        $this->paper_serv = new PaperService();
        // 实例化权限service
        $this->right_serv = new RightService();
        // 实例化答卷service
        $this->answer_serv = new AnswerService();

        return true;
    }

    public function Index_post()
    {
        // 接收post参数
        $params = I('post.');
        // 参数为空,返回提示"参数不能为空"
        if (empty($params)) {

            E('_ERR_PARAMS_NOT_NULL');
        }

        // 试卷id
        $ep_id = intval($params['ep_id']);
        // 试卷id为空,返回提示"试卷ID不能为空"
        if (!$ep_id) {

            E('_EMPTY_EP_ID');
        }

        // 根据试卷id获取试卷详情
        $paper = $this->paper_serv->get($ep_id);
        // 试卷不存在
        if (empty($paper)) {

            E('_ERR_PAPER_NOT_FOUND');
        }

        // 查询条件初始化
        $answer_conds = [
            'ep_id' => $ep_id,
            'answer_status' => AnswerService::READ_OVER, // 已批阅
        ];

        // 【部门】
        if (isset($params['dpIds']) && !empty($params['dpIds']) && is_array($params['dpIds'])) {

            $params_dpids = $params['dpIds'];
            $dpServ = &Department::instance();
            // 取子级部门ID
            $child_ids = $dpServ->list_childrens_by_cdid($params_dpids);
            // 合并部门ID
            $dp_ids = array_merge($params_dpids, array_values($child_ids));

            $dp_conds = [
                'dpIdList' => $dp_ids
            ];
            $dp_users = $this->user->listAll($dp_conds);

            // 选择部门下的员工id集合
            $d_uids = array_column($dp_users, 'memUid');
            // 组装查询条件
            $dp_uids = $this->answer_serv->get_uids($paper['ep_id'], $d_uids);

            if (!empty($dp_uids)) {

                $answer_conds['uid'] = $dp_uids;
            } else {
                // 空查询所有 为了避免查询所有传入0
                $answer_conds['uid'] = [0];
            }
        }

        // 总分
        $score_total = 0;
        // 部门下考试的员工考试信息
        $join = [];
        // 试卷类型
        $paper_type = $paper['paper_type'];
        // 分页
        $page_option = null;
        // 排序
        $order_by = [];
        // 查询字段
        $fields = 'ea_id,uid,my_score,created';
        // 模拟考试
        if (PaperService::SIMULATION_PAPER_TYPE == $paper_type) {
            // 部门下模拟考试的员工考试信息
            $join = $this->answer_serv->get_mock_join_list($answer_conds, $page_option, $order_by, $fields);
            if (!empty($join)) {
                // 取考分列
                $my_max_score = array_column($join, 'my_max_score');
                // 考分之和
                $score_total = array_sum($my_max_score);
            }
        } elseif (PaperService::EVALUATION_PAPER_TYPE == $paper_type) { // 测评考试
            // 只用最高分进行计算
            $answer_conds['is_score_top'] = AnswerService::IS_SCORE_TOP_TRUE;
            // 部门测评考试通过的员工考试信息
            $join = $this->answer_serv->list_by_conds($answer_conds, $page_option, $order_by, $fields);
            if (!empty($join)) {
                // 取考分列
                $my_score = array_column($join, 'my_score');
                // 考分之和
                $score_total = array_sum($my_score);
            }
        }

        $data_x = [];
        $data_y = [];
        // 平均分初始化
        $average = 0;
        if (!empty($join)) {
            // 试卷总分
            $total_score = intval($paper['total_score']);
            // 试卷总分小于10
            if ($total_score < self::AVGNUM_MAX) {
                // x轴数据:分数区段
                $data_x = $this->numberAvg($total_score, $total_score);
            } else {
                // 余数
                $remainder = $total_score % self::AVGNUM_MAX;
                // 余数不为空
                if ($remainder) {
                    // 不能整除,除以9,余数放到第10份
                    $data_x = $this->numberAvg($total_score, self::AVGNUM_MIN);
                } else {
                    // 能够整除分10份
                    $data_x = $this->numberAvg($total_score, self::AVGNUM_MAX);
                }
            }

            // y轴数据:人数
            $data_y = $this->getListData($data_x, $join, $paper_type);
            // 平均分
            $average = round(($score_total / count($join)), 2);
        }

        // 返回结果
        $this->_result = [
            'average' => $average,
            'data_x' => $data_x,
            'data_y' => $data_y
        ];
    }

    /**
     * 组装返回的x轴、y轴数据
     *
     * @param $data_x array 成绩区间段
     * @param $join array 部门下有权限考试的员工的考试信息
     * @param $paper_type int 试卷类型:0=测评考试,1=模拟考试
     *
     * @return array 返回y轴数据
     */
    protected function getListData($data_x, $join, $paper_type)
    {
        // 模拟考试
        if (PaperService::SIMULATION_PAPER_TYPE == $paper_type) {

            $score_col = array_column($join, 'my_max_score');
        } elseif (PaperService::EVALUATION_PAPER_TYPE == $paper_type) { // 测评考试

            $score_col = array_column($join, 'my_score');
        }

        // 初始化返回数据
        $data_y = [];
        // 初始为与data_x等长的数组
        $data_y = array_pad($data_y, count($data_x), 0);
        $score_col = array_unique($score_col);

        // 组装返回数据
        foreach ($score_col as $score) {
            // 模拟考试
            if (PaperService::SIMULATION_PAPER_TYPE == $paper_type) {

                $score_list = $this->answer_serv->seekarr($join, 'my_max_score', $score);
            } elseif (PaperService::EVALUATION_PAPER_TYPE == $paper_type) { // 测评考试

                $score_list = $this->answer_serv->seekarr($join, 'my_score', $score);
            }

            // 分数为0,归为第一个分区
            if (0 == $score) {

                $data_y[0] = $data_y[0] + count($score_list);
            } else {
                // 循环判断是否在分数区段内
                foreach ($data_x as $key => $val) {
                    // 分隔分区分数
                    $score_arr = explode('-', $val);
                    // 分数在区段内,进行统计
                    if ($score > $score_arr[0] && $score <= $score_arr[1]) {

                        $data_y[$key] = $data_y[$key] + count($score_list);
                    }
                }
            }
        }

        return $data_y;
    }

    /**
     * 将一个数值划分为n个区段
     *
     * @param $number int 划分的数值(整数)
     * @param $avgNumber int 份数
     *
     * @return array 区段数组
     */
    protected function numberAvg($number, $avgNumber)
    {
        // 初始化
        $array = [];
        // 待划分数值为0,
        if ($number == 0) {
            // 返回份数长度值为0的数组
            $array = array_fill(0, $avgNumber, 0);
        } else {
            // 平均值整数部分
            $avg = floor($number / $avgNumber);
            // 余数
            $remainder = $number % $avgNumber;
            // 分段最大值
            $ceilSum = $avg * $avgNumber;

            $k = 0;
            for ($i = 0; $i < $avgNumber; $i++) {

                $str = $k . '-' . ($k + $avg);
                array_push($array, $str);
                $k = $k + $avg;
            }

            // 有余数
            if ($remainder) {

                $key = array_pop(array_keys($array)) + 1;
                $value = $ceilSum . '-' . $number;
                $array[$key] = strval($value);
            }
        }

        return $array;
    }
}