Question.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use think\Db;
  5. use app\utils\RedisKeyEnum;
  6. use app\utils\RedisUtil;
  7. /**
  8. * 答题
  9. */
  10. class Question extends Api
  11. {
  12. protected $noNeedLogin = [];
  13. protected $noNeedRight = ['*'];
  14. public function __construct(){
  15. $this->error('投票活动结束了');
  16. }
  17. //取题之前弹机构
  18. public function get_question_before(){
  19. $jigou = Db::name('vote_jigou')->where('id',$this->auth->bind_jigou_id)->value('title');
  20. $times = config('site.bind_jigou_times') - $this->auth->bind_jigou_times;
  21. $rs = [
  22. 'bind_jigou_id' => $this->auth->bind_jigou_id,
  23. 'jigou_title' => $jigou,
  24. 'times' => $times,
  25. ];
  26. $this->success(1,$rs);
  27. }
  28. //获取10个题
  29. public function get_question(){
  30. //上次绑定选手的时间不是今天
  31. if(empty($this->auth->bind_jigou_id)){
  32. $this->error('先绑定单位再答题',null,2);
  33. }
  34. //今天,总答题次数
  35. $gift_question = config('site.exam_times_user_eday');
  36. //今天,已答题次数
  37. $submit_question = RedisUtil::getInstance(RedisKeyEnum::EAXM_TIMES.date('Y-m-d').':'.$this->auth->id)->get();
  38. //今日剩余答题次数
  39. $today_my_question = $gift_question - $submit_question;
  40. if($today_my_question < 0){
  41. $today_my_question = 0;
  42. }
  43. if($today_my_question == 0){
  44. $this->error('今日答题次数用完了,明天再来吧');
  45. }
  46. //获取10个随机题目
  47. $lists = Db::name('exam_question')
  48. ->field('id,kind,title,options_json')
  49. ->where('is_material_child', 0)// 材料题子题不显示
  50. ->where('status', 'NORMAL')// 正常
  51. ->where('deletetime', NULL)
  52. ->orderRaw('rand()')->limit($today_my_question)->select();
  53. foreach($lists as $key => $val){
  54. $val['options_json'] = $this->getOptionsJsonAttr($val['options_json']);
  55. $lists[$key] = $val;
  56. }
  57. $this->success(1,$lists);
  58. }
  59. private function getOptionsJsonAttr($value)
  60. {
  61. if ($value = json_decode($value, true)) {
  62. $data = [];
  63. foreach ($value as $key => $row) {
  64. $arr['key'] = $key;
  65. $arr['value'] = $row;
  66. array_push($data, $arr);
  67. }
  68. return $data;
  69. }
  70. return [];
  71. }
  72. /**
  73. * 答题
  74. */
  75. public function submit()
  76. {
  77. $this->error('接口作废');
  78. if(!$this->apiLimit('操作太快了,休息一下吧'));
  79. //上次绑定选手的时间不是今天
  80. if(empty($this->auth->bind_jigou_id)){
  81. $this->error('先绑定单位再答题',null,2);
  82. }
  83. //检查今日答题次数
  84. $exam_times_user_eday = config('site.exam_times_user_eday');
  85. $count = RedisUtil::getInstance(RedisKeyEnum::EAXM_TIMES.date('Y-m-d').':'.$this->auth->id)->get();
  86. if($count >= $exam_times_user_eday){
  87. $this->error('今日答题次数用完了,明天再来吧');
  88. }
  89. //答题
  90. $user_questions = input('questions','','htmlspecialchars_decode');
  91. $user_questions = json_decode($user_questions,true);
  92. if (!$user_questions) {
  93. $this->error('提交数据有误');
  94. }
  95. //避免超次数
  96. if(count($user_questions) + $count > $exam_times_user_eday){
  97. $this->error('今日答题次数用完了,明天再来吧!');
  98. }
  99. $questions_ids = array_column($user_questions, 'id'); // 答题id
  100. $answers = array_column($user_questions, 'answer'); // 用户答案
  101. $is_right_number = 0;
  102. $log_data = [];
  103. $questions = Db::name('exam_question')->field('id,kind,answer')->where('id','IN', $questions_ids)->orderRaw('field(id,'. implode(',', $questions_ids) .')')->select();
  104. foreach($questions as $key => $question){
  105. $is_right = $this->paperExam($question,$answers[$key]);
  106. if($is_right){
  107. $is_right_number ++;
  108. }
  109. $log_data[] = [
  110. 'user_id' => $this->auth->id,
  111. 'question_id' => $question['id'],
  112. 'is_right' => $is_right ? 1 : 0,
  113. 'jigou_id' => $this->auth->bind_jigou_id,
  114. 'createtime' => time(),
  115. 'createdate' => strtotime(date('Y-m-d')),
  116. ];
  117. }
  118. Db::startTrans();
  119. //答题日志
  120. $log_id = Db::name('user_question_log')->insertAll($log_data);
  121. if(!$log_id){
  122. Db::rollback();
  123. $this->error('答题失败');
  124. }
  125. if($is_right_number > 0){
  126. //给机构加分
  127. $rs = Db::name('vote_jigou')->where('id',$this->auth->bind_jigou_id)->setInc('score',$is_right_number);
  128. if($rs === false){
  129. Db::rollback();
  130. $this->error('答题失败');
  131. }
  132. }
  133. Db::commit();
  134. //今日答题次数,自增一次
  135. $count = RedisUtil::getInstance(RedisKeyEnum::EAXM_TIMES.date('Y-m-d').':'.$this->auth->id)->incrby_expire(count($user_questions),86400);
  136. if($is_right_number > 0){
  137. //今日答对次数,自增一次
  138. RedisUtil::getInstance(RedisKeyEnum::EAXM_RIGHT.date('Y-m-d').':'.$this->auth->id)->incrby_expire($is_right_number,86400);
  139. }
  140. //返回正确了几道题,剩余答题次数
  141. $result = [
  142. 'remark' => '答题完成,获得'.$is_right_number.'次投票次数,答题最多可获得'.$exam_times_user_eday.'次投票机会',
  143. 'submit_number'=> count($user_questions),
  144. 'right_number' => $is_right_number,
  145. 'remain' => $exam_times_user_eday - $count,
  146. ];
  147. $this->success('答题完毕',$result);
  148. }
  149. /**
  150. * 试题
  151. * @param $question_id
  152. * @param $answer
  153. * @return bool
  154. */
  155. private function paperExam($question,$answer)
  156. {
  157. $is_right = false;
  158. if(empty($question)){
  159. return false;
  160. }
  161. switch ($question['kind']) {
  162. case 'JUDGE': // 判断题
  163. case 'SINGLE': // 单选题
  164. case 'MULTI': // 多选题
  165. // 答题正确
  166. if (strtoupper($answer) == $question['answer']) {
  167. $is_right = true;
  168. } else {
  169. $is_right = false;
  170. }
  171. break;
  172. case 'SHORT': // 简答题
  173. // 答案得分配置
  174. $answer_config = is_string($question['answer']) ? json_decode($question['answer'], true) : $question['answer'];
  175. $user_answers = $answer;
  176. foreach ($answer_config['config'] as $answer_item) {
  177. // 匹配答案关键词
  178. if (strpos($user_answers, $answer_item['answer']) !== false) {
  179. $is_right = true;
  180. break;
  181. }
  182. }
  183. break;
  184. }
  185. return $is_right;
  186. }
  187. }