|
|
@@ -0,0 +1,171 @@
|
|
|
+package nju.seec.helper.api.bok;
|
|
|
+
|
|
|
+import com.fasterxml.jackson.annotation.JsonProperty;
|
|
|
+import com.google.common.collect.ImmutableMap;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.google.common.collect.Maps;
|
|
|
+import lombok.Data;
|
|
|
+import nju.seec.helper.dto.question.BaseQuestionDTO;
|
|
|
+import nju.seec.helper.dto.question.ChoiceQuestionDTO;
|
|
|
+import nju.seec.helper.dto.question.TrueOrFalseQuestionDTO;
|
|
|
+import nju.seec.helper.enums.ExceptionType;
|
|
|
+import nju.seec.helper.enums.QuestionType;
|
|
|
+import nju.seec.helper.exception.HelperException;
|
|
|
+import nju.seec.helper.util.Consts;
|
|
|
+import nju.seec.helper.util.RestRequestUtil;
|
|
|
+import nju.seec.helper.util.cache.GuavaCacheUtils;
|
|
|
+import nju.seec.helper.vo.question.BokQuestionVO;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.domain.Page;
|
|
|
+import org.springframework.data.domain.PageImpl;
|
|
|
+import org.springframework.data.domain.Pageable;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author xst
|
|
|
+ * <p>
|
|
|
+ * updated by cst
|
|
|
+ */
|
|
|
+@Component
|
|
|
+public class QuestionApi {
|
|
|
+ private final RestRequestUtil restRequestUtil;
|
|
|
+ private final GuavaCacheUtils cacheUtils;
|
|
|
+ @Value("${bok.tqUrl}")
|
|
|
+ private String tqUrl;
|
|
|
+ @Value("${bok.tqStemSearchUrl}")
|
|
|
+ private String tqStemSearchUrl;
|
|
|
+ @Value("${bok.tqIdSearchUrl}")
|
|
|
+ private String tqIdSearchUrl;
|
|
|
+
|
|
|
+ public QuestionApi(RestRequestUtil restRequestUtil, GuavaCacheUtils cacheUtils) {
|
|
|
+ this.restRequestUtil = restRequestUtil;
|
|
|
+ this.cacheUtils = cacheUtils;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Page<BokQuestionVO> bokFindByStemLike(String stem, Pageable pageable) {
|
|
|
+ Map<String, String> urlParams = ImmutableMap.of(
|
|
|
+ "content", stem,
|
|
|
+ "page", String.valueOf(1 + pageable.getPageNumber()),
|
|
|
+ "size", String.valueOf(pageable.getPageSize())
|
|
|
+ );
|
|
|
+ BokSearchResult result = restRequestUtil.sendGetRequest(tqStemSearchUrl, BokSearchResult.class, urlParams);
|
|
|
+
|
|
|
+ List<BokQuestionVO> bokQuestionVOList = result.getEmbedded().getQuestions();
|
|
|
+ cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, bokQuestionVOList.parallelStream().collect(Collectors.toMap(BokQuestionVO::getId, bokQuestion -> bokQuestion)));
|
|
|
+ return new PageImpl<>(bokQuestionVOList, pageable, result.getPage().getTotalElements());
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final String BOK_QUESTION_CACHE_NAME = Consts.SYS_NAME + "_bok_question";
|
|
|
+
|
|
|
+ @SuppressWarnings({"unchecked", "rawtypes"})
|
|
|
+ public List<BokQuestionVO> bokFindByIdIn(final List<String> ids) {
|
|
|
+ Map<String, BokQuestionVO> bokQuestionsMap = Maps.newHashMapWithExpectedSize(ids.size());
|
|
|
+
|
|
|
+ final Map<String, BokQuestionVO> cacheBokQuestionsMap = (Map) cacheUtils.multiGet(BOK_QUESTION_CACHE_NAME, ids);
|
|
|
+ bokQuestionsMap.putAll(cacheBokQuestionsMap);
|
|
|
+
|
|
|
+ List<String> requestIds = Lists.newArrayList(ids);
|
|
|
+ requestIds.removeAll(cacheBokQuestionsMap.keySet());
|
|
|
+ //未缓存的去这里拿
|
|
|
+ if (!requestIds.isEmpty()) {
|
|
|
+ Map<String, String> urlParams = ImmutableMap.of("id", requestIds.stream().reduce((a, b) -> a + "," + b).orElse(""));
|
|
|
+
|
|
|
+ BokSearchResult result = restRequestUtil.sendGetRequest(tqIdSearchUrl, BokSearchResult.class, urlParams);
|
|
|
+ List<BokQuestionVO> bokQuestionVOList = result.getEmbedded().getQuestions();
|
|
|
+
|
|
|
+ Map<String, BokQuestionVO> remoteBokQuestionsMap = bokQuestionVOList.parallelStream().collect(Collectors.toMap(BokQuestionVO::getId, bokQuestion -> bokQuestion));
|
|
|
+
|
|
|
+ bokQuestionsMap.putAll(remoteBokQuestionsMap);
|
|
|
+ cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, (Map) remoteBokQuestionsMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ids.stream()
|
|
|
+ .map(bokQuestionsMap::get)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ public BokQuestionVO bokFindById(String questionId) {
|
|
|
+ Object cachedBokQuestion = cacheUtils.get(BOK_QUESTION_CACHE_NAME, questionId);
|
|
|
+ if (cachedBokQuestion instanceof BokQuestionVO) {
|
|
|
+ return (BokQuestionVO) cachedBokQuestion;
|
|
|
+ }
|
|
|
+ BokQuestionVO bokQuestionVO = restRequestUtil.sendGetRequest(tqUrl + "/" + questionId, BokQuestionVO.class, Collections.emptyMap());
|
|
|
+ cacheUtils.set(BOK_QUESTION_CACHE_NAME, bokQuestionVO.getId(), bokQuestionVO);
|
|
|
+ return bokQuestionVO;
|
|
|
+ }
|
|
|
+
|
|
|
+ public BokQuestionVO createQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
|
|
|
+ BokQuestionVO bokQuestionVO = getQuestion(baseQuestionDTO);
|
|
|
+ bokQuestionVO.setId(questionId);
|
|
|
+ bokQuestionVO = restRequestUtil.sendPostRequest(tqUrl, bokQuestionVO, BokQuestionVO.class);
|
|
|
+ return bokQuestionVO;
|
|
|
+ }
|
|
|
+
|
|
|
+ public BokQuestionVO modifyQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
|
|
|
+ BokQuestionVO bokQuestionVO = getQuestion(baseQuestionDTO);
|
|
|
+ bokQuestionVO.setId(questionId);
|
|
|
+ restRequestUtil.sendPutRequest(tqUrl + "/" + questionId, bokQuestionVO);
|
|
|
+ return bokFindById(questionId);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void deleteQuestion(String questionId) {
|
|
|
+ restRequestUtil.sendDeleteRequest(tqUrl + "/" + questionId);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void starQuestion(String userId, String questionId) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private BokQuestionVO getQuestion(BaseQuestionDTO baseQuestionDTO) {
|
|
|
+ BokQuestionVO bokQuestionVO = new BokQuestionVO();
|
|
|
+ bokQuestionVO.setType(baseQuestionDTO.getType());
|
|
|
+ bokQuestionVO.setStem(baseQuestionDTO.getStem());
|
|
|
+ bokQuestionVO.setKeyPoints(baseQuestionDTO.getKeyPoints());
|
|
|
+ bokQuestionVO.setTags(baseQuestionDTO.getTags());
|
|
|
+ bokQuestionVO.setKnowledgeId(baseQuestionDTO.getKnowledgeId());
|
|
|
+
|
|
|
+ final QuestionType questionType = QuestionType.getQuestionType(baseQuestionDTO.getType());
|
|
|
+ switch (Objects.requireNonNull(questionType)) {
|
|
|
+ case CHOICE:
|
|
|
+ ChoiceQuestionDTO choiceQuestionDTO = (ChoiceQuestionDTO) baseQuestionDTO;
|
|
|
+ bokQuestionVO.setOptions(choiceQuestionDTO.getOptions());
|
|
|
+ bokQuestionVO.setAnswer(choiceQuestionDTO.getAnswer());
|
|
|
+ bokQuestionVO.setAnalysis(choiceQuestionDTO.getAnalysis());
|
|
|
+ break;
|
|
|
+ case TRUE_FALSE:
|
|
|
+ TrueOrFalseQuestionDTO trueOrFalseQuestionDTO = (TrueOrFalseQuestionDTO) baseQuestionDTO;
|
|
|
+ bokQuestionVO.setAnswer(String.valueOf(trueOrFalseQuestionDTO.getAnswer()));
|
|
|
+ bokQuestionVO.setAnalysis(trueOrFalseQuestionDTO.getAnalysis());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw HelperException.of(ExceptionType.ERROR, "不支持的题目类型");
|
|
|
+ }
|
|
|
+ return bokQuestionVO;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Data
|
|
|
+ private static class BokSearchResult {
|
|
|
+ @JsonProperty("_embedded")
|
|
|
+ private Embedded embedded = new Embedded();
|
|
|
+ private Page page;
|
|
|
+
|
|
|
+ @Data
|
|
|
+ private static class Embedded {
|
|
|
+ private List<BokQuestionVO> questions = Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Data
|
|
|
+ private static class Page {
|
|
|
+ private int size;
|
|
|
+ private int number;
|
|
|
+ private int totalPages;
|
|
|
+ private long totalElements;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|