当前路径:app/common/model/exam/Paper.php <?php declare(strict_types=1); namespace app\common\model\exam; use app\common\model\account\User as UserModel; use app\common\model\Base; use app\common\model\exam\paper\Record; use app\control\model\User; use app\common\model\account\User as ModelUser; use Exception; use mb\helper\Collection; use think\facade\Db; use think\facade\Log; /** * Class Paper * @package app\common\model\exam */ class Paper { //组卷方式 public const MODE = ['hand', 'random']; //试卷类型 public const TYPE = ['competition', 'promote', 'beginner', 'simulate']; //出题方式 public const WAY = ['fixed', 'random', 'question']; /** * @param array $filter * @param int $pIndex * @param int $pSize * @param int $total * @return array */ public static function search(array $filter, int $pIndex = 1, int $pSize = 10, &$total = 0) { $where = []; if (!empty($filter['type'])) { $where[] = ['type', '=', $filter['type']]; } if (!empty($filter['title'])) { $where[] = ['title', 'like', "%{$filter['title']}%"]; } if (!empty($filter['mode'])) { $where[] = ['mode', '=', $filter['mode']]; } if (!empty($filter['timeStart'])) { $where[] = ['time_start', '<=', strtotime($filter['timeStart'])]; } if (!empty($filter['timeEnd'])) { $where[] = ['time_end', '>=', strtotime($filter['timeEnd'])]; } if (!empty($filter['id'])) { $where[] = ['id', '=', $filter['id']]; } if (!empty($filter['ids'])) { $where[] = ['id', 'in', $filter['ids']]; } if (!empty($filter['question'])) { $where[] = ['question', 'like', "%:{$filter['question']};%"]; } try { $total = Db::table('exam_papers')->where($where)->count(); $query = Db::table('exam_papers')->where($where); if (!empty($pIndex)) { $query->page($pIndex, $pSize); } $dataSet = $query->order('time_created', 'desc') ->field('id,title,type,mode,way,founder,time_start,time_end,total_points,question_type,time,result') ->select()->toArray(); if (!empty($dataSet)) { return array_map( function ($val) { $val = Collection::keyStyle($val, Collection::NAME_STYLE_JAVA); $userInfo = UserModel::fetch(intval($val['founder'])); $val['founderTitle'] = isset($userInfo['uid']) ? $userInfo['uid'] : ''; return $val; }, $dataSet ); } else { return []; } } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return []; } /** * @param array $data * @param int $id * @return int|string */ public static function modify(array $data, int $id) { $newData = Collection::keyStyle($data, Collection::NAME_STYLE_C); $questions = []; if ($newData['mode'] == 'hand') { foreach ($newData['strategies'] as &$str) { foreach ($str['strategy'] as $k => &$val) { if (!empty($val)) { if (!isset($questions[$str['type']])) { $questions[$str['type']] = []; } if ($newData['mode'] == 'hand') { array_push($questions[$str['type']], $val); continue; } } } } } else { $questions = self::make($newData['strategies']); if (is_error($questions)) { return error(-10, '题库策略发生变更,请修改试题策略'); } } $newData['strategies'] = serialize($newData['strategies']); $newData['question_type'] = serialize($newData['question_type']); $newData['question'] = serialize($questions); $newData['time_created'] = time(); $watch = $newData['watch']; $mark = $newData['mark']; $newData['watch'] = serialize($newData['watch']); $newData['mark'] = serialize($newData['mark']); try { if (empty($id)) { $id = Db::table('exam_papers')->insertGetId($newData); } else { unset($newData['time_created']); $where = self::parseFilters($id); $offect = Db::table('exam_papers')->where($where)->update($newData); if (!$offect === 1) { return 0; } } Base::watch('paper_watch', array_merge($watch, ['paramId' => $id, 'type' => '', 'binding_id' => 0])); Base::watch('paper_mark', array_merge($mark, ['paramId' => $id, 'type' => '', 'binding_id' => 0])); return $id; } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return 0; } /** * @param string $type * @param int $knowledge * @param int $subject * @param string $level * @return array */ public static function matchQuestion(string $type, int $knowledge, int $subject, string $level) { $question = Question::search( ['type' => $type, 'knowledge' => $knowledge, 'subjects' => $subject, 'difficultyLevel' => $level], 0 ); return Base::neaten($question, 'id'); } /** * 生成策略 * filter.type * filter.subject * filter.knowledge * mode * @param array $filter * @param string $mode * @return array */ public static function strategy(array $filter, string $mode) { $question = Question::search($filter, 0); if (empty($question)) { return []; } if ($mode == 'hand') { $question = array_map(function ($val) { unset($val['analysis'], $val['options'], $val['answer'], $val['score']); return $val; }, $question); return $question; } $type = []; foreach ($question as $v) { $type[$v['type']][] = $v; } $difficulty = Question::DIFFICULTY_LEVEL; $difficulty = array_keys($difficulty); $count = []; $res = []; foreach ($type as $t) { foreach ($difficulty as $d) { $count[$d] = 0; } foreach ($t as $item) { ++$count[$item['difficultyLevel']]; } $res[] = [ 'type' => $t[0]['type'], 'knowledge' => $t[0]['knowledge'], 'subject' => $t[0]['subject'], 'strategy' => $count ]; } return $res; } /** * @param $filters * @return array * @throws \think\Exception */ public static function parseFilters($filters) { $newFilters = []; if (is_array($filters)) { if (!empty($filters['id'])) { $newFilters[] = ['id', '=', $filters['id']]; } if (empty($filters)) { throw error(-19, '缺少必填参数ID'); } if (!empty($filters['founder'])) { $newFilters[] = ['founder', '=', $filters['founder']]; } } else { $newFilters[] = ['id', '=' ,intval($filters)]; } return $newFilters; } /** * @param $id * @return array|\think\Model|null * @throws \think\Exception */ public static function detail($id) { $filter = self::parseFilters($id); try { $detail = Db::table('exam_papers')->where($filter)->find(); if (empty($detail)) { return []; } $detail['strategies'] = @unserialize($detail['strategies']); $detail['question_type'] = @unserialize($detail['question_type']); $detail['watch'] = @unserialize($detail['watch']); $detail['mark'] = @unserialize($detail['mark']); $detail = Collection::keyStyle($detail, Collection::NAME_STYLE_JAVA); return $detail; } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return []; } /** * @param $id * @return bool */ public static function check($id) { try { $detail = self::detail($id); $user = User::fetchCurrent(); if (($user['role'] != 'root') && ($detail['founder'] != $user['id'])) { return false; } else { return true; } } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return false; } /** * @param string $type * @param string $ids * @return bool */ public static function delete(string $type, string $ids) { if ($type == 'single') { $where[] = ['id', '=', $ids]; $watchWhere[] = ['paper_id', '=', $ids]; } else { $where[] = ['id', 'in', "{$ids}"]; $watchWhere[] = ['paper_id', 'in', "{$ids}"]; } try { $offect = Db::table('exam_papers') ->where($where) ->delete(); if ($offect) { Db::table('exam_paper_mark')->where($watchWhere)->delete(); Db::table('exam_paper_watch')->where($watchWhere)->delete(); return true; } return false; } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return false; } /** * 试卷是否被使用 * @param array $paperIds * @return bool */ public static function paperUsed(array $paperIds) { try { foreach ($paperIds as $val) { $record = Record::recordNum(['paper' => intval($val)]); if (!empty($record)) { return false; break; } } return true; } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return false; } /** * 所有应参考人员 * @param $id * @return array|string */ public static function watchUsers($id) { try { $res = Db::table('exam_paper_watch')->where(['paper_id' => $id])->select()->toArray(); if ((count($res) == 1) && empty($res[0]['type'])) { $users = Db::table('account_users')->field('id')->select()->toArray(); return Base::neaten($users, 'id'); } $department = []; $user = []; foreach ($res as $val) { if ($val['type'] == 'department') { array_push($department, $val['binding_id']); } if ($val['type'] == 'user') { array_push($user, $val['binding_id']); } } $departmentUser = []; if (!empty($department)) { foreach ($department as $v) { $res = ModelUser::search(['department' => $v], 0); if (!empty($res)) { $ids = Base::neaten($res, 'id'); $departmentUser = array_merge($departmentUser, $ids); } } } $allUsers = array_unique(array_merge($departmentUser, $user)); return $allUsers; } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return []; } /** * @param $filter * @param null $question * @return array|\Error|\think\Exception * @throws \think\Exception */ public static function preview($filter, $question = null) { $filter = self::parseFilters($filter); try { $paper = Db::table('exam_papers')->where($filter)->withoutField('watch, mark, strategies')->find(); $paper['question_type'] = unserialize(Base::mb_unserialize($paper['question_type'])); if (empty($question)) { $question = @unserialize($paper['question']); } $check = self::checkQuestionExist($question); if (is_error($check)) { return error(-11, '题库发生变更,请联系管理员修改试卷内容'); } $paper['question'] = self::sort($paper['question_type'], $question, $paper['way']); $paper['questionNum'] = 0; foreach ($paper['question_type'] as $q) { $paper['questionNum'] += $q['questionNum']; } $paper = Collection::keyStyle($paper, Collection::NAME_STYLE_JAVA); return $paper; } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return []; } /** * 试卷题目排序 * @param $questionType * @param $question * @param $type * @return array */ public static function sort($questionType, $question, $type) { if (count($questionType) > 1) { $order = array_column($questionType, 'sort'); array_multisort($order, SORT_ASC, $questionType); } $questionType = Base::neaten($questionType, 'type'); $newData = []; foreach ($questionType as $v) { if ($type != 'fixed') { shuffle($question[$v]); } $newData[$v] = $question[$v]; } return $newData; } /** * @param $question * @return array|bool|\Error|\think\Exception */ public static function checkQuestionExist($question) { foreach ($question as $item) { $count = 0; Question::search(['ids' => $item], 0, 0, $count); if ($count != count($item)) { return error(-1, '题库发生变更,请联系管理员修改试卷内容'); } } return true; } /** * 所有用户可以看的试卷 * @param null $user * @return array */ public static function userWatch($user = null) { try { if (empty($user)) { $user = User::fetchCurrent(); } if ($user['role'] != 'root') { $paperIds = Db::table('exam_paper_watch')->where( "`type` = '' or (`type` = 'department' and `binding_id` = {$user['department']}) or (`type` = 'user' and `binding_id` = {$user['id']})" )->group('paper_id')->field('paper_id')->select()->toArray(); } else { $paperIds = Db::table('exam_papers')->group('id')->field('id as paper_id')->select()->toArray(); } return Base::neaten($paperIds, 'paper_id'); } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return []; } /** * @param $filter * @return array * @throws \think\Exception */ public static function fetch($filter) { $filter = self::parseFilters($filter); try { return Db::table('exam_papers')->where($filter)->find(); } catch (Exception $e) { Log::channel('myError')->write($e->getMessage(), \think\Log::ERROR); } return []; } /** * 组题 * @param $strategies * @return array */ public static function make($strategies) { $questions = []; foreach ($strategies as &$str) { foreach ($str['strategy'] as $k => &$val) { if (!empty($val)) { if (!isset($questions[$str['type']])) { $questions[$str['type']] = []; } $tmpQue = self::matchQuestion( $str['type'], $str['knowledge'], $str['subject'], $k ); if (empty($tmpQue) || ($val > count($tmpQue))) { return error(-1, '题库策略发生更改,请修改试卷策略'); } $tmpKey = array_rand($tmpQue, $val); $newArr = []; if (is_array($tmpKey)) { foreach ($tmpKey as $v) { $newArr[] = $tmpQue[$v]; } } else { $newArr = [$tmpQue[rand(0, count($tmpQue) - 1)]]; } $questions[$str['type']] = array_merge($questions[$str['type']], $newArr); } } } return $questions; } /** * 转换答题时间 * @param $times * @return string */ public static function secToTime($times) { $result = '00:00:00'; if ($times > 0) { $hour = strval(floor($times / 3600)); $minute = strval(floor(($times - 3600 * $hour) / 60)); $second = strval(floor((($times - 3600 * $hour) - 60 * $minute) % 60)); $hour = strlen($hour) == 1 ? '0' . $hour : $hour; $minute = strlen($minute) == 1 ? '0' . $minute : $minute; $second = strlen($second) == 1 ? '0' . $second : $second; $result = $hour . ':' . $minute . ':' . $second; } return $result; } }
相关源码
- 可旋转的彩色立方体C#源代码2021-10-29
- 在线考试系统2021-10-15
- EduSoho开源网校系统源码2019-06-27
- 仿拼多多小程序商城源码2019-06-06
- PHP5网站运行监测系统源码2017-04-14
关于我们 | 顾问团队 | 发展历程 | 联系我们 | 源码上传
联系电话(Tel):4008-010-151(免长途)
地址:北京市海淀区大恒科技大厦五层 邮编:100080
Floor 5th,Daheng Building,Zhongguancun,Beijing,China,100080
51Aspx.com 版权所有 CopyRight © 2006-2022. 京ICP备09089570号 | 京公网安备11010702000869号
联系电话(Tel):4008-010-151(免长途)
地址:北京市海淀区大恒科技大厦五层 邮编:100080
Floor 5th,Daheng Building,Zhongguancun,Beijing,China,100080
51Aspx.com 版权所有 CopyRight © 2006-2022. 京ICP备09089570号 | 京公网安备11010702000869号