293 lines
9.3 KiB
PHP
293 lines
9.3 KiB
PHP
<?php
|
|
|
|
namespace app\api\model\app\exam;
|
|
use think\Model;
|
|
use app\api\model\app\exam\Exercises;
|
|
use app\api\model\app\exam\WarehouseQuestion;
|
|
use app\api\model\app\exam\ExercisesBindWarehouseGroup;
|
|
/**
|
|
* 题库练习记录答案
|
|
*/
|
|
class ExercisesLogAnswer extends Model
|
|
{
|
|
// 表名,不含前缀
|
|
protected $name = 'app_exam_exercises_log_answer';
|
|
// 自动写入时间戳字段
|
|
protected $autoWriteTimestamp = false;
|
|
// 定义时间戳字段名
|
|
protected $createTime = false;
|
|
protected $updateTime = false;
|
|
// 追加属性
|
|
protected $append = [
|
|
];
|
|
|
|
|
|
/**
|
|
* 效验答案
|
|
* @param $logId
|
|
* @param $questionList 问题列表
|
|
* @param $answerList 用户答案
|
|
* @return void
|
|
*/
|
|
public function checkAnswer($questionList,$answerList){
|
|
|
|
if(empty($answerList) || empty($questionList)){
|
|
return [];
|
|
}
|
|
|
|
$questionKeyVals = [];
|
|
foreach ($questionList as $question){
|
|
$questionKeyVals[$question['id']] = $question;
|
|
}
|
|
|
|
$result = [];
|
|
|
|
|
|
$questionKeys = array_keys($questionKeyVals);
|
|
|
|
$trueCount = 0;
|
|
$errorCount = 0;
|
|
|
|
foreach ($answerList as $key => $answer){
|
|
//判断答案的题目ID 是不是全在问题列表里
|
|
if(!in_array($key,$questionKeys)){
|
|
throw new \app\common\exception\Exception('答案数据异常');
|
|
}
|
|
|
|
$type = $questionKeyVals[$key]['type'];
|
|
//判断答案的范围是否正确
|
|
switch ($type){
|
|
case 'judge':
|
|
if($answer > 1 || $answer < 0){
|
|
throw new \app\common\exception\Exception('判断题答案数据异常');
|
|
}
|
|
break;
|
|
case 'single':
|
|
if($answer > (count($questionKeyVals[$key]['option']) - 1) || $answer < 0){
|
|
throw new \app\common\exception\Exception('单选题答案数据异常');
|
|
}
|
|
break;
|
|
case 'multiple':
|
|
case 'indefinite':
|
|
if(!is_array($answer)){
|
|
throw new \app\common\exception\Exception('多选题答案数据异常');
|
|
}
|
|
foreach ($answer as $option){
|
|
if($option > (count($questionKeyVals[$key]['option']) - 1) || $option < 0){
|
|
throw new \app\common\exception\Exception('多选题答案数据异常');
|
|
}
|
|
}
|
|
break;
|
|
case 'fillblank':
|
|
if(!is_array($answer)){
|
|
throw new \app\common\exception\Exception('填空题答案数据异常');
|
|
}
|
|
break;
|
|
case 'essay':
|
|
break;
|
|
}
|
|
|
|
$temp = [
|
|
'question_id'=>$key,
|
|
'createtime'=>time()
|
|
];
|
|
|
|
$isCorrect = false;
|
|
|
|
switch ($type){
|
|
case 'single':
|
|
case 'judge':
|
|
$temp['right_answer'] = $questionKeyVals[$key]['answer'];
|
|
$temp['user_answer'] = $answer;
|
|
$isCorrect = ($temp['right_answer'] == $temp['user_answer']);
|
|
break;
|
|
case 'multiple':
|
|
case 'indefinite':
|
|
$rightAnswer = $this->normalizeChoiceAnswer($questionKeyVals[$key]['answer']);
|
|
$answer = $this->normalizeChoiceAnswer($answer);
|
|
$temp['right_answer'] = implode(",",$rightAnswer);
|
|
$temp['user_answer'] = implode(",",$answer);
|
|
$isCorrect = ($rightAnswer == $answer);
|
|
break;
|
|
case 'fillblank':
|
|
$rightAnswer = is_array($questionKeyVals[$key]['answer']) ? $questionKeyVals[$key]['answer'] : json_decode($questionKeyVals[$key]['answer'],true);
|
|
$temp['right_answer'] = json_encode($rightAnswer,JSON_UNESCAPED_UNICODE);
|
|
$temp['user_answer'] = json_encode($answer,JSON_UNESCAPED_UNICODE);
|
|
$isCorrect = $this->checkFillblankAnswer($answer,$rightAnswer);
|
|
break;
|
|
case 'essay':
|
|
$temp['right_answer'] = $questionKeyVals[$key]['answer'];
|
|
$temp['user_answer'] = (is_array($answer) || is_object($answer))
|
|
? json_encode($answer, JSON_UNESCAPED_UNICODE)
|
|
: $answer;
|
|
$isCorrect = false;
|
|
break;
|
|
}
|
|
|
|
if($isCorrect){
|
|
$trueCount++;
|
|
$temp['result'] = 1;
|
|
$temp['error_book_show'] = 0;
|
|
}else{
|
|
$temp['result'] = 0;
|
|
// 问答题属于主观题,不纳入错题本
|
|
$temp['error_book_show'] = ($type == 'essay') ? 2 : 1;
|
|
if($type != 'essay'){
|
|
$errorCount++;
|
|
}
|
|
}
|
|
|
|
$result[] = $temp;
|
|
}
|
|
|
|
return [
|
|
'answer_list'=>$result,
|
|
'error_count'=>$errorCount,
|
|
'true_count'=>$trueCount,
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* 校验填空题答案
|
|
* @param array $userAnswer 用户答案
|
|
* @param array $rightAnswer 正确答案
|
|
* @return bool
|
|
*/
|
|
protected function checkFillblankAnswer($userAnswer,$rightAnswer){
|
|
|
|
if(empty($rightAnswer) || empty($userAnswer)){
|
|
return false;
|
|
}
|
|
|
|
if(count($userAnswer) != count($rightAnswer)){
|
|
return false;
|
|
}
|
|
|
|
foreach ($rightAnswer as $index => $acceptedAnswers){
|
|
$userBlankAnswer = isset($userAnswer[$index]) ? trim($userAnswer[$index]) : '';
|
|
$blankCorrect = false;
|
|
if(!is_array($acceptedAnswers)){
|
|
$acceptedAnswers = [$acceptedAnswers];
|
|
}
|
|
foreach ($acceptedAnswers as $acceptedAnswer){
|
|
if(strcasecmp(trim($acceptedAnswer),$userBlankAnswer) === 0){
|
|
$blankCorrect = true;
|
|
break;
|
|
}
|
|
}
|
|
if(!$blankCorrect){
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 规范化选择题答案,避免多选/不定项因顺序不同误判。
|
|
* @param mixed $answer
|
|
* @return array
|
|
*/
|
|
protected function normalizeChoiceAnswer($answer)
|
|
{
|
|
if(!is_array($answer)){
|
|
$answer = ($answer === '' || $answer === null) ? [] : explode(",",$answer);
|
|
}
|
|
|
|
$result = [];
|
|
foreach ($answer as $item){
|
|
if($item === '' || $item === null){
|
|
continue;
|
|
}
|
|
$result[] = intval($item);
|
|
}
|
|
|
|
$result = array_values(array_unique($result));
|
|
sort($result, SORT_NUMERIC);
|
|
return $result;
|
|
}
|
|
|
|
|
|
/**
|
|
* 博阿村答案
|
|
* @param $userId
|
|
* @param $logId
|
|
* @param $answerList
|
|
* @return void
|
|
*/
|
|
public function saveAnswer($userId,$exercisesId,$logId,$answerList){
|
|
|
|
foreach ($answerList as &$item){
|
|
$item['createtime'] = time();
|
|
$item['exercises_log_id'] = $logId;
|
|
$item['exercises_id'] = $exercisesId;
|
|
$item['user_id'] = $userId;
|
|
$item['uniacid'] = UNIACID;
|
|
}
|
|
|
|
return self::insertAll($answerList);
|
|
}
|
|
|
|
|
|
/**
|
|
* 获取用户提交的答案
|
|
* @param $userId
|
|
* @param $exercisesId
|
|
* @param $logId
|
|
* @return array
|
|
*/
|
|
public function getUserAnswer($userId,$exercisesId,$logId = 0){
|
|
|
|
$where = [
|
|
'user_id'=>$userId
|
|
];
|
|
|
|
if($exercisesId){
|
|
$where['exercises_id'] = $exercisesId;
|
|
}
|
|
|
|
if($logId){
|
|
$where['exercises_log_id'] = $logId;
|
|
}
|
|
|
|
$list = self::with(['warehouse_question'])->where($where)->group('question_id')->order('id','desc')->select();
|
|
|
|
$data = [];
|
|
if(!$list){
|
|
return $data;
|
|
}
|
|
|
|
$list = collection($list)->toArray();
|
|
foreach ($list as $item){
|
|
$type = isset($item['warehouse_question']['type']) ? $item['warehouse_question']['type'] : '';
|
|
switch ($type){
|
|
case 'multiple':
|
|
case 'indefinite':
|
|
$data[$item['question_id']] = [];
|
|
foreach (explode(",",$item['user_answer']) as $option){
|
|
$data[$item['question_id']][] = intval($option);
|
|
}
|
|
break;
|
|
case 'fillblank':
|
|
$data[$item['question_id']] = json_decode($item['user_answer'],true);
|
|
break;
|
|
case 'essay':
|
|
$decoded = json_decode($item['user_answer'], true);
|
|
$data[$item['question_id']] = is_array($decoded) ? $decoded : $item['user_answer'];
|
|
break;
|
|
default:
|
|
$data[$item['question_id']] = intval($item['user_answer']);
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
|
|
public function warehouseQuestion()
|
|
{
|
|
return $this->belongsTo('app\api\model\app\exam\WarehouseQuestion', 'question_id', 'id', [], 'LEFT')->setEagerlyType(0);
|
|
}
|
|
}
|