basePath . "/../lib/plugins/topic-html/src/TopicArr/TopicArr.php"; //include Yii::app()->basePath . "/../lib/plugins/topic-html/src/TopicArr/TopicHtmlArr.php"; class TeachingPhysics { private $subjectId; private $schoolId = 0; private $examId = 0; private $classId = 0; private $examGroupId = 0; private $error = array(); private $controllerObj = null;//controller对象 private $examObj = null; private $sprObj = null; private $sptRsObj = null; private $isPushSameTrain = false; public function __construct(&$controllerObj) { $this->controllerObj = $controllerObj; $documentRoot = Yii::app()->basePath . "/../"; require_once($documentRoot."lib/plugins/topic-html/vendor/autoload.php"); } /** * 生成PDF返回PDF地址 * @param $schoolId * @param $examId * @param int $force * @param int $viewHtml * @return array */ public function getTeachingPdf($schoolId,$examId,$force = 0,$viewHtml = 0) { if (!$schoolId) { $this->errorMsg(0, '学校ID不正确!'); } $this->schoolId = $schoolId; if(!$examId || !is_numeric($examId)){ $this->errorMsg(0, '考试ID参数不正确!'); } if (!$this->error) { $force = $viewHtml ? 1 : 0; if (is_cli()) { $force = 1; } $this->examId = $examId; $this->examObj = new Exam(); $examInfo = $this->examObj->getTeachingInfoPhysics($examId); if(!$examInfo){ $this->errorMsg(0, '没有考试信息!'); } $this->isPushSameTrain = $this->isPushSameTrain($examId); } if (!$this->error) { if($examInfo['subject_id']){ $this->subjectId = $examInfo['subject_id']; $this->examGroupId = $examInfo['exam_group_id']; $this->classId = $examInfo['class_id']; } $pdfurl = $examInfo['academicr_pdf_path']; $res = array();//生成pdf命令结果 if(strpos($examInfo['academicr_pdf_path'],'http') !== false){ if(!file_get_contents($examInfo['academicr_pdf_path'])){ $force = 1; } }else{ $force = 1; } if (!(!$examInfo['academicr_pdf_path'] || $examInfo['is_academicr_pdf'] == 0 || $force)) { //文件已生成不再生成 $result = array( 'status' => 0, 'error' => '', 'is_create' => 1, 'pdf_url' => $pdfurl, 'pdf_path' => '', ); return $result; } } if (!$this->error) { $paperObj = new SPaper(); $ptrObj = new SPaperTopicRelation(); $this->sprObj = new SStudentPaperRelation(); $this->sptRsObj = new SStudentPaperTopicRs(); /**************************** 一、班级情况分析 ***********************************/ //当前考试需要的数据 $actionRs = $this->curExamNeedData($this->sprObj ,$paperObj); if ($actionRs) { list($paperId, $paperScore, $examStuScore) = $actionRs; } //上次考试需要的数据 if (!$this->error) { $actionRs = $this->preExamNeedData($examInfo,$this->sprObj,$paperObj); if ($actionRs) { list($prePaperScore, $preExamStuScore) = $actionRs; } } //班级排名得分率人数等数据 if (!$this->error) { $classAnalyseArr = $this->getClassAnalyse($paperScore,$examStuScore,$prePaperScore, $preExamStuScore); } //大幅进步,大幅退步,前5名和后5名($needStudentArr:得分大于0的学生) if (!$this->error) { list($largeOrderArr,$needStudentArr) = $this->getLargeOrder($examStuScore,$preExamStuScore); } //unset($preExamStuScore); /**************************** 二、考试情况分析 ***********************************/ if (!$this->error) { $paperTopicInfo = $ptrObj->getPaperInfo($paperId); if(!$paperTopicInfo){ $this->errorMsg(0, '没有试卷题数据!'); }else{ $topicScoreArr = array(); foreach ($paperTopicInfo as $item) { $topicScoreArr[$item['topic_id']] = $item['score']; } $tplDataArr = json_decode($examInfo['tpl_data'], true); $topicNoArr = $this->getToicNoArr($paperTopicInfo, $tplDataArr); $changeDoTopicNoArr = $this->getChangeDoToicNoArr($paperTopicInfo, $tplDataArr); unset($paperTopicInfo); } } // 学生得分 if (!$this->error) { $stuRsArr = $this->sptRsObj->getStudentRsOnePaper($paperId); if(!$stuRsArr){ $this->errorMsg(0, '没有学生做题数据!'); } } if (!$this->error) { $paperAnalyseArr = $this->paperAnalyse($topicNoArr,$stuRsArr,$needStudentArr,$topicScoreArr,$changeDoTopicNoArr); } /**************************** 三、知识点掌握情况 ***********************************/ if (!$this->error) { $topicInfoArr = $this->getTopicInfoArr($topicNoArr); } if (!$this->error) { $kpsAnalyseArr = $this->kpsAnalyse($topicInfoArr,$topicScoreArr,$topicNoArr,$stuRsArr,$needStudentArr); } /**************************** 四、试卷讲评 ***********************************/ if (!$this->error) { $paperCommentsArr = $this->paperComments($needStudentArr,$stuRsArr,$topicScoreArr,$topicInfoArr,$topicNoArr); } /***************************** 五 共性题 ************************************/ if (!$this->error){ $commonTopic = $this->commonTopic(); } //获取试题详情 if (!$this->error) { $_topicInfoArr = array(); $topicIds = array(); foreach ($topicInfoArr as $topicId => $topicDetail) { $topicIds[$topicId] = $topicId; } unset($topicInfoArr); foreach ($paperCommentsArr as $topicDetail) { if (isset($topicDetail['push_topic_id']) && $topicDetail['push_topic_id']) { $topicIds[$topicDetail['push_topic_id']] = $topicDetail['push_topic_id']; } } foreach ($commonTopic as $ke=>$item){ $topicIds[$item['isp_topic_id']] = $item['isp_topic_id']; $commonTopic[$ke]['topic_no'] = isset($topicNoArr[$item["topic_id"]])?$topicNoArr[$item["topic_id"]]:$item['topic_no']; } $topicDetailArr = $this->getTopicInfoArrNoReplace($topicIds); } if (!$this->error) { $topicCss = $this->getTopicHtmlArr($_topicInfoArr, $topicDetailArr); } /**************************** 生产HTML和PDF ***********************************/ if (!$this->error) { //学生名称 $stuInfoObj = new SStudentInfo(); $stuNameArr = $stuInfoObj->getStudentNames(array_keys($needStudentArr)); $classObj = new SClass(); $className = $classObj->getClassName($this->classId); $data = array(); $data['stuScore'] = $examStuScore; $data['className'] = $className; $data['examInfo'] = $examInfo; $data['stuNameArr'] = $stuNameArr; $data['classAnalyseArr'] = $classAnalyseArr; $data['largeOrderArr'] = $largeOrderArr; $data['paperAnalyseArr'] = $paperAnalyseArr; $data['kpsAnalyseArr'] = $kpsAnalyseArr; $data['paperCommentsArr'] = $paperCommentsArr; $data['topicInfoArr'] = $_topicInfoArr; $data['topicCss'] = $topicCss; $data['stuNameArr'] = $stuNameArr; $data['zsyas2Url'] = $this->getDomain(); $data['commonTopics'] = $commonTopic; $data['isPushSameTrain'] = $this->isPushSameTrain($this->classId); if (is_cli()) { $html = $this->controllerObj->viewRender("teach_physics", $data, true); }else{ if ($viewHtml) { $this->controllerObj->renderPartial("teaching/teach_physics",$data);exit(); }else{ $html = $this->controllerObj->renderPartial("teaching/teach_physics", $data, true); } } unset($data); $actionRs = $this->htmlToPdf($res,$html,$className,$examInfo['exam_name']); if ($actionRs) { list($pdfurl, $pdfpath) = $actionRs; } } } if(!(isset($pdfurl) && $pdfurl && fileGetContents($pdfurl))){ $this->error[] = '文件尚未生成!!,错题信息:'.(isset($res)?json_encode($res):''); } $result = array( 'status' => 1, 'error' => '', 'is_create' => 0, 'pdf_url' => '', 'pdf_path' => '', ); if (!$this->error) { $result['status'] = 0; $result['is_create'] = 1; $result['pdf_url'] = $pdfurl; $result['pdf_path'] = $pdfpath; }else{ $result['error'] = implode(',',$this->error); } return $result; } /** * 试题详情 * @param $topicInfoArr * @param $topicDetailArr 题详情 */ protected function getTopicHtmlArr(&$topicInfoArr,&$topicDetailArr) { $topicHtmlObj = new \TopicHtml\TopicArr\TopicHtmlArr(); $topicHtmlObj->setIsShowAnswerParse(false); $topicCssObj = new \TopicHtml\TopicArr\TopicCss(); $topicCssObj->setTopicFontSize('7.5pt'); //选择题题干和选项是否分离 $topicCss = $topicCssObj->getTopicCss(); foreach ($topicDetailArr as $topic_id => $topicInfo) { $topicInfoArr[$topic_id] = $topicHtmlObj->getTopicHtmlArr($topicInfo); unset($topicInfo); } if (!$topicCss) { $this->errorMsg(0, '获取试题样式失败'); return ''; } return $topicCss; } /** * 获取题号 * @param $info 试卷题数据 * @param $tpl_data_arr exam tpl_data数组 */ private function getToicNoArr(&$info,$tplDataArr) { $topicNoArr = array(); foreach ($info as $item) { $topicNoArr[$item['topic_id']] = $item['order']; } asort($topicNoArr); $topicIdsArr = array_keys($topicNoArr); //选做题题号 if (isset($tplDataArr['new_items']) && $tplDataArr['new_items']) { foreach (array_values($tplDataArr['new_items']) as $key => $item) { if (isset($topicIdsArr[$key])) { $topic_id = $topicIdsArr[$key]; //$no = preg_replace('/[A-Za-z]+/','' ,$item['alias']); $no =$item['alias']; $topicNoArr[$topic_id] = $no; } } } //debug($topicNoArr); //asort($topicNoArr); return $topicNoArr; } /** * 判断PDF是否存在 * @param $pdf_path * @return bool */ private function check_pdf($pdf_path) { if (substr($pdf_path, strlen($pdf_path) - 4, 4) == ".pdf") { if (file_exists($pdf_path)) { return true; } } return false; } /** * 当前考试需要的数据 * @param $examObj * @param $examInfo * @param $sprObj * @param $paperObj */ private function curExamNeedData(&$sprObj,&$paperObj) { $error = array(); $examId = $this->examId; //试卷关联学生 $sprInfoArr = $sprObj->getStudentExamInfo(array($examId)); if(!$sprInfoArr){ $error[] = '考试没有学生数据!'; } if (!$error) { $examStuScore = array();//考试关联学生得分 $paperId = 0; foreach($sprInfoArr as $key => $value){ $studentId = $value['student_id']; $paperId = $value['paper_id']; $examStuScore[$studentId] = $value['scoring']; unset($sprInfoArr[$key]); } unset($sprInfoArr); //试卷总分 $paperScore = $paperObj->getPaperScore(array($paperId)); if(!$paperScore){ $error[] = '试卷总分不正确!'; } if (!$examStuScore) { $error[] = '没有当前班级数据!'; } } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return array($paperId,$paperScore, $examStuScore); } } /** * 上次考试需要的数据 * @param $examInfo * @param $examObj * @param $sprObj * @param $paperObj * @return array */ private function preExamNeedData($examInfo,$sprObj,$paperObj) { $error = array(); $examId = $this->examId; //获取当前考试的上一次考试数据 $cepObj = new SClassExamPrinter(); $preInfo = $cepObj->getPreExamId($examId,$examInfo['subject_id'],$examInfo['class_id']); $preExamId = isset($preInfo['exam_id'])?$preInfo['exam_id']:''; $prePaperScore = 0; $examRelPaper = array(); $preExamStuScore = array();//考试关联学生得分 if($preExamId){ $sprInfoArr = $sprObj->getStudentExamInfo(array($preExamId)); if(!$sprInfoArr){ $error[] = '考试没有关联学生数据!'; } if (!$error) { foreach($sprInfoArr as $key => $value){ $studentId = $value['student_id']; $examRelPaper[$value['exam_id']] = $value['paper_id']; $preExamStuScore[$studentId] = $value['scoring']; unset($sprInfoArr[$key]); } unset($sprInfoArr); if($examRelPaper){ $prePaperScore = $paperObj->getPaperScore(array_values($examRelPaper)); } if(!$prePaperScore){ $error[] = '试卷总分不正确!'; } } } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return array($prePaperScore, $preExamStuScore); } } /** * 班级排名得分率人数等数据 * @param $paperScore * @param $examStuScore * @return array */ private function getClassAnalyse($paperScore,&$examStuScore,$prePaperScore, &$preExamStuScore) { $error = array(); $classAnalyArr = array( 'exam_stu_num' => 0,//参加考试人数 'miss_stu_num' => 0,//缺考考人数 'avg_score_rate' => 0,//学生平均得分率 'pre_avg_rate_diff' => 0,//较上次考试平均得分率上升或下降 'avg_scoring' => 0,//学生平均分 'max_scoring' => 0,//最高分 'min_scoring' => 0,//最低分 'full_scoring' => 0,//满分 'pass_rate' => 0,//及格率 'pass_rate_gt_90' => 0,//其中得分率90%以上的有x人 ); $passStuNum = 0;//及格人数 foreach ($examStuScore as $stuId => $stuScoring) { if ($stuScoring > 0) { $classAnalyArr['exam_stu_num']++; }else{ $classAnalyArr['miss_stu_num']++; continue; } if ($stuScoring > $classAnalyArr['max_scoring']) { $classAnalyArr['max_scoring'] = $stuScoring; } if ($classAnalyArr['min_scoring'] == 0) { $classAnalyArr['min_scoring'] = $stuScoring; } if ($stuScoring < $classAnalyArr['min_scoring']) { $classAnalyArr['min_scoring'] = $stuScoring; } $scoring_rate = ($stuScoring / $paperScore) * 100; if ($scoring_rate >= 60) { $passStuNum++; } if ($scoring_rate > 90) { $classAnalyArr['pass_rate_gt_90']++; } } if (!$classAnalyArr['exam_stu_num']) { $error[] = '班级没有得分大于0的学生!'; } if (!$error) { $classAnalyArr['pass_rate'] = $this->numberFormat($passStuNum / $classAnalyArr['exam_stu_num'], 4) * 100; $classAnalyArr['full_scoring'] = $paperScore; $classAnalyArr['avg_score_rate'] = $this->numberFormat(array_sum($examStuScore) / ($classAnalyArr['exam_stu_num'] * $paperScore), 4) * 100; $classAnalyArr['avg_scoring'] = $this->numberFormat(array_sum($examStuScore) / $classAnalyArr['exam_stu_num'], 1); //上一次班级平均得分率 if ($preExamStuScore) { $preExamStuNum = 0;//上次参加考试人数 foreach ($preExamStuScore as $stuId => $stuScoring) { if ($stuScoring > 0) { $preExamStuNum++; } } //上次平均得分率 if ($preExamStuNum) { $preAvgScoreRate = $this->numberFormat(array_sum($preExamStuScore) / ($preExamStuNum * $prePaperScore), 4) * 100; }else{ $preAvgScoreRate = 0; } $classAnalyArr['pre_avg_rate_diff'] = intval($classAnalyArr['avg_score_rate'] - $preAvgScoreRate); } } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return $classAnalyArr; } } /** * 考试分析,大幅进步,大幅退步,前5名和后5名 * @param $examStuScore * @param $preExamStuScore * @return array */ private function getLargeOrder($examStuScore,$preExamStuScore){ $largeOrderArr = array( 'font_five' => array(),//班级前五名 'back_five' => array(),//班级后五名 'stu_diff_order' => array(),//名次提升或下降 'stu_order' => array(),//学生名次 'increase_stu' => array(),//大幅进步五名 'reduce_stu' => array(),//大幅退步五名 ); //得分数组(得分>0) $scoringArr = array(); $needStudentArr = array();//得分大于0的学生 foreach ($examStuScore as $stuId => $stuScoring) { if ($stuScoring > 0) { $scoringArr[] = $stuScoring; $needStudentArr[$stuId] = $stuId; } } //学生排名 $stuOrderArr = array(); foreach($examStuScore as $stuId => $stuScoring){ if($stuScoring > 0){ $stuOrderArr[$stuId] = $this->getOrder($stuScoring,$scoringArr); } } if($stuOrderArr){ asort($stuOrderArr); } $diffNum = ceil(count($stuOrderArr)*0.2); //班级前五名 //前5名和后5名 $font5 = $back5 = array(); $i = 1; foreach($stuOrderArr as $stuId => $order){ if($i <= 5){ $font5[$stuId] = $order; }else{ break; } $i++; } $largeOrderArr['font_five'] = $font5; $i = 1; //删除前5排名 $_stuOrderArr = $stuOrderArr; foreach($_stuOrderArr as $k => $order){ if(isset($font5[$k])){ unset($_stuOrderArr[$k]); } } arsort($_stuOrderArr); foreach($_stuOrderArr as $stuId => $order){ if($i <= 5){ $back5[$stuId] = $order; }else{ break; } $i++; } $largeOrderArr['back_five'] = $back5; /////大幅进步,退步 //上次得分数组(>0) $preScoringArr = array(); foreach ($preExamStuScore as $stuId => $stuScoring) { if ($stuScoring > 0) { $preScoringArr[] = $stuScoring; } } //上次考试学生排名 $preStuOrderArr = array(); foreach($preExamStuScore as $stuId => $stuScoring){ if($stuScoring>0){ $preStuOrderArr[$stuId] = $this->getOrder($stuScoring,$preScoringArr); } } if($preStuOrderArr){ asort($preStuOrderArr); } if($preStuOrderArr){ $interOrderArr = array_intersect_key($stuOrderArr,$preStuOrderArr); if(!$interOrderArr){ $interOrderArr = $stuOrderArr; } }else{ $interOrderArr = array(); } $increaseArr = $reduceArr = array(); $stuDiffOrder = array(); if($interOrderArr){ foreach($stuOrderArr as $stuId => $order){ if(isset($interOrderArr[$stuId]) && isset($preStuOrderArr[$stuId])){ $stuDiffOrder[$stuId] = -($order - $preStuOrderArr[$stuId]); }else{ $stuDiffOrder[$stuId] = 0; } } arsort($stuDiffOrder); foreach($stuDiffOrder as $stuId => $num){ if($num >= $diffNum){ $increaseArr[] = $stuId; } } $increaseArr = array_slice($increaseArr,0,5,true); asort($stuDiffOrder); foreach($stuDiffOrder as $stuId => $num){ if($num <= -$diffNum){ $reduceArr[] = $stuId; } } $reduceArr = array_slice($reduceArr,0,5,true); }else{ $increaseArr = array_slice($stuOrderArr,0,5,true); $reduceArr = array(); } $largeOrderArr['stu_diff_order'] = $stuDiffOrder; $largeOrderArr['stu_order'] = $stuOrderArr; $largeOrderArr['increase_stu'] = $increaseArr; $largeOrderArr['reduce_stu'] = $reduceArr; return array($largeOrderArr,$needStudentArr); } /** * 获取排名 * @param $ele * @param $arr * @return false|int|string */ private function getOrder($ele,$arr){ $orderRs = 0; if($arr){ arsort($arr); $arr = array_values($arr); $index = array_search($ele,$arr); $orderRs = $index + 1; } return $orderRs; } /** * 试卷情况分析 * @param $topicNoArr * @param $stuRsArr * @param $needStudentArr * @param $topicScoreArr * @return array */ private function paperAnalyse($topicNoArr,&$stuRsArr,$needStudentArr,$topicScoreArr,&$changeDoTopicNoArr) { //$changeTopicStuNum选做题实际做题人数 $changeTopicStuNum = $paperAnalyseArr = array(); $topicWrongNumArr = array();//题答错人数 foreach ($needStudentArr as $stuId) { if(!(isset($stuRsArr[$stuId])) && $stuRsArr[$stuId]) continue; foreach ($stuRsArr[$stuId] as $topicId => $rs) { if (!isset($topicWrongNumArr[$topicId])) { $topicWrongNumArr[$topicId] = 0; } if ($rs['scoring'] < $topicScoreArr[$topicId] ) { $topicWrongNumArr[$topicId]++; } if(!empty($changeDoTopicNoArr) && isset($changeDoTopicNoArr["list"][$topicId])){//选做题实际做题人数 if (!isset($changeTopicStuNum[$topicId])) { $changeTopicStuNum[$topicId] = 0; } $changeTopicStuNum[$topicId] ++; } } } $stuTotalNum = count($needStudentArr);//学生总人数 foreach ($topicNoArr as $topicId => $no) { $wrongNum = isset($topicWrongNumArr[$topicId]) ? $topicWrongNumArr[$topicId] : 0; if(!empty($changeDoTopicNoArr) && isset($changeDoTopicNoArr["list"][$topicId]) && isset($changeTopicStuNum[$topicId])){ $countStuTotalNum = $changeTopicStuNum[$topicId];//选做题实际做题人数 }else{ $countStuTotalNum = $stuTotalNum;//正常题目的人数 } $paperAnalyseArr[] = array( 'no' => $no, 'wrong_num' => $wrongNum, 'wrong_rate' => $this->numberFormat($wrongNum / $countStuTotalNum, 4) * 100, ); } return $paperAnalyseArr; } /** * 获取题内容 * @param $topicNoArr */ private function getTopicInfoArr($topicNoArr) { $error = array(); $topicIds = array_keys($topicNoArr); $_params = array('isFormat' => 1 , 'isTird' => 1); $topicDetails = $this->apiBrainPost('/topic/batchAll', array('topicIds' => $topicIds,'subjectId' => $this->subjectId ,'params' => $_params),25,true); if (!$topicDetails) { $error[] = '获取接口batchALL无数据!'; } elseif (isset($topicDetails['status']) && $topicDetails['status']==0) { $error[] = $topicDetails['error'][0]; } if (!$error) { // $diff_id_arr = array_diff($topicIds, array_keys($topicDetails)); $diff_id_arr = array(); foreach ($topicNoArr as $topicId => $v) { if (!isset($topicDetails[$topicId])) { $diff_id_arr[] = $topicId; } } if ($diff_id_arr) { $error[] = "没有试题内容!(" . implode(',', $diff_id_arr) . ")"; } } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return $topicDetails; } } /** * 获取题内容(不替换内容) * @param $topicNoArr */ private function getTopicInfoArrNoReplace($topicIds) { $error = array(); $topicDetailsArr = array(); $topicDetails = $this->apiBrainPost('/topic/batchAll', array('topicIds' => array_values($topicIds),'subjectId' => $this->subjectId),25,true); if (!$topicDetails) { $error[] = '获取接口batchALL无数据!'; } elseif (isset($topicDetails['status']) && $topicDetails['status']==0) { $error[] = $topicDetails['error'][0]; } if (!$error) { // $diff_id_arr = array_diff($topicIds, array_keys($topicDetails)); foreach ($topicDetails as $key => $detail) { $topicDetailsArr[number_format($detail['id'], 0, '', '')] = $detail; unset($topicDetails[$key]); } $diff_id_arr = array(); foreach ($topicIds as $topicId => $topicId) { if (!isset($topicDetailsArr[$topicId])) { $diff_id_arr[] = $topicId; } } if ($diff_id_arr) { $error[] = "没有试题内容!(" . implode(',', $diff_id_arr) . ")"; } } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return $topicDetailsArr; } } /** * 知识点掌握情况 * @param $topicInfoArr * @param $topicScoreArr * @param $topicNoArr * @param $stuRsArr * @param $needStudentArr * @return array */ public function kpsAnalyse(&$topicInfoArr,$topicScoreArr, &$topicNoArr,&$stuRsArr,$needStudentArr) { $kpsAnalyseArr = array(); $kpsNameArr = array();//知识点名称 $kpsTopicArr = array();//知识点关联的题 $topicKpsArr = array();//试题关联的知识点 foreach ($topicInfoArr as $topicId => $topicInfo) { if (!isset($topicKpsArr[$topicId])) { $topicKpsArr[$topicId] = array(); } if (isset($topicInfo['kps']) && is_array($topicInfo['kps']) && $topicInfo['kps']) { foreach ($topicInfo['kps'] as $kpId => $kpName) { $kpsNameArr[$kpId] = $kpName; if (!isset($kpsTopicArr[$kpId])) { $kpsTopicArr[$kpId] = array(); } $kpsTopicArr[$kpId][$topicId] = $topicId; $topicKpsArr[$topicId][$kpId] = $kpId; } } unset($topicInfo); } //试题对应的所有学生得分 $topicScoringArr = array();//试题得分 $topicTotalScoreArr = array();//试题总分 $wrongStuArr = array();//答错学生 foreach ($stuRsArr as $stuId => $stuTopicRs) { foreach ($stuTopicRs as $topicId => $stuRs) { if(!isset($needStudentArr[$stuId])) continue; if (!isset($topicScoringArr[$topicId])) { $topicScoringArr[$topicId] = 0; } $topicScoringArr[$topicId] += $stuRs['scoring']; if (!isset($topicTotalScoreArr[$topicId])) { $topicTotalScoreArr[$topicId] = 0; } $topicTotalScoreArr[$topicId] += isset($topicScoreArr[$topicId]) ? $topicScoreArr[$topicId] : 0; //答错学生 if ($stuRs['scoring'] < $topicScoreArr[$topicId]) { foreach ($topicKpsArr[$topicId] as $kpId) { if (!isset($wrongStuArr[$kpId])) { $wrongStuArr[$kpId] = array(); } $wrongStuArr[$kpId][$stuId] = $stuId; } } } } //计算班级得分率需要的数据 $kpsScoringArr = array();//知识点得分 $kpsTotalScoreArr = array();//知识点总分 $kpsTopicNoArr = array();//知识点总分 foreach ($kpsTopicArr as $kpId => $topicIds) { foreach ($topicIds as $topicId) { if(!isset($topicScoringArr[$topicId])) continue; if (!isset($kpsScoringArr[$kpId])) { $kpsScoringArr[$kpId] = 0; } $kpsScoringArr[$kpId] += $topicScoringArr[$topicId]; if (!isset($kpsTotalScoreArr[$kpId])) { $kpsTotalScoreArr[$kpId] = 0; } $kpsTotalScoreArr[$kpId] += $topicTotalScoreArr[$topicId]; if (!isset($kpsTopicNoArr[$kpId])) { $kpsTopicNoArr[$kpId] = array(); } $kpsTopicNoArr[$kpId][] = $topicNoArr[$topicId]; } } $classScoringRateArr = array();//班级得分率 $kpsRateStarArr = array();//知识点掌握水平 foreach ($kpsScoringArr as $kpId => $scoring) { $_rate = $this->numberFormat($scoring / $kpsTotalScoreArr[$kpId], 4) * 100; $classScoringRateArr[$kpId] = $_rate; $kpsRateStarArr[$kpId] = $this->getStarNum($_rate); } //表单排序:按知识点的班级得分率由高到低排序 arsort($classScoringRateArr); foreach ($classScoringRateArr as $kpId => $rate) { $kp_topic_no = isset($kpsTopicNoArr[$kpId]) ? $kpsTopicNoArr[$kpId] : array(); asort($kp_topic_no); $kpsAnalyseArr[] = array( 'kp_name' => isset($kpsNameArr[$kpId]) ? $kpsNameArr[$kpId] : '', 'kp_star' => isset($kpsRateStarArr[$kpId]) ? $kpsRateStarArr[$kpId] : 0, 'class_scoring_rate' => $rate, 'wrong_stu_num' => isset($wrongStuArr[$kpId]) ? count($wrongStuArr[$kpId]) : 0, 'kp_topic_no' => $kp_topic_no, ); } return $kpsAnalyseArr; } /** * 根据知识点的班级得分率显示1~5星 ★★★★★:90%≦班级得分率≦100% ★★★★:80%≦班级得分率<90% ★★★:70%≦班级得分率<80% ★★:60%≦班级得分率<70% ★:班级得分率<60% * @param $rate */ private function getStarNum($rate) { $starNum = 5; if ($rate >= 90 && $rate <= 100) { $starNum = 5; }elseif($rate >= 80 && $rate < 90){ $starNum = 4; }elseif($rate >= 70 && $rate < 80){ $starNum = 3; }elseif($rate >= 60 && $rate < 70){ $starNum = 2; }else{ $starNum = 1; } return $starNum; } /** * 试卷讲评 * @param $needStudentArr * @param $stuRsArr * @param $topicScoreArr * @param $topicInfoArr * @param $topicNoArr * @return array */ private function paperComments(&$needStudentArr,&$stuRsArr,$topicScoreArr,&$topicInfoArr,$topicNoArr) { $paperCommentsArr = array(); // $_paperCommentsArr = array( // 'topic_no' => 0,//试题序号 // 'class_scoring_rate' => 0,//班级得分率 // 'grade_scoring_rate' => 0,//年级得分率 // 'wrong_stu_arr' => 0,//答错学生 // 'right_stu_num' => 0,//答对学生数 // 'push_topic_id' => 0,//推送题ID // ); //试题对应的所有学生得分 $topicScoringArr = array();//试题得分 $topicTotalScoreArr = array();//试题总分 $wrongStuArr = array();//答错学生 $rightStuNumArr = array();//答对学生数 foreach ($stuRsArr as $stuId => $stuTopicRs) { foreach ($stuTopicRs as $topicId => $stuRs) { if(!isset($needStudentArr[$stuId])) continue; if (!isset($topicScoringArr[$topicId])) { $topicScoringArr[$topicId] = 0; } $topicScoringArr[$topicId] += $stuRs['scoring']; if (!isset($topicTotalScoreArr[$topicId])) { $topicTotalScoreArr[$topicId] = 0; } $topicTotalScoreArr[$topicId] += isset($topicScoreArr[$topicId]) ? $topicScoreArr[$topicId] : 0; //答错学生 if ($stuRs['scoring'] == $topicScoreArr[$topicId]) { if (!isset($rightStuNumArr[$topicId])) { $rightStuNumArr[$topicId] = 0; } $rightStuNumArr[$topicId]++; }else{ if (!isset($wrongStuArr[$topicId])) { $wrongStuArr[$topicId] = array(); } $wrongStuArr[$topicId][$stuId] = $stuId; } } } //班级得分率 $classScoringRateArr = array(); foreach ($topicScoringArr as $topicId => $scoring) { $classScoringRateArr[$topicId] = $this->numberFormat($scoring / $topicTotalScoreArr[$topicId], 2) * 100; } //推送试题 $pushTopicArr = $this->pushTopic($topicInfoArr); if ($pushTopicArr) { //年级得分率 $gradeScoringRateArr = $this->getGradeScoringRate($topicScoreArr); foreach ($topicNoArr as $topicId => $topicNo) { $_wrongStuArr = isset($wrongStuArr[$topicId]) ? $wrongStuArr[$topicId] : array(); $paperCommentsArr[] = array( 'topic_id' => $topicId, 'topic_no' => $topicNo, 'class_scoring_rate' => isset($classScoringRateArr[$topicId])?$classScoringRateArr[$topicId]:0, 'grade_scoring_rate' => isset($gradeScoringRateArr[$topicId])?$gradeScoringRateArr[$topicId]:0, 'wrong_stu_arr' => array_keys($_wrongStuArr), 'wrong_stu_num' => count($_wrongStuArr), 'right_stu_num' => isset($rightStuNumArr[$topicId])?$rightStuNumArr[$topicId]:0, 'push_topic_id' => isset($pushTopicArr[$topicId])?$pushTopicArr[$topicId]:array() ); } } return $paperCommentsArr; } /** * 推送试题 * @param $topicInfoArr * @return array */ private function pushTopic(&$topicInfoArr) { $error = array(); $pushTopicArr = array();//推送题 $topicRelTopicIdsArr = array();//试题关联题 $topicDiffArr = array();//试题难度系数 $relTopicArr = array();//所有关联题 foreach ($topicInfoArr as $topicId => $topicInfo) { $relationTopicArr = $topicInfo['relation_topic'] ? explode(',', $topicInfo['relation_topic']) : array(); $topicDiffArr[$topicId] = $topicInfo['difficulty_degree']; $topicRelTopicIdsArr[$topicId] = $relationTopicArr; foreach ($relationTopicArr as $_topicId) { $relTopicArr[$_topicId] = $_topicId; } } if(!$relTopicArr){ $error[] = '试题没有关联题'; } //关联题详情 if (!$error) { $relTopicDiffArr = array();//所有关联题难度 foreach (array_chunk($relTopicArr, 50) as $topicIds) { $_topicInfoArr = $this->getTopicInfoArr(array_flip($topicIds)); if ($_topicInfoArr) { foreach ($_topicInfoArr as $topicId => $_info) { $relTopicDiffArr[$topicId] = $_info['difficulty_degree']; } } unset($_topicInfoArr); } //从原题的关联题中推荐难度最接近的任1题即可 $pushedTopicArr = array();//已推送的题 foreach ($topicDiffArr as $topicId => $originDiff) { $relDiffArr = array();//关联题难度差 foreach ($topicRelTopicIdsArr[$topicId] as $relTopicId) { $relDiffArr[$relTopicId] = abs($originDiff - $relTopicDiffArr[$relTopicId]); } asort($relDiffArr); foreach ($relDiffArr as $_topicId => $diff) { if (isset($pushedTopicArr[$_topicId])) { continue; } $pushTopicArr[$topicId] = (string)$_topicId; $pushedTopicArr[$_topicId] = $_topicId; break; } } //获取推送题详情 if (!$pushTopicArr) { $error[] = '没有推送到试题'; } } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return $pushTopicArr; } } /** * 年级得分率 * @param $topicScoreArr 试题分数 * @param $topicScoringArr 试题得分(初始值是班级得分) * @param $topicTotalScoreArr 试题总分分(初始值是班级总分) * @return array */ private function getGradeScoringRate($topicScoreArr) { $gradeScoringRateArr = array(); $examIds = $this->examObj->getExamIds($this->examGroupId); $needStuArr = array();//得分大于0的学生 $paperIds = array(); if($examIds){ //试卷关联学生 $sprInfoArr = $this->sprObj->getStudentExamInfo($examIds); if ($sprInfoArr) { foreach ($sprInfoArr as $sprInfo) { if ($sprInfo['scoring'] > 0) { $needStuArr[$sprInfo['student_id']] = $sprInfo['student_id']; $paperIds[$sprInfo['paper_id']] = $sprInfo['paper_id']; } } } unset($sprInfoArr); } $topicScoringArr = array(); $topicTotalScoreArr = array(); if ($paperIds) { foreach ($paperIds as $paperId) { $_stuRsArr = $this->sptRsObj->getStudentRsOnePaper($paperId); if(!$_stuRsArr){ continue; } foreach ($_stuRsArr as $stuId => $stuTopicRs) { foreach ($stuTopicRs as $topicId => $stuRs) { if(!isset($needStuArr[$stuId])) continue; if (!isset($topicScoringArr[$topicId])) { $topicScoringArr[$topicId] = 0; } $topicScoringArr[$topicId] += $stuRs['scoring']; if (!isset($topicTotalScoreArr[$topicId])) { $topicTotalScoreArr[$topicId] = 0; } $topicTotalScoreArr[$topicId] += isset($topicScoreArr[$topicId]) ? $topicScoreArr[$topicId] : 0; } unset($stuTopicRs); } unset($_stuRsArr); } } //年级得分率 foreach ($topicScoringArr as $topicId => $scoring) { $gradeScoringRateArr[$topicId] = $this->numberFormat($scoring / $topicTotalScoreArr[$topicId], 2) * 100; } return $gradeScoringRateArr; } /** * hmtl生产PDF * @param $res * @param $html * @param $className * @param $examName * @return string */ private function htmlToPdf($res,&$html,$className,$examName) { $error = array(); $examId = $this->examId; $htmlpath = str_replace("protected", "", Yii::app()->basePath) . '/upload/tmpDir/academicr/'; //存放生成的HTML路径 $pdfpath = str_replace("protected", "", Yii::app()->basePath) . '/upload/tmpDir/academicr/' . $this->schoolId . "/"; //存放生成的PDF路径 $pdfurl = '/upload/tmpDir/academicr/' . $this->schoolId . "/"; if (!is_dir($htmlpath)) { if (!mkdir($htmlpath, 0777, true)) { $error[] = 'Create directory fail: ' . $htmlpath; } } if (!is_dir($pdfpath)) { if (!mkdir($pdfpath, 0777, true)) { $error[] = 'Create directory fail: ' . $pdfpath; } } if (!$error) { $locale='en_US.UTF-8'; // 或 $locale='zh_CN.UTF-8'; setlocale(LC_ALL,$locale); putenv('LC_ALL='.$locale); $htmlpath .= $examId . ".html"; $f = fopen($htmlpath, "w"); fwrite($f, $html); fclose($f); $htmlurl = '/upload/tmpDir/academicr/' . $examId . ".html"; //访问HTML的路径 $server = Yii::app()->params['phantomjs_server']; $js = 'html2pdf.js'; $htmlurl = $this->getDomain() . $htmlurl; $pdffname = $this->classId . "-" . $examId . ".pdf"; $pdfpath = $pdfpath . $pdffname; $pdfurl = $pdfurl . $pdffname; $commond = $server . " " . Yii::app()->basePath . '/../js/'.$js . " " . " {$htmlurl}" . " {$pdfpath}" . " 176mm*250mm '{$className}|||{$examName}|||时间:".date('Y-m-d')."'"; exec($commond, $res, $code); } if(isset($res) && isset($res[0])){ $isBool = false; foreach($res as $msg){ if (strpos($msg, 'succeed') !== false){ $isBool = true; } } if ($isBool) {//命令返回成功 if (file_exists($pdfpath)) { // $pdfurl=iconv("GBK", "UTF-8",$pdfurl); $repdf = $examId . ".pdf"; $rename = 'zsyas2/academicr/'.$this->schoolId.'/'. date('Y') . '/' . date('m') . '/' . date('d').'/'. uniqid() . '.' . $repdf; $ucloud = new HuaweiCloud(); $uploadInfo = $ucloud->putFile($rename, $pdfpath); if ($uploadInfo['status'] == 0) { $pdfurl = $this->getDomain() . $pdfurl; $this->getSchoolDbObj()->createCommand()->update("exam", array("academicr_pdf_path" => $pdfurl, "academicr_pdf_time" => time(), "is_academicr_pdf" => 1), "exam_id = '{$examId}'"); }else{ $pdfurl = $uploadInfo['url']; $this->getSchoolDbObj()->createCommand()->update("exam", array("academicr_pdf_path" => $pdfurl, "academicr_pdf_time" => time(), "is_academicr_pdf" => 1), "exam_id = '{$examId}'"); //批量生产不生产PDF if (!is_cli()) { @unlink($pdfpath); } } @unlink($htmlpath); } else { $this->getSchoolDbObj()->createCommand()->update("exam", array("academicr_pdf_path" => "", "academicr_pdf_time" => 0, "is_academicr_pdf" => 0), "exam_id = '{$examId}'"); @unlink($htmlpath); $error[] = 'PDF文件未找到! '; } } else { @unlink($htmlpath); $error[] = 'PDF创建失败!,错误信息:(' . json_encode($res) . ') '; } }else{ Curl::post(Yii::app()->params['handle_log_api'], array( "exam_group_id" => (string)$this->examGroupId, "operate_project" => 'zsyas2', "school_id" => $this->schoolId, "title" => '下载教师讲案', "operate_account" => is_cli()?'':Yii::app()->session['coachInfo']['coach_name'], "operate_method" => $this->action, "operate_url" => $this->getRoute(), "operate_sql" => '', "operate_param" =>json_encode(array('post'=>array("examId"=>$examId,"pdf"=>array("commond"=>$commond,"res"=>$res,"code"=>$code),"htmlurl"=>''))), )); $error[] = 'PDF创建失败! '; } if ($error) { $this->errorMsg(0, implode(',', $error)); return false; }else{ return array($pdfurl,$pdfpath); } } /** * 调题的接口 * @param $path * @param $arr * @param int $type * @return bool|mixed */ public function apiBrainPost($path, $arr, $timeout=25,$is_array = false) { $ch = @curl_init(); $result = FALSE; if ($ch) { $data = json_encode($arr); $url = Yii::app()->params['api'][0]['prefix'] . $path; $username = Yii::app()->params['api'][0]['username']; $password = Yii::app()->params['api'][0]['password']; curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password); // 不输出头部 curl_setopt($ch, CURLOPT_HEADER, 0); // curl_exec 获取到的内容不直接输出, 而是返回 curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_TIMEOUT,$timeout); // 请求重启路由器的地址 传参 进行重启 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, 'Api Client/1.0.0 (chengfei@liancaitech.com)'); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: '. strlen($data), )); if( !curl_errno($ch)) { $result = json_decode(curl_exec($ch),$is_array); } // 释放资源 curl_close($ch); } return $result; } public function getDomain() { if (is_cli()) { return Yii::app()->params['zsyas2_url']; }else{ return Yii::app()->request->hostInfo; } } /** * 错误信息 * @param $status * @param $msg */ private function errorMsg($status,$msg) { $this->error[] = $msg; // echo json_encode(array("status" => $status, "error" => $msg)); // exit; } /** * 学校数据库连接对象 * @return mixed */ protected function getSchoolDbObj() { if (is_cli()) { return $this->controllerObj->getSchConnObj(); }else{ return $this->controllerObj->sConn; } } /** * 数组格式化 * @param $num 小数 * @param $bat 小数位数 * @return float|int */ private function numberFormat($num,$bat) { $pow = pow(10, $bat); $num = $num * $pow; $num = floor($num) / $pow; return $num; } /** * 获取共性题数据 * @return array */ private function commonTopic() { $commonTopics = array(); if($this->isPushSameTrain){ $rs = SProductAlikeIspTopic::model()->getCommonTopic($this->examId,'template_id,topic_id'); foreach ($rs as $item){ $commonTopics[$item['template_id']]['topic_id'] = $item['template_id']; $commonTopics[$item['template_id']]['isp_topic_id'] = $item['topic_id']; } }else{ $rs = SProductCommonTopic::model()->getCommonTopic($this->examId, 0); foreach ($rs as $item){ $commonTopics[$item['template_id']]['topic_id'] = $item['template_id']; $commonTopics[$item['template_id']]['topic_no'] = $item['template_no']; $commonTopics[$item['template_id']]['isp_topic_id'] = $item['topic_id']; } } return $commonTopics; } //读取考试班级产品设置相同题 public function isPushSameTrain($classId) { $classSet=$this->getSchoolDbObj()->createCommand("select wb_isp from product_class_set where class_id='{$classId}' and subject_id=12")->queryScalar(); if($classSet){ $template=$this->getSchoolDbObj()->createCommand("select config_text from product_template where template_id={$classSet}")->queryScalar(); if($template){ $jsonData=json_decode($template,true); if(isset($jsonData['studentLevelDivide']['isPushSameTrain']) && $jsonData['studentLevelDivide']['isPushSameTrain']){ return true; } } }else{ $template=$this->getSchoolDbObj()->createCommand("select config_text from product_template where subject_id=12 and is_default=1 and product_type=3")->queryScalar(); if($template){ $jsonData=json_decode($template,true); if(isset($jsonData['studentLevelDivide']['isPushSameTrain']) && $jsonData['studentLevelDivide']['isPushSameTrain']){ return true; } } } return false; } /** * 获取选做题题号 * @param $info 题号 * @param $tpl_data_arr exam tpl_data数组 */ private function getChangeDoToicNoArr(&$info,$tplDataArr) { $topicNoArr = array(); foreach ($info as $item) { $topicNoArr[$item['topic_id']] = $item['order']; } asort($topicNoArr); $topicIdsArr = array_keys($topicNoArr); $changeDoToicNo = array( "list" => array(),//详情 "gather"=> array(),//汇总 ); //选做题题号 if (isset($tplDataArr['new_items']) && $tplDataArr['new_items']) { foreach (array_values($tplDataArr['new_items']) as $key => $item) { if (isset($topicIdsArr[$key]) && isset($item['sameAliasNo']) && $item['sameAliasNo']>0) { $topic_id = $topicIdsArr[$key]; $no =$item['alias']; $changeDoToicNo["list"][$topic_id]["sameAliasNo"] = $item['sameAliasNo'];//选做题组id $changeDoToicNo["list"][$topic_id]["smTopicLen"] = $item['smTopicLen'];//选做题组必做数量 $changeDoToicNo["list"][$topic_id]["no"] = $no;//选做题组必做数量 $changeDoToicNo["gather"][$item['sameAliasNo']][] = $topic_id; } } } asort($changeDoToicNo); return $changeDoToicNo; } }