123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- <?php
- declare(strict_types=1);
- namespace App\Controller\Api\v1;
- use App\Controller\AbstractController;
- use App\Service\QueueService;
- use App\Utils\AppResult;
- use App\Utils\Control\AuthUser;
- use Hyperf\DbConnection\Db;
- //
- use App\Request\Api\v1\Question\SubmitRequest;
- use App\Request\Api\v1\Question\BindjigouRequest;
- use App\Master\Enum\RedisKeyEnum;
- use App\Utils\RedisUtil;
- use Hyperf\Di\Annotation\Inject;
- /**
- * 选手接口
- * PlayerController
- */
- class QuestionController extends AbstractController
- {
- // 日志模块名称
- const LOG_MODULE = 'v1/QuestionController';
- #[Inject]
- protected QueueService $service;
- //用户绑定机构
- public function bindjigou(BindjigouRequest $request){
- //验证活动开始时间,结束时间
- if( time() < strtotime(site('subject_starttime')) )
- {
- return AppResult::error('活动开始时间:'.site('subject_starttime'));
- }
- if( strtotime(site('subject_endtime')) < time() )
- {
- return AppResult::error('活动在'.site('subject_endtime').'就结束了');
- }
- $params = $request->validated();// 获取校验通过的参数
- $user = AuthUser::getInstance()->get();
- $jigou_id = $params['jigou_id'];
- $jigou_info = Db::table('vote_jigou')->where('id',$jigou_id)->first();
- if(!$jigou_info){
- return AppResult::error('不存在的单位');
- }
- $times = site('bind_jigou_times');
- if($user['bind_jigou_times'] >= $times){
- return AppResult::error('最多修改绑定单位'.$times.'次');
- }
- if($user['bind_jigou_id'] == $jigou_id){
- return AppResult::error('绑定单位没有改变');
- }
- $data = [
- 'bind_jigou_id' => $jigou_id,
- 'bind_jigou_times' => $user['bind_jigou_times'] + 1,
- ];
- $rs = Db::table('user')->where('id',$user['id'])->update($data);
- if(!$rs){
- return AppResult::error('修改绑定失败');
- }
- //曾经 答题贡献的分数,用户曾经都要给到新机构
- if(!empty($user['bind_jigou_id'])){
- $this->service->bindjigouPush(['user_id' => $user['id'], 'old_jigou_id' => $user['bind_jigou_id'], 'new_jigou_id' => $jigou_id], 0);
- }
- return AppResult::success('绑定成功');
- }
- /**
- * 答题
- */
- public function submit(SubmitRequest $request)
- {
- //验证活动开始时间,结束时间
- if( time() < strtotime(site('subject_starttime')) )
- {
- return AppResult::error('活动开始时间:'.site('subject_starttime'));
- }
- if( strtotime(site('subject_endtime')) < time() )
- {
- return AppResult::error('活动在'.site('subject_endtime').'就结束了');
- }
- $params = $request->validated();// 获取校验通过的参数
- $user = AuthUser::getInstance()->get();
- if (!RedisUtil::getInstance(RedisKeyEnum::API_REQUEST_TRAFFIC.':'.$user['id'])->tryTimes(1, 5)) {
- return AppResult::error('操作太快了,休息一下吧');
- }
- //上次绑定选手的时间不是今天
- if(empty($user['bind_jigou_id'])){
- return AppResult::response_fast(2,'先绑定单位再答题');//给不同的code,0报错,2跳到答题
- }
- //检查今日答题次数
- $exam_times_user_eday = site('exam_times_user_eday');
- $count = RedisUtil::getInstance(RedisKeyEnum::EAXM_TIMES.date('Y-m-d').':'.$user['id'])->get();
- if($count >= $exam_times_user_eday){
- return AppResult::error('今日答题次数用完了,明天再来吧');
- }
- //答题
- $user_questions = htmlspecialchars_decode($params['questions']);
- $user_questions = json_decode($user_questions,true);
- if (!$user_questions) {
- return AppResult::error('提交数据有误');
- }
- //避免超次数
- if(count($user_questions) + $count > $exam_times_user_eday){
- return AppResult::error('今日答题次数用完了,明天再来吧!');
- }
- $questions_ids = array_column($user_questions, 'id'); // 答题id
- $answers = array_column($user_questions, 'answer'); // 用户答案
- $is_right_number = 0;
- $log_data = [];
- $questions = Db::table('exam_question')->select(['id','kind','answer'])->whereIn('id',$questions_ids)->orderByRaw('FIELD(id, '. implode(',', $questions_ids) .')')->get();
- $questions = json_decode(json_encode($questions),true);
- foreach($questions as $key => $question){
- $is_right = $this->paperExam($question,$answers[$key]);
- if($is_right){
- $is_right_number ++;
- }
- $log_data[] = [
- 'user_id' => $user['id'],
- 'question_id' => $question['id'],
- 'is_right' => $is_right ? 1 : 0,
- 'score' => $is_right ? site('question_right_getscore') : 0,
- 'jigou_id' => $user['bind_jigou_id'],
- 'createtime' => time(),
- 'createdate' => strtotime(date('Y-m-d')),
- ];
- }
- //今日答题次数,自增一次
- $count = RedisUtil::getInstance(RedisKeyEnum::EAXM_TIMES.date('Y-m-d').':'.$user['id'])->incrby_expire(count($user_questions),86400);
- if($is_right_number > 0){
- //今日答对次数,自增一次
- RedisUtil::getInstance(RedisKeyEnum::EAXM_RIGHT.date('Y-m-d').':'.$user['id'])->incrby_expire($is_right_number,86400);
- }
- //答题日志
- $right_score = intval(bcmul((string)$is_right_number,(string)site('question_right_getscore'),0));//乘以基数,也就是答题获得的分数
- $this->service->questionPush(['log_data' => $log_data, 'is_right_number' => $right_score, 'bind_jigou_id' => $user['bind_jigou_id']], 0);
- //给机构加分
- //返回正确了几道题,剩余答题次数
- $right_vote = intval(bcmul((string)$is_right_number,(string)site('question_right_getvotenum'),0));//乘以基数,也就是答题获得的票数
- $question_vote = intval(bcmul((string)$exam_times_user_eday,(string)site('question_right_getvotenum'),0));//乘以基数,也就是答题获得的票数
- $result = [
- 'remark' => '答对'.$is_right_number.'题,获得'.$right_vote.'次投票次数,答题最多可获得'.$question_vote.'次投票机会',
- 'submit_number'=> count($user_questions),
- 'right_number' => $is_right_number,
- 'remain' => $exam_times_user_eday - $count,
- ];
- return AppResult::success('答题完毕',$result);
- }
- /**
- * 试题
- * @param $question_id
- * @param $answer
- * @return bool
- */
- private function paperExam($question,$answer)
- {
- $is_right = false;
- if(empty($question)){
- return false;
- }
- $question = json_decode(json_encode($question),true);
- switch ($question['kind']) {
- case 'JUDGE': // 判断题
- case 'SINGLE': // 单选题
- case 'MULTI': // 多选题
- // 答题正确
- if (strtoupper($answer) == $question['answer']) {
- $is_right = true;
- } else {
- $is_right = false;
- }
- break;
- case 'SHORT': // 简答题
- // 答案得分配置
- $answer_config = is_string($question['answer']) ? json_decode($question['answer'], true) : $question['answer'];
- $user_answers = $answer;
- foreach ($answer_config['config'] as $answer_item) {
- // 匹配答案关键词
- if (strpos($user_answers, $answer_item['answer']) !== false) {
- $is_right = true;
- break;
- }
- }
- break;
- }
- return $is_right;
- }
- }
|