You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RollCall/src/main/java/com/wbq/service/impl/StudentServiceImpl.java

394 lines
13 KiB

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<StudentCourseInfoVO> page = studentCourseMapper.pageQuery4CourseInfo(courseId);
return new PageResult(page.getTotal(), page.getResult());
}
/**
* 随机点名核心代码
* @param courseId
* @param studentIds
* @return
*/
@Override
public Student coreCall(int courseId, List<Integer> 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<Integer> 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<Integer> studentIds = studentCourseMapper.getByCourseId(courseId);
// 筛选方式
Iterator<Integer> 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<Integer> studentIds = studentCourseMapper.getByCourseId(courseId);
// 筛选方式
Iterator<Integer> 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<CallRecord> 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<CourseVO> courseList() {
int studentId = studentMapper.getById(BaseContext.getCurrentId()).getStudentId();
List<CourseVO> courseVOList = new ArrayList<>();
List<Integer> courseIdList = studentCourseMapper.getByStudentId(studentId);
List<Course> 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<StudentDTO> 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<StudentDTO> parseExcel(MultipartFile file) throws Exception {
List<StudentDTO> 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<CallRecord> page = callRecordMapper.pageQuery(studentPageQueryDTO, studentId, courseDescription);
List<CallRecord> callRecordList = page.getResult();
List<CourseCallVO> 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);
}
}