|
@@ -0,0 +1,331 @@
|
|
|
+package cn.com.qmth.dp.examcloud.oe.modules.update_correct_answer;
|
|
|
+
|
|
|
+import cn.com.qmth.dp.examcloud.oe.modules.update_correct_answer.entity.*;
|
|
|
+import cn.com.qmth.dp.examcloud.oe.modules.update_correct_answer.util.OKHttpUtil;
|
|
|
+import cn.com.qmth.dp.examcloud.oe.modules.update_correct_answer.util.QmthUtil;
|
|
|
+import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
|
+import cn.com.qmth.examcloud.commons.util.HttpMethod;
|
|
|
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
|
+import com.mongodb.client.result.UpdateResult;
|
|
|
+import com.mysql.cj.util.StringUtils;
|
|
|
+import okhttp3.Response;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.mongodb.core.MongoTemplate;
|
|
|
+import org.springframework.data.mongodb.core.query.Criteria;
|
|
|
+import org.springframework.data.mongodb.core.query.Query;
|
|
|
+import org.springframework.data.mongodb.core.query.Update;
|
|
|
+import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.text.DecimalFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Description 更新标准答案,并重新计算分数
|
|
|
+ * @Author lideyin
|
|
|
+ * @Date 2020/4/25 12:52
|
|
|
+ * @Version 1.0
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class FixCorrectAnswerAndResetScoreService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ JdbcTemplate jdbcTemplate;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ MongoTemplate mongoTemplate;
|
|
|
+
|
|
|
+ @Async
|
|
|
+ public void start(long examId, String courseCode) {
|
|
|
+ List<ExamRecordDataEntity> examRecordDataList = queryExamRecordDataList(examId, courseCode);
|
|
|
+
|
|
|
+ if (examRecordDataList.isEmpty()) {
|
|
|
+ throw new StatusException("100001", "找不到对应的考试记录");
|
|
|
+ }
|
|
|
+
|
|
|
+ //首先更新mongo中的作答记录
|
|
|
+ modifyMongoQuestionAnswer(examRecordDataList);
|
|
|
+
|
|
|
+ //重新计算分数并保存
|
|
|
+ modifyDbScore(examRecordDataList);
|
|
|
+
|
|
|
+ System.out.println("999.all is over.....");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void modifyDbScore(List<ExamRecordDataEntity> examRecordDataList) {
|
|
|
+ Set<Long> examStudentIdSet = new HashSet<>();
|
|
|
+ int effectiveNum = 0;//有效数量
|
|
|
+ //按考试记录更新分数表
|
|
|
+ for (ExamRecordDataEntity record : examRecordDataList) {
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(Criteria.where("_id").is(record.getExamRecordQuestionsId()));
|
|
|
+ ExamRecordQuestionsEntity erq = mongoTemplate.findOne(query, ExamRecordQuestionsEntity.class, "examRecordQuestions");
|
|
|
+ if (erq == null) continue;
|
|
|
+
|
|
|
+ List<ExamQuestionEntity> objectiveQuesList = erq.getExamQuestionEntities().stream()
|
|
|
+ .filter(p -> isObjectiveQues(p.getQuestionType())).collect(Collectors.toList());
|
|
|
+
|
|
|
+ double objectiveScore = calcTotalObjectiveScore(objectiveQuesList);
|
|
|
+ double objectiveAccuracy = calcTotalObjectiveAccuracy(objectiveQuesList);
|
|
|
+
|
|
|
+ updateExamScore(objectiveScore, objectiveAccuracy, record.getId());
|
|
|
+ System.out.println(String.format("2.更新第%d条分数成功---examRecordDataId=%s", ++effectiveNum, record.getId()));
|
|
|
+ examStudentIdSet.add(record.getExamStudentId());
|
|
|
+ }
|
|
|
+
|
|
|
+ int esNum = 0;
|
|
|
+ //按考生id,删除考生最终分数表(此表如果不存在数据,获取时,系统会重新计算)
|
|
|
+ for (Long estId : examStudentIdSet) {
|
|
|
+ deleteFinalScore(estId);
|
|
|
+ System.out.println(String.format("3.删除第%d条最终分数成功---examStudentId=%s", ++esNum, estId));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void deleteFinalScore(Long estId) {
|
|
|
+ String strSql = String.format("delete from ec_oe_exam_student_final_score where exam_student_id=%d ", estId);
|
|
|
+
|
|
|
+ jdbcTemplate.execute(strSql);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算客观题总分
|
|
|
+ *
|
|
|
+ * @param objectiveQuesList
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private double calcTotalObjectiveScore(List<ExamQuestionEntity> objectiveQuesList) {
|
|
|
+ double totalObjectiveScore = 0d;//客观题总分
|
|
|
+ for (ExamQuestionEntity eq : objectiveQuesList) {
|
|
|
+ totalObjectiveScore += eq.getStudentScore();
|
|
|
+ }
|
|
|
+
|
|
|
+ return totalObjectiveScore;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算客观题正确率
|
|
|
+ *
|
|
|
+ * @param objectiveQuesList
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private double calcTotalObjectiveAccuracy(List<ExamQuestionEntity> objectiveQuesList) {
|
|
|
+ double correctNum = 0d;
|
|
|
+ double totalNum = 0d;
|
|
|
+ for (ExamQuestionEntity eq : objectiveQuesList) {
|
|
|
+ if (!StringUtils.isNullOrEmpty(eq.getStudentAnswer())
|
|
|
+ && !StringUtils.isNullOrEmpty(eq.getCorrectAnswer())
|
|
|
+ && eq.getStudentAnswer().equals(eq.getCorrectAnswer())) {
|
|
|
+ correctNum += 1;
|
|
|
+ }
|
|
|
+ totalNum += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (totalNum == 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return Double.valueOf(new DecimalFormat("#.00").format(correctNum * 100D / totalNum));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新考试作答记录
|
|
|
+ *
|
|
|
+ * @param examRecordDataList
|
|
|
+ */
|
|
|
+ private void modifyMongoQuestionAnswer(List<ExamRecordDataEntity> examRecordDataList) {
|
|
|
+ int rubbishNum = 0;
|
|
|
+ int effectiveNum = 0;//有效数量
|
|
|
+ for (ExamRecordDataEntity record : examRecordDataList) {
|
|
|
+ try {
|
|
|
+ String examRecordQuestionsId = record.getExamRecordQuestionsId();
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(Criteria.where("_id").is(examRecordQuestionsId));
|
|
|
+ ExamRecordQuestionsEntity erq = mongoTemplate.findOne(query, ExamRecordQuestionsEntity.class, "examRecordQuestions");
|
|
|
+
|
|
|
+ if (erq == null) {
|
|
|
+ System.out.println(String.format("发现%d条垃圾数据:examRecordDataId=%s", ++rubbishNum, record.getId()));
|
|
|
+ continue;//垃圾数据
|
|
|
+ }
|
|
|
+
|
|
|
+ List<ExamQuestionEntity> examQuestionList = erq.getExamQuestionEntities();
|
|
|
+
|
|
|
+ //所有主观题的试题id集合
|
|
|
+ List<String> questionIdList = examQuestionList.stream()
|
|
|
+ .filter(p -> isObjectiveQues(p.getQuestionType()))
|
|
|
+ .map(ExamQuestionEntity::getQuestionId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+
|
|
|
+ for (String quesId : questionIdList) {
|
|
|
+ //最小维度的小题单元集合
|
|
|
+ List<ExamQuestionEntity> questionUnitList = examQuestionList.stream()
|
|
|
+ .filter(p -> p.getQuestionId().equals(quesId))
|
|
|
+ .sorted((o1, o2) -> o1.getOrder().intValue() - o2.getOrder().intValue())
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ //根据题目id获取正确答案集合
|
|
|
+ List<String> rightAnswerList = getRightAnswerList(quesId);
|
|
|
+
|
|
|
+ if (rightAnswerList == null) {
|
|
|
+ throw new StatusException("102003", String.format("找不到quesId=%s的答案数据", quesId));
|
|
|
+ }
|
|
|
+
|
|
|
+ //循环保存所有小题单元
|
|
|
+ for (int i = 0; i < questionUnitList.size(); i++) {
|
|
|
+ String rightAnswer = rightAnswerList.get(i);
|
|
|
+ ExamQuestionEntity curQues = questionUnitList.get(i);
|
|
|
+
|
|
|
+ updatePartialQuestionAnswer(examRecordQuestionsId, curQues.getOrder(),
|
|
|
+ rightAnswer, calcStudentUnitScore(rightAnswer, curQues));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println(String.format("1.更新第%d条作答记录成功---examRecordDataId=%s", ++effectiveNum, record.getId()));
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println(String.format("1.更新第%d条作答记录失败---examRecordDataId=%s", ++effectiveNum, record.getId()));
|
|
|
+ throw new StatusException("100002", e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算学生的小题得分
|
|
|
+ *
|
|
|
+ * @param rightAnswer
|
|
|
+ * @param curQues
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Double calcStudentUnitScore(String rightAnswer, ExamQuestionEntity curQues) {
|
|
|
+ String studentAnswer = curQues.getStudentAnswer();
|
|
|
+ Double studentUnitScore = 0D;
|
|
|
+ if (!StringUtils.isNullOrEmpty(rightAnswer)
|
|
|
+ && !(StringUtils.isNullOrEmpty(studentAnswer))
|
|
|
+ && rightAnswer.equals(studentAnswer)) {
|
|
|
+ studentUnitScore = curQues.getQuestionScore();
|
|
|
+ }
|
|
|
+ return studentUnitScore;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取题目正式答案
|
|
|
+ *
|
|
|
+ * @param quesId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<String> getRightAnswerList(String quesId) {
|
|
|
+// if (1 == 1) {
|
|
|
+// List<String> list = new ArrayList<>();
|
|
|
+// list.add("2");
|
|
|
+// list.add("2");
|
|
|
+// list.add("2");
|
|
|
+// list.add("2");
|
|
|
+// list.add("2");
|
|
|
+// list.add("2");
|
|
|
+// return list;
|
|
|
+// }
|
|
|
+
|
|
|
+ OuterGetQuestionAnswerReq reqBody = new OuterGetQuestionAnswerReq();
|
|
|
+ reqBody.setQuestionId(quesId);
|
|
|
+
|
|
|
+ String url = QmthUtil.buildUrl("/api/exchange/outer/question/getQuestionAnswer");
|
|
|
+ Response resp = null;
|
|
|
+ try {
|
|
|
+ resp = OKHttpUtil.call(HttpMethod.POST, url, QmthUtil.getSecurityHeaders(),
|
|
|
+ JsonUtil.toJson(reqBody));
|
|
|
+ if (resp.code() == 200) {
|
|
|
+ String resultJson = resp.body().string();
|
|
|
+ OuterGetQuestionAnswerResp outerGetQuestionAnswerResp = JsonUtil.fromJson(resultJson, OuterGetQuestionAnswerResp.class);
|
|
|
+
|
|
|
+ return outerGetQuestionAnswerResp.getAnswerList();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ throw new StatusException("102002", e.getMessage(), e);
|
|
|
+ } finally {
|
|
|
+ IOUtils.closeQuietly(resp);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否为主观题
|
|
|
+ *
|
|
|
+ * @param questionType
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean isObjectiveQues(String questionType) {
|
|
|
+ return "SINGLE_CHOICE".equals(questionType)
|
|
|
+ || "MULTIPLE_CHOICE".equals(questionType)
|
|
|
+ || "TRUE_OR_FALSE".equals(questionType);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<ExamRecordDataEntity> queryExamRecordDataList(Long examId, String courseCode) {
|
|
|
+ String strSql = String.format("SELECT " +
|
|
|
+ "t1.`id`, " +
|
|
|
+ "t1.`exam_student_id`, " +
|
|
|
+ "t1.exam_record_questions_id " +
|
|
|
+ "FROM " +
|
|
|
+ "ec_oe_exam_record_data t1 " +
|
|
|
+ "INNER JOIN ec_b_course t2 ON t1.course_id = t2.id " +
|
|
|
+ "WHERE " +
|
|
|
+ "t1.exam_id = %d " +
|
|
|
+ "AND t2.`code` ='%s' ", examId, courseCode);
|
|
|
+
|
|
|
+ java.util.List<Map<String, Object>> mapList = jdbcTemplate.queryForList(strSql);
|
|
|
+ java.util.List<ExamRecordDataEntity> resultList = new ArrayList<>();
|
|
|
+ for (Map<String, Object> map : mapList) {
|
|
|
+ ExamRecordDataEntity entity = new ExamRecordDataEntity();
|
|
|
+ if (map.get("id") != null) {
|
|
|
+ entity.setId(Long.valueOf(map.get("id").toString()));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (map.get("exam_student_id") != null) {
|
|
|
+ entity.setExamStudentId(Long.valueOf(map.get("exam_student_id").toString()));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (map.get("exam_record_questions_id") != null) {
|
|
|
+ entity.setExamRecordQuestionsId(map.get("exam_record_questions_id").toString());
|
|
|
+ }
|
|
|
+ resultList.add(entity);
|
|
|
+ }
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateExamScore(double objectiveScore, double objectiveAccuracy,
|
|
|
+ Long examRecordDataId) {
|
|
|
+ String strSql = String.format("UPDATE ec_oe_exam_score " +
|
|
|
+ "SET objective_score = %s, " +
|
|
|
+ "objective_accuracy = %s, " +
|
|
|
+ "total_score = objective_score+ IFNULL(subjective_score,0) " +
|
|
|
+ "WHERE " +
|
|
|
+ "exam_record_data_id = %d ", objectiveScore, objectiveAccuracy, examRecordDataId);
|
|
|
+
|
|
|
+ jdbcTemplate.execute(strSql);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新学生作答的部分数据
|
|
|
+ *
|
|
|
+ * @param examRecordQuestionsId
|
|
|
+ * @param order
|
|
|
+ * @param newAnswer
|
|
|
+ * @param studentScore
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public long updatePartialQuestionAnswer(String examRecordQuestionsId, Integer order, String newAnswer, Double studentScore) {
|
|
|
+ // 查询相应的题目
|
|
|
+ Query query = Query.query(Criteria.where("_id").is(examRecordQuestionsId)
|
|
|
+ .and("examQuestionEntities.order").is(order));
|
|
|
+ Update update = new Update();
|
|
|
+ update.set("examQuestionEntities.$.correctAnswer", newAnswer);
|
|
|
+ update.set("examQuestionEntities.$.studentScore", studentScore);
|
|
|
+
|
|
|
+ UpdateResult upResult = mongoTemplate.updateFirst(query, update, "examRecordQuestions");
|
|
|
+ return upResult.getMatchedCount();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|