TeachingPhysics.php 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511
  1. <?php
  2. /**
  3. * 新版物理教学宝
  4. * User: Administrator
  5. * Date: 2021/3/18
  6. * Time: 14:48
  7. */
  8. //include Yii::app()->basePath . "/../lib/plugins/topic-html/src/TopicArr/TopicArr.php";
  9. //include Yii::app()->basePath . "/../lib/plugins/topic-html/src/TopicArr/TopicHtmlArr.php";
  10. class TeachingPhysics
  11. {
  12. private $subjectId;
  13. private $schoolId = 0;
  14. private $examId = 0;
  15. private $classId = 0;
  16. private $examGroupId = 0;
  17. private $error = array();
  18. private $controllerObj = null;//controller对象
  19. private $examObj = null;
  20. private $sprObj = null;
  21. private $sptRsObj = null;
  22. private $isPushSameTrain = false;
  23. public function __construct(&$controllerObj)
  24. {
  25. $this->controllerObj = $controllerObj;
  26. $documentRoot = Yii::app()->basePath . "/../";
  27. require_once($documentRoot."lib/plugins/topic-html/vendor/autoload.php");
  28. }
  29. /**
  30. * 生成PDF返回PDF地址
  31. * @param $schoolId
  32. * @param $examId
  33. * @param int $force
  34. * @param int $viewHtml
  35. * @return array
  36. */
  37. public function getTeachingPdf($schoolId,$examId,$force = 0,$viewHtml = 0)
  38. {
  39. if (!$schoolId) {
  40. $this->errorMsg(0, '学校ID不正确!');
  41. }
  42. $this->schoolId = $schoolId;
  43. if(!$examId || !is_numeric($examId)){
  44. $this->errorMsg(0, '考试ID参数不正确!');
  45. }
  46. if (!$this->error) {
  47. $force = $viewHtml ? 1 : 0;
  48. if (is_cli()) {
  49. $force = 1;
  50. }
  51. $this->examId = $examId;
  52. $this->examObj = new Exam();
  53. $examInfo = $this->examObj->getTeachingInfoPhysics($examId);
  54. if(!$examInfo){
  55. $this->errorMsg(0, '没有考试信息!');
  56. }
  57. $this->isPushSameTrain = $this->isPushSameTrain($examId);
  58. }
  59. if (!$this->error) {
  60. if($examInfo['subject_id']){
  61. $this->subjectId = $examInfo['subject_id'];
  62. $this->examGroupId = $examInfo['exam_group_id'];
  63. $this->classId = $examInfo['class_id'];
  64. }
  65. $pdfurl = $examInfo['academicr_pdf_path'];
  66. $res = array();//生成pdf命令结果
  67. if(strpos($examInfo['academicr_pdf_path'],'http') !== false){
  68. if(!file_get_contents($examInfo['academicr_pdf_path'])){
  69. $force = 1;
  70. }
  71. }else{
  72. $force = 1;
  73. }
  74. if (!(!$examInfo['academicr_pdf_path'] || $examInfo['is_academicr_pdf'] == 0 || $force)) {
  75. //文件已生成不再生成
  76. $result = array(
  77. 'status' => 0,
  78. 'error' => '',
  79. 'is_create' => 1,
  80. 'pdf_url' => $pdfurl,
  81. 'pdf_path' => '',
  82. );
  83. return $result;
  84. }
  85. }
  86. if (!$this->error) {
  87. $paperObj = new SPaper();
  88. $ptrObj = new SPaperTopicRelation();
  89. $this->sprObj = new SStudentPaperRelation();
  90. $this->sptRsObj = new SStudentPaperTopicRs();
  91. /**************************** 一、班级情况分析 ***********************************/
  92. //当前考试需要的数据
  93. $actionRs = $this->curExamNeedData($this->sprObj ,$paperObj);
  94. if ($actionRs) {
  95. list($paperId, $paperScore, $examStuScore) = $actionRs;
  96. }
  97. //上次考试需要的数据
  98. if (!$this->error) {
  99. $actionRs = $this->preExamNeedData($examInfo,$this->sprObj,$paperObj);
  100. if ($actionRs) {
  101. list($prePaperScore, $preExamStuScore) = $actionRs;
  102. }
  103. }
  104. //班级排名得分率人数等数据
  105. if (!$this->error) {
  106. $classAnalyseArr = $this->getClassAnalyse($paperScore,$examStuScore,$prePaperScore, $preExamStuScore);
  107. }
  108. //大幅进步,大幅退步,前5名和后5名($needStudentArr:得分大于0的学生)
  109. if (!$this->error) {
  110. list($largeOrderArr,$needStudentArr) = $this->getLargeOrder($examStuScore,$preExamStuScore);
  111. }
  112. //unset($preExamStuScore);
  113. /**************************** 二、考试情况分析 ***********************************/
  114. if (!$this->error) {
  115. $paperTopicInfo = $ptrObj->getPaperInfo($paperId);
  116. if(!$paperTopicInfo){
  117. $this->errorMsg(0, '没有试卷题数据!');
  118. }else{
  119. $topicScoreArr = array();
  120. foreach ($paperTopicInfo as $item) {
  121. $topicScoreArr[$item['topic_id']] = $item['score'];
  122. }
  123. $tplDataArr = json_decode($examInfo['tpl_data'], true);
  124. $topicNoArr = $this->getToicNoArr($paperTopicInfo, $tplDataArr);
  125. $changeDoTopicNoArr = $this->getChangeDoToicNoArr($paperTopicInfo, $tplDataArr);
  126. unset($paperTopicInfo);
  127. }
  128. }
  129. // 学生得分
  130. if (!$this->error) {
  131. $stuRsArr = $this->sptRsObj->getStudentRsOnePaper($paperId);
  132. if(!$stuRsArr){
  133. $this->errorMsg(0, '没有学生做题数据!');
  134. }
  135. }
  136. if (!$this->error) {
  137. $paperAnalyseArr = $this->paperAnalyse($topicNoArr,$stuRsArr,$needStudentArr,$topicScoreArr,$changeDoTopicNoArr);
  138. }
  139. /**************************** 三、知识点掌握情况 ***********************************/
  140. if (!$this->error) {
  141. $topicInfoArr = $this->getTopicInfoArr($topicNoArr);
  142. }
  143. if (!$this->error) {
  144. $kpsAnalyseArr = $this->kpsAnalyse($topicInfoArr,$topicScoreArr,$topicNoArr,$stuRsArr,$needStudentArr);
  145. }
  146. /**************************** 四、试卷讲评 ***********************************/
  147. if (!$this->error) {
  148. $paperCommentsArr = $this->paperComments($needStudentArr,$stuRsArr,$topicScoreArr,$topicInfoArr,$topicNoArr);
  149. }
  150. /***************************** 五 共性题 ************************************/
  151. if (!$this->error){
  152. $commonTopic = $this->commonTopic();
  153. }
  154. //获取试题详情
  155. if (!$this->error) {
  156. $_topicInfoArr = array();
  157. $topicIds = array();
  158. foreach ($topicInfoArr as $topicId => $topicDetail) {
  159. $topicIds[$topicId] = $topicId;
  160. }
  161. unset($topicInfoArr);
  162. foreach ($paperCommentsArr as $topicDetail) {
  163. if (isset($topicDetail['push_topic_id']) && $topicDetail['push_topic_id']) {
  164. $topicIds[$topicDetail['push_topic_id']] = $topicDetail['push_topic_id'];
  165. }
  166. }
  167. foreach ($commonTopic as $ke=>$item){
  168. $topicIds[$item['isp_topic_id']] = $item['isp_topic_id'];
  169. $commonTopic[$ke]['topic_no'] = isset($topicNoArr[$item["topic_id"]])?$topicNoArr[$item["topic_id"]]:$item['topic_no'];
  170. }
  171. $topicDetailArr = $this->getTopicInfoArrNoReplace($topicIds);
  172. }
  173. if (!$this->error) {
  174. $topicCss = $this->getTopicHtmlArr($_topicInfoArr, $topicDetailArr);
  175. }
  176. /**************************** 生产HTML和PDF ***********************************/
  177. if (!$this->error) {
  178. //学生名称
  179. $stuInfoObj = new SStudentInfo();
  180. $stuNameArr = $stuInfoObj->getStudentNames(array_keys($needStudentArr));
  181. $classObj = new SClass();
  182. $className = $classObj->getClassName($this->classId);
  183. $data = array();
  184. $data['stuScore'] = $examStuScore;
  185. $data['className'] = $className;
  186. $data['examInfo'] = $examInfo;
  187. $data['stuNameArr'] = $stuNameArr;
  188. $data['classAnalyseArr'] = $classAnalyseArr;
  189. $data['largeOrderArr'] = $largeOrderArr;
  190. $data['paperAnalyseArr'] = $paperAnalyseArr;
  191. $data['kpsAnalyseArr'] = $kpsAnalyseArr;
  192. $data['paperCommentsArr'] = $paperCommentsArr;
  193. $data['topicInfoArr'] = $_topicInfoArr;
  194. $data['topicCss'] = $topicCss;
  195. $data['stuNameArr'] = $stuNameArr;
  196. $data['zsyas2Url'] = $this->getDomain();
  197. $data['commonTopics'] = $commonTopic;
  198. $data['isPushSameTrain'] = $this->isPushSameTrain($this->classId);
  199. if (is_cli()) {
  200. $html = $this->controllerObj->viewRender("teach_physics", $data, true);
  201. }else{
  202. if ($viewHtml) {
  203. $this->controllerObj->renderPartial("teaching/teach_physics",$data);exit();
  204. }else{
  205. $html = $this->controllerObj->renderPartial("teaching/teach_physics", $data, true);
  206. }
  207. }
  208. unset($data);
  209. $actionRs = $this->htmlToPdf($res,$html,$className,$examInfo['exam_name']);
  210. if ($actionRs) {
  211. list($pdfurl, $pdfpath) = $actionRs;
  212. }
  213. }
  214. }
  215. if(!(isset($pdfurl) && $pdfurl && fileGetContents($pdfurl))){
  216. $this->error[] = '文件尚未生成!!,错题信息:'.(isset($res)?json_encode($res):'');
  217. }
  218. $result = array(
  219. 'status' => 1,
  220. 'error' => '',
  221. 'is_create' => 0,
  222. 'pdf_url' => '',
  223. 'pdf_path' => '',
  224. );
  225. if (!$this->error) {
  226. $result['status'] = 0;
  227. $result['is_create'] = 1;
  228. $result['pdf_url'] = $pdfurl;
  229. $result['pdf_path'] = $pdfpath;
  230. }else{
  231. $result['error'] = implode(',',$this->error);
  232. }
  233. return $result;
  234. }
  235. /**
  236. * 试题详情
  237. * @param $topicInfoArr
  238. * @param $topicDetailArr 题详情
  239. */
  240. protected function getTopicHtmlArr(&$topicInfoArr,&$topicDetailArr)
  241. {
  242. $topicHtmlObj = new \TopicHtml\TopicArr\TopicHtmlArr();
  243. $topicHtmlObj->setIsShowAnswerParse(false);
  244. $topicCssObj = new \TopicHtml\TopicArr\TopicCss();
  245. $topicCssObj->setTopicFontSize('7.5pt');
  246. //选择题题干和选项是否分离
  247. $topicCss = $topicCssObj->getTopicCss();
  248. foreach ($topicDetailArr as $topic_id => $topicInfo) {
  249. $topicInfoArr[$topic_id] = $topicHtmlObj->getTopicHtmlArr($topicInfo);
  250. unset($topicInfo);
  251. }
  252. if (!$topicCss) {
  253. $this->errorMsg(0, '获取试题样式失败');
  254. return '';
  255. }
  256. return $topicCss;
  257. }
  258. /**
  259. * 获取题号
  260. * @param $info 试卷题数据
  261. * @param $tpl_data_arr exam tpl_data数组
  262. */
  263. private function getToicNoArr(&$info,$tplDataArr)
  264. {
  265. $topicNoArr = array();
  266. foreach ($info as $item) {
  267. $topicNoArr[$item['topic_id']] = $item['order'];
  268. }
  269. asort($topicNoArr);
  270. $topicIdsArr = array_keys($topicNoArr);
  271. //选做题题号
  272. if (isset($tplDataArr['new_items']) && $tplDataArr['new_items']) {
  273. foreach (array_values($tplDataArr['new_items']) as $key => $item) {
  274. if (isset($topicIdsArr[$key])) {
  275. $topic_id = $topicIdsArr[$key];
  276. //$no = preg_replace('/[A-Za-z]+/','' ,$item['alias']);
  277. $no =$item['alias'];
  278. $topicNoArr[$topic_id] = $no;
  279. }
  280. }
  281. }
  282. //debug($topicNoArr);
  283. //asort($topicNoArr);
  284. return $topicNoArr;
  285. }
  286. /**
  287. * 判断PDF是否存在
  288. * @param $pdf_path
  289. * @return bool
  290. */
  291. private function check_pdf($pdf_path) {
  292. if (substr($pdf_path, strlen($pdf_path) - 4, 4) == ".pdf") {
  293. if (file_exists($pdf_path)) {
  294. return true;
  295. }
  296. }
  297. return false;
  298. }
  299. /**
  300. * 当前考试需要的数据
  301. * @param $examObj
  302. * @param $examInfo
  303. * @param $sprObj
  304. * @param $paperObj
  305. */
  306. private function curExamNeedData(&$sprObj,&$paperObj)
  307. {
  308. $error = array();
  309. $examId = $this->examId;
  310. //试卷关联学生
  311. $sprInfoArr = $sprObj->getStudentExamInfo(array($examId));
  312. if(!$sprInfoArr){
  313. $error[] = '考试没有学生数据!';
  314. }
  315. if (!$error) {
  316. $examStuScore = array();//考试关联学生得分
  317. $paperId = 0;
  318. foreach($sprInfoArr as $key => $value){
  319. $studentId = $value['student_id'];
  320. $paperId = $value['paper_id'];
  321. $examStuScore[$studentId] = $value['scoring'];
  322. unset($sprInfoArr[$key]);
  323. }
  324. unset($sprInfoArr);
  325. //试卷总分
  326. $paperScore = $paperObj->getPaperScore(array($paperId));
  327. if(!$paperScore){
  328. $error[] = '试卷总分不正确!';
  329. }
  330. if (!$examStuScore) {
  331. $error[] = '没有当前班级数据!';
  332. }
  333. }
  334. if ($error) {
  335. $this->errorMsg(0, implode(',', $error));
  336. return false;
  337. }else{
  338. return array($paperId,$paperScore, $examStuScore);
  339. }
  340. }
  341. /**
  342. * 上次考试需要的数据
  343. * @param $examInfo
  344. * @param $examObj
  345. * @param $sprObj
  346. * @param $paperObj
  347. * @return array
  348. */
  349. private function preExamNeedData($examInfo,$sprObj,$paperObj)
  350. {
  351. $error = array();
  352. $examId = $this->examId;
  353. //获取当前考试的上一次考试数据
  354. $cepObj = new SClassExamPrinter();
  355. $preInfo = $cepObj->getPreExamId($examId,$examInfo['subject_id'],$examInfo['class_id']);
  356. $preExamId = isset($preInfo['exam_id'])?$preInfo['exam_id']:'';
  357. $prePaperScore = 0;
  358. $examRelPaper = array();
  359. $preExamStuScore = array();//考试关联学生得分
  360. if($preExamId){
  361. $sprInfoArr = $sprObj->getStudentExamInfo(array($preExamId));
  362. if(!$sprInfoArr){
  363. $error[] = '考试没有关联学生数据!';
  364. }
  365. if (!$error) {
  366. foreach($sprInfoArr as $key => $value){
  367. $studentId = $value['student_id'];
  368. $examRelPaper[$value['exam_id']] = $value['paper_id'];
  369. $preExamStuScore[$studentId] = $value['scoring'];
  370. unset($sprInfoArr[$key]);
  371. }
  372. unset($sprInfoArr);
  373. if($examRelPaper){
  374. $prePaperScore = $paperObj->getPaperScore(array_values($examRelPaper));
  375. }
  376. if(!$prePaperScore){
  377. $error[] = '试卷总分不正确!';
  378. }
  379. }
  380. }
  381. if ($error) {
  382. $this->errorMsg(0, implode(',', $error));
  383. return false;
  384. }else{
  385. return array($prePaperScore, $preExamStuScore);
  386. }
  387. }
  388. /**
  389. * 班级排名得分率人数等数据
  390. * @param $paperScore
  391. * @param $examStuScore
  392. * @return array
  393. */
  394. private function getClassAnalyse($paperScore,&$examStuScore,$prePaperScore, &$preExamStuScore)
  395. {
  396. $error = array();
  397. $classAnalyArr = array(
  398. 'exam_stu_num' => 0,//参加考试人数
  399. 'miss_stu_num' => 0,//缺考考人数
  400. 'avg_score_rate' => 0,//学生平均得分率
  401. 'pre_avg_rate_diff' => 0,//较上次考试平均得分率上升或下降
  402. 'avg_scoring' => 0,//学生平均分
  403. 'max_scoring' => 0,//最高分
  404. 'min_scoring' => 0,//最低分
  405. 'full_scoring' => 0,//满分
  406. 'pass_rate' => 0,//及格率
  407. 'pass_rate_gt_90' => 0,//其中得分率90%以上的有x人
  408. );
  409. $passStuNum = 0;//及格人数
  410. foreach ($examStuScore as $stuId => $stuScoring) {
  411. if ($stuScoring > 0) {
  412. $classAnalyArr['exam_stu_num']++;
  413. }else{
  414. $classAnalyArr['miss_stu_num']++;
  415. continue;
  416. }
  417. if ($stuScoring > $classAnalyArr['max_scoring']) {
  418. $classAnalyArr['max_scoring'] = $stuScoring;
  419. }
  420. if ($classAnalyArr['min_scoring'] == 0) {
  421. $classAnalyArr['min_scoring'] = $stuScoring;
  422. }
  423. if ($stuScoring < $classAnalyArr['min_scoring']) {
  424. $classAnalyArr['min_scoring'] = $stuScoring;
  425. }
  426. $scoring_rate = ($stuScoring / $paperScore) * 100;
  427. if ($scoring_rate >= 60) {
  428. $passStuNum++;
  429. }
  430. if ($scoring_rate > 90) {
  431. $classAnalyArr['pass_rate_gt_90']++;
  432. }
  433. }
  434. if (!$classAnalyArr['exam_stu_num']) {
  435. $error[] = '班级没有得分大于0的学生!';
  436. }
  437. if (!$error) {
  438. $classAnalyArr['pass_rate'] = $this->numberFormat($passStuNum / $classAnalyArr['exam_stu_num'], 4) * 100;
  439. $classAnalyArr['full_scoring'] = $paperScore;
  440. $classAnalyArr['avg_score_rate'] = $this->numberFormat(array_sum($examStuScore) / ($classAnalyArr['exam_stu_num'] * $paperScore), 4) * 100;
  441. $classAnalyArr['avg_scoring'] = $this->numberFormat(array_sum($examStuScore) / $classAnalyArr['exam_stu_num'], 1);
  442. //上一次班级平均得分率
  443. if ($preExamStuScore) {
  444. $preExamStuNum = 0;//上次参加考试人数
  445. foreach ($preExamStuScore as $stuId => $stuScoring) {
  446. if ($stuScoring > 0) {
  447. $preExamStuNum++;
  448. }
  449. }
  450. //上次平均得分率
  451. if ($preExamStuNum) {
  452. $preAvgScoreRate = $this->numberFormat(array_sum($preExamStuScore) / ($preExamStuNum * $prePaperScore), 4) * 100;
  453. }else{
  454. $preAvgScoreRate = 0;
  455. }
  456. $classAnalyArr['pre_avg_rate_diff'] = intval($classAnalyArr['avg_score_rate'] - $preAvgScoreRate);
  457. }
  458. }
  459. if ($error) {
  460. $this->errorMsg(0, implode(',', $error));
  461. return false;
  462. }else{
  463. return $classAnalyArr;
  464. }
  465. }
  466. /**
  467. * 考试分析,大幅进步,大幅退步,前5名和后5名
  468. * @param $examStuScore
  469. * @param $preExamStuScore
  470. * @return array
  471. */
  472. private function getLargeOrder($examStuScore,$preExamStuScore){
  473. $largeOrderArr = array(
  474. 'font_five' => array(),//班级前五名
  475. 'back_five' => array(),//班级后五名
  476. 'stu_diff_order' => array(),//名次提升或下降
  477. 'stu_order' => array(),//学生名次
  478. 'increase_stu' => array(),//大幅进步五名
  479. 'reduce_stu' => array(),//大幅退步五名
  480. );
  481. //得分数组(得分>0)
  482. $scoringArr = array();
  483. $needStudentArr = array();//得分大于0的学生
  484. foreach ($examStuScore as $stuId => $stuScoring) {
  485. if ($stuScoring > 0) {
  486. $scoringArr[] = $stuScoring;
  487. $needStudentArr[$stuId] = $stuId;
  488. }
  489. }
  490. //学生排名
  491. $stuOrderArr = array();
  492. foreach($examStuScore as $stuId => $stuScoring){
  493. if($stuScoring > 0){
  494. $stuOrderArr[$stuId] = $this->getOrder($stuScoring,$scoringArr);
  495. }
  496. }
  497. if($stuOrderArr){
  498. asort($stuOrderArr);
  499. }
  500. $diffNum = ceil(count($stuOrderArr)*0.2);
  501. //班级前五名
  502. //前5名和后5名
  503. $font5 = $back5 = array();
  504. $i = 1;
  505. foreach($stuOrderArr as $stuId => $order){
  506. if($i <= 5){
  507. $font5[$stuId] = $order;
  508. }else{
  509. break;
  510. }
  511. $i++;
  512. }
  513. $largeOrderArr['font_five'] = $font5;
  514. $i = 1;
  515. //删除前5排名
  516. $_stuOrderArr = $stuOrderArr;
  517. foreach($_stuOrderArr as $k => $order){
  518. if(isset($font5[$k])){
  519. unset($_stuOrderArr[$k]);
  520. }
  521. }
  522. arsort($_stuOrderArr);
  523. foreach($_stuOrderArr as $stuId => $order){
  524. if($i <= 5){
  525. $back5[$stuId] = $order;
  526. }else{
  527. break;
  528. }
  529. $i++;
  530. }
  531. $largeOrderArr['back_five'] = $back5;
  532. /////大幅进步,退步
  533. //上次得分数组(>0)
  534. $preScoringArr = array();
  535. foreach ($preExamStuScore as $stuId => $stuScoring) {
  536. if ($stuScoring > 0) {
  537. $preScoringArr[] = $stuScoring;
  538. }
  539. }
  540. //上次考试学生排名
  541. $preStuOrderArr = array();
  542. foreach($preExamStuScore as $stuId => $stuScoring){
  543. if($stuScoring>0){
  544. $preStuOrderArr[$stuId] = $this->getOrder($stuScoring,$preScoringArr);
  545. }
  546. }
  547. if($preStuOrderArr){
  548. asort($preStuOrderArr);
  549. }
  550. if($preStuOrderArr){
  551. $interOrderArr = array_intersect_key($stuOrderArr,$preStuOrderArr);
  552. if(!$interOrderArr){
  553. $interOrderArr = $stuOrderArr;
  554. }
  555. }else{
  556. $interOrderArr = array();
  557. }
  558. $increaseArr = $reduceArr = array();
  559. $stuDiffOrder = array();
  560. if($interOrderArr){
  561. foreach($stuOrderArr as $stuId => $order){
  562. if(isset($interOrderArr[$stuId]) && isset($preStuOrderArr[$stuId])){
  563. $stuDiffOrder[$stuId] = -($order - $preStuOrderArr[$stuId]);
  564. }else{
  565. $stuDiffOrder[$stuId] = 0;
  566. }
  567. }
  568. arsort($stuDiffOrder);
  569. foreach($stuDiffOrder as $stuId => $num){
  570. if($num >= $diffNum){
  571. $increaseArr[] = $stuId;
  572. }
  573. }
  574. $increaseArr = array_slice($increaseArr,0,5,true);
  575. asort($stuDiffOrder);
  576. foreach($stuDiffOrder as $stuId => $num){
  577. if($num <= -$diffNum){
  578. $reduceArr[] = $stuId;
  579. }
  580. }
  581. $reduceArr = array_slice($reduceArr,0,5,true);
  582. }else{
  583. $increaseArr = array_slice($stuOrderArr,0,5,true);
  584. $reduceArr = array();
  585. }
  586. $largeOrderArr['stu_diff_order'] = $stuDiffOrder;
  587. $largeOrderArr['stu_order'] = $stuOrderArr;
  588. $largeOrderArr['increase_stu'] = $increaseArr;
  589. $largeOrderArr['reduce_stu'] = $reduceArr;
  590. return array($largeOrderArr,$needStudentArr);
  591. }
  592. /**
  593. * 获取排名
  594. * @param $ele
  595. * @param $arr
  596. * @return false|int|string
  597. */
  598. private function getOrder($ele,$arr){
  599. $orderRs = 0;
  600. if($arr){
  601. arsort($arr);
  602. $arr = array_values($arr);
  603. $index = array_search($ele,$arr);
  604. $orderRs = $index + 1;
  605. }
  606. return $orderRs;
  607. }
  608. /**
  609. * 试卷情况分析
  610. * @param $topicNoArr
  611. * @param $stuRsArr
  612. * @param $needStudentArr
  613. * @param $topicScoreArr
  614. * @return array
  615. */
  616. private function paperAnalyse($topicNoArr,&$stuRsArr,$needStudentArr,$topicScoreArr,&$changeDoTopicNoArr)
  617. {
  618. //$changeTopicStuNum选做题实际做题人数
  619. $changeTopicStuNum = $paperAnalyseArr = array();
  620. $topicWrongNumArr = array();//题答错人数
  621. foreach ($needStudentArr as $stuId) {
  622. if(!(isset($stuRsArr[$stuId])) && $stuRsArr[$stuId]) continue;
  623. foreach ($stuRsArr[$stuId] as $topicId => $rs) {
  624. if (!isset($topicWrongNumArr[$topicId])) {
  625. $topicWrongNumArr[$topicId] = 0;
  626. }
  627. if ($rs['scoring'] < $topicScoreArr[$topicId] ) {
  628. $topicWrongNumArr[$topicId]++;
  629. }
  630. if(!empty($changeDoTopicNoArr) && isset($changeDoTopicNoArr["list"][$topicId])){//选做题实际做题人数
  631. if (!isset($changeTopicStuNum[$topicId])) {
  632. $changeTopicStuNum[$topicId] = 0;
  633. }
  634. $changeTopicStuNum[$topicId] ++;
  635. }
  636. }
  637. }
  638. $stuTotalNum = count($needStudentArr);//学生总人数
  639. foreach ($topicNoArr as $topicId => $no) {
  640. $wrongNum = isset($topicWrongNumArr[$topicId]) ? $topicWrongNumArr[$topicId] : 0;
  641. if(!empty($changeDoTopicNoArr) && isset($changeDoTopicNoArr["list"][$topicId]) && isset($changeTopicStuNum[$topicId])){
  642. $countStuTotalNum = $changeTopicStuNum[$topicId];//选做题实际做题人数
  643. }else{
  644. $countStuTotalNum = $stuTotalNum;//正常题目的人数
  645. }
  646. $paperAnalyseArr[] = array(
  647. 'no' => $no,
  648. 'wrong_num' => $wrongNum,
  649. 'wrong_rate' => $this->numberFormat($wrongNum / $countStuTotalNum, 4) * 100,
  650. );
  651. }
  652. return $paperAnalyseArr;
  653. }
  654. /**
  655. * 获取题内容
  656. * @param $topicNoArr
  657. */
  658. private function getTopicInfoArr($topicNoArr)
  659. {
  660. $error = array();
  661. $topicIds = array_keys($topicNoArr);
  662. $_params = array('isFormat' => 1 , 'isTird' => 1);
  663. $topicDetails = $this->apiBrainPost('/topic/batchAll', array('topicIds' => $topicIds,'subjectId' => $this->subjectId ,'params' => $_params),25,true);
  664. if (!$topicDetails) {
  665. $error[] = '获取接口batchALL无数据!';
  666. } elseif (isset($topicDetails['status']) && $topicDetails['status']==0) {
  667. $error[] = $topicDetails['error'][0];
  668. }
  669. if (!$error) {
  670. // $diff_id_arr = array_diff($topicIds, array_keys($topicDetails));
  671. $diff_id_arr = array();
  672. foreach ($topicNoArr as $topicId => $v) {
  673. if (!isset($topicDetails[$topicId])) {
  674. $diff_id_arr[] = $topicId;
  675. }
  676. }
  677. if ($diff_id_arr) {
  678. $error[] = "没有试题内容!(" . implode(',', $diff_id_arr) . ")";
  679. }
  680. }
  681. if ($error) {
  682. $this->errorMsg(0, implode(',', $error));
  683. return false;
  684. }else{
  685. return $topicDetails;
  686. }
  687. }
  688. /**
  689. * 获取题内容(不替换内容)
  690. * @param $topicNoArr
  691. */
  692. private function getTopicInfoArrNoReplace($topicIds)
  693. {
  694. $error = array();
  695. $topicDetailsArr = array();
  696. $topicDetails = $this->apiBrainPost('/topic/batchAll', array('topicIds' => array_values($topicIds),'subjectId' => $this->subjectId),25,true);
  697. if (!$topicDetails) {
  698. $error[] = '获取接口batchALL无数据!';
  699. } elseif (isset($topicDetails['status']) && $topicDetails['status']==0) {
  700. $error[] = $topicDetails['error'][0];
  701. }
  702. if (!$error) {
  703. // $diff_id_arr = array_diff($topicIds, array_keys($topicDetails));
  704. foreach ($topicDetails as $key => $detail) {
  705. $topicDetailsArr[number_format($detail['id'], 0, '', '')] = $detail;
  706. unset($topicDetails[$key]);
  707. }
  708. $diff_id_arr = array();
  709. foreach ($topicIds as $topicId => $topicId) {
  710. if (!isset($topicDetailsArr[$topicId])) {
  711. $diff_id_arr[] = $topicId;
  712. }
  713. }
  714. if ($diff_id_arr) {
  715. $error[] = "没有试题内容!(" . implode(',', $diff_id_arr) . ")";
  716. }
  717. }
  718. if ($error) {
  719. $this->errorMsg(0, implode(',', $error));
  720. return false;
  721. }else{
  722. return $topicDetailsArr;
  723. }
  724. }
  725. /**
  726. * 知识点掌握情况
  727. * @param $topicInfoArr
  728. * @param $topicScoreArr
  729. * @param $topicNoArr
  730. * @param $stuRsArr
  731. * @param $needStudentArr
  732. * @return array
  733. */
  734. public function kpsAnalyse(&$topicInfoArr,$topicScoreArr, &$topicNoArr,&$stuRsArr,$needStudentArr)
  735. {
  736. $kpsAnalyseArr = array();
  737. $kpsNameArr = array();//知识点名称
  738. $kpsTopicArr = array();//知识点关联的题
  739. $topicKpsArr = array();//试题关联的知识点
  740. foreach ($topicInfoArr as $topicId => $topicInfo) {
  741. if (!isset($topicKpsArr[$topicId])) {
  742. $topicKpsArr[$topicId] = array();
  743. }
  744. if (isset($topicInfo['kps']) && is_array($topicInfo['kps']) && $topicInfo['kps']) {
  745. foreach ($topicInfo['kps'] as $kpId => $kpName) {
  746. $kpsNameArr[$kpId] = $kpName;
  747. if (!isset($kpsTopicArr[$kpId])) {
  748. $kpsTopicArr[$kpId] = array();
  749. }
  750. $kpsTopicArr[$kpId][$topicId] = $topicId;
  751. $topicKpsArr[$topicId][$kpId] = $kpId;
  752. }
  753. }
  754. unset($topicInfo);
  755. }
  756. //试题对应的所有学生得分
  757. $topicScoringArr = array();//试题得分
  758. $topicTotalScoreArr = array();//试题总分
  759. $wrongStuArr = array();//答错学生
  760. foreach ($stuRsArr as $stuId => $stuTopicRs) {
  761. foreach ($stuTopicRs as $topicId => $stuRs) {
  762. if(!isset($needStudentArr[$stuId])) continue;
  763. if (!isset($topicScoringArr[$topicId])) {
  764. $topicScoringArr[$topicId] = 0;
  765. }
  766. $topicScoringArr[$topicId] += $stuRs['scoring'];
  767. if (!isset($topicTotalScoreArr[$topicId])) {
  768. $topicTotalScoreArr[$topicId] = 0;
  769. }
  770. $topicTotalScoreArr[$topicId] += isset($topicScoreArr[$topicId]) ? $topicScoreArr[$topicId] : 0;
  771. //答错学生
  772. if ($stuRs['scoring'] < $topicScoreArr[$topicId]) {
  773. foreach ($topicKpsArr[$topicId] as $kpId) {
  774. if (!isset($wrongStuArr[$kpId])) {
  775. $wrongStuArr[$kpId] = array();
  776. }
  777. $wrongStuArr[$kpId][$stuId] = $stuId;
  778. }
  779. }
  780. }
  781. }
  782. //计算班级得分率需要的数据
  783. $kpsScoringArr = array();//知识点得分
  784. $kpsTotalScoreArr = array();//知识点总分
  785. $kpsTopicNoArr = array();//知识点总分
  786. foreach ($kpsTopicArr as $kpId => $topicIds) {
  787. foreach ($topicIds as $topicId) {
  788. if(!isset($topicScoringArr[$topicId])) continue;
  789. if (!isset($kpsScoringArr[$kpId])) {
  790. $kpsScoringArr[$kpId] = 0;
  791. }
  792. $kpsScoringArr[$kpId] += $topicScoringArr[$topicId];
  793. if (!isset($kpsTotalScoreArr[$kpId])) {
  794. $kpsTotalScoreArr[$kpId] = 0;
  795. }
  796. $kpsTotalScoreArr[$kpId] += $topicTotalScoreArr[$topicId];
  797. if (!isset($kpsTopicNoArr[$kpId])) {
  798. $kpsTopicNoArr[$kpId] = array();
  799. }
  800. $kpsTopicNoArr[$kpId][] = $topicNoArr[$topicId];
  801. }
  802. }
  803. $classScoringRateArr = array();//班级得分率
  804. $kpsRateStarArr = array();//知识点掌握水平
  805. foreach ($kpsScoringArr as $kpId => $scoring) {
  806. $_rate = $this->numberFormat($scoring / $kpsTotalScoreArr[$kpId], 4) * 100;
  807. $classScoringRateArr[$kpId] = $_rate;
  808. $kpsRateStarArr[$kpId] = $this->getStarNum($_rate);
  809. }
  810. //表单排序:按知识点的班级得分率由高到低排序
  811. arsort($classScoringRateArr);
  812. foreach ($classScoringRateArr as $kpId => $rate) {
  813. $kp_topic_no = isset($kpsTopicNoArr[$kpId]) ? $kpsTopicNoArr[$kpId] : array();
  814. asort($kp_topic_no);
  815. $kpsAnalyseArr[] = array(
  816. 'kp_name' => isset($kpsNameArr[$kpId]) ? $kpsNameArr[$kpId] : '',
  817. 'kp_star' => isset($kpsRateStarArr[$kpId]) ? $kpsRateStarArr[$kpId] : 0,
  818. 'class_scoring_rate' => $rate,
  819. 'wrong_stu_num' => isset($wrongStuArr[$kpId]) ? count($wrongStuArr[$kpId]) : 0,
  820. 'kp_topic_no' => $kp_topic_no,
  821. );
  822. }
  823. return $kpsAnalyseArr;
  824. }
  825. /**
  826. * 根据知识点的班级得分率显示1~5星
  827. ★★★★★:90%≦班级得分率≦100%
  828. ★★★★:80%≦班级得分率<90%
  829. ★★★:70%≦班级得分率<80%
  830. ★★:60%≦班级得分率<70%
  831. ★:班级得分率<60%
  832. * @param $rate
  833. */
  834. private function getStarNum($rate)
  835. {
  836. $starNum = 5;
  837. if ($rate >= 90 && $rate <= 100) {
  838. $starNum = 5;
  839. }elseif($rate >= 80 && $rate < 90){
  840. $starNum = 4;
  841. }elseif($rate >= 70 && $rate < 80){
  842. $starNum = 3;
  843. }elseif($rate >= 60 && $rate < 70){
  844. $starNum = 2;
  845. }else{
  846. $starNum = 1;
  847. }
  848. return $starNum;
  849. }
  850. /**
  851. * 试卷讲评
  852. * @param $needStudentArr
  853. * @param $stuRsArr
  854. * @param $topicScoreArr
  855. * @param $topicInfoArr
  856. * @param $topicNoArr
  857. * @return array
  858. */
  859. private function paperComments(&$needStudentArr,&$stuRsArr,$topicScoreArr,&$topicInfoArr,$topicNoArr)
  860. {
  861. $paperCommentsArr = array();
  862. // $_paperCommentsArr = array(
  863. // 'topic_no' => 0,//试题序号
  864. // 'class_scoring_rate' => 0,//班级得分率
  865. // 'grade_scoring_rate' => 0,//年级得分率
  866. // 'wrong_stu_arr' => 0,//答错学生
  867. // 'right_stu_num' => 0,//答对学生数
  868. // 'push_topic_id' => 0,//推送题ID
  869. // );
  870. //试题对应的所有学生得分
  871. $topicScoringArr = array();//试题得分
  872. $topicTotalScoreArr = array();//试题总分
  873. $wrongStuArr = array();//答错学生
  874. $rightStuNumArr = array();//答对学生数
  875. foreach ($stuRsArr as $stuId => $stuTopicRs) {
  876. foreach ($stuTopicRs as $topicId => $stuRs) {
  877. if(!isset($needStudentArr[$stuId])) continue;
  878. if (!isset($topicScoringArr[$topicId])) {
  879. $topicScoringArr[$topicId] = 0;
  880. }
  881. $topicScoringArr[$topicId] += $stuRs['scoring'];
  882. if (!isset($topicTotalScoreArr[$topicId])) {
  883. $topicTotalScoreArr[$topicId] = 0;
  884. }
  885. $topicTotalScoreArr[$topicId] += isset($topicScoreArr[$topicId]) ? $topicScoreArr[$topicId] : 0;
  886. //答错学生
  887. if ($stuRs['scoring'] == $topicScoreArr[$topicId]) {
  888. if (!isset($rightStuNumArr[$topicId])) {
  889. $rightStuNumArr[$topicId] = 0;
  890. }
  891. $rightStuNumArr[$topicId]++;
  892. }else{
  893. if (!isset($wrongStuArr[$topicId])) {
  894. $wrongStuArr[$topicId] = array();
  895. }
  896. $wrongStuArr[$topicId][$stuId] = $stuId;
  897. }
  898. }
  899. }
  900. //班级得分率
  901. $classScoringRateArr = array();
  902. foreach ($topicScoringArr as $topicId => $scoring) {
  903. $classScoringRateArr[$topicId] = $this->numberFormat($scoring / $topicTotalScoreArr[$topicId], 2) * 100;
  904. }
  905. //推送试题
  906. $pushTopicArr = $this->pushTopic($topicInfoArr);
  907. if ($pushTopicArr) {
  908. //年级得分率
  909. $gradeScoringRateArr = $this->getGradeScoringRate($topicScoreArr);
  910. foreach ($topicNoArr as $topicId => $topicNo) {
  911. $_wrongStuArr = isset($wrongStuArr[$topicId]) ? $wrongStuArr[$topicId] : array();
  912. $paperCommentsArr[] = array(
  913. 'topic_id' => $topicId,
  914. 'topic_no' => $topicNo,
  915. 'class_scoring_rate' => isset($classScoringRateArr[$topicId])?$classScoringRateArr[$topicId]:0,
  916. 'grade_scoring_rate' => isset($gradeScoringRateArr[$topicId])?$gradeScoringRateArr[$topicId]:0,
  917. 'wrong_stu_arr' => array_keys($_wrongStuArr),
  918. 'wrong_stu_num' => count($_wrongStuArr),
  919. 'right_stu_num' => isset($rightStuNumArr[$topicId])?$rightStuNumArr[$topicId]:0,
  920. 'push_topic_id' => isset($pushTopicArr[$topicId])?$pushTopicArr[$topicId]:array()
  921. );
  922. }
  923. }
  924. return $paperCommentsArr;
  925. }
  926. /**
  927. * 推送试题
  928. * @param $topicInfoArr
  929. * @return array
  930. */
  931. private function pushTopic(&$topicInfoArr)
  932. {
  933. $error = array();
  934. $pushTopicArr = array();//推送题
  935. $topicRelTopicIdsArr = array();//试题关联题
  936. $topicDiffArr = array();//试题难度系数
  937. $relTopicArr = array();//所有关联题
  938. foreach ($topicInfoArr as $topicId => $topicInfo) {
  939. $relationTopicArr = $topicInfo['relation_topic'] ? explode(',', $topicInfo['relation_topic']) : array();
  940. $topicDiffArr[$topicId] = $topicInfo['difficulty_degree'];
  941. $topicRelTopicIdsArr[$topicId] = $relationTopicArr;
  942. foreach ($relationTopicArr as $_topicId) {
  943. $relTopicArr[$_topicId] = $_topicId;
  944. }
  945. }
  946. if(!$relTopicArr){
  947. $error[] = '试题没有关联题';
  948. }
  949. //关联题详情
  950. if (!$error) {
  951. $relTopicDiffArr = array();//所有关联题难度
  952. foreach (array_chunk($relTopicArr, 50) as $topicIds) {
  953. $_topicInfoArr = $this->getTopicInfoArr(array_flip($topicIds));
  954. if ($_topicInfoArr) {
  955. foreach ($_topicInfoArr as $topicId => $_info) {
  956. $relTopicDiffArr[$topicId] = $_info['difficulty_degree'];
  957. }
  958. }
  959. unset($_topicInfoArr);
  960. }
  961. //从原题的关联题中推荐难度最接近的任1题即可
  962. $pushedTopicArr = array();//已推送的题
  963. foreach ($topicDiffArr as $topicId => $originDiff) {
  964. $relDiffArr = array();//关联题难度差
  965. foreach ($topicRelTopicIdsArr[$topicId] as $relTopicId) {
  966. $relDiffArr[$relTopicId] = abs($originDiff - $relTopicDiffArr[$relTopicId]);
  967. }
  968. asort($relDiffArr);
  969. foreach ($relDiffArr as $_topicId => $diff) {
  970. if (isset($pushedTopicArr[$_topicId])) {
  971. continue;
  972. }
  973. $pushTopicArr[$topicId] = (string)$_topicId;
  974. $pushedTopicArr[$_topicId] = $_topicId;
  975. break;
  976. }
  977. }
  978. //获取推送题详情
  979. if (!$pushTopicArr) {
  980. $error[] = '没有推送到试题';
  981. }
  982. }
  983. if ($error) {
  984. $this->errorMsg(0, implode(',', $error));
  985. return false;
  986. }else{
  987. return $pushTopicArr;
  988. }
  989. }
  990. /**
  991. * 年级得分率
  992. * @param $topicScoreArr 试题分数
  993. * @param $topicScoringArr 试题得分(初始值是班级得分)
  994. * @param $topicTotalScoreArr 试题总分分(初始值是班级总分)
  995. * @return array
  996. */
  997. private function getGradeScoringRate($topicScoreArr)
  998. {
  999. $gradeScoringRateArr = array();
  1000. $examIds = $this->examObj->getExamIds($this->examGroupId);
  1001. $needStuArr = array();//得分大于0的学生
  1002. $paperIds = array();
  1003. if($examIds){
  1004. //试卷关联学生
  1005. $sprInfoArr = $this->sprObj->getStudentExamInfo($examIds);
  1006. if ($sprInfoArr) {
  1007. foreach ($sprInfoArr as $sprInfo) {
  1008. if ($sprInfo['scoring'] > 0) {
  1009. $needStuArr[$sprInfo['student_id']] = $sprInfo['student_id'];
  1010. $paperIds[$sprInfo['paper_id']] = $sprInfo['paper_id'];
  1011. }
  1012. }
  1013. }
  1014. unset($sprInfoArr);
  1015. }
  1016. $topicScoringArr = array();
  1017. $topicTotalScoreArr = array();
  1018. if ($paperIds) {
  1019. foreach ($paperIds as $paperId) {
  1020. $_stuRsArr = $this->sptRsObj->getStudentRsOnePaper($paperId);
  1021. if(!$_stuRsArr){
  1022. continue;
  1023. }
  1024. foreach ($_stuRsArr as $stuId => $stuTopicRs) {
  1025. foreach ($stuTopicRs as $topicId => $stuRs) {
  1026. if(!isset($needStuArr[$stuId])) continue;
  1027. if (!isset($topicScoringArr[$topicId])) {
  1028. $topicScoringArr[$topicId] = 0;
  1029. }
  1030. $topicScoringArr[$topicId] += $stuRs['scoring'];
  1031. if (!isset($topicTotalScoreArr[$topicId])) {
  1032. $topicTotalScoreArr[$topicId] = 0;
  1033. }
  1034. $topicTotalScoreArr[$topicId] += isset($topicScoreArr[$topicId]) ? $topicScoreArr[$topicId] : 0;
  1035. }
  1036. unset($stuTopicRs);
  1037. }
  1038. unset($_stuRsArr);
  1039. }
  1040. }
  1041. //年级得分率
  1042. foreach ($topicScoringArr as $topicId => $scoring) {
  1043. $gradeScoringRateArr[$topicId] = $this->numberFormat($scoring / $topicTotalScoreArr[$topicId], 2) * 100;
  1044. }
  1045. return $gradeScoringRateArr;
  1046. }
  1047. /**
  1048. * hmtl生产PDF
  1049. * @param $res
  1050. * @param $html
  1051. * @param $className
  1052. * @param $examName
  1053. * @return string
  1054. */
  1055. private function htmlToPdf($res,&$html,$className,$examName)
  1056. {
  1057. $error = array();
  1058. $examId = $this->examId;
  1059. $htmlpath = str_replace("protected", "", Yii::app()->basePath) . '/upload/tmpDir/academicr/'; //存放生成的HTML路径
  1060. $pdfpath = str_replace("protected", "", Yii::app()->basePath) . '/upload/tmpDir/academicr/' . $this->schoolId . "/"; //存放生成的PDF路径
  1061. $pdfurl = '/upload/tmpDir/academicr/' . $this->schoolId . "/";
  1062. if (!is_dir($htmlpath)) {
  1063. if (!mkdir($htmlpath, 0777, true)) {
  1064. $error[] = 'Create directory fail: ' . $htmlpath;
  1065. }
  1066. }
  1067. if (!is_dir($pdfpath)) {
  1068. if (!mkdir($pdfpath, 0777, true)) {
  1069. $error[] = 'Create directory fail: ' . $pdfpath;
  1070. }
  1071. }
  1072. if (!$error) {
  1073. $locale='en_US.UTF-8'; // 或 $locale='zh_CN.UTF-8';
  1074. setlocale(LC_ALL,$locale);
  1075. putenv('LC_ALL='.$locale);
  1076. $htmlpath .= $examId . ".html";
  1077. $f = fopen($htmlpath, "w");
  1078. fwrite($f, $html);
  1079. fclose($f);
  1080. $htmlurl = '/upload/tmpDir/academicr/' . $examId . ".html"; //访问HTML的路径
  1081. $server = Yii::app()->params['phantomjs_server'];
  1082. $js = 'html2pdf.js';
  1083. $htmlurl = $this->getDomain() . $htmlurl;
  1084. $pdffname = $this->classId . "-" . $examId . ".pdf";
  1085. $pdfpath = $pdfpath . $pdffname;
  1086. $pdfurl = $pdfurl . $pdffname;
  1087. $commond = $server . " "
  1088. . Yii::app()->basePath . '/../js/'.$js . " "
  1089. . " {$htmlurl}"
  1090. . " {$pdfpath}"
  1091. . " 176mm*250mm '{$className}|||{$examName}|||时间:".date('Y-m-d')."'";
  1092. exec($commond, $res, $code);
  1093. }
  1094. if(isset($res) && isset($res[0])){
  1095. $isBool = false;
  1096. foreach($res as $msg){
  1097. if (strpos($msg, 'succeed') !== false){
  1098. $isBool = true;
  1099. }
  1100. }
  1101. if ($isBool) {//命令返回成功
  1102. if (file_exists($pdfpath)) {
  1103. // $pdfurl=iconv("GBK", "UTF-8",$pdfurl);
  1104. $repdf = $examId . ".pdf";
  1105. $rename = 'zsyas2/academicr/'.$this->schoolId.'/'. date('Y') . '/' . date('m') . '/' . date('d').'/'. uniqid() . '.' . $repdf;
  1106. $ucloud = new HuaweiCloud();
  1107. $uploadInfo = $ucloud->putFile($rename, $pdfpath);
  1108. if ($uploadInfo['status'] == 0) {
  1109. $pdfurl = $this->getDomain() . $pdfurl;
  1110. $this->getSchoolDbObj()->createCommand()->update("exam", array("academicr_pdf_path" => $pdfurl, "academicr_pdf_time" => time(), "is_academicr_pdf" => 1), "exam_id = '{$examId}'");
  1111. }else{
  1112. $pdfurl = $uploadInfo['url'];
  1113. $this->getSchoolDbObj()->createCommand()->update("exam", array("academicr_pdf_path" => $pdfurl, "academicr_pdf_time" => time(), "is_academicr_pdf" => 1), "exam_id = '{$examId}'");
  1114. //批量生产不生产PDF
  1115. if (!is_cli()) {
  1116. @unlink($pdfpath);
  1117. }
  1118. }
  1119. @unlink($htmlpath);
  1120. } else {
  1121. $this->getSchoolDbObj()->createCommand()->update("exam", array("academicr_pdf_path" => "", "academicr_pdf_time" => 0, "is_academicr_pdf" => 0), "exam_id = '{$examId}'");
  1122. @unlink($htmlpath);
  1123. $error[] = 'PDF文件未找到! ';
  1124. }
  1125. } else {
  1126. @unlink($htmlpath);
  1127. $error[] = 'PDF创建失败!,错误信息:(' . json_encode($res) . ') ';
  1128. }
  1129. }else{
  1130. Curl::post(Yii::app()->params['handle_log_api'], array(
  1131. "exam_group_id" => (string)$this->examGroupId,
  1132. "operate_project" => 'zsyas2',
  1133. "school_id" => $this->schoolId,
  1134. "title" => '下载教师讲案',
  1135. "operate_account" => is_cli()?'':Yii::app()->session['coachInfo']['coach_name'],
  1136. "operate_method" => $this->action,
  1137. "operate_url" => $this->getRoute(),
  1138. "operate_sql" => '',
  1139. "operate_param" =>json_encode(array('post'=>array("examId"=>$examId,"pdf"=>array("commond"=>$commond,"res"=>$res,"code"=>$code),"htmlurl"=>''))),
  1140. ));
  1141. $error[] = 'PDF创建失败! ';
  1142. }
  1143. if ($error) {
  1144. $this->errorMsg(0, implode(',', $error));
  1145. return false;
  1146. }else{
  1147. return array($pdfurl,$pdfpath);
  1148. }
  1149. }
  1150. /**
  1151. * 调题的接口
  1152. * @param $path
  1153. * @param $arr
  1154. * @param int $type
  1155. * @return bool|mixed
  1156. */
  1157. public function apiBrainPost($path, $arr, $timeout=25,$is_array = false)
  1158. {
  1159. $ch = @curl_init();
  1160. $result = FALSE;
  1161. if ($ch)
  1162. {
  1163. $data = json_encode($arr);
  1164. $url = Yii::app()->params['api'][0]['prefix'] . $path;
  1165. $username = Yii::app()->params['api'][0]['username'];
  1166. $password = Yii::app()->params['api'][0]['password'];
  1167. curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  1168. curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
  1169. // 不输出头部
  1170. curl_setopt($ch, CURLOPT_HEADER, 0);
  1171. // curl_exec 获取到的内容不直接输出, 而是返回
  1172. curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
  1173. curl_setopt($ch, CURLOPT_TIMEOUT,$timeout);
  1174. // 请求重启路由器的地址 传参 进行重启
  1175. curl_setopt($ch, CURLOPT_URL, $url);
  1176. curl_setopt($ch, CURLOPT_USERAGENT, 'Api Client/1.0.0 (chengfei@liancaitech.com)');
  1177. curl_setopt($ch, CURLOPT_POST, 1);
  1178. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  1179. curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  1180. 'Content-Type: application/json',
  1181. 'Content-Length: '. strlen($data),
  1182. ));
  1183. if( !curl_errno($ch))
  1184. {
  1185. $result = json_decode(curl_exec($ch),$is_array);
  1186. }
  1187. // 释放资源
  1188. curl_close($ch);
  1189. }
  1190. return $result;
  1191. }
  1192. public function getDomain()
  1193. {
  1194. if (is_cli()) {
  1195. return Yii::app()->params['zsyas2_url'];
  1196. }else{
  1197. return Yii::app()->request->hostInfo;
  1198. }
  1199. }
  1200. /**
  1201. * 错误信息
  1202. * @param $status
  1203. * @param $msg
  1204. */
  1205. private function errorMsg($status,$msg)
  1206. {
  1207. $this->error[] = $msg;
  1208. // echo json_encode(array("status" => $status, "error" => $msg));
  1209. // exit;
  1210. }
  1211. /**
  1212. * 学校数据库连接对象
  1213. * @return mixed
  1214. */
  1215. protected function getSchoolDbObj()
  1216. {
  1217. if (is_cli()) {
  1218. return $this->controllerObj->getSchConnObj();
  1219. }else{
  1220. return $this->controllerObj->sConn;
  1221. }
  1222. }
  1223. /**
  1224. * 数组格式化
  1225. * @param $num 小数
  1226. * @param $bat 小数位数
  1227. * @return float|int
  1228. */
  1229. private function numberFormat($num,$bat)
  1230. {
  1231. $pow = pow(10, $bat);
  1232. $num = $num * $pow;
  1233. $num = floor($num) / $pow;
  1234. return $num;
  1235. }
  1236. /**
  1237. * 获取共性题数据
  1238. * @return array
  1239. */
  1240. private function commonTopic()
  1241. {
  1242. $commonTopics = array();
  1243. if($this->isPushSameTrain){
  1244. $rs = SProductAlikeIspTopic::model()->getCommonTopic($this->examId,'template_id,topic_id');
  1245. foreach ($rs as $item){
  1246. $commonTopics[$item['template_id']]['topic_id'] = $item['template_id'];
  1247. $commonTopics[$item['template_id']]['isp_topic_id'] = $item['topic_id'];
  1248. }
  1249. }else{
  1250. $rs = SProductCommonTopic::model()->getCommonTopic($this->examId, 0);
  1251. foreach ($rs as $item){
  1252. $commonTopics[$item['template_id']]['topic_id'] = $item['template_id'];
  1253. $commonTopics[$item['template_id']]['topic_no'] = $item['template_no'];
  1254. $commonTopics[$item['template_id']]['isp_topic_id'] = $item['topic_id'];
  1255. }
  1256. }
  1257. return $commonTopics;
  1258. }
  1259. //读取考试班级产品设置相同题
  1260. public function isPushSameTrain($classId)
  1261. {
  1262. $classSet=$this->getSchoolDbObj()->createCommand("select wb_isp from product_class_set where class_id='{$classId}' and subject_id=12")->queryScalar();
  1263. if($classSet){
  1264. $template=$this->getSchoolDbObj()->createCommand("select config_text from product_template where template_id={$classSet}")->queryScalar();
  1265. if($template){
  1266. $jsonData=json_decode($template,true);
  1267. if(isset($jsonData['studentLevelDivide']['isPushSameTrain']) && $jsonData['studentLevelDivide']['isPushSameTrain']){
  1268. return true;
  1269. }
  1270. }
  1271. }else{
  1272. $template=$this->getSchoolDbObj()->createCommand("select config_text from product_template where subject_id=12 and is_default=1 and product_type=3")->queryScalar();
  1273. if($template){
  1274. $jsonData=json_decode($template,true);
  1275. if(isset($jsonData['studentLevelDivide']['isPushSameTrain']) && $jsonData['studentLevelDivide']['isPushSameTrain']){
  1276. return true;
  1277. }
  1278. }
  1279. }
  1280. return false;
  1281. }
  1282. /**
  1283. * 获取选做题题号
  1284. * @param $info 题号
  1285. * @param $tpl_data_arr exam tpl_data数组
  1286. */
  1287. private function getChangeDoToicNoArr(&$info,$tplDataArr)
  1288. {
  1289. $topicNoArr = array();
  1290. foreach ($info as $item) {
  1291. $topicNoArr[$item['topic_id']] = $item['order'];
  1292. }
  1293. asort($topicNoArr);
  1294. $topicIdsArr = array_keys($topicNoArr);
  1295. $changeDoToicNo = array(
  1296. "list" => array(),//详情
  1297. "gather"=> array(),//汇总
  1298. );
  1299. //选做题题号
  1300. if (isset($tplDataArr['new_items']) && $tplDataArr['new_items']) {
  1301. foreach (array_values($tplDataArr['new_items']) as $key => $item) {
  1302. if (isset($topicIdsArr[$key]) && isset($item['sameAliasNo']) && $item['sameAliasNo']>0) {
  1303. $topic_id = $topicIdsArr[$key];
  1304. $no =$item['alias'];
  1305. $changeDoToicNo["list"][$topic_id]["sameAliasNo"] = $item['sameAliasNo'];//选做题组id
  1306. $changeDoToicNo["list"][$topic_id]["smTopicLen"] = $item['smTopicLen'];//选做题组必做数量
  1307. $changeDoToicNo["list"][$topic_id]["no"] = $no;//选做题组必做数量
  1308. $changeDoToicNo["gather"][$item['sameAliasNo']][] = $topic_id;
  1309. }
  1310. }
  1311. }
  1312. asort($changeDoToicNo);
  1313. return $changeDoToicNo;
  1314. }
  1315. }