package com.guo.learningprogresstracker.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.protobuf.ServiceException; import com.guo.learningprogresstracker.dto.StudySessionsDto; import com.guo.learningprogresstracker.dto.response.StudySessionResponse; import com.guo.learningprogresstracker.entity.StudyReportFragmentsEntity; import com.guo.learningprogresstracker.entity.StudyReportsEntity; import com.guo.learningprogresstracker.entity.StudySessionsEntity; import com.guo.learningprogresstracker.entity.TaskEntity; import com.guo.learningprogresstracker.enums.StudySessionStateEnum; import com.guo.learningprogresstracker.exception.ErrorParameterException; import com.guo.learningprogresstracker.exception.NotFindEntitiesException; import com.guo.learningprogresstracker.mapStruct.StudySessionConvert; import com.guo.learningprogresstracker.mapper.StudyReportFragmentsMapper; import com.guo.learningprogresstracker.mapper.StudyReportsMapper; import com.guo.learningprogresstracker.mapper.StudySessionsMapper; import com.guo.learningprogresstracker.service.StudySessionsService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Optional; import java.util.stream.Collectors; /** * 针对表【study_sessions(记录每次学习会话的具体数据)】的数据库操作Service实现 */ @Slf4j @Service @RequiredArgsConstructor public class StudySessionsServiceImpl extends ServiceImpl implements StudySessionsService { public static final int WORK_DURATION = 25; private final TasksServiceImpl tasksServiceImpl; private final StudyReportFragmentsServiceImpl studyReportFragmentsServiceImpl; private final StudyReportFragmentsMapper studyReportFragmentsMapper; private final StudyReportsMapper studyReportsMapper; public StudySessionResponse startOrContinueStudySession(String taskNum) throws NotFindEntitiesException, ServiceException { TaskEntity taskEntity = tasksServiceImpl.getOneOpt( Wrappers.lambdaQuery(TaskEntity.class).eq(TaskEntity::getTaskNum, taskNum)) .orElseThrow(() -> new NotFindEntitiesException(String.format("[%s]不存在", taskNum))); StudySessionsEntity session = this.getOneOpt(Wrappers.lambdaQuery() .eq(StudySessionsEntity::getTaskNum, taskNum) .ne(StudySessionsEntity::getSessionState, StudySessionStateEnum.ENDED.name())) .orElseGet(() -> { // 如果没有则创建新会话 StudySessionsEntity newSession = StudySessionsEntity.initNewSession(); newSession.setTaskNum(taskNum); newSession.setLastStartTime(LocalDateTime.now()); this.save(newSession); return newSession; }); session.calculatePointerPosition(); if (session.isOverTime()) { session.pausedStudySession(session.getLastStartTime().plusMinutes(WORK_DURATION)); this.updateById(session); } StudySessionResponse response = StudySessionConvert.MAPPER.toStudySessionResponse(session); response.setTaskName(taskEntity.getTaskName()); if (session.isOverTime()) { response.setSystemMessage("上段学习任务已经超时25分钟,将仅计算为25分钟的有效学习时间,请注意休息!"); } return response; } @Override public void pauseStudySession(String sessionNum, LocalDateTime endTime) throws ErrorParameterException, ServiceException { StudySessionsEntity studySessionsEntity = this.getOneOpt(Wrappers.lambdaQuery(StudySessionsEntity.class) .eq(StudySessionsEntity::getSessionNum, sessionNum)) .orElseThrow(() -> new ErrorParameterException("会话[" + sessionNum + "]不存在")); if (StudySessionStateEnum.PAUSED.name().equals(studySessionsEntity.getSessionState())) { log.error("会话[" + studySessionsEntity.getSessionNum() + "]重复暂停"); throw new ErrorParameterException("会话[" + sessionNum + "]已经暂停,请勿重复暂停!"); } studySessionsEntity.calculatePointerPosition(); studySessionsEntity.pausedStudySession(endTime); this.updateById(studySessionsEntity); } @Override public String endedStudySession(String sessionNum, String content) throws ErrorParameterException { StudySessionsEntity studySessionsEntity = this.getOneOpt(Wrappers.lambdaQuery(StudySessionsEntity.class) .eq(StudySessionsEntity::getSessionNum, sessionNum)) .orElseThrow(() -> new ErrorParameterException("会话[" + sessionNum + "]不存在")); boolean wasOngoing = StudySessionStateEnum.ONGOING.name().equals(studySessionsEntity.getSessionState()); studySessionsEntity.endedStudySession(); this.updateById(studySessionsEntity); StudyReportsEntity studyReportsEntity = new StudyReportsEntity(); studyReportsEntity.setSessionNum(sessionNum); studyReportsEntity.setContent(content); studyReportsMapper.insert(studyReportsEntity); if (wasOngoing && studySessionsEntity.getEffectiveTime() == 0) { return "本次有效学习时间不足10分钟,不计入总学习时间"; } return null; } @Override public StudySessionResponse getNotEndedStudySessionByTaskNum(String taskNum) throws ErrorParameterException { TaskEntity task = tasksServiceImpl.getOneOpt(Wrappers.lambdaQuery(TaskEntity.class) .eq(TaskEntity::getTaskNum, taskNum)) .orElseThrow(() -> new ErrorParameterException("任务[" + taskNum + "]不存在")); StudySessionsDto dto = Optional.ofNullable(studyReportsMapper.getNotEndedStudySessionDtoByTaskNum(taskNum)) .orElseThrow(() -> new ErrorParameterException("任务[" + taskNum + "]不存在进行中或暂停中的会话")); return StudySessionConvert.MAPPER.toStudySessionResponse(dto); } @Override public ArrayList getAllFragments(String sessionNum) throws ErrorParameterException { if (this.exists(Wrappers.lambdaQuery(StudySessionsEntity.class) .eq(StudySessionsEntity::getSessionNum, sessionNum))) { return studyReportFragmentsMapper.selectList(Wrappers.lambdaQuery(StudyReportFragmentsEntity.class) .eq(StudyReportFragmentsEntity::getSessionNum, sessionNum)) .stream().map(StudyReportFragmentsEntity::getContent).collect(Collectors.toCollection(ArrayList::new)); } else { throw new ErrorParameterException("会话[" + sessionNum + "]不存在"); } } @Override public void continueStudySession(String sessionNum) throws ErrorParameterException, ServiceException { StudySessionsEntity studySessionsEntity = this.getOneOpt(Wrappers.lambdaQuery(StudySessionsEntity.class) .eq(StudySessionsEntity::getSessionNum, sessionNum)) .orElseThrow(() -> new ErrorParameterException("会话[" + sessionNum + "]不存在")); if (StudySessionStateEnum.ONGOING.name().equals(studySessionsEntity.getSessionState())) { log.error("会话[" + studySessionsEntity.getSessionNum() + "]重复开始"); throw new ErrorParameterException("会话[" + sessionNum + "]已经开始,请勿重复开始!"); } else if (StudySessionStateEnum.ENDED.name().equals(studySessionsEntity.getSessionState())) { log.error("会话[" + studySessionsEntity.getSessionNum() + "]处于结束状态,不可开始该会话!"); throw new ErrorParameterException("会话[" + sessionNum + "]处于结束状态,不可开始该会话!"); } studySessionsEntity.continueStudySession(); this.updateById(studySessionsEntity); } /** * 通过 sessionNum 获取学习会话 */ public StudySessionResponse getStudySessionBySessionNum(String sessionNum) throws ErrorParameterException { StudySessionsEntity session = this.getOneOpt(Wrappers.lambdaQuery(StudySessionsEntity.class) .eq(StudySessionsEntity::getSessionNum, sessionNum)) .orElseThrow(() -> new ErrorParameterException("会话[" + sessionNum + "]不存在")); return StudySessionConvert.MAPPER.toStudySessionResponse(session); } }