diff --git a/api/errcode/errcode.go b/api/errcode/errcode.go index 4a0efe65..1b57d323 100644 --- a/api/errcode/errcode.go +++ b/api/errcode/errcode.go @@ -10,6 +10,7 @@ var ErrCodeMsgMap = map[ErrCode]string{ ErrCodeApolloReadFail: "Apollo配置读取失败,请立即联系管理员", ErrCodeApolloVersionFormatError: "Apollo版本号配置格式错误", ErrCodeUserVersionFormatError: "用户上送版本号格式错误", + ErrCodeIndexOutOfRange: "数组越界", ErrCodeAssertionFail: "严重错误:类型断言异常,请立即联系管理员", ErrCodeSelfOnlyOperation: "权限不足:该操作仅可对当前登录用户执行", ErrCodeRolePrivilegesNotEnough: "权限不足:当前用户角色禁止执行该操作", @@ -238,6 +239,7 @@ const ( ErrCodeAssertionFail ErrCode = -12 // 类型断言异常 ErrCodeApolloVersionFormatError ErrCode = -13 // Apollo版本号配置格式错误 ErrCodeUserVersionFormatError ErrCode = -14 // 用户上送版本号格式错误 + ErrCodeIndexOutOfRange ErrCode = -15 // 数组越界 ErrCodeSelfOnlyOperation ErrCode = -20 // 权限不足:该操作仅可对当前登录用户执行 ErrCodeRolePrivilegesNotEnough ErrCode = -21 // 权限不足: 当前用户角色禁止执行该操作 ErrCodeOpRoleOnlyOperation ErrCode = -22 // 权限不足: 后台系统仅允许超级管理员和运营操作 diff --git a/api/proto/Raven_IQ_test/proto/Raven_IQ_test_vo_api.go b/api/proto/Raven_IQ_test/proto/Raven_IQ_test_vo_api.go index b3581490..8f52a4ad 100644 --- a/api/proto/Raven_IQ_test/proto/Raven_IQ_test_vo_api.go +++ b/api/proto/Raven_IQ_test/proto/Raven_IQ_test_vo_api.go @@ -10,6 +10,7 @@ type ApiListVO struct { UserId int64 `json:"user_id"` // 用户id Age int64 `json:"age"` // 年龄 TotalScore float64 `json:"total_score"` // 总得分 + IQ int64 `json:"IQ"` // 智商值 *apollostruct.IQResult ClassScoreList []*ApiClassScoreVO `json:"class_score_list"` // 大类得分list } @@ -30,12 +31,13 @@ func (vo *ApiListVO) CopyRavenIQTest(test *dbstruct.RavenIQTest) *ApiListVO { vo.UserId = test.GetUserId() vo.Age = test.GetAge() vo.TotalScore = test.GetTotalScore() + vo.IQ = test.GetIQ() vo.IQBlockId = test.GetIQBlockId() vo.ClassScoreList = make([]*ApiClassScoreVO, 0) for _, score := range test.ClassScoreList { vo.ClassScoreList = append(vo.ClassScoreList, &ApiClassScoreVO{ ClassBlockId: score.GetClassBlockId(), - Score: score.GetScore(), + Score: score.GetConvertedScore(), ClassInfo: &apollostruct.ClassInfo{ ClassId: score.GetClassId(), }, diff --git a/apollostruct/RavenIQtest.go b/apollostruct/RavenIQtest.go index 402ab644..02a43c72 100644 --- a/apollostruct/RavenIQtest.go +++ b/apollostruct/RavenIQtest.go @@ -12,11 +12,13 @@ type RavenIQTestQuestion struct { } type IQResult struct { - IQBlockId int64 `json:"IQ_Block_Id"` // IQ分段id - IQGrade string `json:"IQ_grade"` // 智商等级 - Percentile int64 `json:"percentile"` // 百分位 - Description string `json:"description"` // 描述 - Suggestions []string `json:"suggestions"` // 建议 + IQBlockId int64 `json:"IQ_Block_Id"` // IQ分段id + IQGrade string `json:"IQ_grade"` // 智商等级 + Percentile int64 `json:"percentile"` // 百分位 + IQLowerBound int64 `json:"IQ_lower_bound"` // IQ下界 + IQUpperBound int64 `json:"IQ_upper_bound"` // IQ上界 + Description string `json:"description"` // 描述 + Suggestions []string `json:"suggestions"` // 建议 } type AgeScore2IQResultMapCfg struct { @@ -40,8 +42,10 @@ type ClassResult struct { } type ClassInfo struct { - ClassId int64 `json:"class_id"` // 大类id - ClassName string `json:"class_name"` // 大类名称 + ClassId int64 `json:"class_id"` // 大类id + ClassName string `json:"class_name"` // 大类名称 + ClassTotalScore int64 `json:"class_total_score"` // 大类总分 + ClassFullScore int64 `json:"class_full_score"` // 大类满分 } type Suggestion struct { @@ -57,4 +61,5 @@ type Tip struct { type ClassResultMapCfg struct { Map map[int64]*ClassResult `json:"map"` ClassInfoMap map[int64]*ClassInfo `json:"class_info_map"` + FullScore int64 `json:"full_score"` // 满分 } diff --git a/app/mix/service/apiservice.go b/app/mix/service/apiservice.go index 87700918..b6dfa9af 100644 --- a/app/mix/service/apiservice.go +++ b/app/mix/service/apiservice.go @@ -2,6 +2,7 @@ package service import ( "fmt" + "math" "service/api/base" "service/api/consts" "service/api/errcode" @@ -3594,29 +3595,19 @@ func (s *Service) ApiCreateRavenIQTest(ctx *gin.Context, req *Raven_IQ_testproto // 缓存数据准备 questionMapcfg := apollostruct.QuestionMapCfg{} - err := apollo.GetJson(consts.QuestionMapKey, &questionMapcfg, apollo.ApolloOpts().SetNamespace("Raven_IQ_test")) + ageScore2IQResultMapCfg := apollostruct.AgeScore2IQResultMapCfg{} + classScore2ClassResultMapCfg := apollostruct.ClassScore2ClassResultMapCfg{} + IQResultMpcfg := apollostruct.IQResultMapCfg{} + classResultMpCfg := apollostruct.ClassResultMapCfg{} + keys := []string{consts.QuestionMapKey, consts.AgeScore2IQResultMapKey, consts.ClassScore2ClassResultMapKey, consts.IQResultMapKey, consts.ClassResultMapKey} + cfgs := []any{&questionMapcfg, &ageScore2IQResultMapCfg, &classScore2ClassResultMapCfg, &IQResultMpcfg, &classResultMpCfg} + err := apollo.GetJsons(keys, cfgs, apollo.ApolloOpts().SetNamespace("Raven_IQ_test")) if err != nil { logger.Error("Apollo read failed : %v", err) return -1, errcode.ErrCodeApolloReadFail } - ageScore2IQResultMapCfg := apollostruct.AgeScore2IQResultMapCfg{} - err = apollo.GetJson(consts.AgeScore2IQResultMapKey, &ageScore2IQResultMapCfg, apollo.ApolloOpts().SetNamespace("Raven_IQ_test")) - if err != nil { - logger.Error("Apollo read failed : %v", err) - ec = errcode.ErrCodeApolloReadFail - return - } - - classScore2ClassResultMapCfg := apollostruct.ClassScore2ClassResultMapCfg{} - err = apollo.GetJson(consts.ClassScore2ClassResultMapKey, &classScore2ClassResultMapCfg, apollo.ApolloOpts().SetNamespace("Raven_IQ_test")) - if err != nil { - logger.Error("Apollo read failed : %v", err) - ec = errcode.ErrCodeApolloReadFail - return - } - - // 计算总得分 + // 计算大类得分、总得分情况 classScoreMap := make(map[int64]int64) for _, classId := range questionMapcfg.ClassList { classScoreMap[classId] = 0 @@ -3634,18 +3625,25 @@ func (s *Service) ApiCreateRavenIQTest(ctx *gin.Context, req *Raven_IQ_testproto req.ClassScoreList = make([]*dbstruct.RavenIQTestClassScore, 0) totalScore := float64(0) for classId, score := range classScoreMap { + classInfo := classResultMpCfg.ClassInfoMap[classId] + covertedScore := int64(math.Ceil(((float64(score) / float64(classInfo.ClassTotalScore) * float64(classResultMpCfg.FullScore)) + float64(classInfo.ClassFullScore)) / 2)) req.ClassScoreList = append(req.ClassScoreList, &dbstruct.RavenIQTestClassScore{ - ClassId: goproto.Int64(classId), - Score: goproto.Int64(score), + ClassId: goproto.Int64(classId), + Score: goproto.Int64(score), + ConvertedScore: goproto.Int64(covertedScore), }) totalScore += float64(score) } req.TotalScore = goproto.Float64(totalScore) - // 换算智商及百分位 + // 获取IQ分组id ageBlockIdx := util.GetLastLessOrEqualForInt64(ageScore2IQResultMapCfg.AgeBlockList, req.GetAge()) list := ageScore2IQResultMapCfg.AgeBlockIndex2ScoreBlockListMap[ageBlockIdx] scoreBlockIdx := util.GetLastLessOrEqualForFloat64(list, req.GetTotalScore()) + if scoreBlockIdx == -1 || scoreBlockIdx >= len(list)-1 { + logger.Error("array index out of bound...") + return -1, errcode.ErrCodeIndexOutOfRange + } IQBlockId := ageScore2IQResultMapCfg.ScoreBlockIndex2IQBlockIdMap[scoreBlockIdx] for _, classScore := range req.ClassScoreList { @@ -3656,6 +3654,13 @@ func (s *Service) ApiCreateRavenIQTest(ctx *gin.Context, req *Raven_IQ_testproto req.IQBlockId = goproto.Int64(IQBlockId) + // 计算智商 + totalScoreLowerBound := list[scoreBlockIdx] + totalScoreUpperBound := list[scoreBlockIdx+1] + IQLowerBound := float64(IQResultMpcfg.Map[IQBlockId].IQLowerBound) + IQUpperBound := float64(IQResultMpcfg.Map[IQBlockId].IQUpperBound) + req.IQ = goproto.Int64(int64(math.Ceil(float64(totalScore-totalScoreLowerBound)/float64(totalScoreUpperBound-totalScoreLowerBound)*(IQUpperBound-IQLowerBound) + IQLowerBound))) + err = _DefaultRavenIQTest.OpCreate(ctx, &Raven_IQ_testproto.OpCreateReq{ BaseRequest: req.BaseRequest, RavenIQTest: req.RavenIQTest, diff --git a/dbstruct/RavenIQTest.go b/dbstruct/RavenIQTest.go index 84620a5f..27ea68bc 100644 --- a/dbstruct/RavenIQTest.go +++ b/dbstruct/RavenIQTest.go @@ -6,6 +6,7 @@ type RavenIQTest struct { Age *int64 `json:"age" bson:"age"` // 年龄 TotalScore *float64 `json:"total_score" bson:"total_score"` // 总得分 IQBlockId *int64 `json:"IQ_block_id" bson:"IQ_block_id"` // 智商值key + IQ *int64 `json:"IQ" bson:"IQ"` // 智商值 AnswerList []*RavenIQTestAnswer `json:"answer_list" bson:"answer_list"` // 答案list ClassScoreList []*RavenIQTestClassScore `json:"class_score_list" bson:"class_score_list"` // 大类得分list Ct *int64 `json:"ct" bson:"ct"` // 创建时间 @@ -19,9 +20,10 @@ type RavenIQTestAnswer struct { } type RavenIQTestClassScore struct { - ClassId *int64 `json:"class_id" bson:"class_id"` // 大类id - Score *int64 `json:"score" bson:"score"` // 得分 - ClassBlockId *int64 `json:"class_block_id" bson:"class_block_id"` // 大类得分key + ClassId *int64 `json:"class_id" bson:"class_id"` // 大类id + Score *int64 `json:"score" bson:"score"` // 得分 + ClassBlockId *int64 `json:"class_block_id" bson:"class_block_id"` // 大类得分key + ConvertedScore *int64 `json:"converted_score" bson:"converted_score"` // 折算后得分 } func (p *RavenIQTest) GetId() int64 { @@ -59,6 +61,13 @@ func (p *RavenIQTest) GetIQBlockId() int64 { return *p.IQBlockId } +func (p *RavenIQTest) GetIQ() int64 { + if p == nil || p.IQ == nil { + return 0 + } + return *p.IQ +} + func (p *RavenIQTestAnswer) GetQuestionId() int64 { if p == nil || p.QuestionId == nil { return 0 @@ -87,6 +96,13 @@ func (p *RavenIQTestClassScore) GetScore() int64 { return *p.Score } +func (p *RavenIQTestClassScore) GetConvertedScore() int64 { + if p == nil || p.ConvertedScore == nil { + return 0 + } + return *p.ConvertedScore +} + func (p *RavenIQTestClassScore) GetClassBlockId() int64 { if p == nil || p.ClassBlockId == nil { return 0 diff --git a/library/apollo/apollo.go b/library/apollo/apollo.go index 87e96a6e..b9b523dc 100644 --- a/library/apollo/apollo.go +++ b/library/apollo/apollo.go @@ -147,3 +147,23 @@ func GetFloat64Value(key string, opts ...*ApolloOptions) (value float64, err err } return } + +func GetJsons(keys []string, vs []interface{}, opts ...*ApolloOptions) (err error) { + opt := mergeApolloOptions(opts...) + for i, key := range keys { + var value string + if opt.GetNamespace() != "" { + value = defaultApolloClient.GetConfig(opt.GetNamespace()).GetStringValue(key, opt.GetDefaultValue()) + } else { + value = defaultApolloClient.GetStringValue(key, opt.GetDefaultValue()) + } + if value != "" { + err = json.Unmarshal([]byte(value), vs[i]) + if err != nil { + return + } + } + } + + return +}