|
|
|
@ -13,7 +13,9 @@ import com.sztzjy.linkCommerce.mapper.StuRankMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.StudentTrainingAnswerMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.StudentTrainingAnswerMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.TaskAllocationMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.TeachingClassStudentMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.TeachingClassStudentMapper;
|
|
|
|
|
|
|
|
import com.sztzjy.linkCommerce.mapper.TrainingTaskMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.WeightMapper;
|
|
|
|
import com.sztzjy.linkCommerce.mapper.WeightMapper;
|
|
|
|
|
|
|
|
import com.sztzjy.linkCommerce.entity.dto.TeacherTaskReviewDTO;
|
|
|
|
import com.sztzjy.linkCommerce.service.ScoreRankService;
|
|
|
|
import com.sztzjy.linkCommerce.service.ScoreRankService;
|
|
|
|
import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService;
|
|
|
|
import com.sztzjy.linkCommerce.service.SchoolDefaultTaskService;
|
|
|
|
import com.sztzjy.linkCommerce.service.TeacherScoreService;
|
|
|
|
import com.sztzjy.linkCommerce.service.TeacherScoreService;
|
|
|
|
@ -30,11 +32,7 @@ import org.springframework.web.bind.annotation.*;
|
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.Collections;
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -57,6 +55,8 @@ public class TeaScoreController {
|
|
|
|
@Autowired
|
|
|
|
@Autowired
|
|
|
|
TaskAllocationMapper taskAllocationMapper;
|
|
|
|
TaskAllocationMapper taskAllocationMapper;
|
|
|
|
@Autowired(required = false)
|
|
|
|
@Autowired(required = false)
|
|
|
|
|
|
|
|
TrainingTaskMapper trainingTaskMapper;
|
|
|
|
|
|
|
|
@Autowired(required = false)
|
|
|
|
StudentTrainingAnswerMapper studentTrainingAnswerMapper;
|
|
|
|
StudentTrainingAnswerMapper studentTrainingAnswerMapper;
|
|
|
|
@Autowired(required = false)
|
|
|
|
@Autowired(required = false)
|
|
|
|
SchoolDefaultTaskService schoolDefaultTaskService;
|
|
|
|
SchoolDefaultTaskService schoolDefaultTaskService;
|
|
|
|
@ -122,6 +122,40 @@ public class TeaScoreController {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@PostMapping("/saveTaskTeacherScore")
|
|
|
|
|
|
|
|
@ApiOperation("保存教师对单个实训任务的评分")
|
|
|
|
|
|
|
|
public ResultEntity<?> saveTaskTeacherScore(@RequestParam String classId,
|
|
|
|
|
|
|
|
@RequestParam String studentUserId,
|
|
|
|
|
|
|
|
@RequestParam String taskId,
|
|
|
|
|
|
|
|
@RequestParam BigDecimal teacherScore,
|
|
|
|
|
|
|
|
HttpServletRequest request) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
JwtUser teacher = currentUser(request);
|
|
|
|
|
|
|
|
teacherScoreService.requireOwnedClass(teacher, classId);
|
|
|
|
|
|
|
|
if (teachingClassStudentMapper.countByStudentUserIdAndTeachingClassId(studentUserId, classId) == 0) {
|
|
|
|
|
|
|
|
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "该学生不在当前教学班");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StudentTrainingAnswer answer = studentTrainingAnswerMapper == null ? null
|
|
|
|
|
|
|
|
: studentTrainingAnswerMapper.selectByStudentClassAndTask(studentUserId, classId, taskId);
|
|
|
|
|
|
|
|
if (answer == null || !isCompleted(answer)) {
|
|
|
|
|
|
|
|
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "仅已完成的实训任务可以评分");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (teacherScore == null || teacherScore.compareTo(BigDecimal.ZERO) < 0
|
|
|
|
|
|
|
|
|| teacherScore.compareTo(new BigDecimal("100")) > 0) {
|
|
|
|
|
|
|
|
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "教师评分必须为0至100之间的数值");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Date scoredAt = new Date();
|
|
|
|
|
|
|
|
studentTrainingAnswerMapper.updateTeacherScore(answer.getId(), teacherScore.setScale(2, BigDecimal.ROUND_HALF_UP),
|
|
|
|
|
|
|
|
teacher.getUserId(), scoredAt);
|
|
|
|
|
|
|
|
answer.setTeacherScore(teacherScore.setScale(2, BigDecimal.ROUND_HALF_UP));
|
|
|
|
|
|
|
|
answer.setTeacherScoredBy(teacher.getUserId());
|
|
|
|
|
|
|
|
answer.setTeacherScoredAt(scoredAt);
|
|
|
|
|
|
|
|
return new ResultEntity<>(HttpStatus.OK, "任务评分保存成功", answer);
|
|
|
|
|
|
|
|
} catch (com.sztzjy.linkCommerce.config.exception.handler.ServiceException e) {
|
|
|
|
|
|
|
|
return new ResultEntity<>(e.getCode(), e.getMessage());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@PostMapping("/selectStuRankAndScore")
|
|
|
|
@PostMapping("/selectStuRankAndScore")
|
|
|
|
@ApiOperation("查询学生成绩和排名")
|
|
|
|
@ApiOperation("查询学生成绩和排名")
|
|
|
|
@AnonymousAccess
|
|
|
|
@AnonymousAccess
|
|
|
|
@ -185,10 +219,9 @@ public class TeaScoreController {
|
|
|
|
if (teachingClassStudentMapper.countByStudentUserIdAndTeachingClassId(userId, teachingClass.getSchoolClassId()) == 0) {
|
|
|
|
if (teachingClassStudentMapper.countByStudentUserIdAndTeachingClassId(userId, teachingClass.getSchoolClassId()) == 0) {
|
|
|
|
return new ResultEntity<>(HttpStatus.FORBIDDEN, "无权查看该学生成绩");
|
|
|
|
return new ResultEntity<>(HttpStatus.FORBIDDEN, "无权查看该学生成绩");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (studentTrainingAnswerMapper != null) {
|
|
|
|
if (studentTrainingAnswerMapper != null && trainingTaskMapper != null) {
|
|
|
|
List<StudentTrainingAnswer> answers = studentTrainingAnswerMapper.selectByStudentAndTeachingClass(userId, classId);
|
|
|
|
|
|
|
|
return new ResultEntity<>(HttpStatus.OK, "查看学生成绩详情成功",
|
|
|
|
return new ResultEntity<>(HttpStatus.OK, "查看学生成绩详情成功",
|
|
|
|
answers == null ? Collections.emptyList() : answers);
|
|
|
|
buildTaskReviews(userId, classId));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 定义模块的固定排序顺序
|
|
|
|
// 定义模块的固定排序顺序
|
|
|
|
List<String> moduleOrder = Arrays.asList(
|
|
|
|
List<String> moduleOrder = Arrays.asList(
|
|
|
|
@ -357,70 +390,56 @@ public class TeaScoreController {
|
|
|
|
if (ranks == null || ranks.isEmpty()) {
|
|
|
|
if (ranks == null || ranks.isEmpty()) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Map<String, BigDecimal> classTeacherScores = Collections.emptyMap();
|
|
|
|
|
|
|
|
if (teacherScoreService != null && StringUtils.isNotBlank(requestedClassId)) {
|
|
|
|
|
|
|
|
Map<String, BigDecimal> loadedScores = teacherScoreService.getTeacherScores(requestedClassId, ranks.stream()
|
|
|
|
|
|
|
|
.map(StuRank::getUserId)
|
|
|
|
|
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
|
|
|
|
|
.distinct()
|
|
|
|
|
|
|
|
.collect(Collectors.toList()));
|
|
|
|
|
|
|
|
if (loadedScores != null) {
|
|
|
|
|
|
|
|
classTeacherScores = loadedScores;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for (StuRank rank : ranks) {
|
|
|
|
for (StuRank rank : ranks) {
|
|
|
|
String classId = StringUtils.isNotBlank(requestedClassId) ? requestedClassId : rank.getSchoolClassId();
|
|
|
|
String classId = StringUtils.isNotBlank(requestedClassId) ? requestedClassId : rank.getSchoolClassId();
|
|
|
|
rank.setTeacherScore(StringUtils.isNotBlank(requestedClassId)
|
|
|
|
List<TaskAllocation> allocations = resolveEnabledTaskAllocations(classId);
|
|
|
|
? classTeacherScores.get(rank.getUserId())
|
|
|
|
int totalTaskCount = (int) allocations.stream().map(TaskAllocation::getModule)
|
|
|
|
: teacherScoreService == null ? null : teacherScoreService.getTeacherScore(classId, rank.getUserId()));
|
|
|
|
.filter(StringUtils::isNotBlank).distinct().count();
|
|
|
|
Set<String> enabledModules = resolveEnabledTaskModules(classId);
|
|
|
|
|
|
|
|
int totalTaskCount = enabledModules.size();
|
|
|
|
|
|
|
|
rank.setTotalTaskCount(totalTaskCount);
|
|
|
|
rank.setTotalTaskCount(totalTaskCount);
|
|
|
|
if (totalTaskCount == 0) {
|
|
|
|
if (totalTaskCount == 0) {
|
|
|
|
rank.setCompletedTaskCount(0);
|
|
|
|
rank.setCompletedTaskCount(0);
|
|
|
|
rank.setTrainingProgress(null);
|
|
|
|
rank.setTrainingProgress(null);
|
|
|
|
|
|
|
|
rank.setTeacherScore(null);
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
List<StudentTrainingAnswer> answers = studentTrainingAnswerMapper == null ? Collections.emptyList()
|
|
|
|
StuGradeExample gradeExample = new StuGradeExample();
|
|
|
|
: studentTrainingAnswerMapper.selectByStudentAndTeachingClass(rank.getUserId(), classId);
|
|
|
|
StuGradeExample.Criteria gradeCriteria = gradeExample.createCriteria().andUserIdEqualTo(rank.getUserId());
|
|
|
|
Map<String, StudentTrainingAnswer> answersByTaskKey = indexAnswersByTaskKey(answers);
|
|
|
|
if (StringUtils.isNotBlank(classId)) {
|
|
|
|
int completedTaskCount = (int) allocations.stream().map(TaskAllocation::getModule)
|
|
|
|
gradeCriteria.andSchoolClassIdEqualTo(classId);
|
|
|
|
.filter(StringUtils::isNotBlank).distinct()
|
|
|
|
}
|
|
|
|
.filter(taskKey -> isCompleted(answersByTaskKey.get(taskKey))).count();
|
|
|
|
List<StuGrade> grades = stuGradeMapper == null ? Collections.emptyList() : stuGradeMapper.selectByExample(gradeExample);
|
|
|
|
|
|
|
|
int completedTaskCount = (int) (grades == null ? Collections.<StuGrade>emptyList() : grades).stream()
|
|
|
|
|
|
|
|
.map(StuGrade::getModule)
|
|
|
|
|
|
|
|
.filter(enabledModules::contains)
|
|
|
|
|
|
|
|
.distinct()
|
|
|
|
|
|
|
|
.count();
|
|
|
|
|
|
|
|
rank.setCompletedTaskCount(completedTaskCount);
|
|
|
|
rank.setCompletedTaskCount(completedTaskCount);
|
|
|
|
rank.setTrainingProgress(BigDecimal.valueOf(completedTaskCount)
|
|
|
|
rank.setTrainingProgress(BigDecimal.valueOf(completedTaskCount)
|
|
|
|
.multiply(BigDecimal.valueOf(100))
|
|
|
|
.multiply(BigDecimal.valueOf(100))
|
|
|
|
.divide(BigDecimal.valueOf(totalTaskCount), 2, BigDecimal.ROUND_HALF_UP));
|
|
|
|
.divide(BigDecimal.valueOf(totalTaskCount), 2, BigDecimal.ROUND_HALF_UP));
|
|
|
|
|
|
|
|
rank.setTeacherScore(calculateTeacherScore(classId, allocations, answersByTaskKey));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Set<String> resolveEnabledTaskModules(String classId) {
|
|
|
|
private List<TaskAllocation> resolveEnabledTaskAllocations(String classId) {
|
|
|
|
if (StringUtils.isBlank(classId)) {
|
|
|
|
if (StringUtils.isBlank(classId)) {
|
|
|
|
return Collections.emptySet();
|
|
|
|
return Collections.emptyList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (taskAllocationMapper == null) {
|
|
|
|
|
|
|
|
return Collections.emptyList();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
List<TaskAllocation> classAllocations = selectTaskAllocations(classId);
|
|
|
|
|
|
|
|
boolean comprehensiveParticipating = hasPublishedComprehensiveTask(classAllocations);
|
|
|
|
List<TaskAllocation> allocations;
|
|
|
|
List<TaskAllocation> allocations;
|
|
|
|
if (schoolDefaultTaskService != null) {
|
|
|
|
if (schoolDefaultTaskService != null) {
|
|
|
|
allocations = schoolDefaultTaskService.resolveForTeachingClass(classId);
|
|
|
|
allocations = schoolDefaultTaskService.resolveForTeachingClass(classId);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (taskAllocationMapper == null) {
|
|
|
|
allocations = classAllocations;
|
|
|
|
return Collections.emptySet();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
allocations = selectTaskAllocations(classId);
|
|
|
|
|
|
|
|
if ((allocations == null || allocations.isEmpty()) && !"999999999".equals(classId)) {
|
|
|
|
if ((allocations == null || allocations.isEmpty()) && !"999999999".equals(classId)) {
|
|
|
|
allocations = selectTaskAllocations("999999999");
|
|
|
|
allocations = selectTaskAllocations("999999999");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (allocations == null ? Collections.<TaskAllocation>emptyList() : allocations).stream()
|
|
|
|
return (allocations == null ? Collections.<TaskAllocation>emptyList() : allocations).stream()
|
|
|
|
.filter(allocation -> allocation.getDisabledStatus() == null || allocation.getDisabledStatus() != 1)
|
|
|
|
.filter(allocation -> allocation.getDisabledStatus() == null || allocation.getDisabledStatus() != 1)
|
|
|
|
.map(TaskAllocation::getModule)
|
|
|
|
.filter(allocation -> !TaskAllocation.PUBLICATION_MARKER.equals(allocation.getModule()))
|
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
|
.filter(allocation -> !"comprehensive-case-training".equals(allocation.getModule())
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|| comprehensiveParticipating)
|
|
|
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<TaskAllocation> selectTaskAllocations(String classId) {
|
|
|
|
private List<TaskAllocation> selectTaskAllocations(String classId) {
|
|
|
|
@ -429,6 +448,129 @@ public class TeaScoreController {
|
|
|
|
return taskAllocationMapper.selectByExample(example);
|
|
|
|
return taskAllocationMapper.selectByExample(example);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean hasPublishedComprehensiveTask(List<TaskAllocation> allocations) {
|
|
|
|
|
|
|
|
boolean published = false;
|
|
|
|
|
|
|
|
boolean enabled = false;
|
|
|
|
|
|
|
|
for (TaskAllocation allocation : allocations == null ? Collections.<TaskAllocation>emptyList() : allocations) {
|
|
|
|
|
|
|
|
if (allocation == null) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TaskAllocation.PUBLICATION_MARKER.equals(allocation.getModule())) {
|
|
|
|
|
|
|
|
published = true;
|
|
|
|
|
|
|
|
} else if ("comprehensive-case-training".equals(allocation.getModule())
|
|
|
|
|
|
|
|
&& (allocation.getDisabledStatus() == null || allocation.getDisabledStatus() == 0)) {
|
|
|
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return published && enabled;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Map<String, StudentTrainingAnswer> indexAnswersByTaskKey(List<StudentTrainingAnswer> answers) {
|
|
|
|
|
|
|
|
Map<String, StudentTrainingAnswer> indexed = new HashMap<>();
|
|
|
|
|
|
|
|
for (StudentTrainingAnswer answer : answers == null ? Collections.<StudentTrainingAnswer>emptyList() : answers) {
|
|
|
|
|
|
|
|
if (answer != null && StringUtils.isNotBlank(answer.getTaskKey())) {
|
|
|
|
|
|
|
|
indexed.put(answer.getTaskKey(), answer);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return indexed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isCompleted(StudentTrainingAnswer answer) {
|
|
|
|
|
|
|
|
return answer != null && (Boolean.TRUE.equals(answer.getSubmitted())
|
|
|
|
|
|
|
|
|| "COMPLETED".equals(answer.getProgressStatus()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private BigDecimal calculateTeacherScore(String classId, List<TaskAllocation> allocations,
|
|
|
|
|
|
|
|
Map<String, StudentTrainingAnswer> answersByTaskKey) {
|
|
|
|
|
|
|
|
if (teacherScoreService == null || trainingTaskMapper == null) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Map<String, List<BigDecimal>> scoresByProject = new HashMap<>();
|
|
|
|
|
|
|
|
boolean hasTeacherScore = false;
|
|
|
|
|
|
|
|
boolean comprehensiveParticipating = false;
|
|
|
|
|
|
|
|
for (TaskAllocation allocation : allocations) {
|
|
|
|
|
|
|
|
if (allocation == null || StringUtils.isBlank(allocation.getModule())) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if ("comprehensive-case-training".equals(allocation.getModule())) {
|
|
|
|
|
|
|
|
comprehensiveParticipating = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TrainingTask task = trainingTaskMapper.selectByTaskKey(allocation.getModule());
|
|
|
|
|
|
|
|
if (task == null || StringUtils.isBlank(task.getProjectName())) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StudentTrainingAnswer answer = answersByTaskKey.get(allocation.getModule());
|
|
|
|
|
|
|
|
BigDecimal taskScore = answer == null ? null : answer.getTeacherScore();
|
|
|
|
|
|
|
|
if (taskScore != null) {
|
|
|
|
|
|
|
|
hasTeacherScore = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
scoresByProject.computeIfAbsent(task.getProjectName(), key -> new ArrayList<>())
|
|
|
|
|
|
|
|
.add(taskScore == null ? BigDecimal.ZERO : taskScore);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hasTeacherScore) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TeachingClassScoreWeight weight = teacherScoreService.getOrCreateWeightForCalculation(classId);
|
|
|
|
|
|
|
|
if (weight == null) {
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
BigDecimal weightedTotal = projectAverage(scoresByProject, "互联网产品开发基础认知").multiply(safeWeight(weight.getFoundationWeight()))
|
|
|
|
|
|
|
|
.add(projectAverage(scoresByProject, "市场洞察与需求分析").multiply(safeWeight(weight.getMarketInsightWeight())))
|
|
|
|
|
|
|
|
.add(projectAverage(scoresByProject, "产品规划与设计").multiply(safeWeight(weight.getPlanningDesignWeight())))
|
|
|
|
|
|
|
|
.add(projectAverage(scoresByProject, "产品开发与测试验证").multiply(safeWeight(weight.getDevelopmentValidationWeight())))
|
|
|
|
|
|
|
|
.add(projectAverage(scoresByProject, "产品上线与运营推广").multiply(safeWeight(weight.getLaunchOperationWeight())))
|
|
|
|
|
|
|
|
.add(projectAverage(scoresByProject, "综合实训").multiply(safeWeight(weight.getComprehensiveTrainingWeight())));
|
|
|
|
|
|
|
|
BigDecimal participatingWeight = safeWeight(weight.getFoundationWeight()).add(safeWeight(weight.getMarketInsightWeight()))
|
|
|
|
|
|
|
|
.add(safeWeight(weight.getPlanningDesignWeight())).add(safeWeight(weight.getDevelopmentValidationWeight()))
|
|
|
|
|
|
|
|
.add(safeWeight(weight.getLaunchOperationWeight()));
|
|
|
|
|
|
|
|
if (comprehensiveParticipating) {
|
|
|
|
|
|
|
|
participatingWeight = participatingWeight.add(safeWeight(weight.getComprehensiveTrainingWeight()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return weightedTotal.divide(participatingWeight.signum() == 0 ? BigDecimal.ONE : participatingWeight,
|
|
|
|
|
|
|
|
2, BigDecimal.ROUND_HALF_UP);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private BigDecimal projectAverage(Map<String, List<BigDecimal>> scoresByProject, String projectName) {
|
|
|
|
|
|
|
|
List<BigDecimal> scores = scoresByProject.get(projectName);
|
|
|
|
|
|
|
|
if (scores == null || scores.isEmpty()) {
|
|
|
|
|
|
|
|
return BigDecimal.ZERO;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
BigDecimal total = scores.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
|
|
|
return total.divide(BigDecimal.valueOf(scores.size()), 4, BigDecimal.ROUND_HALF_UP);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private BigDecimal safeWeight(BigDecimal weight) {
|
|
|
|
|
|
|
|
return weight == null ? BigDecimal.ZERO : weight;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<TeacherTaskReviewDTO> buildTaskReviews(String studentUserId, String classId) {
|
|
|
|
|
|
|
|
Map<String, StudentTrainingAnswer> answersByTaskKey = indexAnswersByTaskKey(
|
|
|
|
|
|
|
|
studentTrainingAnswerMapper.selectByStudentAndTeachingClass(studentUserId, classId));
|
|
|
|
|
|
|
|
List<TeacherTaskReviewDTO> reviews = new ArrayList<>();
|
|
|
|
|
|
|
|
Set<String> seenTaskKeys = new HashSet<>();
|
|
|
|
|
|
|
|
for (TaskAllocation allocation : resolveEnabledTaskAllocations(classId)) {
|
|
|
|
|
|
|
|
if (allocation == null || StringUtils.isBlank(allocation.getModule()) || !seenTaskKeys.add(allocation.getModule())) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TrainingTask task = trainingTaskMapper.selectByTaskKey(allocation.getModule());
|
|
|
|
|
|
|
|
if (task == null) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StudentTrainingAnswer answer = answersByTaskKey.get(allocation.getModule());
|
|
|
|
|
|
|
|
TeacherTaskReviewDTO review = new TeacherTaskReviewDTO();
|
|
|
|
|
|
|
|
review.setTaskId(task.getId());
|
|
|
|
|
|
|
|
review.setTaskKey(task.getTaskKey());
|
|
|
|
|
|
|
|
review.setTaskName(task.getTaskName());
|
|
|
|
|
|
|
|
review.setProjectName(task.getProjectName());
|
|
|
|
|
|
|
|
review.setProgressStatus(answer == null ? "NOT_STARTED" : answer.getProgressStatus());
|
|
|
|
|
|
|
|
review.setSubmitted(answer != null && Boolean.TRUE.equals(answer.getSubmitted()));
|
|
|
|
|
|
|
|
review.setAiAssessmentScore(answer == null ? null : answer.getAiAssessmentScore());
|
|
|
|
|
|
|
|
review.setTeacherScore(answer == null ? null : answer.getTeacherScore());
|
|
|
|
|
|
|
|
reviews.add(review);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return reviews;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Retained for existing direct controller tests; the HTTP route is the JWT-scoped overload above.
|
|
|
|
// Retained for existing direct controller tests; the HTTP route is the JWT-scoped overload above.
|
|
|
|
public void exportStuScore(HttpServletResponse response, String schoolId, String classId, String userName, String name) {
|
|
|
|
public void exportStuScore(HttpServletResponse response, String schoolId, String classId, String userName, String name) {
|
|
|
|
StuRankExample example = new StuRankExample();
|
|
|
|
StuRankExample example = new StuRankExample();
|
|
|
|
|