232 lines
5.9 KiB
Go
232 lines
5.9 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"time"
|
||
|
||
model "go-common/app/interface/main/credit/model"
|
||
"go-common/app/service/main/archive/api"
|
||
arcMDL "go-common/app/service/main/archive/model/archive"
|
||
blkmdl "go-common/app/service/main/member/model/block"
|
||
"go-common/library/ecode"
|
||
"go-common/library/log"
|
||
"go-common/library/net/metadata"
|
||
xtime "go-common/library/time"
|
||
"go-common/library/xstr"
|
||
)
|
||
|
||
// AddQs add labour question.
|
||
func (s *Service) AddQs(c context.Context, qs *model.LabourQs) (err error) {
|
||
return s.dao.AddQs(c, qs)
|
||
}
|
||
|
||
// SetQs set labour question field.
|
||
func (s *Service) SetQs(c context.Context, id int64, ans int64, status int64) (err error) {
|
||
return s.dao.SetQs(c, id, ans, status)
|
||
}
|
||
|
||
// DelQs del labour question.
|
||
func (s *Service) DelQs(c context.Context, id int64, isDel int64) (err error) {
|
||
return s.dao.DelQs(c, id, isDel)
|
||
}
|
||
|
||
// GetQs get question.
|
||
func (s *Service) GetQs(c context.Context, mid int64) (qs []*model.LabourQs, err error) {
|
||
var (
|
||
ok bool
|
||
arc *api.Arc
|
||
getids, qsids, avids []int64
|
||
marc map[int64]*api.Arc
|
||
block *blkmdl.RPCResInfo
|
||
)
|
||
defer func() {
|
||
if err == nil {
|
||
if len(avids) != 0 {
|
||
marc, _ = s.arcRPC.Archives3(c, &arcMDL.ArgAids2{Aids: avids, RealIP: metadata.String(c, metadata.RemoteIP)})
|
||
}
|
||
for _, q := range qs {
|
||
qsids = append(qsids, q.ID)
|
||
if arc, ok = marc[q.AvID]; !ok {
|
||
log.Warn("aid(%d) is not extists, [mid(%d)-qid(%d)]", q.AvID, mid, q.ID)
|
||
q.AvID = 0
|
||
continue
|
||
}
|
||
q.AvTitle = arc.Title
|
||
if !model.ArcVisible(arc.State) {
|
||
log.Warn("aid(%d) atitle(%s) state(%d) is not visible, [mid(%d)-qid(%d)]", q.AvID, q.AvTitle, arc.State, mid, q.ID)
|
||
q.AvID = 0
|
||
}
|
||
}
|
||
qsCache := &model.QsCache{
|
||
Stime: xtime.Time(time.Now().Unix()),
|
||
QsStr: xstr.JoinInts(qsids),
|
||
}
|
||
s.dao.SetQsCache(c, mid, qsCache)
|
||
}
|
||
}()
|
||
if block, err = s.memRPC.BlockInfo(c, &blkmdl.RPCArgInfo{MID: mid}); err != nil {
|
||
return
|
||
}
|
||
status := int8(block.BlockStatus)
|
||
if status == model.BlockStatusNone {
|
||
err = ecode.CreditNoblock
|
||
return
|
||
}
|
||
if status == model.BlockStatusForever {
|
||
err = ecode.CreditForeverBlock
|
||
return
|
||
}
|
||
var qsIDs *model.AIQsID
|
||
qsIDs, err = s.dao.GetQS(c, mid)
|
||
if err != nil {
|
||
log.Error("s.dao.GetQS(%d,%s) error(%+v)", mid, metadata.String(c, metadata.RemoteIP), err)
|
||
err = nil
|
||
qs = s.question
|
||
avids = s.avIDs
|
||
return
|
||
}
|
||
getids = append(getids, qsIDs.Pend...)
|
||
getids = append(getids, qsIDs.Done...)
|
||
idStr := xstr.JoinInts(getids)
|
||
if _, qs, avids, err = s.dao.QsAllList(c, idStr); err != nil {
|
||
return
|
||
}
|
||
if len(qs) != s.c.Property.QsNum {
|
||
log.Warn("creditQsNumError(mid:%d,idstr:%s,qs:%+v),len:%d", mid, idStr, qs, len(qs))
|
||
qs = s.question
|
||
avids = s.avIDs
|
||
}
|
||
return
|
||
}
|
||
|
||
// CommitQs commit questions.
|
||
func (s *Service) CommitQs(c context.Context, mid int64, refer string, ua string, buvid string, ans *model.LabourAns) (commitRs *model.CommitRs, err error) {
|
||
var (
|
||
num int64
|
||
qs map[int64]*model.LabourQs
|
||
block *blkmdl.RPCResInfo
|
||
)
|
||
if block, err = s.memRPC.BlockInfo(c, &blkmdl.RPCArgInfo{MID: mid}); err != nil {
|
||
return
|
||
}
|
||
status := int8(block.BlockStatus)
|
||
if status == model.BlockStatusNone {
|
||
err = ecode.CreditNoblock
|
||
return
|
||
}
|
||
if status == model.BlockStatusForever {
|
||
err = ecode.CreditForeverBlock
|
||
return
|
||
}
|
||
if len(ans.ID) != s.c.Property.QsNum || len(ans.Answer) != s.c.Property.QsNum {
|
||
err = ecode.CreditAnsNumError
|
||
log.Error("CreditAnsNumError(mid:%d,id:%+v,ans:%+v)", mid, ans.ID, ans.Answer)
|
||
return
|
||
}
|
||
idStr := xstr.JoinInts(ans.ID)
|
||
qsCache, _ := s.dao.GetQsCache(c, mid)
|
||
if qsCache == nil || qsCache.QsStr != idStr {
|
||
err = ecode.RequestErr
|
||
return
|
||
}
|
||
if qs, _, _, err = s.dao.QsAllList(c, idStr); err != nil {
|
||
return
|
||
}
|
||
if len(qs) != s.c.Property.QsNum {
|
||
log.Error("CreditRightAnsNumError(mid:%d,qs:%+v)", mid, qs)
|
||
}
|
||
for id, qsid := range ans.ID {
|
||
if ans.Answer[id] != 1 && ans.Answer[id] != 2 {
|
||
err = ecode.RequestErr
|
||
log.Error("CreditAnsError(mid:%d,id:%+v,ans:%+v)", mid, ans.ID, ans.Answer)
|
||
return
|
||
}
|
||
if v, ok := qs[qsid]; ok {
|
||
if v.Ans == ans.Answer[id] {
|
||
num++
|
||
}
|
||
}
|
||
}
|
||
commitRs = &model.CommitRs{}
|
||
commitRs.Score = num * s.c.Property.PerScore
|
||
if commitRs.Score >= 100 {
|
||
commitRs.Score = 100
|
||
if status == model.BlockStatusNone {
|
||
commitRs.Day = 0
|
||
} else {
|
||
rts := time.Until(time.Unix(block.EndTime, 0))
|
||
commitRs.Day = int64(rts / (time.Hour * 24))
|
||
if int64(rts%(time.Hour*24)) > 0 {
|
||
commitRs.Day++
|
||
}
|
||
}
|
||
}
|
||
anstr, err := json.Marshal(ans)
|
||
if err != nil {
|
||
log.Error("json.Marshal() error(%v)", err)
|
||
return
|
||
}
|
||
id, err := s.dao.AddAnsLog(c, mid, commitRs.Score, string(anstr), qsCache.Stime)
|
||
if err != nil {
|
||
return
|
||
}
|
||
var msg model.DataBusResult
|
||
msg.Mid = mid
|
||
msg.Buvid = buvid
|
||
msg.IP = metadata.String(c, metadata.RemoteIP)
|
||
msg.Ua = ua
|
||
msg.Refer = refer
|
||
msg.Score = commitRs.Score
|
||
for idx, qsid := range ans.ID {
|
||
var rs = model.Rs{}
|
||
rs.ID = qsid
|
||
rs.Ans = ans.Answer[idx]
|
||
if v, ok := qs[qsid]; ok {
|
||
rs.Question = v.Question
|
||
rs.TrueAns = v.Ans
|
||
rs.AvID = v.AvID
|
||
rs.Status = v.Status
|
||
rs.Source = v.Source
|
||
rs.Ctime = v.Ctime
|
||
rs.Mtime = v.Mtime
|
||
}
|
||
msg.Rs = append(msg.Rs, rs)
|
||
}
|
||
if err = s.dao.PubLabour(c, id, msg); err != nil {
|
||
log.Error("s.dao.PubLabour(%d,%+v) error(%+v)", id, msg, err)
|
||
return
|
||
}
|
||
log.Info("PubLabour id(%d) msg(%+v)", id, msg)
|
||
s.dao.DelQsCache(c, mid)
|
||
return
|
||
}
|
||
|
||
// IsAnswered labour check user is answwered question between the time.
|
||
func (s *Service) IsAnswered(c context.Context, mid int64, mtime int64) (state int8, err error) {
|
||
var (
|
||
mc = true
|
||
found bool
|
||
)
|
||
if state, found, err = s.dao.GetAnswerStateCache(c, mid); err != nil {
|
||
err = nil
|
||
mc = false
|
||
}
|
||
if found {
|
||
return
|
||
}
|
||
var status bool
|
||
if status, err = s.dao.AnswerStatus(c, mid, time.Unix(mtime, 0)); err != nil {
|
||
return
|
||
}
|
||
if status {
|
||
state = model.LabourOkAnswer
|
||
}
|
||
if mc {
|
||
s.addCache(func() {
|
||
s.dao.SetAnswerStateCache(context.TODO(), mid, state)
|
||
})
|
||
}
|
||
return
|
||
}
|