|
|
@@ -212,7 +212,8 @@ public class LiveCompletionCouponServiceImpl implements ILiveCompletionCouponSer
|
|
|
throw new BaseException("未配置今日问题");
|
|
|
}
|
|
|
|
|
|
- boolean allCorrect = evaluateAnswers(param.getAnswers(), configuredQuestionIds);
|
|
|
+ List<LiveCompletionCouponAnswerItem> normalizedAnswers = normalizeUserAnswers(param.getAnswers());
|
|
|
+ boolean allCorrect = evaluateAnswers(normalizedAnswers, configuredQuestionIds);
|
|
|
saveAnswerRecordToday(liveId, userId, allCorrect);
|
|
|
|
|
|
LiveCompletionCouponAnswerResult result = new LiveCompletionCouponAnswerResult();
|
|
|
@@ -255,6 +256,81 @@ public class LiveCompletionCouponServiceImpl implements ILiveCompletionCouponSer
|
|
|
return couponUser;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 将 App 扁平选项格式归一为每题一条作答记录。
|
|
|
+ * <p>App 可能按「每个选项一条」提交(含 answerIndex / answerName / isAnswer),
|
|
|
+ * 而题库答案按选项文案存储,需合并后再校验。</p>
|
|
|
+ */
|
|
|
+ private List<LiveCompletionCouponAnswerItem> normalizeUserAnswers(List<LiveCompletionCouponAnswerItem> rawAnswers) {
|
|
|
+ if (rawAnswers == null || rawAnswers.isEmpty()) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean flatOptionFormat = rawAnswers.stream().anyMatch(a -> a.getIsAnswer() != null)
|
|
|
+ || rawAnswers.stream()
|
|
|
+ .filter(a -> a.getQuestionId() != null)
|
|
|
+ .collect(Collectors.groupingBy(LiveCompletionCouponAnswerItem::getQuestionId))
|
|
|
+ .values().stream().anyMatch(list -> list.size() > 1);
|
|
|
+ if (!flatOptionFormat) {
|
|
|
+ return rawAnswers;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, List<LiveCompletionCouponAnswerItem>> grouped = rawAnswers.stream()
|
|
|
+ .filter(a -> a.getQuestionId() != null)
|
|
|
+ .collect(Collectors.groupingBy(LiveCompletionCouponAnswerItem::getQuestionId));
|
|
|
+
|
|
|
+ List<Long> questionIds = new ArrayList<>(grouped.keySet());
|
|
|
+ Map<Long, LiveQuestionBank> questionMap = liveQuestionBankMapper.selectLiveQuestionBankByIds(questionIds)
|
|
|
+ .stream()
|
|
|
+ .collect(Collectors.toMap(LiveQuestionBank::getId, q -> q, (a, b) -> a));
|
|
|
+
|
|
|
+ List<LiveCompletionCouponAnswerItem> normalized = new ArrayList<>();
|
|
|
+ for (Map.Entry<Long, List<LiveCompletionCouponAnswerItem>> entry : grouped.entrySet()) {
|
|
|
+ Long questionId = entry.getKey();
|
|
|
+ List<LiveCompletionCouponAnswerItem> options = entry.getValue();
|
|
|
+
|
|
|
+ List<LiveCompletionCouponAnswerItem> selected = options.stream()
|
|
|
+ .filter(a -> a.getIsAnswer() != null && a.getIsAnswer() == 1)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ LiveCompletionCouponAnswerItem item = new LiveCompletionCouponAnswerItem();
|
|
|
+ item.setQuestionId(questionId);
|
|
|
+
|
|
|
+ if (selected.isEmpty()) {
|
|
|
+ if (options.size() == 1) {
|
|
|
+ item.setAnswer(resolveAnswerText(options.get(0)));
|
|
|
+ normalized.add(item);
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ LiveQuestionBank question = questionMap.get(questionId);
|
|
|
+ boolean multiChoice = question != null && question.getType() != null && question.getType() == 2L;
|
|
|
+
|
|
|
+ if (multiChoice) {
|
|
|
+ List<String> names = selected.stream()
|
|
|
+ .map(this::resolveAnswerText)
|
|
|
+ .filter(StringUtils::isNotEmpty)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ item.setAnswer(JSON.toJSONString(names));
|
|
|
+ } else {
|
|
|
+ item.setAnswer(resolveAnswerText(selected.get(0)));
|
|
|
+ }
|
|
|
+ normalized.add(item);
|
|
|
+ }
|
|
|
+ return normalized;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String resolveAnswerText(LiveCompletionCouponAnswerItem item) {
|
|
|
+ if (item == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(item.getAnswerName())) {
|
|
|
+ return item.getAnswerName().trim();
|
|
|
+ }
|
|
|
+ return StringUtils.isEmpty(item.getAnswer()) ? null : item.getAnswer().trim();
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 校验是否答完全部题目,并返回是否全部答对(答错不阻断记录)
|
|
|
*/
|