|
|
@ -2,19 +2,19 @@ package com.ccsens.braintraining.service; |
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollectionUtil; |
|
|
|
import cn.hutool.core.lang.Snowflake; |
|
|
|
import cn.hutool.core.util.StrUtil; |
|
|
|
import com.alibaba.fastjson.JSONArray; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.ccsens.braintraining.bean.dto.BrainDto; |
|
|
|
import com.ccsens.braintraining.bean.po.*; |
|
|
|
import com.ccsens.braintraining.bean.vo.BrainVo; |
|
|
|
import com.ccsens.braintraining.bean.vo.RuleGenerateVo; |
|
|
|
import com.ccsens.braintraining.bean.vo.RuleScoreVo; |
|
|
|
import com.ccsens.braintraining.persist.dao.BrainDao; |
|
|
|
import com.ccsens.braintraining.persist.mapper.TrainActiveLogMapper; |
|
|
|
import com.ccsens.braintraining.persist.mapper.TrainActiveMapper; |
|
|
|
import com.ccsens.braintraining.persist.mapper.TrainActiveScoreMapper; |
|
|
|
import com.ccsens.braintraining.persist.mapper.TrainActiveUserMapper; |
|
|
|
import com.ccsens.braintraining.persist.mapper.*; |
|
|
|
import com.ccsens.braintraining.util.BrainTrainingCodeError; |
|
|
|
import com.ccsens.braintraining.util.BrainTrainingConstant; |
|
|
|
import com.ccsens.util.RedisUtil; |
|
|
|
import com.ccsens.util.exception.BaseException; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
@ -22,9 +22,8 @@ import org.springframework.transaction.annotation.Propagation; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
|
|
|
|
import javax.annotation.Resource; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Random; |
|
|
|
import java.math.BigDecimal; |
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: |
|
|
@ -38,15 +37,21 @@ public class BrainService implements IBrainService { |
|
|
|
@Resource |
|
|
|
private Snowflake snowflake; |
|
|
|
@Resource |
|
|
|
private RedisUtil redisUtil; |
|
|
|
@Resource |
|
|
|
private BrainDao brainDao; |
|
|
|
@Resource |
|
|
|
private TrainActiveMapper trainActiveMapper; |
|
|
|
@Resource |
|
|
|
private TrainActiveUserMapper trainActiveUserMapper; |
|
|
|
@Resource |
|
|
|
private TrainActiveScoreMapper trainActiveScoreMapper; |
|
|
|
private TrainActiveQuestionMapper trainActiveQuestionMapper; |
|
|
|
@Resource |
|
|
|
private TrainActiveLogMapper trainActiveLogMapper; |
|
|
|
@Resource |
|
|
|
private TrainRuleScoreMapper trainRuleScoreMapper; |
|
|
|
@Resource |
|
|
|
private TrainClassifyMapper trainClassifyMapper; |
|
|
|
|
|
|
|
@Override |
|
|
|
public BrainVo.Active generateTest(BrainDto.Equipment param, Long userId) { |
|
|
@ -75,18 +80,17 @@ public class BrainService implements IBrainService { |
|
|
|
trainActiveUserMapper.insertSelective(activeUser); |
|
|
|
// 遍历规则,查询试题
|
|
|
|
List<TrainActiveQuestion> questions = new ArrayList<>(); |
|
|
|
rules.forEach(rule -> generateQuestion(userId, active, questions, rule)); |
|
|
|
rules.forEach(rule -> generateQuestion(activeUser.getId(), questions, rule)); |
|
|
|
// 批量添加题库内容
|
|
|
|
if (CollectionUtil.isNotEmpty(questions)) { |
|
|
|
log.info("批量生成活动题目"); |
|
|
|
brainDao.batchInsertActiveQuestion(questions); |
|
|
|
} |
|
|
|
return new BrainVo.Active(active.getId(), rules); |
|
|
|
return new BrainVo.Active(activeUser.getId(), rules); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public BrainVo.QuestionClassify queryByClassify(BrainDto.Question param, Long userId) { |
|
|
|
long now = System.currentTimeMillis(); |
|
|
|
// 判断是否已经做过
|
|
|
|
Integer score = brainDao.getScore(param.getActiveUserId(), param.getClassifyId()); |
|
|
|
log.info("参数:{},{},分数:{}", param.getActiveUserId(), param.getClassifyId(), score); |
|
|
@ -107,33 +111,433 @@ public class BrainService implements IBrainService { |
|
|
|
return question; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void saveAnswer(BrainDto.Answer param, Long userId) { |
|
|
|
Long now = System.currentTimeMillis(); |
|
|
|
if (CollectionUtil.isEmpty(param.getQuestions())) { |
|
|
|
log.info("保存答案时没有保存题目的信息"); |
|
|
|
throw new BaseException(BrainTrainingCodeError.PARAM_ERROR); |
|
|
|
} |
|
|
|
// 判断有无正在进行的分数保存
|
|
|
|
String key = StrUtil.format(BrainTrainingConstant.Train.REDIS_SAVE_ANSWER, param.getActiveUserId(), param.getClassifyId(), param.getQuestions().get(0).getQuestionId()); |
|
|
|
Object o = redisUtil.get(key); |
|
|
|
if (o != null) { |
|
|
|
throw new BaseException(BrainTrainingCodeError.BRAIN_ACTIVE_QUESTION_ANSWER_SAVING); |
|
|
|
} |
|
|
|
// 存储当前正在进行的题目
|
|
|
|
redisUtil.set(key, param.getActiveUserId(), BrainTrainingConstant.Train.REDIS_TIME_DEFAULT); |
|
|
|
try { |
|
|
|
// 判断是否已经做过
|
|
|
|
Integer score = brainDao.getScore(param.getActiveUserId(), param.getClassifyId()); |
|
|
|
log.info("参数:{},{},分数:{}", param.getActiveUserId(), param.getClassifyId(), score); |
|
|
|
if (score != null) { |
|
|
|
throw new BaseException(BrainTrainingCodeError.BRAIN_ACTIVE_QUESTION_ANSWER_YES); |
|
|
|
} |
|
|
|
// 查询分类
|
|
|
|
TrainClassify classify = trainClassifyMapper.selectByPrimaryKey(param.getClassifyId()); |
|
|
|
if (classify == null) { |
|
|
|
throw new BaseException(BrainTrainingCodeError.PARAM_ERROR); |
|
|
|
} |
|
|
|
// 后续使用的参数处理
|
|
|
|
List<BrainDto.QuestionAnswer> answerParams = new ArrayList<>(); |
|
|
|
List<TrainActiveLog> logs = new ArrayList<>(); |
|
|
|
List<TrainActiveQuestion> activeQuestions = new ArrayList<>(); |
|
|
|
initNeedData(classify, param, userId, answerParams, logs, activeQuestions); |
|
|
|
|
|
|
|
// 查询用户活动信息
|
|
|
|
TrainActiveUser activeUser = trainActiveUserMapper.selectByPrimaryKey(param.getActiveUserId()); |
|
|
|
if (activeUser == null) { |
|
|
|
log.info("没有找到用户活动信息:{}", param.getActiveUserId()); |
|
|
|
throw new BaseException(BrainTrainingCodeError.PARAM_ERROR); |
|
|
|
} |
|
|
|
// 查询类型计分规则
|
|
|
|
TrainRuleScore ruleScore = getTrainRuleScore(activeUser.getActiveId(), param.getClassifyId()); |
|
|
|
// 分数计算
|
|
|
|
List<TrainActiveScore> scores = getTrainActiveScores(param, now, answerParams, ruleScore); |
|
|
|
|
|
|
|
//存储分数
|
|
|
|
if (CollectionUtil.isNotEmpty(scores)) { |
|
|
|
brainDao.batchInsertScore(scores); |
|
|
|
} |
|
|
|
// 存储日志
|
|
|
|
TrainActiveLog log = initFinishLog(param, userId); |
|
|
|
logs.add(log); |
|
|
|
brainDao.batchInsertLog(logs); |
|
|
|
}finally { |
|
|
|
redisUtil.del(key); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
private TrainActiveLog initFinishLog(BrainDto.Answer param, Long userId) { |
|
|
|
TrainActiveLog log = new TrainActiveLog(); |
|
|
|
log.setId(snowflake.nextId()); |
|
|
|
log.setActiveUserId(param.getActiveUserId()); |
|
|
|
log.setClassifyId(param.getClassifyId()); |
|
|
|
log.setQuestionId(0L); |
|
|
|
log.setOptionContent(""); |
|
|
|
log.setTime(System.currentTimeMillis()); |
|
|
|
log.setOperationType(param.getFinishReason()); |
|
|
|
log.setOperator(userId); |
|
|
|
return log; |
|
|
|
} |
|
|
|
|
|
|
|
private List<TrainActiveScore> getTrainActiveScores(BrainDto.Answer param, Long now, List<BrainDto.QuestionAnswer> answerParams, TrainRuleScore ruleScore) { |
|
|
|
List<TrainActiveScore> scores = new ArrayList<>(); |
|
|
|
switch (ruleScore.getCalculateType()) { |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_NO:break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_WRONG_SUB: |
|
|
|
BigDecimal wrongSubScore = getWrongSubScore(param.getActiveUserId(), param.getClassifyId(), now, answerParams, ruleScore.getCalculateParam()); |
|
|
|
TrainActiveScore wrongSubActiveScore = initScore(param.getActiveUserId(), param.getClassifyId(), 0L, wrongSubScore); |
|
|
|
scores.add(wrongSubActiveScore); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_RIGHT_NUMBER: |
|
|
|
BigDecimal rightNumScore = getRightNumScore(param.getActiveUserId(), param.getClassifyId(), now, answerParams, ruleScore.getCalculateParam()); |
|
|
|
TrainActiveScore rightNumActiveScore = initScore(param.getActiveUserId(), param.getClassifyId(), 0L, rightNumScore); |
|
|
|
scores.add(rightNumActiveScore); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_WRONG_ZERO: |
|
|
|
BigDecimal wrongZeroScore = getWrongZeroScore(param.getActiveUserId(), param.getClassifyId(), now, answerParams, ruleScore.getCalculateParam()); |
|
|
|
TrainActiveScore wrongZeroActiveScore = initScore(param.getActiveUserId(), param.getClassifyId(), 0L, wrongZeroScore ); |
|
|
|
scores.add(wrongZeroActiveScore); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_CLASSIFY: |
|
|
|
initClassifyScore(param, answerParams, ruleScore, scores); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_CONTINUE_SUB: |
|
|
|
BigDecimal continueSubScore = getContinueSubScore(param.getActiveUserId(), param.getClassifyId(), now, param.getQuestions(), ruleScore.getCalculateParam()); |
|
|
|
scores.add(initScore(param.getActiveUserId(), param.getClassifyId(), 0L, continueSubScore)); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_SORT: |
|
|
|
BigDecimal sortScore = getSortScore(param.getActiveUserId(), param.getClassifyId(), now, param.getQuestions().get(0), ruleScore.getCalculateParam()); |
|
|
|
scores.add(initScore(param.getActiveUserId(), param.getClassifyId(), param.getQuestions().get(0).getQuestionId(), sortScore)); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_SCORE_SPACE: |
|
|
|
BigDecimal spaceScore = getSpaceScore(param.getActiveUserId(), param.getClassifyId(), now, param.getQuestions(), ruleScore.getCalculateParam()); |
|
|
|
scores.add(initScore(param.getActiveUserId(), param.getClassifyId(), 0L, spaceScore)); |
|
|
|
break; |
|
|
|
default: |
|
|
|
|
|
|
|
} |
|
|
|
return scores; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按照个数计算分数 |
|
|
|
* @param activeUserId 活动ID |
|
|
|
* @param classifyId 类型ID |
|
|
|
* @param now 时间 |
|
|
|
* @param answerParams 答案 |
|
|
|
* @param calculateParam 规则 |
|
|
|
* @return 分数 |
|
|
|
*/ |
|
|
|
private BigDecimal getSpaceScore(Long activeUserId, Long classifyId, Long now, List<BrainDto.UserAnswer> answerParams, String calculateParam) { |
|
|
|
// 正确的个数
|
|
|
|
List<Long> questionIds = new ArrayList<>(); |
|
|
|
answerParams.forEach(answerParam->{ |
|
|
|
questionIds.add(answerParam.getQuestionId()); |
|
|
|
}); |
|
|
|
List<BrainVo.QuestionAnswer> answers = brainDao.queryQuestionAnswers(activeUserId, questionIds); |
|
|
|
Map<Long, List<String>> answerMap = new HashMap<>(); |
|
|
|
answers.forEach(questionAnswer->{ |
|
|
|
List<String> answerList = answerMap.getOrDefault(questionAnswer.getQuestionId(), new ArrayList<>()); |
|
|
|
answerList.add(questionAnswer.getContent()); |
|
|
|
answerMap.put(questionAnswer.getQuestionId(), answerList); |
|
|
|
}); |
|
|
|
int rightNum = 0; |
|
|
|
for (BrainDto.UserAnswer userAnswer:answerParams) { |
|
|
|
List<String> options = answerMap.get(userAnswer.getQuestionId()); |
|
|
|
if (CollectionUtil.isEmpty(options) || CollectionUtil.isEmpty(userAnswer.getTimeAndOptions()) |
|
|
|
|| options.size() != userAnswer.getTimeAndOptions().size()) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
boolean current = true; |
|
|
|
for (BrainDto.OptionTime optionTime: userAnswer.getTimeAndOptions()) { |
|
|
|
if (!options.contains(optionTime.getContent())) { |
|
|
|
current = false; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
rightNum += current ? 1 : 0; |
|
|
|
} |
|
|
|
return getByNum(activeUserId, classifyId, now, calculateParam, rightNum); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 计算对加错减类型的分数 |
|
|
|
* @param activeUserId 活动用户ID |
|
|
|
* @param classifyId 类型ID |
|
|
|
* @param now 保存答案时间 |
|
|
|
* @param question 题目 |
|
|
|
* @param calculateParam 计分规则字符串 |
|
|
|
* @return 分数 |
|
|
|
*/ |
|
|
|
private BigDecimal getSortScore(Long activeUserId, Long classifyId, Long now, BrainDto.UserAnswer question, String calculateParam) { |
|
|
|
// 查询正确的答案
|
|
|
|
List<String> answerSorts = brainDao.queryAnswerSort(question.getQuestionId()); |
|
|
|
// 比较答案并计算分数
|
|
|
|
int rightNum = 0; |
|
|
|
int wrongNum = 0; |
|
|
|
int j = 0; |
|
|
|
List<BrainDto.OptionTime> options = question.getTimeAndOptions(); |
|
|
|
for (int i = 0; i < answerSorts.size() && j < options.size(); i++) { |
|
|
|
for (; j < options.size() ; j++) { |
|
|
|
if (answerSorts.get(i).equals(options.get(j).getContent())) { |
|
|
|
rightNum++; |
|
|
|
j++; |
|
|
|
break; |
|
|
|
} else { |
|
|
|
wrongNum++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return calculateWrongSubScore(activeUserId, classifyId, now, calculateParam, rightNum, wrongNum); |
|
|
|
} |
|
|
|
|
|
|
|
private BigDecimal getContinueSubScore(Long activeUserId, Long classifyId, Long now, List<BrainDto.UserAnswer> answerParams, String calculateParam) { |
|
|
|
// 判断正误
|
|
|
|
|
|
|
|
TrainActiveQuestion question = trainActiveQuestionMapper.selectByPrimaryKey(answerParams.get(0).getQuestionId()); |
|
|
|
if (question == null) { |
|
|
|
log.info("连续减法题目错误:{}", answerParams.get(0).getQuestionId()); |
|
|
|
throw new BaseException(BrainTrainingCodeError.PARAM_ERROR); |
|
|
|
} |
|
|
|
int totalNums = question.getQuestionAnswer().equals(answerParams.get(0).getTimeAndOptions().get(0).getContent()) ? 1 : 0; |
|
|
|
for (int i = 1; i<answerParams.size(); i++) { |
|
|
|
BrainDto.UserAnswer answer = answerParams.get(i); |
|
|
|
int right = getAnswer(answer.getQuestionContent()); |
|
|
|
totalNums += right == Integer.parseInt(answer.getTimeAndOptions().get(0).getContent()) ? 1 : 0; |
|
|
|
} |
|
|
|
log.info("{}连续减法正确的个数:{}", activeUserId, totalNums); |
|
|
|
// 根据个数计算规则
|
|
|
|
return getByNum(activeUserId, classifyId, now, calculateParam, totalNums); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 查询计分规则 |
|
|
|
* @param activeId 用户ID |
|
|
|
* @param classifyId 分类ID |
|
|
|
* @return 计分规则 |
|
|
|
*/ |
|
|
|
private TrainRuleScore getTrainRuleScore(Long activeId, Long classifyId) { |
|
|
|
TrainRuleScoreExample scoreExample = new TrainRuleScoreExample(); |
|
|
|
scoreExample.createCriteria().andActiveIdEqualTo(activeId) |
|
|
|
.andClassifyIdEqualTo(classifyId); |
|
|
|
scoreExample.setOrderByClause("id desc limit 1"); |
|
|
|
List<TrainRuleScore> ruleScores = trainRuleScoreMapper.selectByExample(scoreExample); |
|
|
|
if (CollectionUtil.isEmpty(ruleScores) || ruleScores.get(0).getCalculateType() == null) { |
|
|
|
log.info("没有找到计分规则,活动:{}, 类型:{}", activeId, classifyId); |
|
|
|
throw new BaseException(BrainTrainingCodeError.SETTING_ERROR); |
|
|
|
} |
|
|
|
// 根据计分规则
|
|
|
|
return ruleScores.get(0); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 对加错0 |
|
|
|
* @param activeUserId 活动ID |
|
|
|
* @param classifyId 类型ID |
|
|
|
* @param now 时间 |
|
|
|
* @param answerParams 答案 |
|
|
|
* @param calculateParam 规则 |
|
|
|
* @return 分数 |
|
|
|
*/ |
|
|
|
private BigDecimal getWrongZeroScore(Long activeUserId, Long classifyId, Long now, List<BrainDto.QuestionAnswer> answerParams, String calculateParam) { |
|
|
|
// 和答案比较,判断正确的个数和错误的个数
|
|
|
|
int rightNum = brainDao.countRight(activeUserId, answerParams); |
|
|
|
RuleScoreVo.WrongZero wrongZeroRule = JSONObject.parseObject(calculateParam, RuleScoreVo.WrongZero.class); |
|
|
|
// 根据规则加减
|
|
|
|
BigDecimal wrongZeroScore = wrongZeroRule.getRightScore().multiply(new BigDecimal(rightNum)); |
|
|
|
// 判断规则中有无时间加减分
|
|
|
|
return addTimeScore(activeUserId, classifyId, now, wrongZeroScore, wrongZeroRule.getTimeScores()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按照个数计算分数 |
|
|
|
* @param activeUserId 活动ID |
|
|
|
* @param classifyId 类型ID |
|
|
|
* @param now 时间 |
|
|
|
* @param answerParams 答案 |
|
|
|
* @param calculateParam 规则 |
|
|
|
* @return 分数 |
|
|
|
*/ |
|
|
|
private BigDecimal getRightNumScore(Long activeUserId, Long classifyId, Long now, List<BrainDto.QuestionAnswer> answerParams, String calculateParam) { |
|
|
|
// 正确的个数
|
|
|
|
int rightNum = brainDao.countRight(activeUserId, answerParams); |
|
|
|
return getByNum(activeUserId, classifyId, now, calculateParam, rightNum); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 计算对加错减类型的分数 |
|
|
|
* @param activeUserId 活动用户ID |
|
|
|
* @param classifyId 类型ID |
|
|
|
* @param now 保存答案时间 |
|
|
|
* @param answerParams 答案 |
|
|
|
* @param calculateParam 计分规则字符串 |
|
|
|
* @return 分数 |
|
|
|
*/ |
|
|
|
private BigDecimal getWrongSubScore(Long activeUserId, Long classifyId, Long now, List<BrainDto.QuestionAnswer> answerParams, String calculateParam) { |
|
|
|
// 和答案比较,判断正确的个数和错误的个数
|
|
|
|
int rightNum = brainDao.countRight(activeUserId, answerParams); |
|
|
|
int wrongNum = answerParams.size() - rightNum; |
|
|
|
return calculateWrongSubScore(activeUserId, classifyId, now, calculateParam, rightNum, wrongNum); |
|
|
|
} |
|
|
|
|
|
|
|
private BigDecimal getByNum(Long activeUserId, Long classifyId, Long now, String calculateParam, int rightNum) { |
|
|
|
RuleScoreVo.RightNum ruleScore = JSONObject.parseObject(calculateParam, RuleScoreVo.RightNum.class); |
|
|
|
BigDecimal totalScore = new BigDecimal(0); |
|
|
|
for (int i = ruleScore.getNumScores().size() - 1; i >= 0 ; i--) { |
|
|
|
RuleScoreVo.NumAndScore rule = ruleScore.getNumScores().get(i); |
|
|
|
if (rightNum >= rule.getNum()) { |
|
|
|
totalScore = rule.getScore(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return addTimeScore(activeUserId, classifyId, now, totalScore, ruleScore.getTimeScores()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 初始化分数对象 |
|
|
|
* @param activeUserId 活动用户ID |
|
|
|
* @param classifyId 分类ID |
|
|
|
* @param totalScore 分数 |
|
|
|
* @return 分数 |
|
|
|
*/ |
|
|
|
private TrainActiveScore initScore(Long activeUserId, Long classifyId, Long questionId, BigDecimal totalScore) { |
|
|
|
TrainActiveScore score = new TrainActiveScore(); |
|
|
|
score.setId(snowflake.nextId()); |
|
|
|
score.setActiveUserId(activeUserId); |
|
|
|
score.setClassifyId(classifyId); |
|
|
|
score.setQuestionId(questionId); |
|
|
|
score.setScore(totalScore); |
|
|
|
return score; |
|
|
|
} |
|
|
|
|
|
|
|
private void initClassifyScore(BrainDto.Answer param, List<BrainDto.QuestionAnswer> answerParams, TrainRuleScore ruleScore, List<TrainActiveScore> scores) { |
|
|
|
// {classifyId:score}
|
|
|
|
List<BrainVo.ClassifyAnswer> classifyAnswers = brainDao.queryClassifyScores(param.getActiveUserId(), answerParams); |
|
|
|
JSONObject scoreRule = JSONObject.parseObject(ruleScore.getCalculateParam()); |
|
|
|
classifyAnswers.forEach(answer -> { |
|
|
|
BigDecimal questionScore = answer.getAnswer() == BrainVo.ClassifyAnswer.ANSWER_RIGHT ? scoreRule.getBigDecimal(answer.getClassifyId() + "") : new BigDecimal(0); |
|
|
|
TrainActiveScore activeScore = initScore(param.getActiveUserId(), param.getClassifyId(), answer.getQuestionId(), questionScore); |
|
|
|
scores.add(activeScore); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private void initNeedData(TrainClassify classify, BrainDto.Answer param, Long userId, List<BrainDto.QuestionAnswer> answerParams, List<TrainActiveLog> logs, List<TrainActiveQuestion> activeQuestions) { |
|
|
|
|
|
|
|
param.getQuestions().forEach(question -> { |
|
|
|
question.getTimeAndOptions().forEach(optionTime -> { |
|
|
|
BrainDto.QuestionAnswer answer = new BrainDto.QuestionAnswer(); |
|
|
|
answer.setQuestionId(question.getQuestionId()); |
|
|
|
answer.setAnswer(optionTime.getContent()); |
|
|
|
answerParams.add(answer); |
|
|
|
TrainActiveLog log = new TrainActiveLog(); |
|
|
|
log.setId(snowflake.nextId()); |
|
|
|
log.setActiveUserId(param.getActiveUserId()); |
|
|
|
log.setClassifyId(param.getClassifyId()); |
|
|
|
log.setQuestionId(question.getQuestionId()); |
|
|
|
log.setOptionContent(optionTime.getContent()); |
|
|
|
log.setTime(optionTime.getOperateTime()); |
|
|
|
log.setOperationType(BrainTrainingConstant.Train.LOG_OPERATE_OPERATE); |
|
|
|
log.setOperator(userId); |
|
|
|
logs.add(log); |
|
|
|
}); |
|
|
|
// 动态生成题目
|
|
|
|
String content = question.getQuestionContent(); |
|
|
|
if (StrUtil.isEmpty(content) || !(question.getQuestionId() != null && question.getQuestionId() != 0)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
switch (classify.getCode()) { |
|
|
|
case BrainTrainingConstant.Train.CLASSIFY_CONTINUE_SUB: |
|
|
|
TrainActiveQuestion activeQuestion = new TrainActiveQuestion(); |
|
|
|
activeQuestion.setId(snowflake.nextId()); |
|
|
|
activeQuestion.setActiveUserId(param.getActiveUserId()); |
|
|
|
activeQuestion.setClassifyId(param.getClassifyId()); |
|
|
|
activeQuestion.setQuestionContent(content); |
|
|
|
int answer = getAnswer(content); |
|
|
|
activeQuestion.setQuestionAnswer(answer + ""); |
|
|
|
activeQuestions.add(activeQuestion); |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private int getAnswer(String content) { |
|
|
|
return Integer.parseInt(content.split(BrainTrainingConstant.Train.SYMBOL_SUB)[0]) - Integer.parseInt(content.split(BrainTrainingConstant.Train.SYMBOL_SUB)[1]); |
|
|
|
} |
|
|
|
|
|
|
|
private BigDecimal calculateWrongSubScore(Long activeUserId, Long classifyId, Long now, String calculateParam, int rightNum, int wrongNum) { |
|
|
|
RuleScoreVo.WrongSub wrongSubRule = JSONObject.parseObject(calculateParam, RuleScoreVo.WrongSub.class); |
|
|
|
// 根据规则加减
|
|
|
|
BigDecimal wrongSubScore = wrongSubRule.getRightScore().multiply(new BigDecimal(rightNum)) |
|
|
|
.add(wrongSubRule.getWrongScore().multiply(new BigDecimal(wrongNum))); |
|
|
|
// 判断规则中有无时间加减分
|
|
|
|
return addTimeScore(activeUserId, classifyId, now, wrongSubScore, wrongSubRule.getTimeScores()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 快速提交加分 |
|
|
|
* @param activeUserId 活动用户ID |
|
|
|
* @param classifyId 类型ID |
|
|
|
* @param now 提交时间 |
|
|
|
* @param totalScore 分数 |
|
|
|
* @param timeScores 时间分数规则 |
|
|
|
*/ |
|
|
|
private BigDecimal addTimeScore(Long activeUserId, Long classifyId, Long now, BigDecimal totalScore, List<RuleScoreVo.TimeAndScore> timeScores) { |
|
|
|
if (CollectionUtil.isEmpty(timeScores)) { |
|
|
|
return totalScore; |
|
|
|
} |
|
|
|
// 计算当前时间 - 查询试题的时间
|
|
|
|
// 查询试题的日志
|
|
|
|
TrainActiveLogExample logExample = new TrainActiveLogExample(); |
|
|
|
logExample.createCriteria().andActiveUserIdEqualTo(activeUserId) |
|
|
|
.andClassifyIdEqualTo(classifyId) |
|
|
|
.andOperationTypeEqualTo(BrainTrainingConstant.Train.LOG_OPERATE_QUERY); |
|
|
|
logExample.setOrderByClause("id desc limit 1"); |
|
|
|
List<TrainActiveLog> queryLogs = trainActiveLogMapper.selectByExample(logExample); |
|
|
|
if (CollectionUtil.isNotEmpty(queryLogs)) { |
|
|
|
TrainActiveLog log = queryLogs.get(0); |
|
|
|
long time = now - log.getTime(); |
|
|
|
for (RuleScoreVo.TimeAndScore timeAndScore: timeScores) { |
|
|
|
if (time <= timeAndScore.getOperationTime() * 1000) { |
|
|
|
return totalScore.add(timeAndScore.getAddScore()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return totalScore; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按照规则生成题目,并添加到questions中 |
|
|
|
* @param userId 操作者ID |
|
|
|
* @param active 活动信息 |
|
|
|
* @param activeUserId 用户活动ID |
|
|
|
* @param questions 题目 |
|
|
|
* @param rule 规则 |
|
|
|
*/ |
|
|
|
private void generateQuestion(Long userId, TrainActive active, List<TrainActiveQuestion> questions, BrainVo.GenerateRule rule) { |
|
|
|
private void generateQuestion(Long activeUserId, List<TrainActiveQuestion> questions, BrainVo.GenerateRule rule) { |
|
|
|
switch (rule.getGenerate()) { |
|
|
|
case BrainTrainingConstant.Train.RULE_GENERATE_RANDOM: |
|
|
|
RuleGenerateVo.Random random = JSONObject.parseObject(rule.getGenerateParam(), RuleGenerateVo.Random.class); |
|
|
|
List<Long> randomIds = brainDao.queryRandom(rule.getActiveId(), random.getNum()); |
|
|
|
addQuestion(questions, randomIds, active.getId(), userId); |
|
|
|
List<Long> randomIds = brainDao.queryRandom(rule.getClassifyId(), random.getNum()); |
|
|
|
addQuestion(questions, randomIds, activeUserId, rule.getClassifyId()); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_GENERATE_CHILD_RANDOM: |
|
|
|
List<RuleGenerateVo.ChildRandom> childRandom = JSONArray.parseArray(rule.getGenerateParam(), RuleGenerateVo.ChildRandom.class); |
|
|
|
List<Long> childRandomIds = brainDao.queryChildRandom(childRandom); |
|
|
|
addQuestion(questions, childRandomIds, active.getId(), userId); |
|
|
|
addQuestion(questions, childRandomIds, activeUserId, rule.getClassifyId()); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_GENERATE_GRADE_RANDOM: |
|
|
|
List<RuleGenerateVo.GradeRandom> gradeRandom = JSONArray.parseArray(rule.getGenerateParam(), RuleGenerateVo.GradeRandom.class); |
|
|
|
List<Long> ids = brainDao.queryGradeRandom(rule.getActiveId(), gradeRandom); |
|
|
|
addQuestion(questions, ids, active.getId(), userId); |
|
|
|
List<Long> ids = brainDao.queryGradeRandom(rule.getClassifyId(), gradeRandom); |
|
|
|
addQuestion(questions, ids, activeUserId, rule.getClassifyId()); |
|
|
|
break; |
|
|
|
case BrainTrainingConstant.Train.RULE_GENERATE_CONTINUE_SUB: |
|
|
|
RuleGenerateVo.ContinuousSub continueSub = JSONObject.parseObject(rule.getGenerateParam(), RuleGenerateVo.ContinuousSub.class); |
|
|
|
TrainActiveQuestion question = initContinueSubQuestion(active.getId(), rule.getClassifyId(), continueSub, userId); |
|
|
|
TrainActiveQuestion question = initContinueSubQuestion(activeUserId, rule.getClassifyId(), continueSub); |
|
|
|
questions.add(question); |
|
|
|
break; |
|
|
|
default: |
|
|
@ -141,12 +545,26 @@ public class BrainService implements IBrainService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private TrainActiveQuestion initContinueSubQuestion(Long activeUserId, Long classifyId, RuleGenerateVo.ContinuousSub continueSub, Long userId) { |
|
|
|
/** |
|
|
|
* 初始化连续减法 |
|
|
|
* @param activeUserId 用户活动ID |
|
|
|
* @param classifyId 分类ID |
|
|
|
* @param continueSub 连续减法规则 |
|
|
|
* @return 题目 |
|
|
|
*/ |
|
|
|
private TrainActiveQuestion initContinueSubQuestion(Long activeUserId, Long classifyId, RuleGenerateVo.ContinuousSub continueSub) { |
|
|
|
Random randomNum = new Random(); |
|
|
|
// 在指定范围内随机生成被减数
|
|
|
|
int minuend = randomNum.nextInt(continueSub.getMinuendMax() - continueSub.getMinuendMin() + 1) + continueSub.getMinuendMin(); |
|
|
|
// 在指定范围内随机生成被减数
|
|
|
|
int subtrahend = randomNum.nextInt(continueSub.getSubtrahendMax() - continueSub.getSubtrahendMin() + 1) + continueSub.getSubtrahendMin(); |
|
|
|
String partition = BrainTrainingConstant.Train.SYMBOL_DOT; |
|
|
|
String nonNums = continueSub.getNonNums(); |
|
|
|
while (StrUtil.isNotEmpty(nonNums) && (nonNums.equals(subtrahend) || nonNums.endsWith(partition + subtrahend) |
|
|
|
|| nonNums.startsWith(subtrahend + partition) || nonNums.contains(partition + subtrahend + partition))) { |
|
|
|
subtrahend = randomNum.nextInt(continueSub.getSubtrahendMax() - continueSub.getSubtrahendMin() + 1) + continueSub.getSubtrahendMin(); |
|
|
|
} |
|
|
|
log.info("{}的连续减法首道题:{}-{}", activeUserId, minuend, subtrahend); |
|
|
|
TrainActiveQuestion question = new TrainActiveQuestion(); |
|
|
|
question.setId(snowflake.nextId()); |
|
|
|
question.setActiveUserId(activeUserId); |
|
|
@ -154,11 +572,18 @@ public class BrainService implements IBrainService { |
|
|
|
question.setQuestionId(0L); |
|
|
|
question.setQuestionContent(minuend + BrainTrainingConstant.Train.SYMBOL_SUB + subtrahend); |
|
|
|
question.setQuestionAnswer(minuend - subtrahend + ""); |
|
|
|
question.setOperator(userId); |
|
|
|
question.setOperator(0L); |
|
|
|
return question; |
|
|
|
} |
|
|
|
|
|
|
|
private void addQuestion(List<TrainActiveQuestion> questions, List<Long> questionIds, Long activeUserId, Long userId) { |
|
|
|
/** |
|
|
|
* 添加题目信息 |
|
|
|
* @param questions 题目列表 |
|
|
|
* @param questionIds 题目ID |
|
|
|
* @param activeUserId 用户活动ID |
|
|
|
* @param classifyId 分类ID |
|
|
|
*/ |
|
|
|
private void addQuestion(List<TrainActiveQuestion> questions, List<Long> questionIds, Long activeUserId, Long classifyId) { |
|
|
|
if (CollectionUtil.isEmpty(questionIds)) { |
|
|
|
log.info("没有查找到题目,不添加该题型的题目"); |
|
|
|
return; |
|
|
@ -167,8 +592,9 @@ public class BrainService implements IBrainService { |
|
|
|
TrainActiveQuestion question = new TrainActiveQuestion(); |
|
|
|
question.setId(snowflake.nextId()); |
|
|
|
question.setActiveUserId(activeUserId); |
|
|
|
question.setClassifyId(classifyId); |
|
|
|
question.setQuestionId(id); |
|
|
|
question.setOperator(userId); |
|
|
|
question.setOperator(0L); |
|
|
|
question.setQuestionContent(""); |
|
|
|
question.setQuestionAnswer(""); |
|
|
|
questions.add(question); |
|
|
|