9 changed files with 181 additions and 5 deletions
@ -0,0 +1,7 @@ |
|||
package com.project.exam.domain.service; |
|||
|
|||
import com.project.exam.domain.dto.ExamRecordDTO; |
|||
|
|||
public interface SubmitPaperDomainService { |
|||
ExamRecordDTO submitPaper(Long recordId) throws Exception; |
|||
} |
|||
@ -1,4 +0,0 @@ |
|||
package com.project.exam.domain.service; |
|||
|
|||
public interface SummitPaperDomainService { |
|||
} |
|||
@ -0,0 +1,127 @@ |
|||
package com.project.exam.domain.service.impl; |
|||
|
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.project.base.domain.exception.BusinessErrorException; |
|||
import com.project.exam.domain.dto.ExamRecordDTO; |
|||
import com.project.exam.domain.entity.ExamRecordEntity; |
|||
import com.project.exam.domain.service.BuildExamRecordDomainService; |
|||
import com.project.exam.domain.service.SubmitPaperDomainService; |
|||
import com.project.exam.mapper.ExamRecordMapper; |
|||
import com.project.task.domain.dto.TaskDTO; |
|||
import com.project.task.domain.entity.TaskEntity; |
|||
import com.project.task.domain.entity.TaskUserEntity; |
|||
import com.project.task.domain.enums.QuestionTypeEnum; |
|||
import com.project.task.domain.enums.TaskUserStatusEnum; |
|||
import com.project.task.domain.service.TaskBaseService; |
|||
import com.project.task.mapper.TaskMapper; |
|||
import com.project.task.mapper.TaskUserMapper; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.math.RoundingMode; |
|||
import java.util.Arrays; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
@Service |
|||
public class SubmitPaperDomainServiceImpl implements SubmitPaperDomainService { |
|||
@Autowired |
|||
private ExamRecordMapper examRecordMapper; |
|||
@Autowired |
|||
private TaskUserMapper taskUserMapper; |
|||
@Autowired |
|||
private TaskMapper taskMapper; |
|||
@Autowired |
|||
private TaskBaseService taskBaseService; |
|||
|
|||
@Autowired |
|||
private BuildExamRecordDomainService buildExamRecordDomainService; |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public ExamRecordDTO submitPaper(Long recordId) throws Exception { |
|||
ExamRecordEntity record = examRecordMapper.selectById(recordId); |
|||
if (record == null || record.getSubmitTime() != null) { |
|||
throw new BusinessErrorException("试卷已提交或记录不存在"); |
|||
} |
|||
// 获取任务配置与用户进度记录
|
|||
TaskUserEntity taskUser = taskUserMapper.selectById(record.getTaskUserId()); |
|||
TaskEntity task = taskMapper.selectById(taskUser.getTaskId()); |
|||
|
|||
// 判分
|
|||
double finalScore = 0.0; |
|||
List<ExamRecordEntity.QuestionSnapshot> snapshotList = record.getAnswerSnapshot(); |
|||
for (ExamRecordEntity.QuestionSnapshot snapshot : snapshotList) { |
|||
// 比对答案
|
|||
if (StrUtil.equals(formatAnswer(snapshot.getUserAnswer()) , formatAnswer(snapshot.getRightAnswer()))) { |
|||
snapshot.setIsRight(true); |
|||
// 根据题型获取任务创建时算好的单题分值
|
|||
finalScore += getQuestionWeight(snapshot.getType(), task); |
|||
} else { |
|||
snapshot.setIsRight(false); |
|||
} |
|||
} |
|||
// 四舍五入处理
|
|||
finalScore = new BigDecimal(finalScore).setScale(2, RoundingMode.HALF_UP).doubleValue(); |
|||
boolean isPassed = finalScore >= task.getPassScore(); |
|||
record.setScore(finalScore); |
|||
record.setPass(isPassed); |
|||
record.setSubmitTime(new Date()); |
|||
record.setAnswerSnapshot(snapshotList); |
|||
examRecordMapper.updateById(record); |
|||
|
|||
// 更新 TaskEntity 冗余字段
|
|||
if (isPassed) { |
|||
taskBaseService.update() |
|||
.setSql("pass_num = pass_num + 1") |
|||
.eq("id", task.getId()) |
|||
.update(); |
|||
} |
|||
|
|||
// 更新 TaskUser 冗余字段
|
|||
updateTaskUserStatus(taskUser , isPassed , recordId); |
|||
// 构建dto
|
|||
ExamRecordDTO dto = record.toDTO(ExamRecordDTO::new); |
|||
dto.setTaskDTO(task.toDTO(TaskDTO::new)); |
|||
return buildExamRecordDomainService.buildDTO(dto); |
|||
} |
|||
|
|||
/** |
|||
* 根据题型映射任务表中的动态分值 |
|||
*/ |
|||
private double getQuestionWeight(Integer type, TaskEntity task) { |
|||
if (QuestionTypeEnum.SINGLE_CHOICE.getValue().equals(type)) { |
|||
return task.getSingleChoiceScore(); |
|||
} else if (QuestionTypeEnum.MULTIPLE_CHOICE.getValue().equals(type)) { |
|||
return task.getMultipleChoiceScore(); |
|||
} |
|||
else if (QuestionTypeEnum.TRUE_FALSE.getValue().equals(type)) { |
|||
return task.getTrueFalseScore(); |
|||
} |
|||
return 0.0; |
|||
} |
|||
|
|||
private void updateTaskUserStatus(TaskUserEntity taskUser, boolean isPassed, Long recordId) { |
|||
taskUser.setLastRecordId(recordId); |
|||
taskUser.setAttemptNum((taskUser.getAttemptNum() == null ? 0 : taskUser.getAttemptNum()) + 1); |
|||
|
|||
if (!TaskUserStatusEnum.Pass.getValue().equals(taskUser.getStatus())) { |
|||
taskUser.setStatus(isPassed ? TaskUserStatusEnum.Pass.getValue() : TaskUserStatusEnum.Fail.getValue()); |
|||
} |
|||
|
|||
taskUserMapper.updateById(taskUser); |
|||
} |
|||
|
|||
private String formatAnswer(String ans) { |
|||
if (StrUtil.isBlank(ans)) return ""; |
|||
// 去空格 -> 转大写 -> 排序(解决 B,A vs A,B 的问题)
|
|||
return Arrays.stream(ans.split(",")) |
|||
.map(String::trim) |
|||
.map(String::toUpperCase) |
|||
.sorted() |
|||
.collect(Collectors.joining(",")); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue