package com.wbq.service.impl; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.wbq.context.BaseContext; import com.wbq.dto.CourseDTO; import com.wbq.dto.StudentDTO; import com.wbq.dto.StudentLoginDTO; import com.wbq.dto.StudentPageQueryDTO; import com.wbq.entity.CallRecord; import com.wbq.entity.Course; import com.wbq.entity.Student; import com.wbq.mapper.*; import com.wbq.result.PageResult; import com.wbq.service.StudentService; import com.wbq.vo.CourseCallVO; import com.wbq.vo.CourseVO; import com.wbq.vo.StudentCourseInfoVO; import org.apache.poi.ss.usermodel.*; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCrypt; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.print.attribute.IntegerSyntax; import java.io.InputStream; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; @Service public class StudentServiceImpl implements StudentService { @Autowired private StudentMapper studentMapper; @Autowired private StudentCourseMapper studentCourseMapper; @Autowired private CourseMapper courseMapper; @Autowired private CallRecordMapper callRecordMapper; @Autowired private AdminMapper adminMapper; @Override public Student getById(int id) { return studentMapper.getById(id); } /** * 更新学生信息 * @param studentDTO */ @Override public void update(StudentDTO studentDTO) { studentMapper.update(studentDTO); } /** * 分页查询学生(按课程积分排名) * @param studentPageQueryDTO * @param courseId * @return */ @Override public PageResult pageQuery(StudentPageQueryDTO studentPageQueryDTO, int courseId) { PageHelper.startPage(studentPageQueryDTO.getPage(), studentPageQueryDTO.getPageSize()); Page page = studentCourseMapper.pageQuery4CourseInfo(courseId); return new PageResult(page.getTotal(), page.getResult()); } /** * 随机点名核心代码 * @param courseId * @param studentIds * @return */ @Override public Student coreCall(int courseId, List studentIds) { // 生成权重 double totalWeight = 0; for (int studentId : studentIds) { StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(studentId, courseId); double studentScore = studentCourseInfoVO.getScore(); totalWeight += 1.0/(studentScore + 1); } double cumulativeWeight = 0; Random random = new Random(); double rand = random.nextDouble(); int selectedStudentId = 0; // 轮盘赌算法 for (int studentId : studentIds) { StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(studentId, courseId); double studentScore = studentCourseInfoVO.getScore(); cumulativeWeight += 1.0/(studentScore + 1); if (cumulativeWeight >= rand*totalWeight) { selectedStudentId = studentId; break; } } // 增加被叫次数 int oldCallCount = studentCourseMapper.getCourseInfo(selectedStudentId, courseId).getCallCount(); int newCallCount = oldCallCount + 1; studentCourseMapper.updateCallCountByStudentIdAndCourseId(newCallCount, selectedStudentId, courseId); Student selectedStudent = studentMapper.getByStudentId(selectedStudentId); // 生成点名记录 CallRecord callRecord = CallRecord.builder() .callTime(LocalDateTime.now()) .courseDescription(courseMapper.getByCourseId(courseId).getDescription()) .adminName(adminMapper.getById(BaseContext.getCurrentId()).getName()) .studentId(selectedStudentId) .build(); callRecordMapper.insert(callRecord); return selectedStudent; } /** * 随机点名 * @param courseId * @return */ @Override public StudentCourseInfoVO callStudent(int courseId) { List studentIds = studentCourseMapper.getByCourseId(courseId); Student selectedStudent = coreCall(courseId, studentIds); StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(selectedStudent.getStudentId(), courseId); return studentCourseInfoVO; } /** * 根据姓氏点名,积分越高,概率越低 * @param courseId * @param firstname * @return */ @Override public StudentCourseInfoVO callStudentByFirstname(int courseId, String firstname) { List studentIds = studentCourseMapper.getByCourseId(courseId); // 筛选方式 Iterator iterator = studentIds.iterator(); while (iterator.hasNext()) { Integer studentId = iterator.next(); Student student = studentMapper.getByStudentId(studentId); String studentName = student.getName(); if (!firstname.equals(Character.toString(studentName.charAt(0)))) { iterator.remove(); // 使用 iterator.remove() 安全地移除元素 } } Student selectedStudent = coreCall(courseId, studentIds); StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(selectedStudent.getStudentId(), courseId); return studentCourseInfoVO; } /** * 根据学号尾数点名 * @param courseId * @param lastNum * @return */ @Override public StudentCourseInfoVO callStudentByLastNum(int courseId, int lastNum) { List studentIds = studentCourseMapper.getByCourseId(courseId); // 筛选方式 Iterator iterator = studentIds.iterator(); while (iterator.hasNext()) { Integer studentId = iterator.next(); if (studentId % 10 != lastNum) { iterator.remove(); // 使用 iterator.remove() 安全地移除元素 } } Student selectedStudent = coreCall(courseId, studentIds); StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(selectedStudent.getStudentId(), courseId); return studentCourseInfoVO; } /** * 手动加分 * @param courseDTO * @param studentDTO * @param score * @return */ @Override public StudentCourseInfoVO addScore(CourseDTO courseDTO, StudentDTO studentDTO, double score) { double oldScore = studentCourseMapper.getCourseInfo(studentDTO.getStudentId(), courseDTO.getCourseId()).getScore(); studentCourseMapper.updateScoreByStudentIdAndCourseId(oldScore + score, studentDTO.getStudentId(), courseDTO.getCourseId()); // 返回更新值 StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(studentDTO.getStudentId(), courseDTO.getCourseId()); // 更新记录 List callRecordList = callRecordMapper.getByStudentId(studentDTO.getStudentId()); CallRecord newCallRecord = callRecordList.getFirst(); newCallRecord.setScore(score); callRecordMapper.update(newCallRecord); return studentCourseInfoVO; } /** * 学生登录 * @param studentLoginDTO * @return */ @Override public Student login(StudentLoginDTO studentLoginDTO) { Student student = null; String hashedPassword = studentMapper.getPasswordByStudentId(studentLoginDTO.getStudentId()); // 使用BCrypt的checkpw方法来验证密码 boolean isPasswordCorrect = BCrypt.checkpw(studentLoginDTO.getPassword(), hashedPassword); // 验证成功 if (isPasswordCorrect) student = studentMapper.getByStudentId(studentLoginDTO.getStudentId()); return student; } /** * 加入课程 * @param courseDTO */ @Override public void joinCourse(StudentDTO studentDTO, CourseDTO courseDTO) { studentCourseMapper.insert(studentDTO.getStudentId(), courseDTO.getCourseId()); } /** * 退出班级 * @param courseDTO * @param studentDTO */ @Override public void dropCourse(CourseDTO courseDTO, StudentDTO studentDTO) { studentCourseMapper.delete(studentDTO.getStudentId(), courseDTO.getCourseId()); } /** * 查询自己加入的班级 * @return */ @Override public List courseList() { int studentId = studentMapper.getById(BaseContext.getCurrentId()).getStudentId(); List courseVOList = new ArrayList<>(); List courseIdList = studentCourseMapper.getByStudentId(studentId); List courseList = courseMapper.getByCourseIdList(courseIdList); for (Course course : courseList) { CourseVO courseVO = new CourseVO(); BeanUtils.copyProperties(course, courseVO); courseVOList.add(courseVO); } return courseVOList; } /** * 查询自己的某门课程信息 * @param studentId * @param courseId * @return */ @Override public StudentCourseInfoVO getStudentCourseInfo(int studentId, int courseId) { return studentCourseMapper.getCourseInfo(studentId, courseId); } /** * 批量增加点名系统的学生 * @param courseId * @param studentDTOs */ @Override public void batchAddStudents(List studentDTOs, int courseId) { if (studentDTOs != null && !studentDTOs.isEmpty()) { for (StudentDTO studentDTO : studentDTOs) { String initPassword = "1234"; String hashedPassword = BCrypt.hashpw(initPassword, BCrypt.gensalt()); studentDTO.setPassword(hashedPassword); } studentCourseMapper.batchInsert(studentDTOs, courseId); } } /** * 解析Excel * @param file * @return * @throws Exception */ @Override public List parseExcel(MultipartFile file) throws Exception { List studentDTOs = new ArrayList<>(); // 获取 Excel 文件的输入流 InputStream inputStream = file.getInputStream(); Workbook workbook = WorkbookFactory.create(inputStream); // 学生信息在第一张表 Sheet sheet = workbook.getSheetAt(0); for (Row row : sheet) { // 跳过表头 /*if (row.getRowNum() == 0) { continue; }*/ StudentDTO studentDTO = new StudentDTO(); if(row.getRowNum() == 103) break; //debug System.out.println("第" + row.getRowNum() + "行"); System.out.println(row.getCell(0).getCellType() + " " + row.getCell(1).getCellType() + " " + row.getCell(2).getCellType()); if(row.getCell(0).getCellType() == CellType.STRING) studentDTO.setStudentId(Integer.parseInt(row.getCell(0).getStringCellValue())); else studentDTO.setStudentId((int)row.getCell(0).getNumericCellValue()); // 学号 studentDTO.setName(row.getCell(1).getStringCellValue()); // 姓名 studentDTO.setPassword(row.getCell(2).getStringCellValue()); // 密码 studentDTOs.add(studentDTO); } workbook.close(); return studentDTOs; } /** * 查询自己某门课程的历次点名记录 * @param courseId * @param studentPageQueryDTO * @return */ @Override public PageResult getCallRecord(StudentPageQueryDTO studentPageQueryDTO, int courseId) { int studentId = studentMapper.getById(BaseContext.getCurrentId()).getStudentId(); String courseDescription = courseMapper.getByCourseId(courseId).getDescription(); PageHelper.startPage(studentPageQueryDTO.getPage(), studentPageQueryDTO.getPageSize()); Page page = callRecordMapper.pageQuery(studentPageQueryDTO, studentId, courseDescription); List callRecordList = page.getResult(); List courseCallVOList = new ArrayList<>(); for (CallRecord callRecord : callRecordList) { CourseCallVO courseCallVO = new CourseCallVO(); BeanUtils.copyProperties(callRecord, courseCallVO); courseCallVOList.add(courseCallVO); } return new PageResult(page.getTotal(), courseCallVOList); } /** * 修改密码 * @param studentDTO */ @Override public void changePassword(StudentDTO studentDTO) { String password = studentDTO.getPassword(); String hashPassword = BCrypt.hashpw(password, BCrypt.gensalt()); studentDTO.setPassword(hashPassword); studentMapper.update(studentDTO); } }