diff --git a/api/controller/share.go b/api/controller/share.go index 7601bf2..cd6e4e0 100644 --- a/api/controller/share.go +++ b/api/controller/share.go @@ -5,7 +5,6 @@ import ( "github.com/gin-gonic/gin" "knowledge/api/dao" "knowledge/api/dto" - "knowledge/api/model" "knowledge/api/requests" "knowledge/api/responses" "knowledge/api/service" @@ -181,7 +180,6 @@ func (r *Share) GetQuestion(c *gin.Context) { } questionQaDao := dao.QuestionQaDao{} - questionQaItemDao := dao.QuestionQaItemDao{} // 获取题库数据 questionQa, err := questionQaDao.GetQuestionQaById(qaId) @@ -203,108 +201,48 @@ func (r *Share) GetQuestion(c *gin.Context) { return } - g := dto.ShareDto{ - Question: []*dto.QuestionDto{}, - BaseTokenItem: []*dto.BaseTokenItemDto{}, - } + questionQaService := service.QuestionQaService{} - // 题目数据 - var questions []*model.QuestionQaItem - - // 题目数据-必备选中 - maps := make(map[string]interface{}) - maps["qa_id"] = questionQa.QaId - maps["is_must_select"] = 1 - questionQaItems, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) - if err == nil && len(questionQaItems) > 0 { - for _, item := range questionQaItems { - questions = append(questions, item) - } - } - - // 题目数据-剩余随机数量 - remainingQuantity := questionQa.QaQuantity - len(questionQaItems) - if remainingQuantity > 0 { - // 随机获取剩余题目 - maps = make(map[string]interface{}) - maps["qa_id"] = questionQa.QaId - maps["is_must_select"] = 0 - questionQaItems, err = questionQaItemDao.GetQuestionQaItemWhereListRand(maps, remainingQuantity) - if err == nil && len(questionQaItems) > 0 { - for _, item := range questionQaItems { - questions = append(questions, item) - } - } - } - - for _, v := range questions { - questionOptionDao := dao.QuestionOptionDao{} - maps = make(map[string]interface{}) - maps["question_id"] = v.QuestionId - questionOption, err := questionOptionDao.GetQuestionOptionList(maps) + // 题库类型1-常规模式 + if questionQa.QaType == 1 { + g, err := questionQaService.GetShareQuestionQaForTypeOne(questionQa) if err != nil { - responses.FailWithMessage("内部错误", c) + responses.FailWithMessage(err.Error(), c) return } - // 处理返回值 - questionDto := dto.GetShareQuestionDto(v.Question) - - // 加载选项 - questionDto.LoadQuestionOptionSimplify(questionOption) - - // 加载图片 - questionDto.LoadQuestionImage(v.Question.QuestionImage) - - // 加载答案 - questionDto.LoadQuestionAnswer(v.Question) - - // 将转换后的结构体添加到新切片中 - g.Question = append(g.Question, questionDto) + responses.OkWithData(g, c) + return } - // 按照难度重新排序题目顺序 - //sort.SliceStable(g.Question, func(i, j int) bool { - // return g.Question[i].Difficulty < g.Question[j].Difficulty - //}) - - // 加载飞花令 - if questionQa.QaDisplayType == 2 { - questionQaTokenDao := dao.QuestionQaTokenDao{} - maps = make(map[string]interface{}) - maps["qa_id"] = questionQa.QaId - questionQaToken, err := questionQaTokenDao.GetQuestionQaTokenList(maps) + // 题库类型2-固定套题模式 + if questionQa.QaType == 2 { + g, err := questionQaService.GetShareQuestionQaForTypeTwo(questionQa) if err != nil { - responses.FailWithMessage("内部错误", c) + responses.FailWithMessage(err.Error(), c) return } - baseTokenItemDao := dao.BaseTokenItemDao{} - for _, v := range questionQaToken { - // 加载详细飞花令 - baseTokenItem, err := baseTokenItemDao.GetBaseTokenItemPreloadOrderByTokenId(v.TokenId) - if err != nil { - responses.FailWithMessage("内部错误", c) - return - } + responses.OkWithData(g, c) + return + } - // 处理返回值 - for _, item := range baseTokenItem { - if len(g.BaseTokenItem) < questionQa.QaQuantity { - // 处理返回值 - baseTokenItemDto := dto.GetBaseTokenItemDto(item) - - // 将转换后的结构体添加到新切片中 - g.BaseTokenItem = append(g.BaseTokenItem, baseTokenItemDto) - } - } + // 题库类型3-多轮固定题型模式 + if questionQa.QaType == 3 { + g, err := questionQaService.GetShareQuestionQaForTypeThree(questionQa) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return } + + responses.OkWithData(g, c) + return } // 记录问答题库打开次数 - questionQaService := service.QuestionQaService{} _ = questionQaService.RecordQuestionQaOpenNum(global.Db, questionQa.QaId) // 返回 - responses.OkWithData(g, c) + responses.FailWithMessage("题库错误", c) + return } diff --git a/api/dao/BaseTokenItem.go b/api/dao/BaseTokenItem.go index 9d8f65d..737244d 100644 --- a/api/dao/BaseTokenItem.go +++ b/api/dao/BaseTokenItem.go @@ -29,8 +29,17 @@ func (r *BaseTokenItemDao) GetBaseTokenItemPreloadById(ItemId int64) (m *model.B return m, nil } -// GetBaseTokenItemPreloadOrderByTokenId 获取数据-加载全部关联-排序-TokenId -func (r *BaseTokenItemDao) GetBaseTokenItemPreloadOrderByTokenId(tokenId int64) (m []*model.BaseTokenItem, err error) { +// GetBaseTokenItemListByTokenId 获取数据-tokenId +func (r *BaseTokenItemDao) GetBaseTokenItemListByTokenId(tokenId int64) (m []*model.BaseTokenItem, err error) { + err = global.Db.Where("token_id = ?", tokenId).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetBaseTokenItemOrderByTokenId 获取数据-排序-TokenId +func (r *BaseTokenItemDao) GetBaseTokenItemOrderByTokenId(tokenId int64) (m []*model.BaseTokenItem, err error) { err = global.Db.Where("token_id = ?", tokenId). Order("item_sort desc"). Order("created_at desc"). diff --git a/api/dao/QuestionQaItem.go b/api/dao/QuestionQaItem.go index 225a96a..80f7c46 100644 --- a/api/dao/QuestionQaItem.go +++ b/api/dao/QuestionQaItem.go @@ -248,6 +248,42 @@ func (r *QuestionQaItemDao) GetQuestionQaItemWhereListRand(maps interface{}, lim return m, nil } +// GetQuestionQaItemNotInListRand 获取列表-随机-排除 +func (r *QuestionQaItemDao) GetQuestionQaItemNotInListRand(maps interface{}, questionType int, notQuestionId []int64, limit int) (m []*model.QuestionQaItem, err error) { + query := global.Db.Model(&model.QuestionQaItem{}) + query = query.Where(maps) + + query = query.Preload("Question") + + // 选项 + query = query.Preload("Question.QuestionOption") + + subQuery := global.Db.Model(&model.Question{}). + Select("question_id"). + Where("question_status = ?", 1). + Where("is_delete = ?", 0) + + // 排除选项 + if len(notQuestionId) > 0 { + subQuery = subQuery.Where("question_id not in (?)", notQuestionId) + } + + // 题目类型 + if questionType != 0 { + subQuery = subQuery.Where("question_type = ?", questionType) + } + + query = query.Where(gorm.Expr("question_id IN (?)", subQuery)) + + query = query.Limit(limit).Order("rand()") + + err = query.Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + //subQuery := global.Db.Model(&model.Question{}). //Where("kb_question.question_id = kb_question_qa_item.question_id"). //Where("question_status = ?", 1). diff --git a/api/dto/Share.go b/api/dto/Share.go index e7f4703..8af640d 100644 --- a/api/dto/Share.go +++ b/api/dto/Share.go @@ -12,7 +12,22 @@ type ShareAuthDto struct { Token string `json:"token"` // token } +// ShareDto 获取返回数据-常规模式 type ShareDto struct { Question []*QuestionDto `json:"question"` // 题库关联题目列表 BaseTokenItem []*BaseTokenItemDto `json:"base_token_item"` // 题库关联飞花令-列表 } + +// ShareDtoForTwo 获取返回数据-固定套题模式 +type ShareDtoForTwo struct { + Question [][]*QuestionDto `json:"question"` // 题库关联题目列表 + BaseTokenItem []*BaseTokenItemDto `json:"base_token_item"` // 题库关联飞花令-列表 +} + +// ShareDtoForThree 获取返回数据-多轮固定题型模式 +type ShareDtoForThree struct { + Single *ShareDto `json:"single"` // 单选题 + Multiple *ShareDto `json:"multiple"` // 多选题 + Judge *ShareDto `json:"judge"` // 判断题 + Qa *ShareDto `json:"qa"` // 问答题 +} diff --git a/api/service/QuestionQa.go b/api/service/QuestionQa.go index 6cb8f78..1eef6da 100644 --- a/api/service/QuestionQa.go +++ b/api/service/QuestionQa.go @@ -6,10 +6,12 @@ import ( "github.com/goccy/go-json" "gorm.io/gorm" "knowledge/api/dao" + "knowledge/api/dto" "knowledge/api/model" "knowledge/api/requests" "knowledge/global" "knowledge/utils" + "math/rand" "strconv" "time" ) @@ -17,6 +19,12 @@ import ( type QuestionQaService struct { } +// 题库-飞花令题目数量规则 +type tokenQuestionContent struct { + QuestionType int `json:"question_type"` // 题目类型(1:单选 2:多选 3:问答 4:判断) + Quantity int `json:"quantity"` // 数量 +} + // AddQuestionQa 新增问答题库 func (r *QuestionQaService) AddQuestionQa(req requests.AddQuestionQa) (bool, error) { // 处理图片 @@ -48,83 +56,10 @@ func (r *QuestionQaService) AddQuestionQa(req requests.AddQuestionQa) (bool, err return false, errors.New("明细题目错误") } - // 选择的明细总数量 += QuestionQaItem.Quantity - itemQuantity := 0 - for _, item := range req.QuestionQaItem { - itemQuantity = itemQuantity + item.Quantity - } - - // 题目总数量 - qaQuantity := req.QaQuantity - - // 常规模式 - if req.QaType == 1 { - // 总数量 需大于 选择的明细数量 - if qaQuantity > itemQuantity { - return false, errors.New("明细题目数量需超过题库所需题目总数量") - } - } - - // 固定套题模式 - if req.QaType == 2 { - // 计算飞花令题目数量 - tokenQuestionQuantity := 0 - for _, content := range req.TokenQuestionContent { - tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity - } - - // 总数量 = 飞花令题目数量 * 飞花令数量 - qaQuantity = tokenQuestionQuantity * *req.TokenNum - if qaQuantity > itemQuantity { - return false, errors.New("明细题目数量需超过题库所需题目总数量") - } - - // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 - for _, content := range req.TokenQuestionContent { - itemQuantity = 0 - for _, item := range req.QuestionQaItem { - if content.QuestionType == item.QuestionType { - itemQuantity = item.Quantity - } - } - - quantity := content.Quantity * *req.TokenNum - - if quantity > itemQuantity { - return false, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") - } - } - } - - // 多轮固定题型模式 - if req.QaType == 3 { - // 计算飞花令题目数量 - tokenQuestionQuantity := 0 - for _, content := range req.TokenQuestionContent { - tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity - } - - // 总数量 = 飞花令题目数量 * 飞花令数量 * 轮次 - qaQuantity = tokenQuestionQuantity * *req.TokenNum * *req.RoundNum - if qaQuantity > itemQuantity { - return false, errors.New("明细题目数量需超过题库所需题目总数量") - } - - // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 * 轮次 - for _, content := range req.TokenQuestionContent { - itemQuantity = 0 - for _, item := range req.QuestionQaItem { - if content.QuestionType == item.QuestionType { - itemQuantity = item.Quantity - } - } - - quantity := content.Quantity * *req.TokenNum * *req.RoundNum - - if quantity > itemQuantity { - return false, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") - } - } + // 获取并检测题库题目数量 + qaQuantity, err := r.CheckAddQaQuestionQuantity(req) + if err != nil { + return false, err } // 开始事务 @@ -180,6 +115,84 @@ func (r *QuestionQaService) AddQuestionQa(req requests.AddQuestionQa) (bool, err return false, errors.New("新增失败") } + // 新增飞花令标签数据 + if req.QaDisplayType == 2 { + questionQaTokenDao := dao.QuestionQaTokenDao{} + baseTokenDao := dao.BaseTokenDao{} + baseTokenItemDao := dao.BaseTokenItemDao{} + + // 飞花令明细总数 + tokenItemQuantity := 0 + for i, item := range req.BaseTokenItem { + tokenId, err := strconv.ParseInt(item.TokenId, 10, 64) + if err != nil { + tx.Rollback() + return false, err + } + + // 检测飞花令基础数据 + _, err = baseTokenDao.GetBaseTokenById(tokenId) + if err != nil { + tx.Rollback() + return false, err + } + + // 获取飞花令明细数据 + baseTokenItem, err := baseTokenItemDao.GetBaseTokenItemListByTokenId(tokenId) + if err != nil { + tx.Rollback() + return false, err + } + + // 飞花令明细总数 + tokenItemQuantity = tokenItemQuantity + len(baseTokenItem) + + questionQaToken := &model.QuestionQaToken{ + QaId: questionQa.QaId, + TokenId: tokenId, + Sort: i + 1, + } + + questionQaToken, err = questionQaTokenDao.AddQuestionQaToken(tx, questionQaToken) + if err != nil { + tx.Rollback() + return false, err + } + } + + // 检测飞花令数量 + if req.QaType == 1 { + // 所需飞花令数量 = 题目总数 + if tokenItemQuantity < qaQuantity { + tx.Rollback() + return false, errors.New("已选择飞花令的数量不满足题库使用") + } + } + + if req.QaType == 2 { + // 所需飞花令数量 = TokenNum + if tokenItemQuantity < *req.TokenNum { + tx.Rollback() + return false, errors.New("已选择飞花令的数量不满足题库使用") + } + } + + if req.QaType == 3 { + // 轮次 * 最大值 = 所需飞花令数量 + maxTokenQuestionQuantity := 0 + for _, content := range req.TokenQuestionContent { + if content.Quantity > maxTokenQuestionQuantity { + maxTokenQuestionQuantity = content.Quantity + } + } + + if tokenItemQuantity < (maxTokenQuestionQuantity * *req.RoundNum) { + tx.Rollback() + return false, errors.New("已选择飞花令的数量不满足题库使用") + } + } + } + // 生成分享链接 questionQaData := make(map[string]interface{}) questionQaData["qa_share_id"] = utils.HashString(fmt.Sprintf("%d", questionQa.QaId)) @@ -233,38 +246,6 @@ func (r *QuestionQaService) AddQuestionQa(req requests.AddQuestionQa) (bool, err } } - // 新增飞花令标签数据 - if req.QaDisplayType == 2 { - questionQaTokenDao := dao.QuestionQaTokenDao{} - baseTokenDao := dao.BaseTokenDao{} - for i, item := range req.BaseTokenItem { - tokenId, err := strconv.ParseInt(item.TokenId, 10, 64) - if err != nil { - tx.Rollback() - return false, err - } - - // 检测飞花令基础数据 - _, err = baseTokenDao.GetBaseTokenById(tokenId) - if err != nil { - tx.Rollback() - return false, err - } - - questionQaToken := &model.QuestionQaToken{ - QaId: questionQa.QaId, - TokenId: tokenId, - Sort: i + 1, - } - - questionQaToken, err = questionQaTokenDao.AddQuestionQaToken(tx, questionQaToken) - if err != nil { - tx.Rollback() - return false, err - } - } - } - tx.Commit() return true, nil } @@ -346,95 +327,20 @@ func (r *QuestionQaService) PutQuestionQa(qaId int64, req requests.PutQuestionQa questionQaData["token_question_content"] = string(tokenQuestionContent) } + // 获取并检测题库题目数量 + qaQuantity, err := r.CheckPutQaQuestionQuantity(req) + if err != nil { + tx.Rollback() + return false, err + } + // 题目数量 - if req.QaQuantity != questionQa.QaQuantity { + if qaQuantity != questionQa.QaQuantity { if req.Action == 1 { tx.Rollback() return false, errors.New("您修改了题目数量,无法正常修改该题库,请重新生成") } - // 选择的明细数量 += QuestionQaItem.Quantity - itemQuantity := 0 - for _, item := range req.QuestionQaItem { - itemQuantity = itemQuantity + item.Quantity - } - - // 题目总数量 - qaQuantity := req.QaQuantity - - // 常规模式 - if req.QaType == 1 { - // 总数量 需大于 选择的明细数量 - if qaQuantity > itemQuantity { - tx.Rollback() - return false, errors.New("明细题目数量需超过题库所需题目总数量") - } - } - - // 固定套题模式 - if req.QaType == 2 { - // 计算飞花令题目数量 - tokenQuestionQuantity := 0 - for _, content := range req.TokenQuestionContent { - tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity - } - - // 总数量 = 飞花令题目数量 * 飞花令数量 - qaQuantity = tokenQuestionQuantity * *req.TokenNum - if qaQuantity > itemQuantity { - tx.Rollback() - return false, errors.New("明细题目数量需超过题库所需题目总数量") - } - - // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 - for _, content := range req.TokenQuestionContent { - itemQuantity = 0 - for _, item := range req.QuestionQaItem { - if content.QuestionType == item.QuestionType { - itemQuantity = item.Quantity - } - } - - quantity := content.Quantity * *req.TokenNum - - if quantity > itemQuantity { - return false, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") - } - } - } - - // 多轮固定题型模式 - if req.QaType == 3 { - // 计算飞花令题目数量 - tokenQuestionQuantity := 0 - for _, content := range req.TokenQuestionContent { - tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity - } - - // 总数量 = 飞花令题目数量 * 飞花令数量 * 轮次 - qaQuantity = tokenQuestionQuantity * *req.TokenNum * *req.RoundNum - if qaQuantity > itemQuantity { - tx.Rollback() - return false, errors.New("明细题目数量需超过题库所需题目总数量") - } - - // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 * 轮次 - for _, content := range req.TokenQuestionContent { - itemQuantity = 0 - for _, item := range req.QuestionQaItem { - if content.QuestionType == item.QuestionType { - itemQuantity = item.Quantity - } - } - - quantity := content.Quantity * *req.TokenNum * *req.RoundNum - - if quantity > itemQuantity { - return false, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") - } - } - } - questionQaData["qa_quantity"] = req.QaQuantity } @@ -521,6 +427,10 @@ func (r *QuestionQaService) PutQuestionQa(qaId int64, req requests.PutQuestionQa // 新增飞花令 if req.QaDisplayType == 2 { baseTokenDao := dao.BaseTokenDao{} + baseTokenItemDao := dao.BaseTokenItemDao{} + + // 飞花令明细总数 + tokenItemQuantity := 0 for i, item := range req.BaseTokenItem { tokenId, err := strconv.ParseInt(item.TokenId, 10, 64) if err != nil { @@ -535,6 +445,16 @@ func (r *QuestionQaService) PutQuestionQa(qaId int64, req requests.PutQuestionQa return false, err } + // 获取飞花令明细数据 + baseTokenItem, err := baseTokenItemDao.GetBaseTokenItemListByTokenId(tokenId) + if err != nil { + tx.Rollback() + return false, err + } + + // 飞花令明细总数 + tokenItemQuantity = tokenItemQuantity + len(baseTokenItem) + questionQaToken := &model.QuestionQaToken{ QaId: questionQa.QaId, TokenId: tokenId, @@ -547,6 +467,38 @@ func (r *QuestionQaService) PutQuestionQa(qaId int64, req requests.PutQuestionQa return false, err } } + + // 检测飞花令数量 + if req.QaType == 1 { + // 所需飞花令数量 = 题目总数 + if tokenItemQuantity < qaQuantity { + tx.Rollback() + return false, errors.New("已选择飞花令的数量不满足题库使用") + } + } + + if req.QaType == 2 { + // 所需飞花令数量 = TokenNum + if tokenItemQuantity < *req.TokenNum { + tx.Rollback() + return false, errors.New("已选择飞花令的数量不满足题库使用") + } + } + + if req.QaType == 3 { + // 轮次 * 最大值 = 所需飞花令数量 + maxTokenQuestionQuantity := 0 + for _, content := range req.TokenQuestionContent { + if content.Quantity > maxTokenQuestionQuantity { + maxTokenQuestionQuantity = content.Quantity + } + } + + if tokenItemQuantity < (maxTokenQuestionQuantity * *req.RoundNum) { + tx.Rollback() + return false, errors.New("已选择飞花令的数量不满足题库使用") + } + } } tx.Commit() @@ -690,3 +642,568 @@ func (r *QuestionQaService) RecordQuestionQaOpenNum(tx *gorm.DB, qaId int64) err return nil } + +// CheckAddQaQuestionQuantity 检测题库题目数量-新增 +func (r *QuestionQaService) CheckAddQaQuestionQuantity(req requests.AddQuestionQa) (qaQuantity int, err error) { + // 题目总数量 + qaQuantity = req.QaQuantity + + // 选择的明细总数量 += QuestionQaItem.Quantity + itemQuantity := 0 + for _, item := range req.QuestionQaItem { + itemQuantity = itemQuantity + item.Quantity + } + + // 常规模式 + if req.QaType == 1 { + // 总数量 需大于 选择的明细数量 + if qaQuantity > itemQuantity { + return qaQuantity, errors.New("明细题目数量需超过题库所需题目总数量") + } + } + + // 固定套题模式 + if req.QaType == 2 { + // 计算飞花令题目数量 + tokenQuestionQuantity := 0 + for _, content := range req.TokenQuestionContent { + tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity + } + + // 总数量 = 飞花令题目数量 * 飞花令数量 + qaQuantity = tokenQuestionQuantity * *req.TokenNum + if qaQuantity > itemQuantity { + return qaQuantity, errors.New("明细题目数量需超过题库所需题目总数量") + } + + // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 + for _, content := range req.TokenQuestionContent { + itemQuantity = 0 + for _, item := range req.QuestionQaItem { + if content.QuestionType == item.QuestionType { + itemQuantity = item.Quantity + } + } + + quantity := content.Quantity * *req.TokenNum + + if quantity > itemQuantity { + return qaQuantity, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") + } + } + } + + // 多轮固定题型模式 + if req.QaType == 3 { + // 计算飞花令题目数量 + tokenQuestionQuantity := 0 + for _, content := range req.TokenQuestionContent { + tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity + } + + // 总数量 = 飞花令题目数量 * 飞花令数量 * 轮次 + qaQuantity = tokenQuestionQuantity * *req.TokenNum * *req.RoundNum + if qaQuantity > itemQuantity { + return qaQuantity, errors.New("明细题目数量需超过题库所需题目总数量") + } + + // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 * 轮次 + for _, content := range req.TokenQuestionContent { + itemQuantity = 0 + for _, item := range req.QuestionQaItem { + if content.QuestionType == item.QuestionType { + itemQuantity = item.Quantity + } + } + + quantity := content.Quantity * *req.TokenNum * *req.RoundNum + + if quantity > itemQuantity { + return qaQuantity, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") + } + } + } + + return qaQuantity, nil +} + +// CheckPutQaQuestionQuantity 检测题库题目数量-修改 +func (r *QuestionQaService) CheckPutQaQuestionQuantity(req requests.PutQuestionQa) (qaQuantity int, err error) { + // 题目总数量 + qaQuantity = req.QaQuantity + + // 选择的明细总数量 += QuestionQaItem.Quantity + itemQuantity := 0 + for _, item := range req.QuestionQaItem { + itemQuantity = itemQuantity + item.Quantity + } + + // 常规模式 + if req.QaType == 1 { + // 总数量 需大于 选择的明细数量 + if qaQuantity > itemQuantity { + return qaQuantity, errors.New("明细题目数量需超过题库所需题目总数量") + } + } + + // 固定套题模式 + if req.QaType == 2 { + // 计算飞花令题目数量 + tokenQuestionQuantity := 0 + for _, content := range req.TokenQuestionContent { + tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity + } + + // 总数量 = 飞花令题目数量 * 飞花令数量 + qaQuantity = tokenQuestionQuantity * *req.TokenNum + if qaQuantity > itemQuantity { + return qaQuantity, errors.New("明细题目数量需超过题库所需题目总数量") + } + + // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 + for _, content := range req.TokenQuestionContent { + itemQuantity = 0 + for _, item := range req.QuestionQaItem { + if content.QuestionType == item.QuestionType { + itemQuantity = item.Quantity + } + } + + quantity := content.Quantity * *req.TokenNum + + if quantity > itemQuantity { + return qaQuantity, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") + } + } + } + + // 多轮固定题型模式 + if req.QaType == 3 { + // 计算飞花令题目数量 + tokenQuestionQuantity := 0 + for _, content := range req.TokenQuestionContent { + tokenQuestionQuantity = tokenQuestionQuantity + content.Quantity + } + + // 总数量 = 飞花令题目数量 * 飞花令数量 * 轮次 + qaQuantity = tokenQuestionQuantity * *req.TokenNum * *req.RoundNum + if qaQuantity > itemQuantity { + return qaQuantity, errors.New("明细题目数量需超过题库所需题目总数量") + } + + // 单个类型总数量 = 单一题目类型数量 * 飞花令数量 * 轮次 + for _, content := range req.TokenQuestionContent { + itemQuantity = 0 + for _, item := range req.QuestionQaItem { + if content.QuestionType == item.QuestionType { + itemQuantity = item.Quantity + } + } + + quantity := content.Quantity * *req.TokenNum * *req.RoundNum + + if quantity > itemQuantity { + return qaQuantity, errors.New(utils.QuestionType(content.QuestionType) + "数量不足") + } + } + } + + return qaQuantity, nil +} + +// GetQuestionQaBaseTokenItemList 获取题库飞花令数据-列表 +func (r *QuestionQaService) GetQuestionQaBaseTokenItemList(qaDisplayType int, qaId int64, quantity int) ([]*model.BaseTokenItem, error) { + // 定义返回值 + var g []*model.BaseTokenItem + + // 判断展示类型 + if qaDisplayType != 2 { + return g, nil + } + + questionQaTokenDao := dao.QuestionQaTokenDao{} + maps := make(map[string]interface{}) + maps["qa_id"] = qaId + questionQaToken, err := questionQaTokenDao.GetQuestionQaTokenPreloadList(maps) + if err != nil { + return g, errors.New("内部错误") + } + + for _, v := range questionQaToken { + // 处理返回值 + for _, item := range v.BaseTokenItem { + if len(g) < quantity { + // 将转换后的结构体添加到新切片中 + g = append(g, item) + } + } + } + + return g, nil +} + +// GetShareQuestionQaForTypeOne 获取题库数据-常规模式 +func (r *QuestionQaService) GetShareQuestionQaForTypeOne(questionQa *model.QuestionQa) (*dto.ShareDto, error) { + // 初始化返回值 + g := &dto.ShareDto{} + + if questionQa.QaType != 1 { + return g, errors.New("题库类型错误") + } + + questionQaItemDao := dao.QuestionQaItemDao{} + + // 题目数据 + var questions []*model.Question + + // 题目数据-必备选中 + maps := make(map[string]interface{}) + maps["qa_id"] = questionQa.QaId + maps["is_must_select"] = 1 + questionQaItems, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) + if err == nil && len(questionQaItems) > 0 { + for _, item := range questionQaItems { + questions = append(questions, item.Question) + } + } + + // 题目数据-剩余随机数量 + remainingQuantity := questionQa.QaQuantity - len(questionQaItems) + if remainingQuantity > 0 { + // 随机获取剩余题目 + maps = make(map[string]interface{}) + maps["qa_id"] = questionQa.QaId + maps["is_must_select"] = 0 + questionQaItems, err = questionQaItemDao.GetQuestionQaItemWhereListRand(maps, remainingQuantity) + if err == nil && len(questionQaItems) > 0 { + for _, item := range questionQaItems { + questions = append(questions, item.Question) + } + } + } + + for _, v := range questions { + questionOptionDao := dao.QuestionOptionDao{} + maps = make(map[string]interface{}) + maps["question_id"] = v.QuestionId + questionOption, err := questionOptionDao.GetQuestionOptionList(maps) + if err != nil { + return g, errors.New("内部错误") + } + + // 处理返回值 + questionDto := dto.GetShareQuestionDto(v) + + // 加载选项 + questionDto.LoadQuestionOptionSimplify(questionOption) + + // 加载图片 + questionDto.LoadQuestionImage(v.QuestionImage) + + // 加载答案 + questionDto.LoadQuestionAnswer(v) + + // 将转换后的结构体添加到新切片中 + g.Question = append(g.Question, questionDto) + } + + // 按照难度重新排序题目顺序 + //sort.SliceStable(g.Question, func(i, j int) bool { + // return g.Question[i].Difficulty < g.Question[j].Difficulty + //}) + + // 获取题库飞花令数据 + baseTokenItems, err := r.GetQuestionQaBaseTokenItemList(questionQa.QaDisplayType, questionQa.QaId, questionQa.QaQuantity) + if err != nil { + return g, errors.New(err.Error()) + } + + g.BaseTokenItem = dto.GetBaseTokenItemListDto(baseTokenItems) + + return g, nil +} + +// GetShareQuestionQaForTypeTwo 获取题库数据-固定套题模式 +func (r *QuestionQaService) GetShareQuestionQaForTypeTwo(questionQa *model.QuestionQa) (*dto.ShareDtoForTwo, error) { + // 初始化返回值 + g := &dto.ShareDtoForTwo{} + + if questionQa.QaType != 2 { + return g, errors.New("题库类型错误") + } + + questionQaItemDao := dao.QuestionQaItemDao{} + + // 题目数据-必备选中 + maps := make(map[string]interface{}) + maps["qa_id"] = questionQa.QaId + maps["is_must_select"] = 1 + mustQuestions, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) + + // 题目数据-未比被选中 + maps = make(map[string]interface{}) + maps["qa_id"] = questionQa.QaId + maps["is_must_select"] = 0 + notMustQuestions, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) + + // 打乱数据 + rand.Shuffle(len(notMustQuestions), func(i, j int) { + notMustQuestions[i], notMustQuestions[j] = notMustQuestions[j], notMustQuestions[i] + }) + + // json转结构体-飞花令题目数量规则 + var tokenQuestionContents []tokenQuestionContent + err = json.Unmarshal([]byte(questionQa.TokenQuestionContent), &tokenQuestionContents) + if err != nil { + return g, errors.New(err.Error()) + } + + // 获取题库飞花令数据-列表 + baseTokenItems, err := r.GetQuestionQaBaseTokenItemList(questionQa.QaDisplayType, questionQa.QaId, *questionQa.TokenNum) + if err != nil { + return g, errors.New(err.Error()) + } + + g.BaseTokenItem = dto.GetBaseTokenItemListDto(baseTokenItems) + + // 先放入question中,题目数量不可大于规则的数量 + // 然后吧question转换为dto。 + // 最后在吧dto转为g + // 飞花令数量 + for i := 0; i < *questionQa.TokenNum; i++ { + // 题目数据 + var questions []*model.Question + + // 套题规则 [{"question_type":1,"quantity":10},{"question_type":2,"quantity":0},{"question_type":3,"quantity":0},{"question_type":4,"quantity":0}] + for _, v2 := range tokenQuestionContents { + // 必选数据 + for _, v3 := range mustQuestions { + // 此处标识已用过 + if v3 == nil { + continue + } + + // 类型相同,加入该组数据中 + if v2.QuestionType == v3.Question.QuestionType { + // 当数量超出时,跳出 + if len(questions) >= v2.Quantity { + continue + } + + questions = append(questions, v3.Question) + + // 标记已被使用 + v3 = nil + } + } + + // 题目数据-剩余随机数量 + remainingQuantity := v2.Quantity - len(questions) + if remainingQuantity > 0 { + // 非必选数据 + for _, v3 := range notMustQuestions { + // 此处标识已用过 + if v3 == nil { + continue + } + + // 当数量超出时,跳出 + if len(questions) >= v2.Quantity { + continue + } + + questions = append(questions, v3.Question) + + // 标记已被使用 + v3 = nil + } + } + } + + // 处理返回值 + questionDtoList := make([]*dto.QuestionDto, len(questions)) + + // 处理数据 + for i2, v2 := range questions { + questionOptionDao := dao.QuestionOptionDao{} + maps = make(map[string]interface{}) + maps["question_id"] = v2.QuestionId + questionOption, err := questionOptionDao.GetQuestionOptionList(maps) + if err != nil { + return g, errors.New("内部错误") + } + + // 处理返回值 + questionDto := dto.GetShareQuestionDto(v2) + + // 加载选项 + questionDto.LoadQuestionOptionSimplify(questionOption) + + // 加载图片 + questionDto.LoadQuestionImage(v2.QuestionImage) + + // 加载答案 + questionDto.LoadQuestionAnswer(v2) + + questionDtoList[i2] = questionDto + } + + g.Question = append(g.Question, questionDtoList) + } + + return g, nil +} + +// GetShareQuestionQaForTypeThree 获取题库数据-多轮固定题型模式 +func (r *QuestionQaService) GetShareQuestionQaForTypeThree(questionQa *model.QuestionQa) ([]*dto.ShareDtoForThree, error) { + // 初始化返回值 + var g []*dto.ShareDtoForThree + + if questionQa.QaType != 3 { + return g, errors.New("题库类型错误") + } + + questionQaItemDao := dao.QuestionQaItemDao{} + + // 题目数据-必备选中 + maps := make(map[string]interface{}) + maps["qa_id"] = questionQa.QaId + maps["is_must_select"] = 1 + mustQuestions, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) + + // 题目数据-未比被选中 + maps = make(map[string]interface{}) + maps["qa_id"] = questionQa.QaId + maps["is_must_select"] = 0 + notMustQuestions, err := questionQaItemDao.GetQuestionQaItemPreloadList(maps) + + // 打乱数据 + rand.Shuffle(len(notMustQuestions), func(i, j int) { + notMustQuestions[i], notMustQuestions[j] = notMustQuestions[j], notMustQuestions[i] + }) + + // json转结构体-飞花令题目数量规则 + var tokenQuestionContents []tokenQuestionContent + err = json.Unmarshal([]byte(questionQa.TokenQuestionContent), &tokenQuestionContents) + if err != nil { + return g, errors.New(err.Error()) + } + + // 获取题库飞花令数据-列表 + baseTokenItems, err := r.GetQuestionQaBaseTokenItemList(questionQa.QaDisplayType, questionQa.QaId, *questionQa.TokenNum) + if err != nil { + return g, errors.New(err.Error()) + } + + for i := 0; i < *questionQa.RoundNum; i++ { + // 单轮次返回值 + shareDtoForThree := &dto.ShareDtoForThree{ + Single: nil, + Multiple: nil, + Judge: nil, + Qa: nil, + } + + shareDto := &dto.ShareDto{} + + // 套题规则 [{"question_type":1,"quantity":10},{"question_type":2,"quantity":0},{"question_type":3,"quantity":0},{"question_type":4,"quantity":0}] + for _, v2 := range tokenQuestionContents { + // 题目数据 + var questions []*model.Question + + // 必选数据 + for _, v3 := range mustQuestions { + // 此处标识已用过 + if v3 == nil { + continue + } + + // 类型相同,加入该组数据中 + if v2.QuestionType == v3.Question.QuestionType { + // 当数量超出时,跳出 + if len(questions) >= v2.Quantity { + continue + } + + questions = append(questions, v3.Question) + + // 标记已被使用 + v3 = nil + } + } + + // 题目数据-剩余随机数量 + remainingQuantity := v2.Quantity - len(questions) + if remainingQuantity > 0 { + // 非必选数据 + for _, v3 := range notMustQuestions { + // 此处标识已用过 + if v3 == nil { + continue + } + + // 当数量超出时,跳出 + if len(questions) >= v2.Quantity { + continue + } + + questions = append(questions, v3.Question) + + // 标记已被使用 + v3 = nil + } + } + + // 处理数据 + for _, v3 := range questions { + questionOptionDao := dao.QuestionOptionDao{} + maps = make(map[string]interface{}) + maps["question_id"] = v3.QuestionId + questionOption, err := questionOptionDao.GetQuestionOptionList(maps) + if err != nil { + return g, errors.New("内部错误1") + } + + // 处理返回值 + questionDto := dto.GetShareQuestionDto(v3) + + // 加载选项 + questionDto.LoadQuestionOptionSimplify(questionOption) + + // 加载图片 + questionDto.LoadQuestionImage(v3.QuestionImage) + + // 加载答案 + questionDto.LoadQuestionAnswer(v3) + + shareDto.Question = append(shareDto.Question, questionDto) + } + + // 处理对应飞花令数据 + for _, item := range baseTokenItems { + if len(shareDto.BaseTokenItem) < v2.Quantity { + questionDto := dto.GetBaseTokenItemDto(item) + shareDto.BaseTokenItem = append(shareDto.BaseTokenItem, questionDto) + } + } + + // 填入对应类别 + if v2.QuestionType == 1 { + shareDtoForThree.Single = shareDto + } else if v2.QuestionType == 2 { + shareDtoForThree.Multiple = shareDto + } else if v2.QuestionType == 2 { + shareDtoForThree.Judge = shareDto + } else if v2.QuestionType == 2 { + shareDtoForThree.Qa = shareDto + } else { + return g, errors.New("内部错误") + } + } + + // 添加如总数据 + g = append(g, shareDtoForThree) + } + + return g, nil +}