123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746 |
- package service
- import (
- "context"
- "encoding/json"
- "fmt"
- "strconv"
- "time"
- "go-common/app/interface/main/answer/conf"
- "go-common/app/interface/main/answer/model"
- accoutCli "go-common/app/service/main/account/api"
- "go-common/library/ecode"
- "go-common/library/log"
- "go-common/library/log/infoc"
- "go-common/library/net/metadata"
- "go-common/library/text/translate/chinese"
- )
- var (
- // concat type type_id : _pendantIDNameMap id
- _rankIDPendantMap = map[int]int{
- // 11: 6,
- // 12: 7,
- // 14: 8,
- // 15: 9,
- // 17: 11,
- // 27: 10,
- // 28: 12,
- // 41: 13,
- // 9: 14,
- 27: 124,
- 28: 127,
- 31: 126,
- 29: 123,
- 18: 121,
- 8: 125,
- 19: 129,
- 15: 130,
- 7: 128,
- }
- // concat pendant
- _pendantIDNameMap = map[int]string{
- 5: "哔哩王",
- 6: "声控",
- 7: "追番党",
- 8: "调教师",
- 9: "动感DJ",
- 10: "局座",
- 11: "攻略组",
- 12: "学霸",
- 13: "迷影者",
- 14: "全明星",
- 122: "哔哩王",
- 124: "声控",
- 127: "追番党",
- 126: "调教师",
- 123: "动感DJ",
- 121: "局座",
- 125: "攻略组",
- 129: "学霸",
- 130: "迷影者",
- 128: "全明星",
- }
- // 老挂件id对应新挂件id
- _oldPIDToNewMap = map[int]int{
- 5: 122,
- 6: 124,
- 7: 127,
- 8: 126,
- 9: 123,
- 10: 121,
- 11: 125,
- 12: 129,
- 13: 130,
- 14: 128,
- 122: 122,
- 124: 124,
- 127: 127,
- 126: 126,
- 123: 123,
- 121: 121,
- 125: 125,
- 129: 129,
- 130: 130,
- 128: 128,
- }
- _pendantIDImgMap = map[int]string{
- 122: "/bfs/face/67ed957ae789852bcc59b1c1e3097ea23179f793.png",
- 124: "/bfs/face/ff61b405cdcf8f7860c67293218340aeaed6e233.png",
- 127: "/bfs/face/369098093a07af821b767eac44b51f97ee8501c5.png",
- 126: "/bfs/face/9e775c3ebe224a774d4b2f99fd5be342eb6f51ec.png",
- 123: "/bfs/face/939fa982d8b1c1fd653de5c7890db03d62e87226.png",
- 121: "/bfs/face/7f6b5cb11ea7abd2e05b04f65f190dfb10456554.png",
- 125: "/bfs/face/90cc47168e40326dc934fad7b9abb82aa748d6ac.png",
- 129: "/bfs/face/42869dad53926c75e3010150c15b16a8925fb268.png",
- 130: "/bfs/face/3d5ee491c125bf452b2dbec082dbb8209b645316.png",
- 128: "/bfs/face/b53937110e8009a720e2426ea69c449483718b3c.png",
- }
- // 125: "攻略组",--> 题库(8,9,12,13,14)
- // 130: "迷影者",--> 题库(15,16,17)
- // 121: "局座",--> 题库(18)
- // 129: "学霸",--> 题库(19,20,21,22,23,24,25,26)
- // 124: "声控",--> 题库(27)
- // 127: "追番党",--> 题库(28)
- // 126: "调教师",--> 题库(31)
- // 123: "动感DJ",--> 题库(30,29)
- // 128: "全明星",--> 题库(35,34,33,32)
- // 122: "哔哩王",
- // 分区合并归类
- _typeIDMap = map[int][]int{
- // 11: {12, 13}, // 动漫作品+动漫内容
- // 15: {15, 16}, // ACG+三次元音乐
- // 17: {17, 18, 19, 20, 21, 22, 23, 24, 25}, // 各类游戏
- // 28: {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 7, 8}, // 科学技术+音频+视频技术
- // 41: {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52}, // 各类影视剧
- 8: {8, 9, 12, 13, 14}, // 游戏
- 19: {19, 20, 21, 22, 23, 24, 25, 26}, // 科技
- 15: {15, 16, 17}, // 影视
- 29: {29, 30}, // 音乐
- 7: {7, 35, 34, 33, 32}, // 鬼畜+流行前线
- }
- // 兼容账号rank错误
- _rank0 = int32(0)
- )
- const (
- _unBindTel = 0
- )
- // ProCheck check second step questions
- func (s *Service) ProCheck(c context.Context, mid int64, ids []int64, ansHash map[int64]string, lang string) (hid int64, err error) {
- var now = time.Now()
- if len(ids) != s.c.Answer.ProNum {
- err = ecode.AnswerQsNumErr
- return
- }
- if s.checkAnswerBlock(c, mid) {
- err = ecode.AnswerBlock
- return
- }
- ah, err := s.history(c, mid)
- if err != nil || ah == nil || ah.StartTime.Add(s.answerDuration()).Before(now) || ah.Score != 0 {
- err = ecode.AnswerBaseNotPassed
- return
- }
- if (now.Unix() - ah.StepTwoStartTime.Unix()) < s.c.Answer.BlockedTimestamp {
- s.answerDao.SetBlockCache(c, mid)
- log.Error("member user answer block, time space(%v)", now.Unix()-ah.StepTwoStartTime.Unix())
- err = ecode.AnswerBlock
- return
- }
- qsidsMc, err := s.answerDao.IdsCache(c, mid, model.Q)
- if err != nil {
- err = ecode.AnswerMidCacheQidsErr
- log.Error("s.answerDao.IdsCache(%d) err(%v) ", mid, err)
- return
- }
- ok, err := s.checkQsIDs(c, ids, mid, qsidsMc, s.c.Answer.ProNum)
- if !ok {
- return
- }
- errIds, rc, err := s.checkAns(c, mid, ids, ansHash, lang, s.c.Answer.ProNum)
- if err != nil {
- return
- }
- rcJSON, err := json.Marshal(rc)
- if err != nil {
- log.Error("json.Marshal(%v) error(%v)", rc, err)
- return
- }
- total := s.c.Answer.BaseNum + s.c.Answer.ProNum + int(ah.StepExtraScore)
- score := total - len(errIds)
- ahDB := &model.AnswerHistory{
- ID: ah.ID,
- Hid: ah.Hid,
- CompleteResult: string(rcJSON),
- CompleteTime: now,
- Score: int8(score),
- IsFirstPass: 0,
- }
- log.Info("user: %d, score:%d, his: %v", mid, score, ahDB)
- member, err := s.accInfo(c, mid)
- if err == nil && member != nil && score >= model.Score60 && member.Rank == model.UserInfoRank {
- ahDB.IsFirstPass = 1
- }
- ahDB.RankID = s.pendant(c, ahDB, mid, metadata.String(c, metadata.RemoteIP), rc)
- r, err := s.answerDao.SetHistory(c, mid, ahDB)
- if err != nil || r != 1 {
- return
- }
- ah.CompleteResult = ahDB.CompleteResult
- ah.CompleteTime = ahDB.CompleteTime
- ah.Score = ahDB.Score
- ah.IsFirstPass = ahDB.IsFirstPass
- ah.RankID = ahDB.RankID
- ah.Mtime = now
- s.userActionLog(mid, model.ProCheck, ah)
- if ahDB.Score >= model.Score60 && ahDB.RankID > 0 {
- if hid, _, err = s.answerDao.PendantHistory(c, mid); err != nil {
- return
- }
- if hid <= 0 {
- s.answerDao.AddPendantHistory(c, mid, ah.Hid)
- }
- }
- hid = ah.Hid
- s.missch.Do(c, func(ctx context.Context) {
- s.answerDao.DelHistoryCache(ctx, mid)
- s.answerDao.DelIdsCache(ctx, mid, model.Q)
- })
- return
- }
- // CheckBase check base question all
- func (s *Service) CheckBase(c context.Context, mid int64, ids []int64, ansHas map[int64]string, lang string) (res *model.AnsCheck, err error) {
- var (
- now = time.Now()
- errIds []int64
- profileReply *accoutCli.ProfileReply
- )
- // 检查手机绑定
- if profileReply, err = s.accountSvc.Profile3(c, &accoutCli.MidReq{Mid: mid}); err != nil || profileReply == nil || profileReply.Profile == nil {
- log.Error("s.accRPC.Profile3(%d) err(%+v)", mid, err)
- err = ecode.AnswerAccCallErr
- return
- }
- if profileReply.Profile.TelStatus == _unBindTel {
- err = ecode.AnswerNeedBindTel
- return
- }
- if len(ids) < s.c.Answer.BaseNum {
- err = ecode.RequestErr
- return
- }
- if s.checkAnswerBlock(c, mid) {
- err = ecode.AnswerBlock
- return
- }
- res = &model.AnsCheck{}
- at, ok := s.checkTime(c, mid, now)
- if !ok {
- err = ecode.AnswerTimeExpire
- return
- }
- if len(ids) != s.c.Answer.BaseNum {
- err = ecode.AnswerQsNumErr
- return
- }
- qsIdsMc, err := s.answerDao.IdsCache(c, mid, model.Q)
- if err != nil {
- log.Error("s.answerDao.IdsCache(%d) err(%v) ", mid, err)
- err = ecode.AnswerMidCacheQidsErr
- return
- }
- ok, err = s.checkQsIDs(c, ids, mid, qsIdsMc, s.c.Answer.BaseNum)
- if err != nil || !ok {
- return
- }
- errIds, _, err = s.checkAns(c, mid, ids, ansHas, lang, s.c.Answer.BaseNum)
- res.QidList = errIds
- if err != nil {
- return
- }
- if len(errIds) > 0 {
- return
- }
- s.basePass(c, mid, at, now)
- res.Pass = true
- return
- }
- // Captcha get question captcha
- func (s *Service) Captcha(c context.Context, mid int64, clientType string, newCaptcha int) (res *model.ProcessRes, err error) {
- if s.checkAnswerBlock(c, mid) {
- err = ecode.AnswerBlock
- return
- }
- ah, err := s.history(c, mid)
- if err != nil || ah == nil || ah.Score == model.Score0 {
- log.Info("answer Captcha(%d) answer history is null or score is zero err(%v) ", mid, err)
- if ah != nil {
- if ah.StepOneCompleteTime == 0 {
- err = ecode.AnswerBaseNotPassed
- return
- }
- if ah.StepExtraCompleteTime == 0 {
- err = ecode.AnswerExtraNoPass
- return
- }
- }
- err = ecode.AnswerProNoPass
- return
- }
- if ah.IsPassCaptcha == model.CaptchaPass {
- err = ecode.AnswerCaptchaPassed
- return
- }
- if !conf.Conf.Answer.Captcha {
- if res, err = s.preProcess(c, mid, metadata.String(c, metadata.RemoteIP), clientType, newCaptcha); err == nil {
- return
- }
- log.Error("s.preProcess(%d,%s,%d) err:%+v", mid, clientType, newCaptcha, err)
- }
- var token, url string
- if token, url, err = s.answerDao.Captcha(c); err != nil {
- return
- }
- res = &model.ProcessRes{
- Token: token,
- URL: url,
- CaptchaType: model.BiliCaptcha,
- }
- return
- }
- // Validate check question captcha
- func (s *Service) Validate(c context.Context, challenge, validate, seccode, clientType string, success int, mid int64,
- cookie, captchaType string, comargs map[string]string) (res *model.AnsCheck, err error) {
- var now = time.Now()
- if s.checkAnswerBlock(c, mid) {
- err = ecode.AnswerBlock
- return
- }
- res = &model.AnsCheck{}
- ah, err := s.history(c, mid)
- log.Info(" Validate ah (%d) res(%v) ", mid, ah)
- if err != nil || ah == nil || ah.Score == model.Score0 {
- log.Info("answer Validate(%d) answer history is null or score is zero err(%v) ", mid, err)
- if ah != nil {
- if ah.StepOneCompleteTime == 0 {
- err = ecode.AnswerBaseNotPassed
- return
- }
- if ah.StepExtraCompleteTime == 0 {
- err = ecode.AnswerExtraNoPass
- return
- }
- }
- err = ecode.AnswerProNoPass
- return
- }
- // passed go to next page
- if ah.IsPassCaptcha == model.CaptchaPass {
- res.Pass = true
- res.HistoryID = ah.Hid
- return
- }
- ip := metadata.String(c, metadata.RemoteIP)
- switch captchaType {
- case model.BiliCaptcha:
- if err = s.answerDao.Verify(c, validate, seccode, ip); err != nil {
- log.Error("answerDao.Verify(%s,%s,%s) error:%+v", validate, seccode, ip, err)
- return
- }
- res.Pass = true
- default:
- if ok := s.validate(c, challenge, validate, seccode, clientType, ip, success, mid); !ok {
- log.Error("Validate validate(%v,%v,%v,%v,%v,%d) error(%v)", challenge, validate, seccode, clientType, success, mid, err)
- err = ecode.AnswerGeetestVaErr
- return
- }
- res.Pass = true
- }
- member, err := s.accInfo(c, mid)
- if err != nil || member == nil {
- log.Error("Validate accInfo(%d) info is null error(%v)", mid, err)
- return
- }
- if _, err = s.answerDao.UpdateCaptcha(c, ah.ID, ah.Mid, model.CaptchaPass); err != nil {
- log.Error("s.answerDao.UpdateCaptcha error (%v) ", err)
- err = ecode.ServerErr
- return
- }
- ah.IsPassCaptcha = model.CaptchaPass
- ah.Mtime = now
- s.userActionLog(mid, model.Captcha, ah)
- s.answerDao.DelHistoryCache(c, mid)
- log.Info(" Validate member (%v) rank(%d) ", ah, member.Rank)
- if ah.Score >= model.Score60 && (member.Rank == model.UserInfoRank || member.Rank == _rank0) {
- log.Info(" beFormal in (%d) ", mid)
- s.sendData(c, comargs, ah, ip)
- if err = s.accountDao.BeFormal(c, mid, ip); err != nil {
- log.Error(" beFormal fail(%d) err(%v)", mid, err)
- s.addRetryBeFormal(&model.Formal{Mid: mid, IP: ip})
- err = ecode.AnswerFormalFailed
- return
- }
- s.answerDao.UpdateLevel(c, ah.ID, ah.Mid, 1, 1)
- ah.IsFirstPass = 1
- ah.PassedLevel = 1
- ah.Mtime = now
- s.userActionLog(mid, model.Level, ah)
- s.answerDao.DelHistoryCache(c, mid)
- s.PendantRec(c, &model.ReqPendant{HID: ah.Hid, MID: mid})
- }
- res.HistoryID = ah.Hid
- return
- }
- // checkQsIDs check question id param.
- func (s *Service) checkQsIDs(c context.Context, ids []int64, mid int64, qsIdsMc []int64, qs int) (ok bool, err error) {
- if qsIdsMc == nil {
- log.Error("CheckBase.qsIdsMc is nil (%d,%v) )", mid, qsIdsMc)
- err = ecode.AnswerMidCacheQidsErr
- return
- }
- if len(ids) != qs {
- err = ecode.AnswerQsNumErr
- return
- }
- qidMap := map[int64]bool{}
- for _, v := range qsIdsMc {
- qidMap[v] = true
- }
- i := 0
- for _, v := range ids {
- if qidMap[v] {
- i++
- }
- }
- if i == qs {
- ok = true
- } else {
- err = ecode.AnswerQidDiffRequestErr
- }
- return
- }
- // checkAns check question ans.
- func (s *Service) checkAns(c context.Context, mid int64, ids []int64, ansHash map[int64]string, lang string, count int) (errIds []int64, rc map[int8]int, err error) {
- qs, err := s.answerDao.ByIds(c, ids)
- if err != nil || qs == nil || len(qs) != count {
- log.Error("checkAns.qs is nil (%v,%v) error(%v)", ids, qs, err)
- err = ecode.AnswerMidDBQueErr
- return
- }
- errIds = []int64{}
- rc = make(map[int8]int)
- for _, q := range qs {
- if lang == model.LangZhTW {
- q.Ans[0] = chinese.Convert(c, q.Ans[0])
- }
- if h := s.ansHash(mid, q.Ans[0]); h != ansHash[q.ID] {
- errIds = append(errIds, q.ID)
- } else {
- rc[q.TypeID]++
- }
- }
- return
- }
- // basePass base question pass.
- func (s *Service) basePass(c context.Context, mid int64, at *model.AnswerTime, now time.Time) {
- h := &model.AnswerHistory{
- Mid: mid,
- StartTime: at.Stime,
- StepOneErrTimes: at.Etimes,
- StepOneCompleteTime: now.Unix() - at.Stime.Unix(),
- Ctime: now,
- Mtime: now,
- }
- r, hid, err := s.answerDao.AddHistory(c, mid, h)
- if err != nil || r != 1 {
- log.Error("answerDao.AddHistory r !=1 (%d,%v) error(%v)", mid, h, err)
- return
- }
- h.Hid, _ = strconv.ParseInt(hid, 10, 64)
- s.userActionLog(mid, model.BasePass, h)
- s.answerDao.DelHistoryCache(c, mid)
- s.answerDao.DelExpireCache(c, mid)
- s.answerDao.DelIdsCache(c, mid, model.Q)
- }
- // setPendant set pendant.
- func (s *Service) pendant(c context.Context, ah *model.AnswerHistory, mid int64, ip string, rc map[int8]int) (rankID int) {
- var (
- ok bool
- ht int
- typeIDScore = map[int8]int{ // key:_typeIDMap`key,value:Score
- 8: 0,
- 19: 0,
- 15: 0,
- 29: 0,
- 7: 0,
- }
- )
- if ah.Score == model.FullScore {
- return model.RankTop // 122: "哔哩王",
- }
- for k, v := range rc {
- switch k {
- case 8, 9, 12, 13, 14: // 游戏 125: "攻略组",--> 题库(8,9,12,13,14)
- typeIDScore[8] += v
- case 15, 16, 17: // 影视 130: "迷影者",--> 题库(15,16,17)
- typeIDScore[15] += v
- case 19, 20, 21, 22, 23, 24, 25, 26: // 科技 129: "学霸",--> 题库(19,20,21,22,23,24,25,26)
- typeIDScore[19] += v
- case 29, 30: // 音乐 123: "动感DJ",--> 题库(30,29)
- typeIDScore[29] += v
- case 7, 35, 34, 33, 32: // 鬼畜+流行前线 128: "全明星",--> 题库(35,34,33,32)
- typeIDScore[7] += v
- default:
- // 121: "局座",--> 题库(18)
- // 124: "声控",--> 题库(27)
- // 127: "追番党",--> 题库(28)
- // 126: "调教师",--> 题库(31)
- typeIDScore[k] += v
- }
- }
- score := 0
- for k, v := range typeIDScore {
- if score < v {
- score = v
- ht = int(k)
- }
- }
- rankID, ok = _rankIDPendantMap[ht]
- if !ok {
- log.Warn("user(%d),pendant() rankId(%d) result:%+v ", mid, _rankIDPendantMap[ht], rc)
- }
- return
- }
- func (s *Service) checkAnswerBlock(c context.Context, mid int64) (block bool) {
- block, _ = s.answerDao.CheckBlockCache(c, mid)
- return
- }
- func (s *Service) sendData(c context.Context, comargs map[string]string, ah *model.AnswerHistory, ip string) {
- s.promBeFormal.Incr("count")
- // add report bigdata log
- ans := []interface{}{
- strconv.FormatInt(ah.StepOneCompleteTime, 10),
- ah.CompleteResult,
- strconv.FormatInt(ah.CompleteTime.Unix()-ah.StepTwoStartTime.Unix(), 10),
- fmt.Sprintf("%d", ah.Score),
- strconv.FormatInt(time.Now().Unix(), 10),
- }
- s.missch.Do(c, func(ctx context.Context) {
- ac := map[string]string{
- "itemType": infoc.ItemTypeLV,
- "action": infoc.ActionAnswer,
- "ip": ip,
- "mid": strconv.FormatInt(ah.Mid, 10),
- "sid": comargs["sid"],
- "ua": comargs["ua"],
- "buvid": comargs["buvid"],
- "refer": comargs["refer"],
- "url": comargs["url"],
- }
- log.Info("s.infoc2.ServiceAntiCheatBus(%v,%v)", ac, ans)
- s.infoc2.ServiceAntiCheatBus(ac, ans)
- })
- }
- // ExtraCheck extra check.
- func (s *Service) ExtraCheck(c context.Context, mid int64, ids []int64, ansHash map[int64]string, ua string, lang string, refer string, buvid string) (err error) {
- var now = time.Now()
- if len(ids) < s.c.Answer.ExtraNum {
- err = ecode.RequestErr
- return
- }
- if s.checkAnswerBlock(c, mid) {
- err = ecode.AnswerBlock
- return
- }
- ah, err := s.history(c, mid)
- if err != nil || ah == nil || ah.StartTime.Add(s.answerDuration()).Before(now) || ah.Score != 0 {
- err = ecode.AnswerBaseNotPassed
- return
- }
- if len(ids) != (s.c.Answer.BaseExtraPassNum + s.c.Answer.BaseExtraNoPassNum) {
- return ecode.AnswerQsNumErr
- }
- passids, err := s.answerDao.IdsCache(c, mid, model.BaseExtraPassQ)
- if err != nil {
- log.Error("s.answerDao.IdsCache(%d) extra pass err(%v) ", mid, err)
- return ecode.AnswerMidCacheQidsErr
- }
- nopassids, err := s.answerDao.IdsCache(c, mid, model.BaseExtraNoPassQ)
- if err != nil {
- log.Error("s.answerDao.IdsCache(%d) extra nopass err(%v) ", mid, err)
- return ecode.AnswerMidCacheQidsErr
- }
- idsmc := append(passids, nopassids...)
- ok, err := s.checkQsIDs(c, ids, mid, idsmc, s.c.Answer.BaseExtraPassNum+s.c.Answer.BaseExtraNoPassNum)
- if err != nil || !ok {
- return
- }
- ret, qs, _ := s.checkExtraPassAns(c, mid, passids, ansHash, lang, s.c.Answer.BaseExtraPassNum)
- ah.StepExtraScore = int64(ret * s.c.Answer.BaseExtraScore)
- ah.StepExtraCompleteTime = now.Unix() - ah.StartTime.Unix()
- if _, err = s.answerDao.UpdateExtraRet(c, ah.ID, mid, ah.StepExtraCompleteTime, ah.StepExtraScore); err != nil {
- log.Error("s.answerDao.UpdateExtraRet(%d) err(%v) ", mid, err)
- return
- }
- ah.Mtime = now
- s.userActionLog(mid, model.ExtraCheck, ah)
- s.answerDao.DelHistoryCache(c, mid)
- s.answerDao.DelIdsCache(c, mid, model.BaseExtraPassQ)
- s.answerDao.DelIdsCache(c, mid, model.BaseExtraNoPassQ)
- // send answer ret to bigdata
- rs, err := s.sendExtraRetMsg(c, mid, qs, nopassids, ansHash, s.c.Answer.BaseExtraNoPassNum)
- if err != nil {
- log.Error("s.sendExtraRetMsg(%d,%v,%v,%v) err(%v) ", mid, qs, nopassids, ansHash, err)
- return
- }
- s.answerDao.PubExtraRet(c, mid, &model.DataBusResult{
- Mid: mid,
- Buvid: buvid,
- IP: metadata.String(c, metadata.RemoteIP),
- Ua: ua,
- Refer: refer,
- Score: int8(ah.StepExtraScore),
- Rs: rs,
- Hid: ah.Hid,
- })
- return
- }
- // checkExtraPassAns check extra question ans.
- func (s *Service) checkExtraPassAns(c context.Context, mid int64, ids []int64, ansHash map[int64]string, lang string, count int) (ret int, qs map[int64]*model.ExtraQst, err error) {
- qs, err = s.answerDao.ExtraByIds(c, ids)
- if err != nil || qs == nil || len(qs) != count {
- log.Error("checkAns extra qs is nil (%v,%v) error(%v)", ids, qs, err)
- err = ecode.AnswerMidDBQueErr
- return
- }
- for _, q := range qs {
- var ans string
- switch q.Ans {
- case model.NormalQ:
- if lang == model.LangZhTW {
- ans = s.ansHash(mid, chinese.Convert(c, model.ExtraAnsA))
- } else {
- ans = s.ansHash(mid, model.ExtraAnsA)
- }
- case model.ViolationQ:
- if lang == model.LangZhTW {
- ans = s.ansHash(mid, chinese.Convert(c, model.ExtraAnsB))
- } else {
- ans = s.ansHash(mid, model.ExtraAnsB)
- }
- }
- if ansHash[q.ID] == ans {
- ret++
- }
- }
- return
- }
- func (s *Service) sendExtraRetMsg(c context.Context, mid int64, passqs map[int64]*model.ExtraQst, nopassids []int64,
- ansHash map[int64]string, count int) (rs []*model.Rs, err error) {
- var (
- qs map[int64]*model.ExtraQst
- )
- qs, err = s.answerDao.ExtraByIds(c, nopassids)
- if err != nil || qs == nil || len(qs) != count {
- log.Error("checkAns extra nopassqs is nil (%v) error(%v)", qs, err)
- err = ecode.AnswerMidDBQueErr
- return
- }
- for k, v := range passqs {
- qs[k] = v
- }
- for _, q := range qs {
- var (
- userAns int8
- )
- ansA := s.ansHash(mid, model.ExtraAnsA)
- ansB := s.ansHash(mid, model.ExtraAnsB)
- switch ansHash[q.ID] {
- case ansA:
- userAns = model.NormalQ
- case ansB:
- userAns = model.ViolationQ
- default:
- userAns = model.UnKownQ
- }
- rs = append(rs, &model.Rs{
- ID: q.OriginID,
- Question: q.Question,
- Ans: userAns,
- TrueAns: q.Ans,
- AvID: q.AvID,
- Status: q.Status,
- Source: q.Source,
- Ctime: q.Ctime,
- Mtime: q.Mtime,
- })
- }
- return
- }
- // PendantRec .
- func (s *Service) PendantRec(c context.Context, arg *model.ReqPendant) (err error) {
- var (
- ok bool
- status int8
- hid, ret int64
- his *model.AnswerHistory
- )
- if hid, status, err = s.answerDao.PendantHistory(c, arg.MID); err != nil {
- return
- }
- if hid != arg.HID {
- log.Warn("mid(%d) arg.hid(%d) db.hid(%d) is invald!", arg.MID, arg.HID, hid)
- return
- }
- if status != model.PendantNotGet {
- log.Warn("mid(%d) hid(%d) not first get!", arg.MID, arg.HID)
- return
- }
- his, err = s.historyByHid(c, arg.HID)
- if err != nil {
- return
- }
- if his.Score < model.Score60 || his.IsFirstPass != 1 {
- log.Warn("mid(%d) hid(%d) score(%d) isFirstPass(%d) not pass or first answer !", arg.MID, arg.HID, his.Score, his.IsFirstPass)
- return
- }
- if _, ok = _pendantIDNameMap[int(his.RankID)]; !ok {
- log.Warn("mid(%d) get illegal pid(%d) by answer first!", arg.MID, int(his.RankID))
- return
- }
- if ret, err = s.answerDao.UpPendantHistory(c, arg.MID, arg.HID); err != nil {
- return
- }
- if ret <= 0 {
- log.Warn("mid(%d) hid(%d) pid(%d) history answer not get!", arg.MID, arg.HID, int(his.RankID))
- return
- }
- s.missch.Do(c, func(ctx context.Context) {
- if pendantErr := s.accountDao.GivePendant(ctx, arg.MID, int64(his.RankID), model.PenDantDays, metadata.String(c, metadata.RemoteIP)); pendantErr != nil {
- log.Error("s.accountDao.GivePendant(%d,%d) error(%+v)", arg.MID, int64(his.RankID), pendantErr)
- }
- })
- return
- }
|