knowledge-api/api/service/QuestionQa.go

1210 lines
32 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"errors"
"fmt"
"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"
)
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) {
// 处理图片
if req.Image != "" {
req.Image = utils.RemoveOssDomain(req.Image)
}
// 验证过期时间
now := time.Now()
// 1:绝对时效
// 获取本地时区
location, err := time.LoadLocation("Local")
if err != nil {
return false, errors.New("新增失败")
}
qaExpireTime, err := time.ParseInLocation("2006-01-02 15:04", req.QaExpireTime, location)
if err != nil {
return false, errors.New("过期时间错误")
}
if qaExpireTime.Before(now) {
return false, errors.New("过期时间需大于当前时间")
}
// 处理明细选题规则
questionQaItemContent, err := json.Marshal(req.QuestionQaItem)
if err != nil {
return false, errors.New("明细题目错误")
}
// 获取并检测题库题目数量
qaQuantity, err := r.CheckAddQaQuestionQuantity(req)
if err != nil {
return false, err
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 新增题目
questionQa := &model.QuestionQa{
QaName: req.QaName,
QaType: req.QaType,
QaQuantity: qaQuantity,
QaStatus: 1,
QaRuleContent: req.QaRuleContent,
TokenNum: nil,
RoundNum: nil,
QaDisplayType: req.QaDisplayType,
QaExpireTime: model.LocalTime(qaExpireTime),
QaPassword: req.QaPassword,
OpenNumber: 0,
Image: req.Image,
ItemContent: string(questionQaItemContent),
}
// 固定套题模式-飞花令数量
if req.QaType == 2 {
questionQa.TokenNum = req.TokenNum
}
// 多轮固定题型模式-飞花令数量、轮次数量
if req.QaType == 3 {
questionQa.TokenNum = req.TokenNum
questionQa.RoundNum = req.RoundNum
}
if req.QaType == 2 || req.QaType == 3 {
// 处理飞花令题目数量规则
tokenQuestionContent, err := json.Marshal(req.TokenQuestionContent)
if err != nil {
return false, errors.New("飞花令题目数量错误")
}
questionQa.TokenQuestionContent = string(tokenQuestionContent)
}
questionQaDao := dao.QuestionQaDao{}
questionQa, err = questionQaDao.AddQuestionQa(tx, questionQa)
if err != nil {
tx.Rollback()
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))
err = questionQaDao.EditQuestionQaById(tx, questionQa.QaId, questionQaData)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
// 新增问答题库题目列表
questionDao := dao.QuestionDao{}
questionQaItemDao := dao.QuestionQaItemDao{}
for _, item := range req.QuestionQaItem {
// 验证数量
maps := make(map[string]interface{})
maps["question_type"] = item.QuestionType
maps["question_status"] = 1
maps["is_delete"] = 0
maps["question_source"] = 1
if item.Difficulty != nil {
maps["difficulty"] = item.Difficulty
}
maps["first_label_id"] = item.FirstLabelId
if item.SecondLabelId != "" {
maps["second_label_id"] = item.SecondLabelId
}
// 获取随机明细题目
questions, err := questionDao.GetQuestionListRand(maps, item.Quantity)
if err != nil {
tx.Rollback()
return false, err
}
if len(questions) < item.Quantity {
tx.Rollback()
return false, errors.New("选题超出可选择题目数量")
}
// 新增明细题目
for _, question := range questions {
questionQaItem := &model.QuestionQaItem{
QaId: questionQa.QaId,
QuestionId: question.QuestionId,
}
questionQaItem, err := questionQaItemDao.AddQuestionQaItem(tx, questionQaItem)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
}
tx.Commit()
return true, nil
}
// PutQuestionQa 修改题目题库
func (r *QuestionQaService) PutQuestionQa(qaId int64, req requests.PutQuestionQa) (bool, error) {
questionQaDao := dao.QuestionQaDao{}
questionDao := dao.QuestionDao{}
questionQa, err := questionQaDao.GetQuestionQaById(qaId)
if err != nil {
return false, errors.New("题库不存在")
}
if questionQa.QaStatus == 2 {
return false, errors.New("题库已失效,请重新创建")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
questionQaData := make(map[string]interface{})
// 名称
if req.QaName != questionQa.QaName {
questionQaData["qa_name"] = req.QaName
}
// 规则解释
if req.QaRuleContent != questionQa.QaRuleContent {
questionQaData["qa_rule_content"] = req.QaRuleContent
}
// 展示类型
if req.QaDisplayType != questionQa.QaDisplayType {
questionQaData["qa_display_type"] = req.QaDisplayType
}
// 验证过期时间
now := time.Now()
// 1:绝对时效
// 获取本地时区
location, err := time.LoadLocation("Local")
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
qaExpireTime, err := time.ParseInLocation("2006-01-02 15:04", req.QaExpireTime, location)
if err != nil {
tx.Rollback()
return false, errors.New("过期时间错误")
}
if qaExpireTime.Before(now) {
tx.Rollback()
return false, errors.New("过期时间需大于当前时间")
}
// 分享密码
if req.QaPassword != questionQa.QaPassword {
questionQaData["qa_password"] = req.QaPassword
}
// 背景图
image := utils.RemoveOssDomain(req.Image)
if image != questionQa.Image {
questionQaData["image"] = image
}
// 处理飞花令题目数量规则
tokenQuestionContent, _ := json.Marshal(req.TokenQuestionContent)
if string(tokenQuestionContent) != questionQa.TokenQuestionContent {
questionQaData["token_question_content"] = string(tokenQuestionContent)
}
// 获取并检测题库题目数量
qaQuantity, err := r.CheckPutQaQuestionQuantity(req)
if err != nil {
tx.Rollback()
return false, err
}
// 题目数量
if qaQuantity != questionQa.QaQuantity {
if req.Action == 1 {
tx.Rollback()
return false, errors.New("您修改了题目数量,无法正常修改该题库,请重新生成")
}
questionQaData["qa_quantity"] = req.QaQuantity
}
// 处理题库明细-需重新生成时才会检测明细
if req.Action == 2 {
// 删除所有明细
questionQaItemDao := dao.QuestionQaItemDao{}
err := questionQaItemDao.DeleteQuestionQaItemByQaId(tx, questionQa.QaId)
if err != nil {
tx.Rollback()
return false, err
}
for _, item := range req.QuestionQaItem {
// 验证数量
maps := make(map[string]interface{})
maps["question_type"] = item.QuestionType
maps["question_status"] = 1
maps["is_delete"] = 0
maps["question_source"] = 1
if item.Difficulty != nil {
maps["difficulty"] = item.Difficulty
}
maps["first_label_id"] = item.FirstLabelId
if item.SecondLabelId != "" {
maps["second_label_id"] = item.SecondLabelId
}
// 获取随机明细题目
questions, err := questionDao.GetQuestionListRand(maps, item.Quantity)
if err != nil {
tx.Rollback()
return false, err
}
if len(questions) < item.Quantity {
tx.Rollback()
return false, errors.New("选题超出现有题目数量")
}
for _, question := range questions {
questionQaItem := &model.QuestionQaItem{
QaId: questionQa.QaId,
QuestionId: question.QuestionId,
}
questionQaItem, err := questionQaItemDao.AddQuestionQaItem(tx, questionQaItem)
if err != nil {
tx.Rollback()
return false, errors.New("新增失败")
}
}
}
// 处理明细选题规则
questionQaItemContent, err := json.Marshal(req.QuestionQaItem)
if err != nil {
tx.Rollback()
return false, err
}
if string(questionQaItemContent) != questionQa.ItemContent {
questionQaData["item_content"] = string(questionQaItemContent)
}
}
if len(questionQaData) > 0 {
err = questionQaDao.EditQuestionQaById(tx, questionQa.QaId, questionQaData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
}
// 删除飞花令
questionQaTokenDao := dao.QuestionQaTokenDao{}
maps := make(map[string]interface{})
maps["qa_id"] = questionQa.QaId
err = questionQaTokenDao.DeleteQuestionQaToken(tx, maps)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
// 新增飞花令
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 {
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("已选择飞花令的数量不满足题库使用")
}
}
}
tx.Commit()
return true, nil
}
// PutQuestionQaPassword 修改题目题库密码
func (r *QuestionQaService) PutQuestionQaPassword(qaId int64, req requests.PutQuestionQaPassword) (bool, error) {
questionQaDao := dao.QuestionQaDao{}
questionQa, err := questionQaDao.GetQuestionQaById(qaId)
if err != nil {
return false, errors.New("题库不存在")
}
if questionQa.QaStatus == 2 {
return false, errors.New("题库已失效")
}
// 分享密码
if req.QaPassword == questionQa.QaPassword {
return true, nil
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
questionQaData := make(map[string]interface{})
questionQaData["qa_password"] = req.QaPassword
err = questionQaDao.EditQuestionQaById(tx, questionQa.QaId, questionQaData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// PutQuestionQaExpire 修改问答题库有效期
func (r *QuestionQaService) PutQuestionQaExpire(qaId int64, req requests.PutQuestionQaExpire) (bool, error) {
questionQaDao := dao.QuestionQaDao{}
questionQa, err := questionQaDao.GetQuestionQaById(qaId)
if err != nil {
return false, errors.New("题库不存在")
}
if questionQa.QaStatus == 2 {
return false, errors.New("题库已失效")
}
// 验证过期时间
now := time.Now()
// 获取本地时区
location, err := time.LoadLocation("Local")
if err != nil {
return false, errors.New("修改失败")
}
qaExpireTime, err := time.ParseInLocation("2006-01-02 15:04", req.QaExpireTime, location)
if err != nil {
return false, errors.New("过期时间错误")
}
if qaExpireTime.Before(now) {
return false, errors.New("过期时间需大于当前时间")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
questionQaData := make(map[string]interface{})
questionQaData["qa_expire_time"] = qaExpireTime
err = questionQaDao.EditQuestionQaById(tx, questionQa.QaId, questionQaData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// PutQuestionQaRule 修改问答题库规则解释
func (r *QuestionQaService) PutQuestionQaRule(qaId int64, req requests.PutQuestionQaRule) (bool, error) {
questionQaDao := dao.QuestionQaDao{}
questionQa, err := questionQaDao.GetQuestionQaById(qaId)
if err != nil {
return false, errors.New("题库不存在")
}
if questionQa.QaStatus == 2 {
return false, errors.New("题库已失效")
}
// 分享密码
if req.QaRuleContent == questionQa.QaRuleContent {
return true, nil
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
questionQaData := make(map[string]interface{})
questionQaData["qa_rule_content"] = req.QaRuleContent
err = questionQaDao.EditQuestionQaById(tx, questionQa.QaId, questionQaData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// RecordQuestionQaOpenNum 记录问答题库打开次数
func (r *QuestionQaService) RecordQuestionQaOpenNum(tx *gorm.DB, qaId int64) error {
questionQaDao := dao.QuestionQaDao{}
err := questionQaDao.Inc(tx, qaId, "open_number", 1)
if err != nil {
return 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
}