update 处理主客观算法

develop
hhb@hotmail.com 1 month ago
parent c1ce2d0be6
commit 48c0351628

@ -148,7 +148,10 @@ public class LaborEducationServiceImpl implements LaborEducationService {
//获取所有课程下的课中活动
List<Exam> exams = new ArrayList<>();
if (!recordIds.isEmpty()) {
exams = examRepository.findExamsByIds(String.format(PK.EXAM, laborDto.getTmdId()), recordIds);
exams = examRepository.findExamsByIds(laborDto.getSource(),recordIds);
exams = exams.stream()
.filter(exam -> !exam.getClasses().isEmpty())
.collect(Collectors.toList());
}
Map<String, List<List<String>>> knowledgeMap = new HashMap<>();
Map<String, List<Double>> point = new HashMap<>();
@ -246,27 +249,7 @@ public class LaborEducationServiceImpl implements LaborEducationService {
}
// 2. 将知识点得分汇总到知识块级别
Map<String, Map<String, Double>> studentKnowledgeBlockScores = new HashMap<>();
for (Map.Entry<String, Map<String, Double>> entry : studentKnowledgePointScores.entrySet()) {
String studentId = entry.getKey();
Map<String, Double> pointScores = entry.getValue();
Map<String, Double> blockScores = studentKnowledgeBlockScores.computeIfAbsent(studentId, k -> new HashMap<>());
// 遍历知识块和知识点的映射关系
for (Map.Entry<String, List<String>> blockEntry : knowledgeBlockToPointsMap.entrySet()) {
String knowledgeBlock = blockEntry.getKey();
List<String> knowledgePoints = blockEntry.getValue();
// 计算该知识块的总得分
double totalScore = 0.0;
for (String knowledgePoint : knowledgePoints) {
if (pointScores.containsKey(knowledgePoint)) {
totalScore += pointScores.get(knowledgePoint);
}
}
blockScores.put(knowledgeBlock, totalScore);
}
}
Map<String, Map<String, Double>> studentKnowledgeBlockScores = getStringMapMap(knowledgeBlockToPointsMap, studentKnowledgePointScores);
// 3. 更新现有的 scores 返回数据
for (Map<String, Object> studentResult : scores) {
@ -293,46 +276,48 @@ public class LaborEducationServiceImpl implements LaborEducationService {
}
double maxCount = 50.0; // 最大次数(可根据实际情况调整)
// 将次数转换为 0-100 的分数
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 如果次数超过最大次数,设置为满分
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
convertedScore = (count / maxCount) * 100;
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
subjectiveTotal += convertedScore;
// 获取对应知识块的客观成绩
// 获取对应知识块的客观成绩并确保在60-100之间
double objectiveScore = knowledgeBlockScores.get(knowledgeBlock);
objectiveScore = Math.max(60.0, Math.min(100.0, objectiveScore)); // 确保60-100分
objectiveTotal += objectiveScore;
// 计算综合得分主观占60%客观占40%
score = convertedScore * 0.6 + objectiveScore * 0.4;
/*
/
String combinedScore = count + "/" + objectiveScore;
*/
double finalCount = convertedScore;
score = Double.parseDouble(String.format("%.2f", score));
// 存储结果
double finalConvertedScore = convertedScore;
double finalObjectiveScore = objectiveScore;
double finalScore = score;
finalScore = Double.parseDouble(String.format("%.2f", finalScore));
double finalScore1 = finalScore;
combinedScores.put(knowledgeBlock, new HashMap<String, Object>() {{
put("count", finalCount);
put("objectiveScore", objectiveScore);
put("compositeScore", finalScore1);
put("count", finalConvertedScore);
put("objectiveScore", finalObjectiveScore);
put("compositeScore", finalScore);
}});
//combinedScores.put(knowledgeBlock, objectiveScore);
}
// 计算客观平均分
double objectiveAverage = (knowledgeBlockCount > 0) ? objectiveTotal / knowledgeBlockCount : 0.0;
objectiveAverage = Double.parseDouble(String.format("%.2f", objectiveAverage));
//计算主观平均分
// 计算主观平均分
double subjectiveAverage = (subjectiveTotal > 0) ? subjectiveTotal / knowledgeBlockCount : 0.0;
subjectiveAverage = Double.parseDouble(String.format("%.2f", subjectiveAverage));
// 计算综合得分(主观占 60%,客观占 40%
// 计算综合得分(主观占60%客观占40%
double compositeScore = (subjectiveAverage * 0.6) + (objectiveAverage * 0.4);
compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));
@ -346,6 +331,37 @@ public class LaborEducationServiceImpl implements LaborEducationService {
return scores;
}
private static @NotNull Map<String, Map<String, Double>> getStringMapMap(Map<String, List<String>> knowledgeBlockToPointsMap, Map<String, Map<String, Double>> studentKnowledgePointScores) {
Map<String, Map<String, Double>> studentKnowledgeBlockScores = new HashMap<>();
for (Map.Entry<String, Map<String, Double>> entry : studentKnowledgePointScores.entrySet()) {
String studentId = entry.getKey();
Map<String, Double> pointScores = entry.getValue();
Map<String, Double> blockScores = studentKnowledgeBlockScores.computeIfAbsent(studentId, k -> new HashMap<>());
// 遍历知识块和知识点的映射关系
for (Map.Entry<String, List<String>> blockEntry : knowledgeBlockToPointsMap.entrySet()) {
String knowledgeBlock = blockEntry.getKey();
List<String> knowledgePoints = blockEntry.getValue();
// 计算该知识块的总得分和知识点数量
double totalScore = 0.0;
int validPointCount = 0; // 有效知识点数量(有实际得分的知识点)
for (String knowledgePoint : knowledgePoints) {
if (pointScores.containsKey(knowledgePoint)) {
totalScore += pointScores.get(knowledgePoint);
validPointCount++;
}
}
// 计算知识块的平均分
double averageScore = (validPointCount > 0) ? totalScore / validPointCount : 60.0; // 无有效知识点时默认60分
averageScore = Math.max(60.0, Math.min(100.0, averageScore)); // 确保得分在60-100之间
blockScores.put(knowledgeBlock, averageScore);
}
}
return studentKnowledgeBlockScores;
}
public static List<Map<String, Object>> calculateScoresWithDetails(List<RecordVo> res, Appraise appraise) {
// 1. 构建知识点到知识块的映射 (一个知识块对应多个知识点)
@ -392,7 +408,6 @@ public class LaborEducationServiceImpl implements LaborEducationService {
studentScores.putIfAbsent(studentKey, new HashMap<>());
Map<String, Integer> studentScoreMap = studentScores.get(studentKey);
// 计分
// 计分
int score = isPraise ? 1 : -1;
int currentScore = studentScoreMap.getOrDefault(knowledgeBlock, 0) + score;
@ -495,32 +510,47 @@ public class LaborEducationServiceImpl implements LaborEducationService {
String studentId, List<ExamClassResult> examResults,
Map<String, List<List<String>>> knowledgeMap, Appraise appraise, Map<String, List<Double>> points) {
Map<String, Double> knowledgeTotalScore = new HashMap<>();
// 计算学生的知识点得分率
List<KnowledgeScoreRate> studentScoreRates = calculateStudentScoreRates(studentId, examResults, knowledgeMap, points, knowledgeTotalScore);
// 查找知识点对应的节点及其父节点
Map<String, Double> parentNodeScoreRates = new HashMap<>();
Map<String, Integer> parentNodeScoreCount = new HashMap<>(); // 记录每个父节点的知识点数量
for (KnowledgeScoreRate scoreRate : studentScoreRates) {
AppraiseTreeNode node = findKnowledgeNode(appraise.getNodes(), scoreRate.getKnowledge());
if (node != null) {
AppraiseTreeNode parentNode = findParentNode(appraise.getNodes(), node.getId());
if (parentNode != null) {
double parentNodeScoreRate = calculateNodeScoreRate(parentNode, knowledgeTotalScore);
parentNodeScoreRates.put(parentNode.getName(), parentNodeScoreRate);
}else {
// 如果没有找到父节点初始化一个默认的得分率为0的父节点得分率
parentNodeScoreRates.put(node.getName(), 0.0);
// 累加父节点的得分
double currentScore = parentNodeScoreRates.getOrDefault(parentNode.getName(), 0.0);
parentNodeScoreRates.put(parentNode.getName(), currentScore + scoreRate.getScoreRate());
// 累加父节点的知识点数量
int currentCount = parentNodeScoreCount.getOrDefault(parentNode.getName(), 0);
parentNodeScoreCount.put(parentNode.getName(), currentCount + 1);
} else {
// 如果没有找到父节点,直接使用当前知识点的得分
parentNodeScoreRates.put(node.getName(), scoreRate.getScoreRate());
parentNodeScoreCount.put(node.getName(), 1);
}
}
}
// 计算父节点的平均得分
parentNodeScoreRates.replaceAll((parentNodeName, totalScore) -> {
int count = parentNodeScoreCount.getOrDefault(parentNodeName, 1);
double averageScore = totalScore / count;
return Math.min(100.0, Math.max(60.0, averageScore)); // 确保得分在60-100之间
});
// 初始化所有同层的父节点
for (AppraiseTreeNode node : appraise.getNodes()) {
if (node.getName().equals("德育")) {
for (AppraiseTreeNode child : node.getChildren()) {
if (!parentNodeScoreRates.containsKey(child.getName())) {
parentNodeScoreRates.put(child.getName(), 0.0);
parentNodeScoreRates.put(child.getName(), 60.0); // 默认60分
}
}
}
@ -617,6 +647,9 @@ public class LaborEducationServiceImpl implements LaborEducationService {
Map<String, Double> scoreRates = calculateKnowledgeScoreRateForStudent(
studentId, examResults, knowledgeMap, appraise, points
);
scoreRates.replaceAll((k, v) ->
Math.min(100.0, Math.max(60.0, v)) // 60分打底最高100分
);
studentScoreRates.put(name, scoreRates);
// 累加班级整体得分率
@ -625,21 +658,17 @@ public class LaborEducationServiceImpl implements LaborEducationService {
}
}
}
}else {
// 无考试数据时,初始化所有学生的默认分数为0
} else {
// 无考试数据时,初始化所有学生的默认分数为60
if (groupList != null) {
for (RMember member : groupList.members) {
String studentId = member.getId();
String studentName = studentIdToName.getOrDefault(studentId, "未知学生");
Map<String, Double> defaultScores = new HashMap<>();
for (String block : knowledgeBlocks) {
defaultScores.put(block, 0.0);
defaultScores.put(block, 60.0); // 初始化为60分
}
studentScoreRates.put(studentName, defaultScores);
// 初始化班级得分率
for (String block : knowledgeBlocks) {
classScoreRates.put(block, 0.0);
}
}
}
}
@ -659,11 +688,15 @@ public class LaborEducationServiceImpl implements LaborEducationService {
String block = entry.getKey();
int count = entry.getValue();
double maxCount = 50.0;
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 如果次数超过最大次数,设置为满分
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
convertedScore = (count / maxCount) * 100;
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
convertedScores.put(block, convertedScore);
@ -676,15 +709,23 @@ public class LaborEducationServiceImpl implements LaborEducationService {
Map<String, Map<String, Double>> compositeStudentScores = new HashMap<>();
for (String studentId : studentIdToName.keySet()) {
String studentName = studentIdToName.get(studentId);
// 获取客观分数已确保60-100分
Map<String, Double> objective = studentScoreRates.getOrDefault(studentName, new HashMap<>());
// 获取主观分数确保60-100分
Map<String, Double> subjective = subjectiveScores.getOrDefault(studentId, new HashMap<>());
Map<String, Double> compositeScores = new HashMap<>();
for (String block : knowledgeBlocks) {
double objectiveScore = objective.getOrDefault(block, 0.0);
double subjectiveScore = subjective.getOrDefault(block, 0.0);
// 客观分数兜底逻辑确保60分
double objectiveScore = objective.getOrDefault(block, 60.0);
// 主观分数兜底逻辑确保60分
double subjectiveScore = subjective.getOrDefault(block, 60.0);
// 计算综合得分主观60% + 客观40%
double compositeScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
compositeScore = Math.min(100.0, compositeScore); // 确保不超过100分
compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));
compositeScores.put(block, compositeScore);
}
compositeStudentScores.put(studentName, compositeScores);
@ -775,6 +816,20 @@ public class LaborEducationServiceImpl implements LaborEducationService {
Map<String, Double> knowledgeTotalAverage = new HashMap<>();
Map<String, Integer> knowledgeExamCount = new HashMap<>();
// 如果没有考试数据初始化所有知识点分数为60分
if (examResults == null || examResults.isEmpty()) {
for (String knowledge : knowledgeMap.values().stream()
.flatMap(List::stream)
.flatMap(List::stream)
.collect(Collectors.toSet())) {
knowledgeTotalScore.put(knowledge, 60.0); // 默认60分
}
return knowledgeTotalScore.entrySet().stream()
.map(entry -> new KnowledgeScoreRate(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
// 正常处理考试数据
for (ExamClassResult examResult : examResults) {
int studentIndex = examResult.getStudentIds().indexOf(studentId);
if (studentIndex == -1) continue;
@ -825,15 +880,29 @@ public class LaborEducationServiceImpl implements LaborEducationService {
}
}
// 计算最终平均分(所有考试平均分的平均)
// 计算最终平均分(所有考试平均分的平均)并限制在60-100分之间
for (String knowledge : knowledgeTotalAverage.keySet()) {
double totalAverage = knowledgeTotalAverage.get(knowledge);
int examCount = knowledgeExamCount.get(knowledge);
double finalAverage = totalAverage / examCount;
finalAverage = Double.parseDouble(String.format("%.2f", finalAverage));
// 确保分数在60-100之间
finalAverage = Math.max(60.0, Math.min(100.0, finalAverage)); // 60分打底不超过100分
finalAverage = Double.parseDouble(String.format("%.2f", finalAverage)); // 保留两位小数
knowledgeTotalScore.put(knowledge, finalAverage);
}
// 如果没有考试数据确保所有知识点都有默认60分
if (knowledgeTotalScore.isEmpty()) {
for (String knowledge : knowledgeMap.values().stream()
.flatMap(List::stream)
.flatMap(List::stream)
.collect(Collectors.toSet())) {
knowledgeTotalScore.put(knowledge, 60.0); // 默认60分
}
}
return knowledgeTotalScore.entrySet().stream()
.map(entry -> new KnowledgeScoreRate(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
@ -911,8 +980,17 @@ public class LaborEducationServiceImpl implements LaborEducationService {
String block = entry.getKey();
int count = entry.getValue();
double maxCount = 50.0;
double convertedScore = (count > maxCount) ? 100.0 : (count / maxCount) * 100;
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
convertedScores.put(block, convertedScore);
}
subjectiveScores.put(studentId, convertedScores);
@ -950,6 +1028,14 @@ public class LaborEducationServiceImpl implements LaborEducationService {
studentId, examResults, knowledgeMap, appraise, points
);
// 确保客观分数最低为60分
for (Map.Entry<String, Double> entry : studentObjectiveScores.entrySet()) {
String block = entry.getKey();
double score = entry.getValue();
score = Math.max(60.0, Math.min(100.0, score)); // 确保60-100分
studentObjectiveScores.put(block, score);
}
// 获取学生的主观分数
Map<String, Double> studentSubjectiveScores = subjectiveScores.getOrDefault(studentId, new HashMap<>());
@ -960,9 +1046,10 @@ public class LaborEducationServiceImpl implements LaborEducationService {
// 计算综合得分主观60%客观40%
for (String block : allBlocks) {
double objectiveScore = studentObjectiveScores.getOrDefault(block, 0.0);
double objectiveScore = studentObjectiveScores.getOrDefault(block, 60.0); // 默认60分
double subjectiveScore = studentSubjectiveScores.getOrDefault(block, 0.0);
double compositeScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
compositeScore = Math.max(60.0, Math.min(100.0, compositeScore)); // 确保60-100分
compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));
// 累加班级得分
@ -982,7 +1069,7 @@ public class LaborEducationServiceImpl implements LaborEducationService {
for (AppraiseTreeNode node : appraise.getNodes()) {
if ("德育".equals(node.getName())) {
node.getChildren().forEach(child ->
classScoresInner.putIfAbsent(child.getName(), 0.0));
classScoresInner.putIfAbsent(child.getName(), 60.0)); // 默认60分
}
}
@ -1007,7 +1094,7 @@ public class LaborEducationServiceImpl implements LaborEducationService {
for (AppraiseTreeNode node : appraise.getNodes()) {
if ("德育".equals(node.getName())) {
node.getChildren().forEach(child ->
gradeScores.putIfAbsent(child.getName(), 0.0));
gradeScores.putIfAbsent(child.getName(), 60.0)); // 默认60分
}
}
@ -1079,7 +1166,7 @@ public class LaborEducationServiceImpl implements LaborEducationService {
List<Map<String, Object>> subjectiveScoresList = calculateScoresWithDetails(res, appraise);
// 3. 将主观次数转换为0-100分数
Map<String, Map<String, Double>> subjectiveScores = new HashMap<>();
//Map<String, Map<String, Double>> subjectiveScores = new HashMap<>();
for (Map<String, Object> studentScore : subjectiveScoresList) {
String studentId = (String) studentScore.get("studentId");
@SuppressWarnings("unchecked")
@ -1090,17 +1177,21 @@ public class LaborEducationServiceImpl implements LaborEducationService {
String block = entry.getKey();
int count = entry.getValue();
double maxCount = 50.0;
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 如果次数超过最大次数,设置为满分
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
convertedScore = (count / maxCount) * 100;
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
convertedScores.put(block, convertedScore);
}
subjectiveScores.put(studentId, convertedScores);
//subjectiveScores.put(studentId, convertedScores);
}
// 4. 遍历所有年级
@ -1156,7 +1247,7 @@ public class LaborEducationServiceImpl implements LaborEducationService {
for (Map.Entry<String, Double> entry : schoolScores.entrySet()) {
String nodeName = entry.getKey();
double totalScore = entry.getValue();
int totalCount = gradeIds.size(); // 每个年级视为一个单位
int totalCount = schoolScores.size(); // 每个年级视为一个单位
schoolScores.put(nodeName, Double.parseDouble(String.format("%.2f", totalScore / totalCount))); // 保留小数点后两位
}
}
@ -1173,6 +1264,10 @@ public class LaborEducationServiceImpl implements LaborEducationService {
}
// 7. 转换 gradeScores 为新的数据结构
return getResult(gradeScores, schoolScores);
}
private static @NotNull Map<String, Object> getResult(Map<String, Map<String, Double>> gradeScores, Map<String, Double> schoolScores) {
List<Map<String, Object>> adjustedGradeScores = new ArrayList<>();
for (Map.Entry<String, Map<String, Double>> entry : gradeScores.entrySet()) {
String gradeName = entry.getKey();

@ -148,7 +148,10 @@ public class MoralEducationServiceImpl implements MoralEducationService {
//获取所有课程下的课中活动
List<Exam> exams = new ArrayList<>();
if (!recordIds.isEmpty()) {
exams = examRepository.findExamsByIds(String.format(PK.EXAM, laborDto.getTmdId()), recordIds);
exams = examRepository.findExamsByIds(laborDto.getSource(),recordIds);
exams = exams.stream()
.filter(exam -> !exam.getClasses().isEmpty())
.collect(Collectors.toList());
}
Map<String, List<List<String>>> knowledgeMap = new HashMap<>();
Map<String, List<Double>> point = new HashMap<>();
@ -246,27 +249,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
}
// 2. 将知识点得分汇总到知识块级别
Map<String, Map<String, Double>> studentKnowledgeBlockScores = new HashMap<>();
for (Map.Entry<String, Map<String, Double>> entry : studentKnowledgePointScores.entrySet()) {
String studentId = entry.getKey();
Map<String, Double> pointScores = entry.getValue();
Map<String, Double> blockScores = studentKnowledgeBlockScores.computeIfAbsent(studentId, k -> new HashMap<>());
// 遍历知识块和知识点的映射关系
for (Map.Entry<String, List<String>> blockEntry : knowledgeBlockToPointsMap.entrySet()) {
String knowledgeBlock = blockEntry.getKey();
List<String> knowledgePoints = blockEntry.getValue();
// 计算该知识块的总得分
double totalScore = 0.0;
for (String knowledgePoint : knowledgePoints) {
if (pointScores.containsKey(knowledgePoint)) {
totalScore += pointScores.get(knowledgePoint);
}
}
blockScores.put(knowledgeBlock, totalScore);
}
}
Map<String, Map<String, Double>> studentKnowledgeBlockScores = getStringMapMap(knowledgeBlockToPointsMap, studentKnowledgePointScores);
// 3. 更新现有的 scores 返回数据
for (Map<String, Object> studentResult : scores) {
@ -293,46 +276,48 @@ public class MoralEducationServiceImpl implements MoralEducationService {
}
double maxCount = 50.0; // 最大次数(可根据实际情况调整)
// 将次数转换为 0-100 的分数
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 如果次数超过最大次数,设置为满分
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
convertedScore = (count / maxCount) * 100;
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
subjectiveTotal += convertedScore;
// 获取对应知识块的客观成绩
// 获取对应知识块的客观成绩并确保在60-100之间
double objectiveScore = knowledgeBlockScores.get(knowledgeBlock);
objectiveScore = Math.max(60.0, Math.min(100.0, objectiveScore)); // 确保60-100分
objectiveTotal += objectiveScore;
// 计算综合得分主观占60%客观占40%
score = convertedScore * 0.6 + objectiveScore * 0.4;
/*
/
String combinedScore = count + "/" + objectiveScore;
*/
double finalCount = convertedScore;
score = Double.parseDouble(String.format("%.2f", score));
// 存储结果
double finalConvertedScore = convertedScore;
double finalObjectiveScore = objectiveScore;
double finalScore = score;
finalScore = Double.parseDouble(String.format("%.2f", finalScore));
double finalScore1 = finalScore;
combinedScores.put(knowledgeBlock, new HashMap<String, Object>() {{
put("count", finalCount);
put("objectiveScore", objectiveScore);
put("compositeScore", finalScore1);
put("count", finalConvertedScore);
put("objectiveScore", finalObjectiveScore);
put("compositeScore", finalScore);
}});
//combinedScores.put(knowledgeBlock, objectiveScore);
}
// 计算客观平均分
double objectiveAverage = (knowledgeBlockCount > 0) ? objectiveTotal / knowledgeBlockCount : 0.0;
objectiveAverage = Double.parseDouble(String.format("%.2f", objectiveAverage));
//计算主观平均分
// 计算主观平均分
double subjectiveAverage = (subjectiveTotal > 0) ? subjectiveTotal / knowledgeBlockCount : 0.0;
subjectiveAverage = Double.parseDouble(String.format("%.2f", subjectiveAverage));
// 计算综合得分(主观占 60%,客观占 40%
// 计算综合得分(主观占60%客观占40%
double compositeScore = (subjectiveAverage * 0.6) + (objectiveAverage * 0.4);
compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));
@ -346,6 +331,37 @@ public class MoralEducationServiceImpl implements MoralEducationService {
return scores;
}
private static @NotNull Map<String, Map<String, Double>> getStringMapMap(Map<String, List<String>> knowledgeBlockToPointsMap, Map<String, Map<String, Double>> studentKnowledgePointScores) {
Map<String, Map<String, Double>> studentKnowledgeBlockScores = new HashMap<>();
for (Map.Entry<String, Map<String, Double>> entry : studentKnowledgePointScores.entrySet()) {
String studentId = entry.getKey();
Map<String, Double> pointScores = entry.getValue();
Map<String, Double> blockScores = studentKnowledgeBlockScores.computeIfAbsent(studentId, k -> new HashMap<>());
// 遍历知识块和知识点的映射关系
for (Map.Entry<String, List<String>> blockEntry : knowledgeBlockToPointsMap.entrySet()) {
String knowledgeBlock = blockEntry.getKey();
List<String> knowledgePoints = blockEntry.getValue();
// 计算该知识块的总得分和知识点数量
double totalScore = 0.0;
int validPointCount = 0; // 有效知识点数量(有实际得分的知识点)
for (String knowledgePoint : knowledgePoints) {
if (pointScores.containsKey(knowledgePoint)) {
totalScore += pointScores.get(knowledgePoint);
validPointCount++;
}
}
// 计算知识块的平均分
double averageScore = (validPointCount > 0) ? totalScore / validPointCount : 60.0; // 无有效知识点时默认60分
averageScore = Math.max(60.0, Math.min(100.0, averageScore)); // 确保得分在60-100之间
blockScores.put(knowledgeBlock, averageScore);
}
}
return studentKnowledgeBlockScores;
}
public static List<Map<String, Object>> calculateScoresWithDetails(List<RecordVo> res, Appraise appraise) {
// 1. 构建知识点到知识块的映射 (一个知识块对应多个知识点)
@ -392,6 +408,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
studentScores.putIfAbsent(studentKey, new HashMap<>());
Map<String, Integer> studentScoreMap = studentScores.get(studentKey);
// 计分
// 计分
int score = isPraise ? 1 : -1;
int currentScore = studentScoreMap.getOrDefault(knowledgeBlock, 0) + score;
@ -449,7 +466,6 @@ public class MoralEducationServiceImpl implements MoralEducationService {
return result;
}
// 构建知识块到知识点的映射 (一个知识块对应多个知识点)
private static Map<String, List<String>> getKnowledgeBlockToPointsMap(Appraise appraise) {
Map<String, List<String>> knowledgeBlockToPointsMap = new HashMap<>();
@ -495,32 +511,47 @@ public class MoralEducationServiceImpl implements MoralEducationService {
String studentId, List<ExamClassResult> examResults,
Map<String, List<List<String>>> knowledgeMap, Appraise appraise, Map<String, List<Double>> points) {
Map<String, Double> knowledgeTotalScore = new HashMap<>();
// 计算学生的知识点得分率
List<KnowledgeScoreRate> studentScoreRates = calculateStudentScoreRates(studentId, examResults, knowledgeMap, points, knowledgeTotalScore);
// 计算学生的知识点得分率
List<LaborEducationServiceImpl.KnowledgeScoreRate> studentScoreRates = calculateStudentScoreRates(studentId, examResults, knowledgeMap, points, knowledgeTotalScore);
// 查找知识点对应的节点及其父节点
Map<String, Double> parentNodeScoreRates = new HashMap<>();
for (KnowledgeScoreRate scoreRate : studentScoreRates) {
Map<String, Integer> parentNodeScoreCount = new HashMap<>(); // 记录每个父节点的知识点数量
for (LaborEducationServiceImpl.KnowledgeScoreRate scoreRate : studentScoreRates) {
AppraiseTreeNode node = findKnowledgeNode(appraise.getNodes(), scoreRate.getKnowledge());
if (node != null) {
AppraiseTreeNode parentNode = findParentNode(appraise.getNodes(), node.getId());
if (parentNode != null) {
double parentNodeScoreRate = calculateNodeScoreRate(parentNode, knowledgeTotalScore);
parentNodeScoreRates.put(parentNode.getName(), parentNodeScoreRate);
}else {
// 如果没有找到父节点初始化一个默认的得分率为0的父节点得分率
parentNodeScoreRates.put(node.getName(), 0.0);
// 累加父节点的得分
double currentScore = parentNodeScoreRates.getOrDefault(parentNode.getName(), 0.0);
parentNodeScoreRates.put(parentNode.getName(), currentScore + scoreRate.getScoreRate());
// 累加父节点的知识点数量
int currentCount = parentNodeScoreCount.getOrDefault(parentNode.getName(), 0);
parentNodeScoreCount.put(parentNode.getName(), currentCount + 1);
} else {
// 如果没有找到父节点,直接使用当前知识点的得分
parentNodeScoreRates.put(node.getName(), scoreRate.getScoreRate());
parentNodeScoreCount.put(node.getName(), 1);
}
}
}
// 计算父节点的平均得分
parentNodeScoreRates.replaceAll((parentNodeName, totalScore) -> {
int count = parentNodeScoreCount.getOrDefault(parentNodeName, 1);
double averageScore = totalScore / count;
return Math.min(100.0, Math.max(60.0, averageScore)); // 确保得分在60-100之间
});
// 初始化所有同层的父节点
for (AppraiseTreeNode node : appraise.getNodes()) {
if (node.getName().equals("劳育")) {
for (AppraiseTreeNode child : node.getChildren()) {
if (!parentNodeScoreRates.containsKey(child.getName())) {
parentNodeScoreRates.put(child.getName(), 0.0);
parentNodeScoreRates.put(child.getName(), 60.0); // 默认60分
}
}
}
@ -617,6 +648,9 @@ public class MoralEducationServiceImpl implements MoralEducationService {
Map<String, Double> scoreRates = calculateKnowledgeScoreRateForStudent(
studentId, examResults, knowledgeMap, appraise, points
);
scoreRates.replaceAll((k, v) ->
Math.min(100.0, Math.max(60.0, v)) // 60分打底最高100分
);
studentScoreRates.put(name, scoreRates);
// 累加班级整体得分率
@ -625,21 +659,17 @@ public class MoralEducationServiceImpl implements MoralEducationService {
}
}
}
}else {
// 无考试数据时,初始化所有学生的默认分数为0
} else {
// 无考试数据时,初始化所有学生的默认分数为60
if (groupList != null) {
for (RMember member : groupList.members) {
String studentId = member.getId();
String studentName = studentIdToName.getOrDefault(studentId, "未知学生");
Map<String, Double> defaultScores = new HashMap<>();
for (String block : knowledgeBlocks) {
defaultScores.put(block, 0.0);
defaultScores.put(block, 60.0); // 初始化为60分
}
studentScoreRates.put(studentName, defaultScores);
// 初始化班级得分率
for (String block : knowledgeBlocks) {
classScoreRates.put(block, 0.0);
}
}
}
}
@ -659,11 +689,15 @@ public class MoralEducationServiceImpl implements MoralEducationService {
String block = entry.getKey();
int count = entry.getValue();
double maxCount = 50.0;
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 如果次数超过最大次数,设置为满分
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
convertedScore = (count / maxCount) * 100;
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
convertedScores.put(block, convertedScore);
@ -676,15 +710,23 @@ public class MoralEducationServiceImpl implements MoralEducationService {
Map<String, Map<String, Double>> compositeStudentScores = new HashMap<>();
for (String studentId : studentIdToName.keySet()) {
String studentName = studentIdToName.get(studentId);
// 获取客观分数已确保60-100分
Map<String, Double> objective = studentScoreRates.getOrDefault(studentName, new HashMap<>());
// 获取主观分数确保60-100分
Map<String, Double> subjective = subjectiveScores.getOrDefault(studentId, new HashMap<>());
Map<String, Double> compositeScores = new HashMap<>();
for (String block : knowledgeBlocks) {
double objectiveScore = objective.getOrDefault(block, 0.0);
double subjectiveScore = subjective.getOrDefault(block, 0.0);
// 客观分数兜底逻辑确保60分
double objectiveScore = objective.getOrDefault(block, 60.0);
// 主观分数兜底逻辑确保60分
double subjectiveScore = subjective.getOrDefault(block, 60.0);
// 计算综合得分主观60% + 客观40%
double compositeScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
compositeScore = Math.min(100.0, compositeScore); // 确保不超过100分
compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));
compositeScores.put(block, compositeScore);
}
compositeStudentScores.put(studentName, compositeScores);
@ -765,7 +807,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
}
private static List<KnowledgeScoreRate> calculateStudentScoreRates(
private static List<LaborEducationServiceImpl.KnowledgeScoreRate> calculateStudentScoreRates(
String studentId,
List<ExamClassResult> examResults,
Map<String, List<List<String>>> knowledgeMap,
@ -775,6 +817,20 @@ public class MoralEducationServiceImpl implements MoralEducationService {
Map<String, Double> knowledgeTotalAverage = new HashMap<>();
Map<String, Integer> knowledgeExamCount = new HashMap<>();
// 如果没有考试数据初始化所有知识点分数为60分
if (examResults == null || examResults.isEmpty()) {
for (String knowledge : knowledgeMap.values().stream()
.flatMap(List::stream)
.flatMap(List::stream)
.collect(Collectors.toSet())) {
knowledgeTotalScore.put(knowledge, 60.0); // 默认60分
}
return knowledgeTotalScore.entrySet().stream()
.map(entry -> new LaborEducationServiceImpl.KnowledgeScoreRate(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
// 正常处理考试数据
for (ExamClassResult examResult : examResults) {
int studentIndex = examResult.getStudentIds().indexOf(studentId);
if (studentIndex == -1) continue;
@ -825,17 +881,31 @@ public class MoralEducationServiceImpl implements MoralEducationService {
}
}
// 计算最终平均分(所有考试平均分的平均)
// 计算最终平均分(所有考试平均分的平均)并限制在60-100分之间
for (String knowledge : knowledgeTotalAverage.keySet()) {
double totalAverage = knowledgeTotalAverage.get(knowledge);
int examCount = knowledgeExamCount.get(knowledge);
double finalAverage = totalAverage / examCount;
finalAverage = Double.parseDouble(String.format("%.2f", finalAverage));
// 确保分数在60-100之间
finalAverage = Math.max(60.0, Math.min(100.0, finalAverage)); // 60分打底不超过100分
finalAverage = Double.parseDouble(String.format("%.2f", finalAverage)); // 保留两位小数
knowledgeTotalScore.put(knowledge, finalAverage);
}
// 如果没有考试数据确保所有知识点都有默认60分
if (knowledgeTotalScore.isEmpty()) {
for (String knowledge : knowledgeMap.values().stream()
.flatMap(List::stream)
.flatMap(List::stream)
.collect(Collectors.toSet())) {
knowledgeTotalScore.put(knowledge, 60.0); // 默认60分
}
}
return knowledgeTotalScore.entrySet().stream()
.map(entry -> new KnowledgeScoreRate(entry.getKey(), entry.getValue()))
.map(entry -> new LaborEducationServiceImpl.KnowledgeScoreRate(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
@ -911,8 +981,17 @@ public class MoralEducationServiceImpl implements MoralEducationService {
String block = entry.getKey();
int count = entry.getValue();
double maxCount = 50.0;
double convertedScore = (count > maxCount) ? 100.0 : (count / maxCount) * 100;
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
convertedScores.put(block, convertedScore);
}
subjectiveScores.put(studentId, convertedScores);
@ -950,6 +1029,14 @@ public class MoralEducationServiceImpl implements MoralEducationService {
studentId, examResults, knowledgeMap, appraise, points
);
// 确保客观分数最低为60分
for (Map.Entry<String, Double> entry : studentObjectiveScores.entrySet()) {
String block = entry.getKey();
double score = entry.getValue();
score = Math.max(60.0, Math.min(100.0, score)); // 确保60-100分
studentObjectiveScores.put(block, score);
}
// 获取学生的主观分数
Map<String, Double> studentSubjectiveScores = subjectiveScores.getOrDefault(studentId, new HashMap<>());
@ -960,9 +1047,10 @@ public class MoralEducationServiceImpl implements MoralEducationService {
// 计算综合得分主观60%客观40%
for (String block : allBlocks) {
double objectiveScore = studentObjectiveScores.getOrDefault(block, 0.0);
double objectiveScore = studentObjectiveScores.getOrDefault(block, 60.0); // 默认60分
double subjectiveScore = studentSubjectiveScores.getOrDefault(block, 0.0);
double compositeScore = (subjectiveScore * 0.6) + (objectiveScore * 0.4);
compositeScore = Math.max(60.0, Math.min(100.0, compositeScore)); // 确保60-100分
compositeScore = Double.parseDouble(String.format("%.2f", compositeScore));
// 累加班级得分
@ -982,7 +1070,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
for (AppraiseTreeNode node : appraise.getNodes()) {
if ("劳育".equals(node.getName())) {
node.getChildren().forEach(child ->
classScoresInner.putIfAbsent(child.getName(), 0.0));
classScoresInner.putIfAbsent(child.getName(), 60.0)); // 默认60分
}
}
@ -1007,7 +1095,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
for (AppraiseTreeNode node : appraise.getNodes()) {
if ("劳育".equals(node.getName())) {
node.getChildren().forEach(child ->
gradeScores.putIfAbsent(child.getName(), 0.0));
gradeScores.putIfAbsent(child.getName(), 60.0)); // 默认60分
}
}
@ -1079,7 +1167,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
List<Map<String, Object>> subjectiveScoresList = calculateScoresWithDetails(res, appraise);
// 3. 将主观次数转换为0-100分数
Map<String, Map<String, Double>> subjectiveScores = new HashMap<>();
//Map<String, Map<String, Double>> subjectiveScores = new HashMap<>();
for (Map<String, Object> studentScore : subjectiveScoresList) {
String studentId = (String) studentScore.get("studentId");
@SuppressWarnings("unchecked")
@ -1090,17 +1178,21 @@ public class MoralEducationServiceImpl implements MoralEducationService {
String block = entry.getKey();
int count = entry.getValue();
double maxCount = 50.0;
// 将次数转换为 60-100 的分数60分基础额外加分不超过40分
double convertedScore;
if (count > maxCount) {
convertedScore = 100.0; // 如果次数超过最大次数,设置为满分
convertedScore = 100.0; // 超过最大次数,直接满分
} else {
convertedScore = (count / maxCount) * 100;
// 计算额外加分占总40分的比例
double additionalScore = (count / maxCount) * 40;
convertedScore = 60 + additionalScore;
// 保留两位小数
convertedScore = Double.parseDouble(String.format("%.2f", convertedScore));
}
convertedScores.put(block, convertedScore);
}
subjectiveScores.put(studentId, convertedScores);
//subjectiveScores.put(studentId, convertedScores);
}
// 4. 遍历所有年级
@ -1156,7 +1248,7 @@ public class MoralEducationServiceImpl implements MoralEducationService {
for (Map.Entry<String, Double> entry : schoolScores.entrySet()) {
String nodeName = entry.getKey();
double totalScore = entry.getValue();
int totalCount = gradeIds.size(); // 每个年级视为一个单位
int totalCount = schoolScores.size(); // 每个年级视为一个单位
schoolScores.put(nodeName, Double.parseDouble(String.format("%.2f", totalScore / totalCount))); // 保留小数点后两位
}
}
@ -1173,6 +1265,10 @@ public class MoralEducationServiceImpl implements MoralEducationService {
}
// 7. 转换 gradeScores 为新的数据结构
return getResult(gradeScores, schoolScores);
}
private static @NotNull Map<String, Object> getResult(Map<String, Map<String, Double>> gradeScores, Map<String, Double> schoolScores) {
List<Map<String, Object>> adjustedGradeScores = new ArrayList<>();
for (Map.Entry<String, Map<String, Double>> entry : gradeScores.entrySet()) {
String gradeName = entry.getKey();

@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author winter
@ -75,8 +76,8 @@ public class AppraiseController {
@PostMapping("findVoteRecord")
@ApiOperation(value = "多条件查询当前登录老师的学生评价(投票)")
public R<List<AppraiseRecordVo>> findMyVoteRecord(@Valid @RequestBody FindVoteRecordDto findVoteRecordDto, HttpServletRequest request) {
List<AppraiseRecordVo> res = evaluationService.findVoteRecord(findVoteRecordDto,request);
public R<Map<String, Object>> findMyVoteRecord(@Valid @RequestBody FindVoteRecordDto findVoteRecordDto, HttpServletRequest request) {
Map<String, Object> res = evaluationService.findVoteRecord(findVoteRecordDto,request);
return R.success(res);
}

@ -24,4 +24,5 @@ public class LaborDto {
public String semesterId;
private String academicYearId;
private String classId;
private String source = "1";
}

@ -16,6 +16,6 @@ public interface ExamRepository extends CosmosRepository<Exam, String> {
List<Exam> findExamByClassId(String code,String classId,String periodId,String subjectId);
@Query("select * from Exam as s where s.code = @code and s.id = @id")
List<Exam> findExamById(@Param("code")String code, @Param("id")String id);
@Query("select s.id,s.name,s.average,s.classes,s.stuCount,s.createTime,s.papers from Exam as s where s.code = @code and s.lessonRecordId in (@ids)")
List<Exam> findExamsByIds(String code, Collection<String> ids);
@Query("select s.id,s.name,s.average,s.classes,s.stuCount,s.createTime,s.papers from Exam as s where s.source = @source and s.lessonRecordId in (@ids)")
List<Exam> findExamsByIds(String source, Collection<String> ids);
}

@ -12,6 +12,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author winter
@ -55,7 +56,7 @@ public interface EvaluationService {
*/
void vote(AppraiseVoteDto appraiseVoteDto);
List<AppraiseRecordVo> findVoteRecord(FindVoteRecordDto findVoteRecordDto, HttpServletRequest request);
Map<String, Object> findVoteRecord(FindVoteRecordDto findVoteRecordDto, HttpServletRequest request);
void recallVote(RecallVoteDto recallVoteDto);

@ -435,7 +435,7 @@ public class EvaluationServiceImpl implements EvaluationService {
}
@Override
public List<AppraiseRecordVo> findVoteRecord(FindVoteRecordDto findVoteRecordDto, HttpServletRequest request) {
public Map<String, Object> findVoteRecord(FindVoteRecordDto findVoteRecordDto, HttpServletRequest request) {
String periodId = findVoteRecordDto.getPeriodId();
String targetId = StringUtils.isBlank(findVoteRecordDto.getTargetId()) ? null : findVoteRecordDto.getTargetId();
String targetType = StringUtils.isBlank(findVoteRecordDto.getTargetType()) ? null : findVoteRecordDto.getTargetType();
@ -445,6 +445,7 @@ public class EvaluationServiceImpl implements EvaluationService {
String teacherId = loginUser.getId();
String schoolId = loginUser.getSchoolId();
Map<String, Object> params = new HashMap<>();
List<School.Semester> semesters = schoolRepository.findSemestersById(schoolId, periodId);
String academicYearId = SchoolDateUtil.calculateAcademicYearId(semesters, LocalDate.now());
// 分页
@ -462,6 +463,7 @@ public class EvaluationServiceImpl implements EvaluationService {
);
List<AppraiseRecordVo> content = appraiseRecordItemPage.getContent();
long total = appraiseRecordItemPage.getTotalElements(); // 获取总数
//提取学生ID 查询学生个人信息
Set<String> studentIds = content.stream().map(AppraiseRecordVo::getTargetId).collect(Collectors.toSet());
if (studentIds.isEmpty()) throw new ServiceException(ErrorCode.PARAM_ERROR.getCode(), "没有对应学生信息");
@ -497,7 +499,9 @@ public class EvaluationServiceImpl implements EvaluationService {
appraiseRecordVo.setClassName(classInfo.getName());
});
}
return content;
params.put("total", total);
params.put("content", content);
return params;
}
@Override

Loading…
Cancel
Save