tianze-pro/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseQuestionSe...

854 lines
42 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.ConcurrentHashSet;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.jlw.util.EnumUtil;
import cn.jlw.util.ToolUtils;
import cn.jlw.validate.ValidateConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ibeetl.admin.core.service.CoreBaseService;
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.QuestionSettingDTO;
import com.ibeetl.jlw.entity.vo.QuestionSettingScoreInfoVO;
import com.ibeetl.jlw.entity.vo.TeacherOpenCourseQuestionSettingAnalysisVO;
import com.ibeetl.jlw.enums.*;
import com.ibeetl.jlw.web.query.*;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;
import static cn.hutool.core.text.CharSequenceUtil.join;
import static cn.jlw.util.CacheUserUtil.getStudent;
import static cn.jlw.util.QuestionUtil.shuffleQuestion;
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.TuckOrErrorEnum.ERROR_TEST;
import static com.ibeetl.jlw.enums.TuckOrErrorEnum.TUCK_TEST;
import static java.util.stream.Collectors.joining;
/**
* 题目配置 Service
* 当分布式ID开启后请勿使用insert(*,true)
*/
@Service
@Transactional
@Slf4j
public class TeacherOpenCourseQuestionSettingService extends CoreBaseService<TeacherOpenCourseQuestionSetting> implements DeleteResourcesBy{
@Autowired private TeacherOpenCourseQuestionSettingDao teacherOpenCourseQuestionSettingDao;
@Autowired private ResourcesQuestionSnapshotDao resourcesQuestionSnapshotDao;
@Autowired private TeacherOpenCourseQuestionLogDao teacherOpenCourseQuestionLogDao;
@Autowired private StudentDao studentDao;
@Autowired private ResourcesQuestionSnapshotService resourcesQuestionSnapshotService;
@Autowired private TeacherOpenCourseQuestionLogService teacherOpenCourseQuestionLogService;
@Autowired private TeacherOpenCourseQuestionLogWrongService teacherOpenCourseQuestionLogWrongService;
@Autowired private ResourcesQuestionService resourcesQuestionService;
@Autowired private CourseInfoService courseInfoService;
@Autowired private TeacherOpenCourseMergeResourcesQuestionService teacherOpenCourseMergeResourcesQuestionService;
@Autowired private TeacherOpenCourseMergeCourseInfoService teacherOpenCourseMergeCourseInfoService;
public PageQuery<TeacherOpenCourseQuestionSetting>queryByCondition(PageQuery query){
PageQuery ret = teacherOpenCourseQuestionSettingDao.queryByCondition(query);
queryListAfter(ret.getList());
return ret;
}
public PageQuery<TeacherOpenCourseQuestionSetting>queryByConditionQuery(PageQuery query){
PageQuery ret = teacherOpenCourseQuestionSettingDao.queryByConditionQuery(query);
queryListAfter(ret.getList());
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)){
teacherOpenCourseQuestionSettingDao.deleteByIds(ids);
}
}
public void deleteByIds(@NotEmpty String ids) {
teacherOpenCourseQuestionSettingDao.deleteByIds(ids);
}
public void deleteSettingAndSnapByIds(@NotEmpty String settingIds) {
teacherOpenCourseQuestionSettingDao.deleteByIds(settingIds);
resourcesQuestionSnapshotService.deleteBySettingIds(settingIds);
}
public void logicDeleteBySettingIds(String ids){
try {
teacherOpenCourseQuestionSettingDao.logicDeleteBySettingIds(ids);
} catch (Exception e) {
throw new PlatformException("批量删除题目配置失败", e);
}
}
public String addAll(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery){
String msg = "";
List<TeacherOpenCourseQuestionSetting> teacherOpenCourseQuestionSettingList = new ArrayList<>();
try {
teacherOpenCourseQuestionSettingList = JSON.parseArray(teacherOpenCourseQuestionSettingQuery.getTeacherOpenCourseQuestionSettingJsonStr(), TeacherOpenCourseQuestionSetting.class);
} catch (Exception e) {
try {
teacherOpenCourseQuestionSettingList.add(JSONObject.parseObject(teacherOpenCourseQuestionSettingQuery.getTeacherOpenCourseQuestionSettingJsonStr(), TeacherOpenCourseQuestionSetting.class));
} catch (Exception e1) {}
}
ToolUtils.deleteNullList(teacherOpenCourseQuestionSettingList);
if(null != teacherOpenCourseQuestionSettingList && teacherOpenCourseQuestionSettingList.size()>0){
for(int i=0;i<teacherOpenCourseQuestionSettingList.size();i++){
TeacherOpenCourseQuestionSetting teacherOpenCourseQuestionSetting = teacherOpenCourseQuestionSettingList.get(i);
teacherOpenCourseQuestionSetting.setUserId(teacherOpenCourseQuestionSettingQuery.getUserId());
teacherOpenCourseQuestionSetting.setOrgId(teacherOpenCourseQuestionSettingQuery.getOrgId());
// 验证唯一
verifyUniqueChapterExercise(teacherOpenCourseQuestionSettingQuery);
}
insertBatch(teacherOpenCourseQuestionSettingList);
}
return msg;
}
public JsonResult add(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery){
String msg = "";
TeacherOpenCourseQuestionSetting teacherOpenCourseQuestionSetting = teacherOpenCourseQuestionSettingQuery.pojo();
// 验证唯一
verifyUniqueChapterExercise(teacherOpenCourseQuestionSettingQuery);
teacherOpenCourseQuestionSettingDao.insert(teacherOpenCourseQuestionSetting);
teacherOpenCourseQuestionSettingQuery.setTeacherOpenCourseQuestionSettingId(teacherOpenCourseQuestionSetting.getTeacherOpenCourseQuestionSettingId());
JsonResult jsonResult = new JsonResult();
jsonResult.setData(teacherOpenCourseQuestionSetting.getTeacherOpenCourseQuestionSettingId());//自增的ID丢进去
jsonResult.setCode(JsonReturnCode.SUCCESS.getCode());
jsonResult.setMsg(msg);
return jsonResult;
}
public String edit(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery){
// 验证唯一
verifyUniqueChapterExercise(teacherOpenCourseQuestionSettingQuery);
String msg = "";
TeacherOpenCourseQuestionSetting teacherOpenCourseQuestionSetting = teacherOpenCourseQuestionSettingQuery.pojo();
teacherOpenCourseQuestionSettingDao.updateTemplateById(teacherOpenCourseQuestionSetting);
return msg;
}
/**
* 根据开课ID + 章节名称
* 判断章节练习时候,的题目配置 唯一性
*
* 数据库设计稍微有点不严谨暂时用名字来作为关联的条件所以这里只能保证同一个开课ID下的名字是唯一的
*
* @param teacherOpenCourseId
* @param teacherOpenCourseQuestionSettingName
* @return
*/
public void verifyUniqueName(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@NotEmpty(message = "题目配置名称不能为空!") String teacherOpenCourseQuestionSettingName ) {
// 数据库设计稍微有点不严谨暂时用名字来作为关联的条件所以这里只能保证同一个开课ID下的名字是唯一的
TeacherOpenCourseQuestionSettingQuery settingQuery = new TeacherOpenCourseQuestionSettingQuery();
settingQuery.setTeacherOpenCourseQuestionSettingName(teacherOpenCourseQuestionSettingName);
settingQuery.setTeacherOpenCourseId(teacherOpenCourseId);
List<TeacherOpenCourseQuestionSetting> oneList = getValuesByQuery(settingQuery);
if(ObjectUtil.isNotEmpty(oneList)) {
throw new PlatformException("当前开课下的题目配置名称重复,请重新设置!");
}
}
/**
* 根据开课ID + 章节名称
* 判断章节练习时候,的题目配置 唯一性
*
* 数据库设计稍微有点不严谨暂时用名字来作为关联的条件所以这里只能保证同一个开课ID下的名字是唯一的
*
* @param query
* @return
*/
public void verifyUniqueChapterExercise(@NotNull TeacherOpenCourseQuestionSettingQuery query) {
ResourcesQuestionSnapshotFromTypeEnum settingType = query.getTeacherOpenCourseQuestionSettingType();
// 只验证章节练习
if (CHAPTER_EXERCISE.equals(settingType) && settingType != null) {
// 数据库设计稍微有点不严谨暂时用名字来作为关联的条件所以这里只能保证同一个开课ID下的名字是唯一的
TeacherOpenCourseQuestionSettingQuery settingQuery = new TeacherOpenCourseQuestionSettingQuery();
settingQuery.setTeacherOpenCourseQuestionSettingName(query.getTeacherOpenCourseQuestionSettingName());
settingQuery.setTeacherOpenCourseId(query.getTeacherOpenCourseId());
List<TeacherOpenCourseQuestionSetting> oneList = getValuesByQuery(settingQuery);
// 考虑到编辑的时候,要排除自身
if (ObjectUtil.isNotEmpty(query.getTeacherOpenCourseQuestionSettingId())) {
oneList.removeIf(s -> s.getTeacherOpenCourseQuestionSettingId().equals(query.getTeacherOpenCourseQuestionSettingId()));
}
if(ObjectUtil.isNotEmpty(oneList)) {
throw new PlatformException("当前开课下的题目配置名称重复,请重新设置!");
}
}
}
public String updateGivenByIds(TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery){
String msg = "";
if(StringUtils.isNotBlank(teacherOpenCourseQuestionSettingQuery.get_given())){
boolean flag = teacherOpenCourseQuestionSettingDao.updateGivenByIds(teacherOpenCourseQuestionSettingQuery) > 0;
if(!flag){
msg = "更新指定参数失败";
}
}else{
msg = "指定参数为空";
}
return msg;
}
public List<TeacherOpenCourseQuestionSetting> getValues (Object paras){
return sqlManager.select(SqlId.of("jlw.teacherOpenCourseQuestionSetting.getTeacherOpenCourseQuestionSettingValues"), TeacherOpenCourseQuestionSetting.class, paras);
}
public List<TeacherOpenCourseQuestionSetting> getValuesByQuery (TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery){
return teacherOpenCourseQuestionSettingDao.getValuesByQuery(teacherOpenCourseQuestionSettingQuery);
}
/**
* 设置题目的分数和完成时间
* @param list
* @param student
*/
public void setMyQuestionLogScoreInfo(List<TeacherOpenCourseQuestionSetting> list, Student student) {
if (ObjectUtil.isAllNotEmpty(list, student)) {
Long studentId = student.getStudentId();
list.forEach(item -> {
Long questionSettingId = item.getTeacherOpenCourseQuestionSettingId();
QuestionSettingScoreInfoVO scoreInfo = teacherOpenCourseQuestionSettingDao.getQuestionSettingScoreInfo(questionSettingId, studentId);
if (null != scoreInfo) {
item.set("finishTime", scoreInfo.getFinishTime());
item.set("finishSecondTime", scoreInfo.getFinishSecondTime());
item.set("myScore", scoreInfo.getMyScore());
}
});
}
}
public TeacherOpenCourseQuestionSetting getInfo (Long teacherOpenCourseQuestionSettingId){
TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery = new TeacherOpenCourseQuestionSettingQuery();
teacherOpenCourseQuestionSettingQuery.setTeacherOpenCourseQuestionSettingId(teacherOpenCourseQuestionSettingId);
teacherOpenCourseQuestionSettingQuery.setTeacherOpenCourseQuestionSettingStatusPlural("1");//需要根据实际情况来
List<TeacherOpenCourseQuestionSetting> list = teacherOpenCourseQuestionSettingDao.getValuesByQuery(teacherOpenCourseQuestionSettingQuery);
if(null != list && list.size()>0){
return list.get(0);
}else{
return null;
}
}
public TeacherOpenCourseQuestionSetting getInfo (TeacherOpenCourseQuestionSettingQuery teacherOpenCourseQuestionSettingQuery){
List<TeacherOpenCourseQuestionSetting> list = teacherOpenCourseQuestionSettingDao.getValuesByQuery(teacherOpenCourseQuestionSettingQuery);
if(null != list && list.size()>0){
return list.get(0);
}else{
return null;
}
}
/**
* 根据开课的课程信息,添加题目配置和题目
* 这里不区分节点是什么类型的。
* 严格要求:
*
* 添加主表
* 任务一:添加主表
* 任务二:添加到题目配置主表;
* 任务二:也可以添加题目快照(非必选)
*/
public void addFrom(@Validated(ValidateConfig.ADD.class) TeacherOpenCourseMergeCourseInfoQuery teacherOpenCourseMergeCourseInfoQuery,
@Nullable Collection<QuestionSettingDTO> questionSettingOptions, CopyFromEnum copyFrom, Map<Long, Long> courseInfoIdPair) {
Long teacherOpenCourseId = teacherOpenCourseMergeCourseInfoQuery.getTeacherOpenCourseId();
TeacherOpenCourseQuestionSettingQuery settingQuery = new TeacherOpenCourseQuestionSettingQuery();
// 设置章节练习的默认配置并设置开课ID
settingQuery.setChapterExerciseDefault().setTeacherOpenCourseId(teacherOpenCourseId);
settingQuery.setTeacherOpenCourseQuestionSettingName(teacherOpenCourseMergeCourseInfoQuery.getCourseInfoName());
settingQuery.setQuestionSettingOptions(new ArrayList<>(questionSettingOptions));
switch (copyFrom) {
case FROM_OPEN_COURSE:
addSettingByOpenCourse(settingQuery, courseInfoIdPair);
case FROM_SYSTEM:
addSettingBySystemCourse(settingQuery, courseInfoIdPair);
break;
}
}
/**
* 增加题目类型的数据 从开课端拉取
*
* 任务一;添加题目配置主表
* 任务二:添加题目快照表
* @param settingQuery
* @return
*/
public void addSettingByOpenCourse(@Validated(ValidateConfig.ADD.class) TeacherOpenCourseQuestionSettingQuery settingQuery, Map<Long, Long> courseInfoIdPair ) {
// 编辑操作
if(ObjectUtil.isNotEmpty(settingQuery.getTeacherOpenCourseQuestionSettingId())) {
String editSettingIds = settingQuery.getTeacherOpenCourseQuestionSettingId().toString();
deleteSettingAndSnapByIds(editSettingIds);
// 删除主键,用于下面的保存方法
settingQuery.setTeacherOpenCourseQuestionSettingId(null);
}
// 添加到作业主表中
add(settingQuery);
// 主表ID
Long teacherOpenCourseQuestionSettingId = settingQuery.getTeacherOpenCourseQuestionSettingId();
// 传入的开课题目IDS
String resourcesQuestionIdPlural = settingQuery.getResourcesQuestionIdPlural();
// 题目类型区分
Collection<QuestionSettingDTO> settingDTOList = null;
if(ObjectUtil.isNotEmpty(resourcesQuestionIdPlural)) {
TeacherOpenCourseMergeResourcesQuestionQuery questionQuery = new TeacherOpenCourseMergeResourcesQuestionQuery();
questionQuery.setQuestionStatus(1);
questionQuery.setTeacherOpenCourseMergeResourcesQuestionIdPlural(resourcesQuestionIdPlural);
List<TeacherOpenCourseMergeResourcesQuestion> list =
teacherOpenCourseMergeResourcesQuestionService.getValuesByQueryNotWithPermission(questionQuery);
// 无差别题目IDS转换成类型区分的集合
Map<ResourcesQuestionTypeEnum, QuestionSettingDTO> map =
teacherOpenCourseMergeResourcesQuestionService.buildSettingDtoListByNoDiffQuestionList(list);
// 设置分值
settingQuery.getQuestionSettingOptions().forEach(item -> {
QuestionSettingDTO settingDTO = map.get(item.getQuestionType());
if(ObjectUtil.isAllNotEmpty(settingDTO, item.getSingleScore())) {
settingDTO.setSingleScore(item.getSingleScore());
}
});
if (ObjectUtil.isNotEmpty(map)) { settingDTOList = map.values(); }
} else {
settingDTOList = settingQuery.getQuestionSettingOptions();
}
resourcesQuestionSnapshotService.insertBatchByOpenResourcesQuestion(teacherOpenCourseQuestionSettingId, settingDTOList, courseInfoIdPair);
}
/**
* 增加题目类型的数据
* 从系统题库中拉取
* <p>
* 任务一;添加题目配置主表
* 任务二:添加题目快照表
*
* @param settingQuery
* @return
*/
public void addSettingBySystemCourse(@Validated(ValidateConfig.ADD.class) TeacherOpenCourseQuestionSettingQuery settingQuery, Map<Long, Long> courseInfoIdPair ) {
// 添加到作业主表中
add(settingQuery);
// 插入快照
Long teacherOpenCourseQuestionSettingId = settingQuery.getTeacherOpenCourseQuestionSettingId();
List<QuestionSettingDTO> questionSettingOptions = settingQuery.getQuestionSettingOptions();
resourcesQuestionSnapshotService.insertBatchBySystemResourcesQuestion(teacherOpenCourseQuestionSettingId, questionSettingOptions, courseInfoIdPair);
}
/**
* 根据开课的课程信息,添加题目配置和题目
*
* 添加主表
* 任务一:添加主表
* 任务二:添加到题目配置主表;
* 任务二:也可以添加题目快照(非必选)
* @param teacherOpenCourseId 开课ID
* @param courseInfoIdWithQuestionSettingOptions Key课程名称Value题型和题目ID的组合列表
*/
public void addSettingByOpenCourse(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@Nullable Map<TeacherOpenCourseMergeCourseInfo, Collection<QuestionSettingDTO>> courseInfoIdWithQuestionSettingOptions,
@NotNull Map<Long, Long> courseInfoIdPair) {
addSettingByOpenCourse(teacherOpenCourseId, courseInfoIdWithQuestionSettingOptions, Integer.valueOf(2), TeacherOpenCourseMergeCourseInfo::getCourseInfoType, courseInfoIdPair);
}
/**
* 根据开课的课程信息,添加题目配置和题目
* <p>
* 添加主表
* 任务一:添加主表
* 任务二:添加到题目配置主表;
* 任务二:也可以添加题目快照(非必选)
*
* @param teacherOpenCourseId 开课ID
* @param courseInfoIdWithQuestionSettingOptions Key课程名称Value题型和题目ID的组合列表
* @param eq 待比对的值
* @param func1 比对的字段取值接口
* @param courseInfoIdPair
*/
public void addSettingByOpenCourse(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@Nullable Map<TeacherOpenCourseMergeCourseInfo, Collection<QuestionSettingDTO>> courseInfoIdWithQuestionSettingOptions,
@NotNull Object eq, @NotNull Func1<TeacherOpenCourseMergeCourseInfo, Integer> func1, @NotNull Map<Long, Long> courseInfoIdPair) {
TeacherOpenCourseQuestionSettingQuery settingQuery = new TeacherOpenCourseQuestionSettingQuery();
// 设置章节练习的默认配置并设置开课ID
settingQuery.setChapterExerciseDefault().setTeacherOpenCourseId(teacherOpenCourseId);
courseInfoIdWithQuestionSettingOptions.forEach((courseInfo, settingDtoList) -> {
// 判断,添加交给外部来控制
try {
if(eq.equals(func1.call(courseInfo))) {
settingQuery.setQuestionSettingOptions(new ArrayList<>(settingDtoList));
settingQuery.setTeacherOpenCourseQuestionSettingName(courseInfo.getCourseInfoName());
addSettingByOpenCourse(settingQuery, courseInfoIdPair);
}
} catch (Exception e) { }
});
}
/**
* 根据开课的课程信息,添加题目配置和题目
*
* 添加主表
* 任务一:添加主表
* 任务二:添加到题目配置主表;
* 任务二:也可以添加题目快照(非必选)
* @param teacherOpenCourseId 开课ID
* @param courseInfoIdWithQuestionSettingOptions Key课程名称Value题型和题目ID的组合列表
*/
public void addSettingBySystemCourse(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@Nullable Map<CourseInfo, Collection<QuestionSettingDTO>> courseInfoIdWithQuestionSettingOptions,
@NotNull Map<Long, Long> courseInfoIdPair) {
addSettingBySystemCourse(teacherOpenCourseId, courseInfoIdWithQuestionSettingOptions, Integer.valueOf(2), CourseInfo::getCourseInfoType, courseInfoIdPair);
}
/**
* 根据开课的课程信息,添加题目配置和题目
* <p>
* 添加主表
* 任务一:添加主表
* 任务二:添加到题目配置主表;
* 任务二:也可以添加题目快照(非必选)
*
* @param teacherOpenCourseId 开课ID
* @param courseInfoIdWithQuestionSettingOptions Key课程名称Value题型和题目ID的组合列表
* @param eq 待比对的值
* @param func1 比对的字段取值接口
* @param courseInfoIdPair
*/
public void addSettingBySystemCourse(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@Nullable Map<CourseInfo, Collection<QuestionSettingDTO>> courseInfoIdWithQuestionSettingOptions,
@NotNull Object eq, @NotNull Func1<CourseInfo, Integer> func1, @NotNull Map<Long, Long> courseInfoIdPair) {
TeacherOpenCourseQuestionSettingQuery settingQuery = new TeacherOpenCourseQuestionSettingQuery();
// 设置章节练习的默认配置并设置开课ID
settingQuery.setChapterExerciseDefault().setTeacherOpenCourseId(teacherOpenCourseId);
courseInfoIdWithQuestionSettingOptions.forEach((courseInfo, settingDtoList) -> {
// 判断,添加交给外部来控制
try {
if(eq.equals(func1.call(courseInfo))) {
settingQuery.setQuestionSettingOptions(new ArrayList<>(settingDtoList));
settingQuery.setTeacherOpenCourseQuestionSettingName(courseInfo.getCourseInfoName());
addSettingBySystemCourse(settingQuery, courseInfoIdPair);
}
} catch (Exception e) { }
});
}
@Override
public void resetOperationByTeacherOpenCourseId(Long teacherOpenCourseId) {
log.info("重置开课题目配置");
sqlManager.lambdaQuery(TeacherOpenCourseQuestionSetting.class)
.andEq(TeacherOpenCourseQuestionSetting::getTeacherOpenCourseId, teacherOpenCourseId)
.delete();
}
@Override
public void deleteTeacherOpenCourseAllRelatedByTeacherOpenCourseId(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId) {
log.info("需要实现删除操作!");
deleteWithSubDataByParams(teacherOpenCourseId, null);
}
/**
* 可以删除子表数据的方法
* 根据名称
* @param teacherOpenCourseId
* @param teacherOpenCourseQuestionSettingName (可为空,为空则不指定名称删除)
*/
public void deleteWithSubDataByParams(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@Nullable String teacherOpenCourseQuestionSettingName) {
// 条件
TeacherOpenCourseQuestionSetting condition = new TeacherOpenCourseQuestionSetting();
condition.setTeacherOpenCourseId(teacherOpenCourseId);
condition.setTeacherOpenCourseQuestionSettingName(teacherOpenCourseQuestionSettingName);
List<TeacherOpenCourseQuestionSetting> settingList = getValues(condition);
// 获取需要删除的ID集合
List<Long> idList = settingList.stream()
.map(TeacherOpenCourseQuestionSetting::getTeacherOpenCourseQuestionSettingId).collect(Collectors.toList());
if(ObjectUtil.isAllNotEmpty(teacherOpenCourseId, teacherOpenCourseQuestionSettingName)) {
// 获取完ID以后删除主表数据
sqlManager.lambdaQuery(TeacherOpenCourseQuestionSetting.class)
.andEq(TeacherOpenCourseQuestionSetting::getTeacherOpenCourseId, teacherOpenCourseId)
.andEq(TeacherOpenCourseQuestionSetting::getTeacherOpenCourseQuestionSettingName, teacherOpenCourseQuestionSettingName)
.delete();
}
// 获取题目配置ID集合
String settingIds = join(",", idList);
if (ObjectUtil.isNotEmpty(settingIds)) {
// 删除子表的数据(题目快照)
resourcesQuestionSnapshotService.deleteBySettingIds(settingIds);
// 删除子表的数据(题目配置)
teacherOpenCourseQuestionLogService.deleteBySettingIds(settingIds);
// 删除子表的数据(错题库)
teacherOpenCourseQuestionLogWrongService.deleteBySettingIds(settingIds);
}
}
/**
* 处理章节节点,下面所有的题目
* 并保存到题目配置和题目快照表
* 从系统题库表拷贝!!!
*
* @param teacherOpenCourseId 开课ID
* @param courseInfos 当前课程下的子节点
* @param courseInfoIdPair 课程的新旧ID片段集合
*/
public void copySystemQuestionChapterTestQuestionToOpenCourse(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
Collection<CourseInfo> courseInfos, Map<Long, Long> courseInfoIdPair) {
// 章节对应下面的所有子集
Map<CourseInfo, List<CourseInfo>> courseChapterInfoIdsWithChildren = courseInfoService.getCourseChapterInfoIdsWithChildren(courseInfos);
courseChapterInfoIdsWithChildren.forEach((courseInfo, chapterInfoList) -> {
// 该列表下的所有ID合并
String allCourseInfoIds = chapterInfoList.stream().map(item -> item.getCourseInfoId().toString()).collect(joining(","));
List<ResourcesQuestion> questionList = resourcesQuestionService.getByCourseInfoIds(allCourseInfoIds);
// 有题目才继续执行
if(ObjectUtil.isNotEmpty(questionList)) {
Map<ResourcesQuestionTypeEnum, QuestionSettingDTO> map = resourcesQuestionService.buildSettingDtoListByNoDiffQuestionList(questionList);
Map<CourseInfo, Collection<QuestionSettingDTO>> courseInfoIdWithQuestionSettingOptions = new HashMap<>(1);
courseInfoIdWithQuestionSettingOptions.put(courseInfo, map.values());
addSettingBySystemCourse(teacherOpenCourseId, courseInfoIdWithQuestionSettingOptions, courseInfoIdPair);
}
});
}
/**
* 复制开课题库中的章节节点题目,到章节练习中
*
* @param teacherOpenCourseId
* @param courseInfoIdPair
*/
public void copyOpenQuestionChapterTestQuestionToOpenCourse(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId, Map<Long, Long> courseInfoIdPair) {
TeacherOpenCourseMergeCourseInfoQuery query = new TeacherOpenCourseMergeCourseInfoQuery();
query.setTeacherOpenCourseId(teacherOpenCourseId);
query.setCourseInfoStatus(1);
// 获取这个开课下的所有的课程章节信息
List<TeacherOpenCourseMergeCourseInfo> list =
teacherOpenCourseMergeCourseInfoService.getValuesByQueryNotWithPermission(query);
if (ObjectUtil.isEmpty(list)) {
return;
}
// 章节点
Set<TeacherOpenCourseMergeCourseInfo> chapterSet = list.stream()
.filter(item -> Integer.valueOf(2).equals(item.getCourseInfoType())).collect(Collectors.toSet());
// 章下面所有小节,包含章节点
Set<TeacherOpenCourseMergeCourseInfo> result = new ConcurrentHashSet<>(12);
for (TeacherOpenCourseMergeCourseInfo chapter : chapterSet) {
result.clear();
Long teacherOpenCourseMergeCourseInfoId = chapter.getTeacherOpenCourseMergeCourseInfoId();
teacherOpenCourseMergeCourseInfoService.getCourseResourcesByList(list, teacherOpenCourseMergeCourseInfoId, result);
result.add(chapter);
// 单个章节下的所有小节的ID。包含章节
String ids = result.stream().map(item -> item.getTeacherOpenCourseMergeCourseInfoId().toString()).collect(joining(","));
TeacherOpenCourseMergeResourcesQuestionQuery questionQuery = new TeacherOpenCourseMergeResourcesQuestionQuery();
questionQuery.setTeacherOpenCourseMergeCourseInfoIdPlural(ids);
// 获取章下面的所有题目
List<TeacherOpenCourseMergeResourcesQuestion> resourcesQuestionList =
teacherOpenCourseMergeResourcesQuestionService.getValuesByQueryNotWithPermission(questionQuery);
TeacherOpenCourseQuestionSettingQuery questionSettingQuery = new TeacherOpenCourseQuestionSettingQuery();
questionSettingQuery.setChapterExerciseDefault()
.setTeacherOpenCourseQuestionSettingName(chapter.getCourseInfoName())
.setTeacherOpenCourseId(teacherOpenCourseId);
// 添加到章节练习题目配置主表
add(questionSettingQuery);
// 如果有关联的题目,则添加到题目快照表
if(ObjectUtil.isNotEmpty(resourcesQuestionList)) {
// 构造章节练习的题目快照
List<ResourcesQuestionSnapshot> resourcesQuestionSnapshots = BeanUtil.copyToList(resourcesQuestionList, ResourcesQuestionSnapshot.class);
resourcesQuestionSnapshots.forEach(item -> item.setTeacherOpenCourseQuestionSettingId(questionSettingQuery.getTeacherOpenCourseQuestionSettingId()));
// 批量添加题目快照
resourcesQuestionSnapshotService.insertBatch(resourcesQuestionSnapshots);
}
}
}
public void editPushStatus(@NotEmpty(message = "题目配置ID不能为空") String ids,
@NotNull(message = "发布状态不能为空!") GlobalPushStatusEnum pushStatus) {
for (String settingId : ids.split(",")) {
TeacherOpenCourseQuestionSetting model = new TeacherOpenCourseQuestionSetting();
model.setTeacherOpenCourseQuestionSettingId(Long.valueOf(settingId));
model.setTeacherOpenCourseQuestionSettingPushStatus(pushStatus);
updateTemplate(model);
}
}
/**
* 根据题目配置ID查询当前时间是否可以参加进行题目测试
* @param questionSettingId
* @return
*/
public boolean verifyQuestionStartAndEndTimeWithNowTime(Long questionSettingId) {
if (ObjectUtil.isNotEmpty(questionSettingId)) {
TeacherOpenCourseQuestionSetting info = getInfo(questionSettingId);
return DateUtil.isIn(DateUtil.date(),
info.getTeacherOpenCourseQuestionStartTime(), info.getTeacherOpenCourseQuestionEndTime());
}
return false;
}
/**
* 根据题目配置ID查询当前时间是否可以参加进行题目测试
* 抛出异常
* @param questionSettingId
* @return
*/
public void verifyQuestionStartAndEndTimeWithNowTimeThrow(Long questionSettingId) {
Assert.isTrue(verifyQuestionStartAndEndTimeWithNowTime(questionSettingId), "当前时间不在题目操作的时间段!");
}
/**
* 章节、作业、考试的试题获取方法
* 错题练习和收藏夹练习不可用
*
* @param teacherOpenCourseQuestionSettingId 开课作业ID
* @param fromTypeEnum
* @return
*/
public List<ResourcesQuestionSnapshot> questionDetail(@NotNull(message = "题目配置ID不能为空") final Long teacherOpenCourseQuestionSettingId,
@NotNull(message = "类型不能为空!") ResourcesQuestionSnapshotFromTypeEnum fromTypeEnum) {
// 获取学生ID
final Student student = getStudent();
Assert.notNull(student, "非学生身份,无法获取题目!");
Assert.isTrue(!fromTypeEnum.equals(HOMEWORK_FILE), "作业-附件类型 不需要获取题目快照!");
// 学生ID
final Long studentId = student.getStudentId();
// 常量 True的Integer表现
final Integer TRUE_CONST = 1;
// 判断章节练习是否需要重发试卷的题目
final boolean selectIsReSend = teacherOpenCourseQuestionLogService.
verifyLogAddTypeIsReSend(teacherOpenCourseQuestionSettingId, studentId, fromTypeEnum, FINALLY_SUBMIT);
List<ResourcesQuestionSnapshot> resourcesQuestionSnapshots;
TeacherOpenCourseQuestionSetting setting = getInfo(teacherOpenCourseQuestionSettingId);
Assert.notNull(setting, "未查询到来源ID对应的题目");
// 章节练习,则跳过次数验证;
// 其他类型,都需要验证作答次数
if (!EnumUtil.contains(fromTypeEnum, CHAPTER_EXERCISE)) {
// 作答次数
Integer teacherOpenCourseQuestionSettingSettingDoCount = setting.getTeacherOpenCourseQuestionSettingDoCount();
Assert.isTrue(teacherOpenCourseQuestionSettingSettingDoCount > 0, "作答次数设置有误,请联系管理员!");
// 数据库查询该学生已经做过的次数, 这个试卷如果已经交卷的话,就提示用户
TeacherOpenCourseQuestionLog teacherOpenCourseQuestionLog = new TeacherOpenCourseQuestionLog();
teacherOpenCourseQuestionLog.setStudentId(studentId);
teacherOpenCourseQuestionLog.setQuestionLogAddType(FINALLY_SUBMIT);
teacherOpenCourseQuestionLog.setTeacherOpenCourseQuestionSettingId(teacherOpenCourseQuestionSettingId);
long doCount = teacherOpenCourseQuestionLogDao.templateCount(teacherOpenCourseQuestionLog);
// 断言判断最大作答次数
Assert.isTrue(doCount < teacherOpenCourseQuestionSettingSettingDoCount, "已超过最大作答次数!");
}
ResourcesQuestionSnapshotQuery questionSnapshotQuery = new ResourcesQuestionSnapshotQuery();
questionSnapshotQuery.setTeacherOpenCourseQuestionSettingId(teacherOpenCourseQuestionSettingId);
// 学生ID
questionSnapshotQuery.setStudentId(studentId);
questionSnapshotQuery.setIsReSend(selectIsReSend);
// 答卷后显示答案解析
if (TRUE_CONST.equals(setting.getTeacherOpenCourseQuestionSettingEndShowQa())) {
/** 实现 {@link TeacherOpenCourseQuestionLogService#questionAnalysis} */
}
// 答卷后显示答案对错
if (TRUE_CONST.equals(setting.getTeacherOpenCourseQuestionSettingEndShowTrueFalse())) {
/** 实现 {@link TeacherOpenCourseQuestionLogService#questionAnalysis} */
}
// 题目乱序(同一大题内)
if (TRUE_CONST.equals(setting.getTeacherOpenCourseQuestionSettingQuestionNoOrder())) {
questionSnapshotQuery.setRand(true);
}
// 题目查询
resourcesQuestionSnapshots = resourcesQuestionSnapshotDao.getValuesByQueryNotWithPermission(questionSnapshotQuery);
//
resourcesQuestionSnapshots = ObjectUtil.defaultIfNull(resourcesQuestionSnapshots, new ArrayList<>());
// 选项乱序(限单选、多选)
if (TRUE_CONST.equals(setting.getTeacherOpenCourseQuestionSettingOptionNoOrder())) {
// 单题选项排序处理
resourcesQuestionSnapshots.forEach(value -> {
shuffleQuestion(value, "questionStem","questionOption",
"questionAnswer", "questionType");
});
}
{
// 做题日志关联学生, 初步提交做题日志信息,不包含学生提交的答案和得分情况
teacherOpenCourseQuestionLogService.preSubmitStudentQuestionLog(studentId, teacherOpenCourseQuestionSettingId, PRE_SUBMIT, null, resourcesQuestionSnapshots, selectIsReSend);
// 学生身份,需要屏蔽答案,再丢给前端
resourcesQuestionSnapshots.forEach(ResourcesQuestionSnapshot::hideAnswer);
}
return resourcesQuestionSnapshots;
}
/**
* 题目配置,统计分析接口
*
* @param teacherOpenCourseId 开课ID
* @param questionSettingType 题目配置类型
* @return
*/
public TeacherOpenCourseQuestionSettingAnalysisVO analysis(@NotNull(message = "开课ID不能为空") Long teacherOpenCourseId,
@NotNull(message = "题目配置类型不能为空!") ResourcesQuestionSnapshotFromTypeEnum questionSettingType) {
return teacherOpenCourseQuestionSettingDao.analysis(teacherOpenCourseId, questionSettingType);
}
/**
* 功能描述: <br>
* 验证学生是否提交试卷
*
* @param questionSettingId 题目配置ID
* @param studentId 学生ID
* @param nothingThrowMessage 没找到任何题目时候异常信息
* @param notSubmitThrowMessage 异常的信息外部定义
* @Author: lx
* @Date: 2022/11/30 23:51
*/
public void validateFinallySubmitThrow(Long questionSettingId, Long studentId, String nothingThrowMessage, String notSubmitThrowMessage) {
boolean isZeroCount = false;
if (ObjectUtil.isAllNotEmpty(questionSettingId, studentId)) {
// 查询未提交题目数量
long submitCount = teacherOpenCourseQuestionLogDao.createLambdaQuery()
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionSettingId, questionSettingId)
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionLogStatus, 1)
.andEq(TeacherOpenCourseQuestionLog::getStudentId, studentId)
.andEq(TeacherOpenCourseQuestionLog::getQuestionLogAddType, FINALLY_SUBMIT)
.count();
// 查询所有题目数量
long allCount = teacherOpenCourseQuestionLogDao.createLambdaQuery()
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionSettingId, questionSettingId)
.andEq(TeacherOpenCourseQuestionLog::getStudentId, studentId)
.andEq(TeacherOpenCourseQuestionLog::getTeacherOpenCourseQuestionLogStatus, 1)
.count();
if (StrUtil.isNotBlank(nothingThrowMessage)) {
// 验证这个试卷是否有题目
Assert.isTrue(allCount > 0, nothingThrowMessage);
}
// 没有提交的题目数量
isZeroCount = submitCount > 0;
}
if (StrUtil.isNotBlank(notSubmitThrowMessage)) {
// 异常的消息,交给调用方来定义
Assert.isTrue(isZeroCount, notSubmitThrowMessage);
}
}
/**
* 功能描述: <br>
* 错题练习,错题库根据试卷来
*
* @param questionSettingId 题目配置ID试卷ID
* @param tuckOrError 练习的类型
* @param student 学生
* @return {@link JsonResult}
* @Author: 87966
* @Date: 2022/12/1 9:27
*/
public List<ResourcesQuestionSnapshot> questionDetailTest(@NotNull(message = "题目配置ID不能为空") Long questionSettingId,
@NotNull(message = "练习类型不能为空!") TuckOrErrorEnum tuckOrError, @NotNull(message = "改接口只能学生访问") Student student) {
final Long studentId = student.getStudentId();
TeacherOpenCourseQuestionLogQuery logQuery = new TeacherOpenCourseQuestionLogQuery();
if (TUCK_TEST.equals(tuckOrError)) {
logQuery.setIsTuck(true);
} else if(ERROR_TEST.equals(tuckOrError)) {
logQuery.setIsErrorFavorite(true);
}
logQuery.setStudentId(studentId);
logQuery.setTeacherOpenCourseQuestionLogStatus(1);
logQuery.setTeacherOpenCourseQuestionSettingId(questionSettingId);
List<TeacherOpenCourseQuestionLog> list = teacherOpenCourseQuestionLogService.getValuesByQueryNotWithPermission(logQuery);
list.forEach(item -> {
item.likeQuestionSnapshotInit();
if (TUCK_TEST.equals(tuckOrError)) {
item.setQuestionLogAddType(TUCK_TEST_INIT);
} else if(ERROR_TEST.equals(tuckOrError)) {
item.setQuestionLogAddType(ERROR_TEST_INIT);
}
});
if (ObjectUtil.isNotEmpty(list)) {
teacherOpenCourseQuestionLogService.insertBatch(list);
return BeanUtil.copyToList(list, ResourcesQuestionSnapshot.class);
}
return Collections.emptyList();
}
}