qirong
2023-06-26 77be36cc9077b09186e69440f3204f9e623c335a
src/main/java/com/mindskip/xzs/service/impl/ExamPaperServiceImpl.java
@@ -1,5 +1,6 @@
package com.mindskip.xzs.service.impl;
import com.mindskip.xzs.configuration.spring.exception.QuestionException;
import com.mindskip.xzs.domain.*;
import com.mindskip.xzs.domain.TextContent;
import com.mindskip.xzs.domain.enums.ExamPaperTypeEnum;
@@ -84,64 +85,24 @@
    @Override
    @Transactional
    public ExamPaper savePaperFromVM(ExamPaperEditRequestVM examPaperEditRequestVM, User user) {
    public ExamPaper savePaperFromVM(ExamPaperEditRequestVM examPaperEditRequestVM, User user) throws QuestionException {
        ActionEnum actionEnum = (examPaperEditRequestVM.getId() == null) ? ActionEnum.ADD : ActionEnum.UPDATE;
        Date now = new Date();
        if (examPaperEditRequestVM.getSubjectSource() != null) {
        List<ExamPaperTitleItemObject> frameTextContentList = new ArrayList<>();
        List<ExamPaperTitleItemVM> titleItemsVM = new ArrayList<>();
        //随机试卷
        if (examPaperEditRequestVM.getSubjectSource().size() != 0) {
//            Map<Integer, Integer> questionList = questionService.getAll().stream().collect(Collectors.toMap(Question::getId, Question::getScore));
            Map<Integer, Integer> subjectSource = examPaperEditRequestVM.getSubjectSource();
            //总数量
            Integer sum = subjectSource.values().stream().mapToInt(Integer::intValue).sum();
            Map<Integer, Integer> map = new HashMap<>();
            Integer avg = 0;
            for (Integer key : subjectSource.keySet()) {    // key:数量
                //该标签对应的分数   多选:3 判断:3 单选:4
                Integer source = examPaperEditRequestVM.getAggregateSource() * subjectSource.get(key) / sum;
                // 多选和判断数量
                Integer multipleNumber = key * 3 / 10;
                //多选和判断分数
                Integer multipleSource = source * 3 / 10;
                List<Integer> questions = questionSubjectService.getQuestion(key)
                        .stream().map(QuestionSubject::getQuestionId).collect(Collectors.toList());
                List<Question> list = questionService.selectByIds(questions);
                Map<Integer, Integer> multiple = new HashMap<>();
                //多选
                Map<Integer, Integer> multipleMap = list.stream()
                        .filter(e -> e.getQuestionType().equals(QuestionTypeEnum.MultipleChoice.getCode()))
                        .collect(Collectors.toMap(Question::getId, Question::getScore));
                selectRandomScores(multiple, multipleMap, multipleNumber, multipleSource);
                //判断
                Map<Integer, Integer> judgmentMap = list.stream()
                        .filter(e -> e.getQuestionType().equals(QuestionTypeEnum.TrueFalse.getCode()))
                        .collect(Collectors.toMap(Question::getId, Question::getScore));
                selectRandomScores(multiple, judgmentMap, multipleNumber, multipleSource);
                //单选数量
                Integer radioNumber = key - (2 * multipleNumber);
                //单选分数
                Integer radioSource = source - (2 * multipleSource);
                //单选
                Map<Integer, Integer> radioMap = list.stream()
                        .filter(e -> e.getQuestionType().equals(QuestionTypeEnum.SingleChoice.getCode()))
                        .collect(Collectors.toMap(Question::getId, Question::getScore));
                selectRandomScores(multiple, radioMap, radioNumber, radioSource);
                ExamPaperTitleItemObject examPaperTitleItemObject = new ExamPaperTitleItemObject();
                examPaperTitleItemObject.setName("测试001");
                Integer order = 0;
                List<ExamPaperQuestionItemObject> examPaperQuestionItemObjectList = new ArrayList<>();
                for (Integer k : multiple.keySet()) {
                    ExamPaperQuestionItemObject examPaperQuestionItemObject = new ExamPaperQuestionItemObject();
                    examPaperQuestionItemObject.setId(k);
                    examPaperQuestionItemObject.setItemOrder(order++);
                    examPaperQuestionItemObjectList.add(examPaperQuestionItemObject);
                }
                examPaperTitleItemObject.setQuestionItems(examPaperQuestionItemObjectList);
            }
            randomQuestion(examPaperEditRequestVM, frameTextContentList, titleItemsVM);
        }
        List<ExamPaperTitleItemVM> titleItemsVM = examPaperEditRequestVM.getTitleItems();
        List<ExamPaperTitleItemObject> frameTextContentList = frameTextContentFromVM(titleItemsVM);
        if (titleItemsVM.size() == 0) {
            titleItemsVM = examPaperEditRequestVM.getTitleItems();
        }
        if (frameTextContentList.size() == 0) {
            frameTextContentList = frameTextContentFromVM(titleItemsVM);
        }
        String frameTextContentStr = JsonUtil.toJsonStr(frameTextContentList);
        ExamPaper examPaper;
@@ -185,14 +146,18 @@
                        .map(q -> q.getId()))
                .collect(Collectors.toList());
        List<Question> questions = questionMapper.selectByIds(questionIds);
        Integer order = 0;
        Set<Integer> generatedNumbers = new HashSet<>();
        Random random = new Random();
        List<ExamPaperTitleItemVM> examPaperTitleItemVMS = examPaperTitleItemObjects.stream().map(t -> {
            ExamPaperTitleItemVM tTitleVM = modelMapper.map(t, ExamPaperTitleItemVM.class);
            List<QuestionEditRequestVM> questionItemsVM = t.getQuestionItems().stream().map(i -> {
                Question question = questions.stream().filter(q -> q.getId().equals(i.getId())).findFirst().get();
                QuestionEditRequestVM questionEditRequestVM = questionService.getQuestionEditRequestVM(question);
                questionEditRequestVM.setItemOrder(i.getItemOrder());
                return questionEditRequestVM;
            }).collect(Collectors.toList());
                        Question question = questions.stream().filter(q -> q.getId().equals(i.getId())).findFirst().get();
                        QuestionEditRequestVM questionEditRequestVM = questionService.getQuestionEditRequestVM(question);
                        questionEditRequestVM.setItemOrder(getRandomNumber(t.getQuestionItems().size() - 1, generatedNumbers, random));
                        return questionEditRequestVM;
                    }).sorted(Comparator.comparing(QuestionEditRequestVM::getItemOrder))
                    .collect(Collectors.toList());
            tTitleVM.setQuestionItems(questionItemsVM);
            return tTitleVM;
        }).collect(Collectors.toList());
@@ -239,6 +204,11 @@
        return examPaperMapper.removeByIds(ids);
    }
    @Override
    public List<ExamPaper> gets(Integer[] ids) {
        return examPaperMapper.gets(ids);
    }
    private void examPaperFromVM(ExamPaperEditRequestVM examPaperEditRequestVM, ExamPaper examPaper, List<ExamPaperTitleItemVM> titleItemsVM) {
//        Integer gradeLevel = subjectService.levelBySubjectId(examPaperEditRequestVM.getSubjectId());
        Integer questionCount = titleItemsVM.stream()
@@ -274,6 +244,9 @@
    }
    private void addExamPaperDepartment(ExamPaperEditRequestVM examPaperEditRequestVM, ExamPaper examPaper) {
        if(examPaperEditRequestVM.getDepartmentIds().length==0){
            return;
        }
        List<ExamPaperDepartment> list = Arrays.asList(examPaperEditRequestVM.getDepartmentIds()).stream().map(e -> {
            ExamPaperDepartment examPaperDepartment = new ExamPaperDepartment();
            examPaperDepartment.setExamPaperId(examPaper.getId());
@@ -295,21 +268,30 @@
        examPaperSubjectService.saves(subjectList);
    }
    public static void selectRandomScores(Map<Integer, Integer> result, Map<Integer, Integer> scoresMap, int quantity, int totalScore) {
//        Map<Integer, Integer> selectedScoresMap = new HashMap<>();
    /**
     * @param result
     * @param scoresMap
     * @param quantity
     * @param totalScore
     */
    public static void selectRandomScores(Map<Integer, Integer> result, Map<Integer, Integer> scoresMap, int quantity, int totalScore) throws QuestionException {
//        Map<String, Integer> selectedScoresMap = new HashMap<>();
        if (quantity <= 0 || totalScore <= 0 || scoresMap.isEmpty()) {
            return; // 返回空Map
        }
        List<Integer> keys = new ArrayList<>(scoresMap.keySet());
        List<Integer> values = new ArrayList<>(scoresMap.values());
        List<Integer> values = scoresMap.values().stream().map(e -> e = e / 10).collect(Collectors.toList());
        Random random = new Random();
        int remainingQuantity = quantity;
        int remainingScore = totalScore;
        for (int i = 0; i < quantity - 1; i++) {
            if (i >= scoresMap.size()) {
                throw new QuestionException();
            }
            int index = random.nextInt(values.size());
            int score = values.get(index);
@@ -325,9 +307,120 @@
        if (!values.isEmpty()) {
            int index = random.nextInt(values.size());
            int score = values.get(index);
            result.put(keys.get(index), remainingScore); // 最后一个分数为剩余的分数
            result.put(keys.get(index), score); // 最后一个分数为剩余的分数
        }
    }
    /**
     * 随机试卷
     *
     * @param examPaperEditRequestVM 传参
     * @param frameTextContentList
     * @param titleItemsVM           title
     */
    private void randomQuestion(ExamPaperEditRequestVM examPaperEditRequestVM, List<ExamPaperTitleItemObject> frameTextContentList, List<ExamPaperTitleItemVM> titleItemsVM) throws QuestionException {
        Map<Integer, Integer> subjectSource = examPaperEditRequestVM.getSubjectSource();
        //总数量
        Integer sum = subjectSource.values().stream().mapToInt(Integer::intValue).sum();
        Integer count = 0;
        Integer mark = 0;
        ExamPaperTitleItemObject examPaperTitleItemObject = new ExamPaperTitleItemObject();
        examPaperTitleItemObject.setName(examPaperEditRequestVM.getTitleItems().get(0).getName());
        ExamPaperTitleItemVM examPaperTitleItemVM = new ExamPaperTitleItemVM();
        //titleItemsVM
        examPaperTitleItemVM.setName(examPaperEditRequestVM.getTitleItems().get(0).getName());
        List<ExamPaperQuestionItemObject> examPaperQuestionItemObjectList = new ArrayList<>();
        List<QuestionEditRequestVM> questionItems = new ArrayList<>();
        Integer order = 0;
        for (Integer key : subjectSource.keySet()) {    // key:数量
            //该标签对应的分数   多选:3 判断:3 单选:4
            Integer source = 80 * subjectSource.get(key) / sum - mark;
            // 多选和判断数量
            Integer multipleNumber = (subjectSource.get(key) + count) * 3 / 10;
            //多选和判断分数
            Integer multipleSource = source * 3 / 10;
            List<Integer> questions = questionSubjectService.getSubject(key)
                    .stream().map(QuestionSubject::getQuestionId).collect(Collectors.toList());
            List<Question> list = questionService.selectByIds(questions);
            Map<Integer, Integer> multiple = new HashMap<>();
            //多选
            Map<Integer, Integer> multipleMap = list.stream()
                    .filter(e -> e.getQuestionType().equals(QuestionTypeEnum.MultipleChoice.getCode()))
                    .collect(Collectors.toMap(Question::getId, Question::getScore));
            selectRandomScores(multiple, multipleMap, multipleNumber < multipleMap.size() ? multipleNumber : multipleMap.size(), multipleSource);
            //判断
            Map<Integer, Integer> judgmentMap = list.stream()
                    .filter(e -> e.getQuestionType().equals(QuestionTypeEnum.TrueFalse.getCode()))
                    .collect(Collectors.toMap(Question::getId, Question::getScore));
            selectRandomScores(multiple, judgmentMap, multipleNumber < judgmentMap.size() ? multipleNumber : judgmentMap.size(), multipleSource);
            //单选数量
            Integer radioNumber = subjectSource.get(key) - multiple.size();
            //单选分数
            Integer radioSource = source - multiple.values().stream().mapToInt(Integer::intValue).sum();
            //单选
            Map<Integer, Integer> radioMap = list.stream()
                    .filter(e -> e.getQuestionType().equals(QuestionTypeEnum.SingleChoice.getCode()))
                    .collect(Collectors.toMap(Question::getId, Question::getScore));
            selectRandomScores(multiple, radioMap, radioNumber < radioMap.size() ? radioNumber : radioMap.size(), radioSource);
//            titleItemsVM.add(examPaperTitleItemVM);
            for (Integer k : multiple.keySet()) {
                ExamPaperQuestionItemObject examPaperQuestionItemObject = new ExamPaperQuestionItemObject();
                examPaperQuestionItemObject.setId(k);
                examPaperQuestionItemObject.setItemOrder(order++);
                examPaperQuestionItemObjectList.add(examPaperQuestionItemObject);
                //titleItemsVM
                QuestionEditRequestVM questionEditRequestVM = new QuestionEditRequestVM();
                questionEditRequestVM.setScore(multiple.get(k).toString());
                questionItems.add(questionEditRequestVM);
            }
            examPaperTitleItemObject.setQuestionItems(examPaperQuestionItemObjectList);
            //titleItemsVM
            examPaperTitleItemVM.setQuestionItems(questionItems);
            //数量 匹配
            count = multiple.size() != subjectSource.get(key) ? subjectSource.get(key) - multiple.size() : 0;
            //分数匹配
            mark = source != multiple.values().stream().mapToInt(Integer::intValue).sum() ? multiple.values().stream().mapToInt(Integer::intValue).sum() - source : 0;
        }
        frameTextContentList.add(examPaperTitleItemObject);
        titleItemsVM.add(examPaperTitleItemVM);
        if (count != 0 || mark != 0) {
            throw new QuestionException();
        }
    }
    public Integer getRandomNumber(Integer a, Set<Integer> generatedNumbers, Random random) {
        if (a <= 0) {
            throw new IllegalArgumentException("a必须为正整数");
        }
        int range = a + 1;
        if (generatedNumbers.size() >= range) {
            generatedNumbers.clear();  // 清空已生成的数字集合
        }
        int randomNumber;
        do {
            randomNumber = random.nextInt(range);
        } while (generatedNumbers.contains(randomNumber));
        generatedNumbers.add(randomNumber);
        return randomNumber;
    }
}