package com.yf.exam.modules.user.book.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.qu.entity.Qu;
import com.yf.exam.modules.qu.service.QuService;
import com.yf.exam.modules.user.UserUtils;
import com.yf.exam.modules.user.book.dto.UserBookDTO;
import com.yf.exam.modules.user.book.entity.UserBook;
import com.yf.exam.modules.user.book.mapper.UserBookMapper;
import com.yf.exam.modules.user.book.service.UserBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
*
* 错题本服务实现类,实现了错题本相关的业务逻辑。
*
*
* @author 聪明笨狗
* @since 2020-05-27 17:56
*/
@Service
public class UserBookServiceImpl extends ServiceImpl implements UserBookService {
/**
* 注入题目服务类,用于获取题目相关信息
*/
@Autowired
private QuService quService;
/**
* 分页查询用户错题本记录
* @param reqDTO 包含分页信息和查询条件的请求对象
* @return 包含分页结果的错题本记录 DTO 对象
*/
@Override
public IPage paging(PagingReqDTO reqDTO) {
// 创建分页对象,指定当前页码和每页显示数量
Page query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
// 构建查询条件包装器
QueryWrapper wrapper = new QueryWrapper<>();
// 只查询当前用户的错题记录
wrapper.lambda().eq(UserBook::getUserId, UserUtils.getUserId(true));
// 获取查询参数
UserBookDTO params = reqDTO.getParams();
if (params != null) {
// 如果标题参数不为空,添加模糊查询条件
if (!StringUtils.isEmpty(params.getTitle())) {
wrapper.lambda().like(UserBook::getTitle, params.getTitle());
}
// 如果考试 ID 参数不为空,添加精确查询条件
if (!StringUtils.isEmpty(params.getExamId())) {
wrapper.lambda().eq(UserBook::getExamId, params.getExamId());
}
}
// 执行分页查询,获取错题本实体分页数据
IPage page = this.page(query, wrapper);
// 将实体分页数据转换为 DTO 分页数据
IPage pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference>(){});
return pageData;
}
/**
* 将错题添加到用户错题本中
* @param examId 考试 ID
* @param quId 题目 ID
*/
@Override
public void addBook(String examId, String quId) {
// 构建查询条件,查找该用户在本次考试中该题目的错题记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getUserId, UserUtils.getUserId())
.eq(UserBook::getExamId, examId)
.eq(UserBook::getQuId, quId);
// 查找已有的错题信息
UserBook book = this.getOne(wrapper, false);
// 获取题目信息
Qu qu = quService.getById(quId);
if (book == null) {
// 如果该错题记录不存在,则创建新的错题记录
book = new UserBook();
book.setExamId(examId);
book.setUserId(UserUtils.getUserId());
book.setTitle(qu.getContent());
book.setQuId(quId);
book.setWrongCount(1);
// 获取当前考试中用户错题的最大排序值,并加 1 作为新记录的排序值
Integer maxSort = this.findMaxSort(examId, UserUtils.getUserId());
book.setSort(maxSort + 1);
// 保存新的错题记录
this.save(book);
} else {
// 如果该错题记录已存在,错误次数加 1
book.setWrongCount(book.getWrongCount() + 1);
// 更新错题记录
this.updateById(book);
}
}
/**
* 查找当前错题的下一个错题的题目 ID
* @param examId 考试 ID
* @param quId 当前错题的题目 ID
* @return 下一个错题的题目 ID,如果不存在则返回 null
*/
@Override
public String findNext(String examId, String quId) {
// 初始化排序值为一个较大值
Integer sort = 999999;
if (!StringUtils.isEmpty(quId)) {
// 构建查询条件,查找当前错题记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getUserId, UserUtils.getUserId())
.eq(UserBook::getExamId, examId)
.eq(UserBook::getQuId, quId);
// 按排序值降序排序
wrapper.last(" ORDER BY `sort` DESC");
// 获取当前错题记录
UserBook last = this.getOne(wrapper, false);
if (last != null) {
// 如果找到当前错题记录,获取其排序值
sort = last.getSort();
}
}
// 构建查询条件,查找排序值小于当前错题的下一个错题记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getUserId, UserUtils.getUserId())
.eq(UserBook::getExamId, examId)
.lt(UserBook::getSort, sort);
// 按排序值降序排序
wrapper.last(" ORDER BY `sort` DESC");
// 获取下一个错题记录
UserBook next = this.getOne(wrapper, false);
if (next != null) {
// 如果找到下一个错题记录,返回其题目 ID
return next.getQuId();
}
return null;
}
/**
* 查找指定考试中用户错题的最大排序值
* @param examId 考试 ID
* @param userId 用户 ID
* @return 最大排序值,如果没有记录则返回 0
*/
private Integer findMaxSort(String examId, String userId) {
// 构建查询条件,查找指定考试中用户的错题记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getExamId, examId)
.eq(UserBook::getUserId, userId);
// 按排序值降序排序
wrapper.last(" ORDER BY `sort` DESC");
// 获取排序值最大的错题记录
UserBook book = this.getOne(wrapper, false);
if (book == null) {
// 如果没有记录,返回 0
return 0;
}
// 返回最大排序值
return book.getSort();
}
}