You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tianze-pro/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseQuestionLo...

1161 lines
56 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.ibeetl.jlw.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONUtil;
import cn.jlw.util.ToolUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ibeetl.admin.core.service.CoreBaseService;
import com.ibeetl.admin.core.service.CoreDictService;
import com.ibeetl.admin.core.util.PlatformException;
import com.ibeetl.admin.core.web.JsonResult;
import com.ibeetl.admin.core.web.JsonReturnCode;
import com.ibeetl.jlw.dao.ResourcesQuestionSnapshotDao;
import com.ibeetl.jlw.dao.StudentDao;
import com.ibeetl.jlw.dao.TeacherOpenCourseQuestionLogDao;
import com.ibeetl.jlw.dao.TeacherOpenCourseQuestionSettingDao;
import com.ibeetl.jlw.entity.*;
import com.ibeetl.jlw.entity.dto.QuestionLogAddDTO;
import com.ibeetl.jlw.entity.dto.TeacherOpenCourseHomeWorkLogDTO;
import com.ibeetl.jlw.entity.vo.FileQuestionLogListVO;
import com.ibeetl.jlw.entity.vo.TeacherOpenCourseHomeWorkLogExportVO;
import com.ibeetl.jlw.entity.vo.TeacherOpenCourseQuestionLogAnswerLockVO;
import com.ibeetl.jlw.enums.GlobalStatusEnum;
import com.ibeetl.jlw.enums.QuestionLogAddTypeEnum;
import com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum;
import com.ibeetl.jlw.web.query.QuestionLogSummaryQuery;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionLogQuery;
import com.ibeetl.jlw.web.query.TeacherOpenCourseQuestionSettingQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.beetl.sql.core.SqlId;
import org.beetl.sql.core.engine.PageQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.MultiValueMapAdapter;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Nullable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static cn.hutool.core.date.DateUnit.SECOND;
import static cn.hutool.core.util.ArrayUtil.isAllNotEmpty;
import static cn.hutool.core.util.ArrayUtil.join;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
import static cn.jlw.util.CacheUserUtil.getStudent;
import static com.ibeetl.admin.core.util.StreamUtils.listJoin;
import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUserId;
import static com.ibeetl.jlw.enums.QuestionBusinessTypeEnum.FROM_OPEN_COURSE;
import static com.ibeetl.jlw.enums.QuestionLogAddTypeEnum.*;
import static com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum.CHAPTER_EXERCISE;
import static com.ibeetl.jlw.enums.ResourcesQuestionSnapshotFromTypeEnum.HOMEWORK_FILE;
import static com.ibeetl.jlw.enums.ResourcesQuestionTypeEnum.isOneQuestion;
import static java.lang.Math.abs;
import static java.lang.Math.toIntExact;
import static java.math.BigDecimal.ZERO;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
/**
* 题目日志 Service
* 当分布式ID开启后请勿使用insert(*,true)
*/
@Service
@Transactional
@Validated
@Slf4j
public class TeacherOpenCourseQuestionLogService extends CoreBaseService<TeacherOpenCourseQuestionLog> implements DeleteResourcesBy{
@Autowired private TeacherOpenCourseQuestionLogDao teacherOpenCourseQuestionLogDao;
@Autowired private StudentDao studentDao;
@Autowired private ResourcesQuestionSnapshotDao resourcesQuestionSnapshotDao;
@Autowired @Lazy
private TeacherOpenCourseQuestionSettingService teacherOpenCourseQuestionSettingService;
@Autowired
private TeacherOpenCourseQuestionSettingDao teacherOpenCourseQuestionSettingDao;
@Autowired private TeacherOpenCourseQuestionLogWrongService teacherOpenCourseQuestionLogWrongService;
@Autowired private QuestionLogSummaryService questionLogSummaryService;
@Autowired private CoreDictService coreDictService;
public PageQuery<TeacherOpenCourseQuestionLog>queryByCondition(PageQuery query){
PageQuery ret = teacherOpenCourseQuestionLogDao.queryByCondition(query);
queryListAfter(ret.getList());
return ret;
}
public PageQuery<TeacherOpenCourseQuestionLog>queryByConditionQuery(PageQuery query){
PageQuery ret = teacherOpenCourseQuestionLogDao.queryByConditionQuery(query);
List<TeacherOpenCourseQuestionLog> list = ret.getList();
queryListAfter(list);
Map<Long, List<Student>> studentMap = new HashMap<>();
if (ObjectUtil.isNotEmpty(list)) {
String studentIds = list.stream().map(TeacherOpenCourseQuestionLog::getStudentId).map(Object::toString).distinct().collect(joining(","));
List<Student> studentList = studentDao.getByIds(studentIds);
dictParser(studentList);
if (ObjectUtil.isNotEmpty(studentList)) {
studentMap.putAll(studentList.stream().collect(groupingBy(Student::getStudentId)));
}
list.forEach(item -> {
List<Student> students = studentMap.get(item.getStudentId());
if (ObjectUtil.isNotEmpty(students)) {
Student student = students.get(0);
// 学生编号
item.set("studentSn", student.getStudentSn());
item.set("studentName", student.getStudentName());
// 班级
item.set("className", defaultIfNull(student.get("classIdText"), "班级不存在"));
}
});
}
return ret;
}
public void deleteByList(List list){
String ids = "";
ToolUtils.deleteNullList(list);
for(int i=0;null != list && i<list.size();i++){
ids += list.get(i).toString()+(i==list.size()-1?"":",");
}
if(StringUtils.isNotBlank(ids)){
teacherOpenCourseQuestionLogDao.deleteByIds(ids);
}
}
public void deleteTeacherOpenCourseQuestionLog(String ids){
try {
teacherOpenCourseQuestionLogDao.deleteTeacherOpenCourseQuestionLogByIds(ids);
} catch (Exception e) {
throw new PlatformException("批量删除题目日志失败", e);
}
}
/**
* 根据题目配置ID 批量真删除
* @param settingIds
*/
public void deleteBySettingIds(String settingIds) {
try {
teacherOpenCourseQuestionLogDao.deleteBySettingIds(settingIds);
} catch (Exception e) {
throw new PlatformException("批量删除题目日志失败", e);
}
}
public void logicDeleteBySettingIds(String settingIds){
try {
teacherOpenCourseQuestionLogDao.logicDeleteBySettingIds(settingIds);
} catch (Exception e) {
throw new PlatformException("批量删除题目日志失败", e);
}
}
public String addAll(TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
String msg = "";
List<TeacherOpenCourseQuestionLog> teacherOpenCourseQuestionLogList = new ArrayList<>();
try {
teacherOpenCourseQuestionLogList = JSON.parseArray(teacherOpenCourseQuestionLogQuery.getTeacherOpenCourseQuestionLogJsonStr(), TeacherOpenCourseQuestionLog.class);
} catch (Exception e) {
try {
teacherOpenCourseQuestionLogList.add(JSONObject.parseObject(teacherOpenCourseQuestionLogQuery.getTeacherOpenCourseQuestionLogJsonStr(), TeacherOpenCourseQuestionLog.class));
} catch (Exception e1) {}
}
ToolUtils.deleteNullList(teacherOpenCourseQuestionLogList);
if(null != teacherOpenCourseQuestionLogList && teacherOpenCourseQuestionLogList.size()>0){
for(int i=0;i<teacherOpenCourseQuestionLogList.size();i++){
TeacherOpenCourseQuestionLog teacherOpenCourseQuestionLog = teacherOpenCourseQuestionLogList.get(i);
teacherOpenCourseQuestionLog.setUserId(teacherOpenCourseQuestionLogQuery.getUserId());
teacherOpenCourseQuestionLog.setOrgId(teacherOpenCourseQuestionLogQuery.getOrgId());
}
insertBatch(teacherOpenCourseQuestionLogList);
}
return msg;
}
public JsonResult add(TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
String msg = "";
TeacherOpenCourseQuestionLog teacherOpenCourseQuestionLog = teacherOpenCourseQuestionLogQuery.pojo();
teacherOpenCourseQuestionLogDao.insert(teacherOpenCourseQuestionLog);
teacherOpenCourseQuestionLogQuery.setTeacherOpenCourseQuestionLogId(teacherOpenCourseQuestionLog.getTeacherOpenCourseQuestionLogId());
JsonResult jsonResult = new JsonResult();
jsonResult.setData(teacherOpenCourseQuestionLog.getTeacherOpenCourseQuestionLogId());//自增的ID丢进去
jsonResult.setCode(JsonReturnCode.SUCCESS.getCode());
jsonResult.setMsg(msg);
return jsonResult;
}
public String edit(TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
String msg = "";
TeacherOpenCourseQuestionLog teacherOpenCourseQuestionLog = teacherOpenCourseQuestionLogQuery.pojo();
teacherOpenCourseQuestionLogDao.updateTemplateById(teacherOpenCourseQuestionLog);
return msg;
}
public String updateGivenByIds(TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
String msg = "";
if(StringUtils.isNotBlank(teacherOpenCourseQuestionLogQuery.get_given())){
boolean flag = teacherOpenCourseQuestionLogDao.updateGivenByIds(teacherOpenCourseQuestionLogQuery) > 0;
if(!flag){
msg = "更新指定参数失败";
}
}else{
msg = "指定参数为空";
}
return msg;
}
public List<TeacherOpenCourseQuestionLog> getValues (Object paras){
return sqlManager.select(SqlId.of("jlw.teacherOpenCourseQuestionLog.getTeacherOpenCourseQuestionLogValues"), TeacherOpenCourseQuestionLog.class, paras);
}
public List<TeacherOpenCourseQuestionLog> getValuesByQuery (TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
return teacherOpenCourseQuestionLogDao.getValuesByQuery(teacherOpenCourseQuestionLogQuery);
}
public List<TeacherOpenCourseQuestionLog> getValuesByQueryNotWithPermission (TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
return teacherOpenCourseQuestionLogDao.getValuesByQueryNotWithPermission(teacherOpenCourseQuestionLogQuery);
}
public List<TeacherOpenCourseQuestionLog> getValuesBySettingIds (String settingIds){
TeacherOpenCourseQuestionLogQuery logQuery = new TeacherOpenCourseQuestionLogQuery();
logQuery.setTeacherOpenCourseQuestionSettingIdPlural(settingIds);
logQuery.setTeacherOpenCourseQuestionLogStatus(1);
return teacherOpenCourseQuestionLogDao.getValuesByQueryNotWithPermission(logQuery);
}
public TeacherOpenCourseQuestionLog getInfo (Long teacherOpenCourseQuestionLogId){
TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery = new TeacherOpenCourseQuestionLogQuery();
teacherOpenCourseQuestionLogQuery.setTeacherOpenCourseQuestionLogId(teacherOpenCourseQuestionLogId);
teacherOpenCourseQuestionLogQuery.setTeacherOpenCourseQuestionLogStatusPlural("1,2");//需要根据实际情况来
List<TeacherOpenCourseQuestionLog> list = teacherOpenCourseQuestionLogDao.getValuesByQuery(teacherOpenCourseQuestionLogQuery);
if(null != list && list.size()>0){
return list.get(0);
}else{
return null;
}
}
public TeacherOpenCourseQuestionLog getInfo (TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery){
List<TeacherOpenCourseQuestionLog> list = teacherOpenCourseQuestionLogDao.getValuesByQuery(teacherOpenCourseQuestionLogQuery);
if(null != list && list.size()>0){
return list.get(0);
}else{
return null;
}
}
/**
* 和题目有关的做题提交方法
*
* @param questionLogMap <题目ID, [数组:前端传递过来不需要考虑排序和重复问题]> 例: {"10086": ["D", "A", "B", "A"]}
* @param questionSettingId 题目配置ID
*/
@Deprecated
public void addQuestionLog(
@NotEmpty(message = "请上传题目快照ID和答案") Map<Long, TreeSet<String>> questionLogMap,
@NotNull(message = "开课题目配置ID不能为空") final Long questionSettingId) {
// 查询学生身份
final Student student = studentDao.getByUserId(getUserId());
List<TeacherOpenCourseQuestionLog> list = new ArrayList<>();
// 不需要判断空,控制类层已经用@NotEmpty判断过了。
questionLogMap.forEach((resourcesQuestionSnapshotId, answerSet) -> {
// 答案逗号隔开
String answersText = join(answerSet.toArray(), ",");
// 构建实体
TeacherOpenCourseQuestionLog questionLog = new TeacherOpenCourseQuestionLog();
questionLog.setTeacherOpenCourseQuestionSettingId(questionSettingId);
questionLog.setTeacherOpenCourseQuestionLogStatus(1);
questionLog.setOrgId(student.getOrgId());
questionLog.setUserId(student.getUserId());
// 包含/字符,代表是路径地址,是附件类型
if(answersText.contains("/")) {
questionLog.setTeacherOpenCourseQuestionLogUploadFile(answersText);
}
// 否则就是普通选择题的答案
else {
questionLog.setTeacherOpenCourseQuestionLogAnswer(answersText);
}
questionLog.setTeacherOpenCourseQuestionLogAddTime(new Date());
questionLog.setResourcesQuestionSnapshotId(resourcesQuestionSnapshotId);
questionLog.setStudentId(student.getStudentId());
// 用于数据权限
questionLog.setOrgId(student.getOrgId());
questionLog.setUserId(student.getUserId());
list.add(questionLog);
});
// 批量入库
insertBatch(list);
}
/**
* 教师端-手动批改一些题目的分数
* 教师端-给学生打分
*
* @param teacherOpenCourseQuestionLogIds 指定更新分数的题目日志IDs
* @param score 分数
* @param reply 评语
*/
public void manualModifyQuestionScores(@NotNull(message = "题目做题日志ID不能为空") final String teacherOpenCourseQuestionLogIds,
@NotNull(message = "设置的分数不能为空!") final BigDecimal score, @Nullable String reply) {
TeacherOpenCourseQuestionLogQuery teacherOpenCourseQuestionLogQuery = new TeacherOpenCourseQuestionLogQuery();
teacherOpenCourseQuestionLogQuery.setTeacherOpenCourseQuestionLogIdPlural(teacherOpenCourseQuestionLogIds);
teacherOpenCourseQuestionLogQuery.setTeacherOpenCourseQuestionLogStatus(1);
List<TeacherOpenCourseQuestionLog> updateList = teacherOpenCourseQuestionLogDao.getValuesByQueryNotWithPermission(teacherOpenCourseQuestionLogQuery);
Assert.notEmpty(updateList, "未查询到做题记录!");
final Date now = new Date();
// 批量更新分数。支持重复设置分数和评语
updateList.forEach(questionLog -> {
BigDecimal questionScore = questionLog.getQuestionScore();
questionLog.setStudentScore(score);
questionLog.setTeacherOpenCourseQuestionLogReply(reply);
// 这里不是记录用时,只是记录教师批阅的时间
questionLog.setTeacherOpenCourseQuestionLogUpdateTime(now);
// 是否错题库,也可以用作标记答案是对的错的
questionLog.setIsErrorFavorite(NumberUtil.equals(questionScore, score));
});
updateBatchTemplate(updateList);
// 处理多个学生的数据
updateList.stream().collect(groupingBy(TeacherOpenCourseQuestionLog::getStudentId)).forEach((studentId, logList) -> {
TeacherOpenCourseQuestionLog questionLog = logList.get(0);
Student student = studentDao.getById(studentId);
if (ObjectUtil.isAllNotEmpty(student, questionLog)) {
addQuestionLogSummary(student, questionLog.getTeacherOpenCourseQuestionSettingId(), updateList);
}
});
}
/**
* 和题目有关的做题提交方法
* 直接计算出学生得分情况flock
* 不能做练习题
*
* @param questionLogAddDTO 题目信息
*/
public void addQuestionLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO) {
final Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, String> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询学生身份
final Student student = getStudent();
Assert.notNull(student, "非学生身份,无法提交!");
TeacherOpenCourseQuestionSetting questionSetting = teacherOpenCourseQuestionSettingService.getInfo(questionSettingId);
Assert.notNull(questionSetting, "未匹配到试卷信息!");
// 校验当前时间是否在考试的时间段
teacherOpenCourseQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId);
switch(questionSetting.getTeacherOpenCourseQuestionSettingType()) {
case HOMEWORK_FILE: {
addFileRelatedLog(join(questionLogMap.values().toArray(), ","), questionSettingId, student);
} break;
// 这些都和题目相关,暂时先放在一个方法
case CHAPTER_EXERCISE:
case EXAM:
case HOMEWORK_QUESTION:{
addQuestionRelatedLog(questionLogAddDTO, questionSetting, student);
} break;
}
}
/**
* 和题目有关的做题提交方法
* 直接计算出学生得分情况
* 只支持练习
*
* @param questionLogAddDTO 题目信息
*/
public void addQuestionLogTest(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO) {
final Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
// 查询学生身份
final Student student = getStudent();
Assert.notNull(student, "非学生身份,无法提交!");
TeacherOpenCourseQuestionSetting questionSetting = teacherOpenCourseQuestionSettingService.getInfo(questionSettingId);
Assert.notNull(questionSetting, "未匹配到试卷信息!");
// 校验当前时间是否在考试的时间段
teacherOpenCourseQuestionSettingService.verifyQuestionStartAndEndTimeWithNowTimeThrow(questionSettingId);
switch(questionSetting.getTeacherOpenCourseQuestionSettingType()) {
// 这些都和题目相关,暂时先放在一个方法
case CHAPTER_EXERCISE: {
addQuestionRelatedLog(questionLogAddDTO, questionSetting, student);
} break;
}
}
/**
* 跟题目相关的题目日志提交方法
* 附件类型的需要单独,拆分除去
*
* @param absFilePath
* @param questionSettingId
* @param student
*/
private void addFileRelatedLog(@NotBlank(message = "上传的附件不能为空!") String absFilePath, Long questionSettingId, Student student) {
Date now = new Date();
TeacherOpenCourseQuestionLogQuery query = new TeacherOpenCourseQuestionLogQuery();
query.setTeacherOpenCourseQuestionLogUploadFile(absFilePath);
query.setTeacherOpenCourseQuestionSettingId(questionSettingId);
query.setTeacherOpenCourseQuestionLogAddTime(now);
query.setTeacherOpenCourseQuestionLogFinishTime(RandomUtil.randomLong(100, 3600));
query.setTeacherOpenCourseQuestionLogStatus(1);
// 附件作业,只有一题,所有默认是全部提交的方式
query.setQuestionLogAddType(FINALLY_SUBMIT);
query.setOrgId(student.getOrgId());
query.setUserId(student.getUserId());
query.setStudentId(student.getStudentId());
add(query);
}
/**
* 跟题目相关的题目日志提交方法
* 附件类型的需要单独,拆分除去
* 提交试卷 试卷提交
*
* @param questionLogAddDTO 题目信息
* @param student 学生信息
*/
private void addQuestionRelatedLog(@NotNull(message = "提交题目信息不能为空") QuestionLogAddDTO questionLogAddDTO,
@NotNull(message = "开课信息不能为空") TeacherOpenCourseQuestionSetting questionSetting,
@NotNull(message = "学生信息不能为空") final Student student) {
// 参数获取
QuestionLogAddTypeEnum addType = questionLogAddDTO.getQuestionLogAddType();
Date addTime = questionLogAddDTO.getAddTime(); Long studentId = student.getStudentId();
Long questionSettingId = questionLogAddDTO.getQuestionSettingId();
Map<String, String> questionLogMap = questionLogAddDTO.getQuestionLogMap();
// 查询符合条件的日志表
String questionSnapshotIds = join(questionLogMap.keySet().toArray(), ",");
// 做题思路先从开课QuestionSetting表中生成题目日志到开课QuestionLog中学生这个时候提交答案再修改日志中的结果。
// 查询条件
TeacherOpenCourseQuestionLogQuery questionLogQuery = TeacherOpenCourseQuestionLogQuery.builder()
.resourcesQuestionSnapshotIdPlural(questionSnapshotIds)
.teacherOpenCourseQuestionLogStatus(1)
.studentId(student.getStudentId())
.teacherOpenCourseQuestionSettingId(questionSettingId)
.build();
List<TeacherOpenCourseQuestionLog> logList = teacherOpenCourseQuestionLogDao.getValuesByQueryNotWithPermission(questionLogQuery);
final List<QuestionLogAddTypeEnum> tempList = Arrays.asList(PRE_SUBMIT, null);
// 只是未提交的数据
logList = logList.stream().filter(item -> tempList.contains(item.getQuestionLogAddType())).collect(Collectors.toList());
Assert.notEmpty(logList, "未查询到题目信息!");
// 题目日志IDs汇总
String logsIds = logList.stream().map(item -> item.getTeacherOpenCourseQuestionLogId().toString()).collect(joining(","));
// 当前时间, 存储要更新的题目日志集合
Date now = new Date(); List<TeacherOpenCourseQuestionLog> updateList = new ArrayList<>();
// 代表填空题和分析题的类型
List<Integer> questionType = Arrays.asList(4, 5);
// 处理答案和分数
logList.forEach(questionLog -> {
// 验证最新的提交时间,防止网络延迟
if (!validateQuestionLogAddTimeLatest(questionSettingId, questionLog.getResourcesQuestionSnapshotId().toString(), studentId, addTime)) {
return;
}
// 验证提交类型
validateQuestionLogAddTypeThrow(questionLog.getQuestionLogAddType(), questionLogAddDTO.getQuestionLogAddType());
// 学生提交的答案
String answer = questionLogMap.get(questionLog.getResourcesQuestionSnapshotId().toString());
// 默认0分
questionLog.setStudentScore(BigDecimal.valueOf(0));
// 学生提交的答案处理
String answersText = null;
if (questionType.contains(questionLog.getQuestionType())) {
answersText = answer;
cn.hutool.json.JSONObject studentAnswerArr = new cn.hutool.json.JSONObject();
if (StrUtil.isNotBlank(answersText)) {
studentAnswerArr = JSONUtil.parseObj(answersText);
}
// 学生答案和正确答案集合
cn.hutool.json.JSONObject questionAnswerArr = JSONUtil.parseObj(questionLog.getQuestionAnswer());
// 每题分数
BigDecimal eachScore = NumberUtil.div(questionLog.getQuestionScore(), questionAnswerArr.size(), 1);
BigDecimal studentScore = new BigDecimal("0");
for (Map.Entry<String, Object> map : questionAnswerArr.entrySet()) {
Object questionAns = map.getValue();
String k = map.getKey();
String studentAns = studentAnswerArr.getStr(k, "");
// 比对答案
if ( StrUtil.isAllNotBlank(questionAns.toString(), studentAns) && questionAns.toString().equalsIgnoreCase(studentAns)) {
studentScore.add(eachScore);
}
}
// 填空题和分析题计算分数
// 计算该题目学生的得分情况
questionLog.setStudentScore(studentScore);
// 是否是错题
questionLog.setIsErrorFavorite(NumberUtil.isLess(studentScore, questionLog.getQuestionScore()));
}else {
answersText = join(answer.split(","), ",");
// 是否是正确答案
Boolean isCorrectAnswer = questionLog.getQuestionAnswer().equalsIgnoreCase(answersText);
// 学生得分
questionLog.setStudentScore(isCorrectAnswer ? questionLog.getQuestionScore() : ZERO);
questionLog.setIsErrorFavorite(!isCorrectAnswer);
}
// 完成时间,从生成试卷时候,开始计算
long finishSecondTime = DateUtil.between(questionLog.getTeacherOpenCourseQuestionLogAddTime(), now, SECOND);
// 填充属性
questionLog.setTeacherOpenCourseQuestionLogAnswer(answersText);
questionLog.setTeacherOpenCourseQuestionLogUpdateTime(now);
questionLog.setTeacherOpenCourseQuestionLogFinishTime(finishSecondTime);
questionLog.setQuestionLogAddType(addType);
questionLog.setOrgId(student.getOrgId());
questionLog.setUserId(student.getUserId());
// 只添加可以更新的数据
updateList.add(questionLog);
});
// 学生做的题目的答案与日志关联
updateBatchTemplate(updateList);
// 最后提交试卷答案时候,才会记录错题
if (addType.equals(FINALLY_SUBMIT)) {
// 计算学生分数,并标记错题
calculateScoreOnSubmit(updateList);
updateBatchTemplate(updateList);
// 添加到题目日志汇总中
addQuestionLogSummary(student, questionSettingId, updateList);
// 批量插入错题集错题库方法内部自带分数判断。内部方法更新log中的错题标记。
teacherOpenCourseQuestionLogWrongService.insertBatchByQuestionLogList(updateList);
// 最终提交以后将日志更改为2 删除状态,仅用于查看
deleteTeacherOpenCourseQuestionLog(listJoin(updateList, TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionLogId));
}
}
/**
* 功能描述: <br>
* 计算学生分数
* 会判断题目是否打完,并抛出异常
*
* @param logList
* @Author: lx
* @Date: 2022/12/4 20:16
*/
public void calculateScoreOnSubmit(@NotEmpty(message = "学生题目日志不能为空!") List<TeacherOpenCourseQuestionLog> logList) {
logList.forEach(questionLog -> {
// 题目原本设置的分数
final BigDecimal questionScore = questionLog.getQuestionScore();
// 题目类型
final Integer questionType = questionLog.getQuestionType();
// 学生提交的结果
final String studentAnswer = defaultIfNull(questionLog.getTeacherOpenCourseQuestionLogAnswer(), "");
// 题目的答案
final String questionAnswer = defaultIfNull(questionLog.getQuestionAnswer(), "");
// 判断答案和学生提交的结果,都不能为空
final boolean allNotEmpty = isAllNotEmpty(questionAnswer, studentAnswer);
// 题目类型,答案属于一道题
final boolean oneQuestion = isOneQuestion(questionType);
// 一条日志记录,属于一道题
if (oneQuestion) {
final boolean isTrue = allNotEmpty && studentAnswer.equalsIgnoreCase(questionAnswer);
final BigDecimal mySimpleScore = isTrue ? questionScore: ZERO;
// 计算学生最后的得分
questionLog.setStudentScore(mySimpleScore);
if (isTrue) {
questionLog.setSuccessCount(1);
}
else {
questionLog.setErrorCount(1);
}
// 错题标记
questionLog.setIsErrorFavorite(!isTrue);
}
// 一条日志记录,属于多道题的逻辑处理
else {
// 分数,正确数量
BigDecimal score = ZERO; int successCount = 0;
// 学生提交的题目结果
final String[] studentAnswerArr = studentAnswer.split(",");
// 正确答案和学生答案对比
String[] successAnswerArr = questionAnswer.split(",");
final int studentAnswerLength = studentAnswerArr.length;
final int questionLength = successAnswerArr.length;
// 断言需要判断,题目答案的数量是否相等,不然会对不上答案,导致分数计算错误
// Assert.isTrue(studentAnswerLength == questionLength, "题干:" + questionLog.getQuestionStem()+ ",有选项未提交!");
// 一道题的分数
BigDecimal simpleQuestionScore = NumberUtil.mul(questionScore, questionLength);
// 循环比对这个题目,是否是复杂的题目:如选词填空或者分析题
for (int i = 0; i < questionLength; i++) {
String sqs = successAnswerArr[i];
boolean isTrue = allNotEmpty && sqs.equalsIgnoreCase(studentAnswerArr[i]);
BigDecimal oneScore = isTrue ? simpleQuestionScore : ZERO;
score = score.add(oneScore);
// 正确的数量计数
if (isTrue) {
successCount++;
}
}
// 全对的题目,才算做正确答案
final boolean isAllTrue = successCount == questionLength;
// 计算学生最后的得分
questionLog.setStudentScore(score);
questionLog.setSuccessCount(successCount);
questionLog.setErrorCount(abs(questionLength - successCount));
// 错题标记
questionLog.setIsErrorFavorite(!isAllTrue);
}
});
}
/**
* 根据题目实时计算,计算分数。并在做题统计表表中添加一条记录
*
* @param student
* @param questionSettingId
* @param updateList
*/
private void addQuestionLogSummary(Student student, Long questionSettingId, List<TeacherOpenCourseQuestionLog> updateList) {
if (student == null || questionSettingId == null) {
return;
}
List<TeacherOpenCourseQuestionLog> logList = getValuesBySettingIds(questionSettingId.toString());
setErrorSuccessCountField(updateList, logList);
TeacherOpenCourseQuestionSetting questionSetting = teacherOpenCourseQuestionSettingService.getInfo(questionSettingId);
if (CollectionUtil.isNotEmpty(logList) && questionSetting != null) {
String logIds = logList.stream().map(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionLogId).map(Objects::toString).collect(joining(","));
addQuestionLogSummary(logIds, logList, student, questionSetting.getTeacherOpenCourseQuestionSettingName(), questionSetting.getTeacherOpenCourseQuestionSettingType());
}
}
/**
* 拷贝正确错误的字段
*
* @param updateList
* @param logList
*/
private void setErrorSuccessCountField(List<TeacherOpenCourseQuestionLog> updateList, List<TeacherOpenCourseQuestionLog> logList) {
Map<Long, List<TeacherOpenCourseQuestionLog>> listMap = updateList.stream()
.collect(groupingBy(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionLogId));
MultiValueMapAdapter<Long, TeacherOpenCourseQuestionLog> mapAdapter = new MultiValueMapAdapter<>(listMap);
logList.forEach(item -> {
TeacherOpenCourseQuestionLog first = mapAdapter.getFirst(item.getTeacherOpenCourseQuestionLogId());
if (first != null) {
item.setErrorCount(first.getErrorCount());
item.setSuccessCount(first.getSuccessCount());
}
});
}
/**
* 功能描述: <br>
* 题目日志信息,分析汇总到某张表里
*
* @param logsIds 题目日志IDs保存
* @param logList 某个questionSettingId对应的题目日志列表
* @param student 学生
* @param questionSettingName 题目配置的名称(试卷名称)
* @param snapshotFromTypeEnum 题目来源
* @Author: lx
* @Date: 2022/12/4 20:16
*/
public void addQuestionLogSummary(
String logsIds, @NotEmpty(message = "学生题目日志不能为空!") List<TeacherOpenCourseQuestionLog> logList,
@NotNull Student student, @NotBlank String questionSettingName, @NotNull ResourcesQuestionSnapshotFromTypeEnum snapshotFromTypeEnum) {
// 构建实体
final QuestionLogSummary questionLogSummary = new QuestionLogSummary();
final Long questionSettingId = logList.get(0).getTeacherOpenCourseQuestionSettingId();
// 这里附件作业的数量,需要单独查询
final Integer questionTotalCount = snapshotFromTypeEnum.equals(HOMEWORK_FILE)
? teacherOpenCourseQuestionSettingDao.getHomeWorkFileTotalCountBySettingId(questionSettingId)
: resourcesQuestionSnapshotDao.getQuestionTotalCountBySettingId(questionSettingId);
// 做对数,做错数,总题数
Integer sumSuccessCount = 0, sumErrorCount = 0, sumDoCount = 0;
// 试卷总分数, 我的分数, 题目日志ID集
BigDecimal questionTotalScore = ZERO, myTotalScore = ZERO; final Set<String> idsSet = new HashSet<>();
// 获取最大的完成时间
TeacherOpenCourseQuestionLog maxFinish = logList.stream()
.max((o1, o2) -> toIntExact(defaultIfNull(o1.getTeacherOpenCourseQuestionLogFinishTime(), 0L) - defaultIfNull(o2.getTeacherOpenCourseQuestionLogFinishTime(), 0L)))
.get();
for (TeacherOpenCourseQuestionLog questionLog : logList) {
Integer successCount = questionLog.getSuccessCount();
Integer errorCount = questionLog.getErrorCount();
Assert.isTrue(ObjectUtil.isAllNotEmpty(successCount, errorCount), "题目正确数量和错误数量,计算出了点小问题!");
sumSuccessCount += successCount;
sumErrorCount += errorCount;
sumDoCount += ObjectUtil.isNotEmpty(questionLog.getTeacherOpenCourseQuestionLogAnswer()) ? 1 : 0;
questionTotalScore = questionTotalScore.add(defaultIfNull(questionLog.getQuestionScore(), questionLog.getStudentScore()));
myTotalScore = myTotalScore.add(defaultIfNull(questionLog.getStudentScore(), ZERO));
idsSet.add(questionLog.getTeacherOpenCourseQuestionLogId().toString());
}
// 及格分值比率
BigDecimal passRateSetting = new BigDecimal("0.6");
// 查询数据字典配置项
String passRateVal = coreDictService.getOrDefault("pass_rate", "0.6");
if (NumberUtil.isNumber(passRateVal)) {
passRateSetting = new BigDecimal(passRateVal);
}
boolean isPass = NumberUtil.isGreaterOrEqual(myTotalScore, NumberUtil.mul(questionTotalScore, passRateSetting));
questionLogSummary.setQuestionSettingId(questionSettingId);
questionLogSummary.setQuestionSettingName(questionSettingName);
questionLogSummary.setQuestionSettingType(snapshotFromTypeEnum);
questionLogSummary.setQuestionLogSummaryFromType(FROM_OPEN_COURSE);
questionLogSummary.setQuestionSettingTotalScore(questionTotalScore);
questionLogSummary.setQuestionLogSummaryStudentTotalScore(myTotalScore);
questionLogSummary.setPersonId(student.getStudentId());
questionLogSummary.setQuestionLogIds(logsIds);
questionLogSummary.setQuestionLogSummaryQuestionTotalCount(questionTotalCount);
questionLogSummary.setQuestionLogSummaryStudentDoCount(sumDoCount);
questionLogSummary.setQuestionLogSummarySuccessCount(sumSuccessCount);
questionLogSummary.setQuestionLogSummaryErrorCount(sumErrorCount);
BigDecimal successRate = NumberUtil.div(sumSuccessCount, questionTotalCount, 3).multiply(new BigDecimal(100));
questionLogSummary.setQuestionLogSummarySuccessRate(successRate);
questionLogSummary.setQuestionLogSummaryCurrentPassRate(passRateSetting);
questionLogSummary.setQuestionLogSummaryIsPass(BooleanUtil.toInteger(isPass));
questionLogSummary.setQuestionLogSummaryStatus(1);
questionLogSummary.setQuestionLogSummaryAddTime(new Date());
questionLogSummary.setOrgId(student.getOrgId());
questionLogSummary.setUserId(student.getUserId());
if (null != maxFinish) {
Long finishTime = maxFinish.getTeacherOpenCourseQuestionLogFinishTime();
questionLogSummary.setFinishTime(DateUtil.secondToTime(finishTime.intValue()));
questionLogSummary.setFinishSecondTime(finishTime);
}
QuestionLogSummaryQuery summaryQuery = new QuestionLogSummaryQuery();
summaryQuery.setQuestionLogSummaryStatus(1);
summaryQuery.setPersonId(student.getStudentId());
summaryQuery.setQuestionSettingId(questionSettingId);
QuestionLogSummary logSummary = questionLogSummaryService.getInfo(summaryQuery);
// 删除之前的题目统计
if (logSummary != null) {
// questionLogSummary.setQuestionLogSummaryId(logSummary.getQuestionLogSummaryId());
// 这个学生之前的其他试卷都设置成删除状态。
QuestionLogSummary updatePO = new QuestionLogSummary();
updatePO.setQuestionLogSummaryId(logSummary.getQuestionLogSummaryId());
updatePO.setQuestionLogSummaryStatus(GlobalStatusEnum.DELETED.getCode());
questionLogSummaryService.updateTemplate(updatePO);
}
// 更新或插入统计数据
// questionLogSummaryService.upsertByTemplate(questionLogSummary);
// 插入统计数据
questionLogSummaryService.insert(questionLogSummary);
}
/**
* 验证前端传递过来的添加时间是否是最新的
* @param questionSettingId 题目配置ID
* @param questionSnapshotIds 题目快照ID
* @param studentId 学生ID
* @param addTime 前端传递的添加时间
* @return
*/
private boolean validateQuestionLogAddTimeLatest(@NotNull(message = "开课题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapshotIds,
@NotNull(message = "学生ID不能为空") Long studentId,
@NotNull(message = "提交时间不能为空!") Date addTime) {
return teacherOpenCourseQuestionLogDao.validateQuestionLogAddTimeLatest(questionSettingId, questionSnapshotIds, studentId, addTime);
}
/**
* 日志关联学生信息和配置ID信息
*
* @param studentId 学生ID
* @param questionSettingId 题目配置ID
* @param judgeAddType 判断是否继续做题的,题目提交类型
* @param initAddType 预先提交到初始化提交类型
* @param resourcesQuestionSnapshots 题目快照结合
* @param isReSend 是否根据题目快照强制重新发题
*/
public void preSubmitStudentQuestionLog(@NotNull(message = "学生ID不能为空") final Long studentId,
@NotNull(message = "题目配置ID不能为空") final Long questionSettingId,
@NotNull(message = "判断是否继续做题的,题目提交类型不能为空!") final QuestionLogAddTypeEnum judgeAddType,
@Nullable final QuestionLogAddTypeEnum initAddType,
@NotEmpty(message = "题目快照列表不能为空!") List<ResourcesQuestionSnapshot> resourcesQuestionSnapshots,
final boolean isReSend
) {
if (CollectionUtil.isEmpty(resourcesQuestionSnapshots)) {
return;
}
// 不是强制发题,则不覆盖现有的题目日志,则继续做题
// 验证题目日志,是否已经存在试卷
if(!isReSend) {
long logCount = teacherOpenCourseQuestionLogDao.getNotSubmitQuestionLogsCount(studentId, questionSettingId);
// 如果题目日志里存在预先布置的题目,则直接返回
if (logCount > 0) {
return;
}
}
// teacherOpenCourseQuestionSettingId类似试卷ID题目日志里会出现重复的试卷ID
// 逻辑删除之前的题目日志,防止学生做题统计数据异常
// 保证试卷是最新的
// 考试逻辑删除记录,作业或者章节练习都是直接删除记录。
// 强制发题
if (isReSend) {
logicDeleteBySettingIds(questionSettingId.toString());
}
List<TeacherOpenCourseQuestionLog> teacherOpenCourseQuestionLogs = BeanUtil.copyToList(resourcesQuestionSnapshots, TeacherOpenCourseQuestionLog.class);
// 设计个单表,后面进行修改操作
teacherOpenCourseQuestionLogs.forEach(questionLog -> {
// 题目的答案,如果最后一位是逗号,则删除掉
String questionAnswer = ReUtil.replaceAll(questionLog.getQuestionAnswer(), "\\,$", "");
questionLog.setTeacherOpenCourseQuestionSettingId(questionSettingId);
questionLog.setTeacherOpenCourseQuestionLogStatus(1);
questionLog.setQuestionLogAddType(initAddType);
questionLog.setStudentId(studentId);
questionLog.setTeacherOpenCourseQuestionLogAddTime(new Date());
questionLog.setQuestionAnswer(questionAnswer);
});
insertBatch(teacherOpenCourseQuestionLogs);
}
/**
* 根据题目配置ID查询题目快照并根据类型分组
*
* @param questionSettingId 题目配置ID
* @return
*/
public Map<Integer, List<TeacherOpenCourseQuestionLog>> questionAnalysis(@NotNull(message = "题目配置ID不能为空") Long questionSettingId, @NotNull(message = "学生ID不能为空") Long studentId) {
TeacherOpenCourseQuestionLogQuery query = new TeacherOpenCourseQuestionLogQuery();
query.setTeacherOpenCourseQuestionSettingId(questionSettingId);
query.setTeacherOpenCourseQuestionLogStatus(1);
query.setStudentId(studentId);
List<TeacherOpenCourseQuestionLog> valuesByQuery = getValuesByQueryNotWithPermission(query);
return questionAnalysis(valuesByQuery);
}
/**
* 从题目日志中获取题目快照信息Bean Copy方式
* @param questionSettingId 题目配置ID
* @param studentId 学生ID
* @return
*/
public List<ResourcesQuestionSnapshot> questionAnalysisBySettingId2(Long questionSettingId, Long studentId) {
Map<Integer, List<TeacherOpenCourseQuestionLog>> tempMap = questionAnalysis(questionSettingId, studentId);
List<TeacherOpenCourseQuestionLog> collect = tempMap.values().stream().flatMap(Collection::stream).collect(Collectors.toList());
List<ResourcesQuestionSnapshot> result = new ArrayList<>();
// 循环遍历某些特殊的属性,单独映射
Optional.ofNullable(collect).ifPresent(item -> {
for (TeacherOpenCourseQuestionLog questionLog : item) {
ResourcesQuestionSnapshot resourcesQuestionSnapshot = BeanUtil.copyProperties(questionLog, ResourcesQuestionSnapshot.class);
// 学生提交过的答案
resourcesQuestionSnapshot.set("teacherOpenCourseQuestionLogAnswer", questionLog.getTeacherOpenCourseQuestionLogAnswer());
result.add(resourcesQuestionSnapshot);
}
});
return result;
}
/**
* 根据题目快照ID查询题目快照并根据类型分组
*
* @param questionSnapshotIds
* @return
*/
public Map<Integer, List<TeacherOpenCourseQuestionLog>> questionAnalysis(@NotNull(message = "题目配置ID不能为空") TreeSet<Long> questionSnapshotIds, @NotNull(message = "学生ID不能为空") Long studentId) {
TeacherOpenCourseQuestionLogQuery query = new TeacherOpenCourseQuestionLogQuery();
query.setResourcesQuestionSnapshotIdPlural(join(questionSnapshotIds.toArray(), ","));
query.setTeacherOpenCourseQuestionLogStatus(1);
query.setStudentId(studentId);
List<TeacherOpenCourseQuestionLog> valuesByQuery = getValuesByQueryNotWithPermission(query);
return questionAnalysis(valuesByQuery);
}
/**
* 开课相关-考试或者作业,答题提交后,获取问题解析。根据配置获取
* @param questionLogList
* @return
*/
public Map<Integer, List<TeacherOpenCourseQuestionLog>> questionAnalysis(@NotEmpty(message = "未查询到题目列表!") final List<TeacherOpenCourseQuestionLog> questionLogList) {
// 如果未查询到题目日志返回空Map
if (ObjectUtil.isEmpty(questionLogList)) {
return MapUtil.empty();
}
TeacherOpenCourseQuestionSettingQuery settingQuery = new TeacherOpenCourseQuestionSettingQuery();
settingQuery.setTeacherOpenCourseQuestionSettingId(questionLogList.get(0).getTeacherOpenCourseQuestionSettingId());
final TeacherOpenCourseQuestionSetting hwSetting = teacherOpenCourseQuestionSettingService.getInfo(settingQuery);
// 答卷后显示答案解析
final Boolean isEndShowQa = BooleanUtil.toBoolean(String.valueOf(hwSetting.getTeacherOpenCourseQuestionSettingEndShowQa()));
// 答卷后显示答案对错
final Boolean isEndShowTrueFalse = BooleanUtil.toBoolean(String.valueOf(hwSetting.getTeacherOpenCourseQuestionSettingEndShowTrueFalse()));
return questionLogList.stream().map(item -> {
item.setQuestionAnswer(isEndShowQa ? item.getQuestionAnswer() : "");
item.setQuestionAnalysis(isEndShowTrueFalse ? item.getQuestionAnswer(): "");
return item;
}).collect(groupingBy(TeacherOpenCourseQuestionLog::getQuestionType));
}
/**
* 查询学生的分数列表信息(分页)
* 不带权限
*
* @param query
*/
public PageQuery<TeacherOpenCourseQuestionLog> studentScoreList(PageQuery query) {
PageQuery ret = teacherOpenCourseQuestionLogDao.studentScoreList(query);
queryListAfter(ret.getList());
return ret;
}
@Override
public void resetOperationByTeacherOpenCourseId(Long teacherOpenCourseId) {
log.info("可能需要实现重置操作!");
}
@Override
public void deleteTeacherOpenCourseAllRelatedByTeacherOpenCourseId(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId) {
log.info("需要实现删除操作!");
}
/**
* 批量收藏题目
* @param teacherOpenCourseQuestionLogIds
* @param isTuck
*/
public void tuckByLogIds(@NotEmpty(message = "题目日志ID不能为空") String teacherOpenCourseQuestionLogIds, final boolean isTuck) {
Function<String, TeacherOpenCourseQuestionLog> stringQuestionLogFunction = logId -> {
TeacherOpenCourseQuestionLog questionLog = new TeacherOpenCourseQuestionLog();
questionLog.setTeacherOpenCourseQuestionLogId(Long.valueOf(logId));
questionLog.setIsTuck(isTuck);
return questionLog;
};
List<TeacherOpenCourseQuestionLog> logSet = Arrays.asList(teacherOpenCourseQuestionLogIds.split(",")).stream()
.map(stringQuestionLogFunction).collect(Collectors.toList());
updateBatchTemplate(logSet);
}
/**
* 收藏题目根据题目配置ID + 题目快照ID
*
* @param questionSettingId 题目配置ID
* @param questionSnapIds 题目快照IDs
* @param isTuck 是否收藏 true收藏 false取消收藏
* @param student 学生信息
*/
public void tuck(@NotNull(message = "题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapIds, boolean isTuck,
@NotNull(message = "学生信息不能为空!") Student student) {
List<TeacherOpenCourseQuestionLog> list = getListBySettingIdAndSnapIds(questionSettingId, questionSnapIds, student);
if (ObjectUtil.isEmpty(list)) {
throw new PlatformException("收藏失败,未查询到要收藏的题目");
}
String logIds = list.stream()
.map(o -> o.getTeacherOpenCourseQuestionLogId().toString()).collect(joining(","));
// 根据做题的日志ID收藏题目
tuckByLogIds(logIds, isTuck);
}
/**
* 收藏题目根据题目配置ID + 题目快照ID
*
* @param questionSettingId 题目配置ID
* @param questionSnapIds 题目快照IDs
* @param student 学生信息
*/
private List<TeacherOpenCourseQuestionLog> getListBySettingIdAndSnapIds(
@NotNull(message = "题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapIds, @NotNull Student student) {
TeacherOpenCourseQuestionLogQuery logQuery = new TeacherOpenCourseQuestionLogQuery();
logQuery.setTeacherOpenCourseQuestionSettingId(questionSettingId);
logQuery.setResourcesQuestionSnapshotIdPlural(questionSnapIds);
logQuery.setTeacherOpenCourseQuestionLogStatus(1);
logQuery.setStudentId(student.getStudentId());
return getValuesByQueryNotWithPermission(logQuery);
}
/**
* 批量收藏到错题库
* @param teacherOpenCourseQuestionLogIds
* @param isErrorFavorite
*/
public void errorFavorite(@NotEmpty(message = "题目日志ID不能为空") String teacherOpenCourseQuestionLogIds, final boolean isErrorFavorite) {
Function<String, TeacherOpenCourseQuestionLog> stringTeacherOpenCourseQuestionLogFunction = logId -> {
TeacherOpenCourseQuestionLog questionLog = new TeacherOpenCourseQuestionLog();
questionLog.setTeacherOpenCourseQuestionLogId(Long.valueOf(logId));
questionLog.setIsErrorFavorite(isErrorFavorite);
return questionLog;
};
List<TeacherOpenCourseQuestionLog> logSet = Arrays.asList(teacherOpenCourseQuestionLogIds.split(",")).stream()
.map(stringTeacherOpenCourseQuestionLogFunction).collect(Collectors.toList());
updateBatchTemplate(logSet);
}
/**
* 查询学生详细得分信息
* 查询分数详细信息
*
* @param query
* @return
*/
public PageQuery<TeacherOpenCourseQuestionLogScoreDetailsInfo> getQuestionLogScoreDetailsInfo(PageQuery query) {
return teacherOpenCourseQuestionLogDao.getQuestionLogScoreDetailsInfo(query);
}
/**
* 验证是否需要重新发题,则返回重新发题的标记
* @param questionSettingId 题目配置ID
* @param studentId 学生ID
* @param questionSettingType 题目配置类型
* @param questionLogAddType 题目日志添加类型(用于判断是否交卷)
* @return boolean
*/
public boolean verifyLogAddTypeIsReSend(Long questionSettingId,
Long studentId, ResourcesQuestionSnapshotFromTypeEnum questionSettingType,
QuestionLogAddTypeEnum questionLogAddType) {
// 只有章节练习,才能进行重发试题的操作
if (!questionSettingType.equals(CHAPTER_EXERCISE)) {
return false;
}
if (ObjectUtil.isAllNotEmpty(questionSettingId, studentId, questionSettingType, questionLogAddType)) {
return teacherOpenCourseQuestionLogDao.verifyLogAddTypeIsReSend(questionSettingId,studentId, questionSettingType, questionLogAddType);
}
return false;
}
/**
* 功能描述: <br>
* 获取实体的答案和解析,并锁定题目日志的状态,无法导致不能去修改选项
*
* @param questionSettingId 题目配置ID
* @param questionSnapIds 题目快照IDs
* @param student 学生信息
* @return {@link List< TeacherOpenCourseQuestionLogAnswerLockVO >}
* @Author: lx
* @Date: 2022/12/1 0:55
*/
public List<TeacherOpenCourseQuestionLogAnswerLockVO> questionLogAnswerLock(
@NotNull(message = "题目配置ID不能为空") Long questionSettingId,
@NotBlank(message = "题目快照IDs不能为空") String questionSnapIds, @NotNull Student student) {
final List<TeacherOpenCourseQuestionLog> list = getListBySettingIdAndSnapIds(questionSettingId, questionSnapIds, student);
Assert.notEmpty(list, "未查询到试卷题目信息!");
// 只取非完成状态的数据
Predicate<TeacherOpenCourseQuestionLog> notFinishPredicate = questionLog -> !questionLog.getQuestionLogAddType().equals(FINALLY_SUBMIT);
// 构建数据
List<TeacherOpenCourseQuestionLog> questionLogs = list.stream().filter(notFinishPredicate).map(questionLog -> {
TeacherOpenCourseQuestionLog generalQuestionLog = new TeacherOpenCourseQuestionLog();
generalQuestionLog.setTeacherOpenCourseQuestionLogId(questionLog.getTeacherOpenCourseQuestionLogId());
generalQuestionLog.setQuestionLogAddType(LOCK); // 锁定状态
return generalQuestionLog;
}).collect(Collectors.toList());
// 批量修改锁定的状态
updateBatchTemplate(questionLogs);
// 只取部分属性给到前端
return BeanUtil.copyToList(list, TeacherOpenCourseQuestionLogAnswerLockVO.class);
}
/**
* 查询附件作业-日志
* @param dto
* @return
*/
public List<TeacherOpenCourseHomeWorkLogExportVO> getHomeWorkLogExportList(TeacherOpenCourseHomeWorkLogDTO dto) {
return teacherOpenCourseQuestionLogDao.getHomeWorkLogExportList(dto);
}
/**
* 查询附件作业-日志(分页)
* @param pageQuery
* @return
*/
public PageQuery<TeacherOpenCourseHomeWorkLogExportVO> getHomeWorkLogExportPageList(PageQuery pageQuery) {
return teacherOpenCourseQuestionLogDao.getHomeWorkLogExportPageList(pageQuery);
}
public FileQuestionLogListVO getFileQuestionLog(TeacherOpenCourseQuestionLogQuery query) {
TeacherOpenCourseQuestionLog log = getInfo(query);
if (null == log) {
return null;
}
Student student = studentDao.getById(log.getStudentId());
if (null != student) {
log.setStudentIdText(student.getStudentName());
log.setStudentSn(student.getStudentSn());
}
return BeanUtil.copyProperties(log, FileQuestionLogListVO.class);
}
}