123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- // Copyright 2019 getensh.com. All rights reserved.
- // Use of this source code is governed by getensh.com.
- package vote
- import (
- "context"
- "encoding/json"
- "fmt"
- "git.getensh.com/common/gopkgs/cache"
- "git.getensh.com/common/gopkgs/logger"
- "go.uber.org/zap"
- "google.golang.org/grpc/status"
- "gopkg.in/mgo.v2/bson"
- "property-garden/errors"
- dbmodel "property-garden/model"
- "property-garden/parser"
- pb_v1 "property-garden/pb/v1"
- "property-garden/utils"
- "strconv"
- )
- func checkVoteResultStatisticParam(req *pb_v1.VoteResultStatisticRequest) error {
- switch {
- case req.GardenId == 0:
- return status.Error(10003, "小区不能为空")
- case req.Id == 0:
- return status.Error(10003, "投票id不能为空")
- }
- return nil
- }
- func StatisticToCache(reply *pb_v1.VoteResultStatisticReply, gardenId int64, id int64) {
- key := fmt.Sprintf("vote_statisic_%d,%d", gardenId, id)
- bytes, _ := json.Marshal(reply)
- cache.Redis().SetEx(key, 30, string(bytes))
- }
- func StatisticFromCache(gardenId int64, id int64) pb_v1.VoteResultStatisticReply {
- key := fmt.Sprintf("vote_statisic_%d,%d", gardenId, id)
- str, _ := cache.Redis().Get(key)
- ret := pb_v1.VoteResultStatisticReply{}
- if str == "" {
- return ret
- }
- json.Unmarshal([]byte(str), &ret)
- return ret
- }
- func StatisticDelCache(gardenId int64, id int64) {
- key := fmt.Sprintf("vote_statisic_%d,%d", gardenId, id)
- cache.Redis().Del(key)
- }
- func VoteResultStatistic(ctx context.Context, req *pb_v1.VoteResultStatisticRequest) (reply *pb_v1.VoteResultStatisticReply, err error) {
- reply = &pb_v1.VoteResultStatisticReply{}
- // 捕获各个task中的异常并返回给调用者
- defer func() {
- if r := recover(); r != nil {
- err = fmt.Errorf("%+v", r)
- e := &status.Status{}
- if er := json.Unmarshal([]byte(err.Error()), e); er != nil {
- logger.Error("err",
- zap.String("system_err", err.Error()),
- zap.Stack("stacktrace"))
- }
- }
- }()
- // 参数检查
- err = checkVoteResultStatisticParam(req)
- if err != nil {
- return nil, err
- }
- dbname := utils.GetGardenDbName(req.GardenId)
- vote, err := getVoteOrigin(dbname, req.Id)
- if err != nil {
- return nil, err
- }
- voteM := map[int64]*pb_v1.VoteTopic{}
- for _, v := range vote.Topics {
- voteM[v.Number] = v
- }
- p := dbmodel.VoteAnswer{}
- exist, err := dbmodel.CheckDbExist(parser.Session, dbmodel.VoteMgoDb)
- if err != nil {
- return nil, errors.DataBaseError
- }
- collection := parser.Session.DB(dbmodel.VoteMgoDb).C(dbmodel.VoteCollection(req.GardenId, req.Id))
- count := int64(0)
- if exist {
- count, err = p.Count(collection, nil)
- if err != nil {
- return nil, errors.DataBaseError
- }
- }
- if count > 0 {
- tmp := StatisticFromCache(req.GardenId, req.Id)
- if len(tmp.List) > 0 {
- *reply = tmp
- return reply, nil
- }
- }
- reply.List = make([]*pb_v1.VoteResultStatisticItem, len(vote.Topics))
- for i, v := range vote.Topics {
- reply.List[i] = &pb_v1.VoteResultStatisticItem{
- TopicType: v.TopicType,
- TopicName: v.TopicName,
- // 总星数,当为评分题时有效
- Star: v.Star,
- // 是否必选
- Must: v.Must,
- // 题目编号
- Number: v.Number,
- // 选择题的选项内容
- ChoiceItems: v.ChoiceItems,
- // 选择题的选项回答统计,当题目类型为选择题时有效
- ChoiceStatistic: []*pb_v1.VoteResultStatisticChoice{},
- // 评分题的分数回答统计,当题目类型为评分题时有效
- StarStatistic: []*pb_v1.VoteResultStatisticStar{},
- // 平均分, 当题目类型为评分题时有效
- StarAvg: 0,
- }
- if count == 0 {
- continue
- }
- // 填空题不统计
- if v.TopicType == TopicTypeCompletion {
- continue
- }
- // 评分题统计
- if v.TopicType == TopicTypeStar {
- filter := []bson.M{
- {"$project": bson.M{"answers": bson.M{"$filter": bson.M{"input": "$answers", "as": "answer", "cond": bson.M{"$eq": []interface{}{"$$answer.number", v.Number}}}}}},
- {"$unwind": "$answers"},
- {"$group": bson.M{"_id": "$answers.star_answer", "count": bson.M{"$sum": 1}}}}
- ret := []bson.M{}
- err = p.Pipe(collection, filter, &ret)
- if err != nil {
- return nil, errors.DataBaseError
- }
- stars := 0
- reply.List[i].StarStatistic = make([]*pb_v1.VoteResultStatisticStar, len(ret))
- for j, w := range ret {
- starStr := fmt.Sprintf("%v", w["_id"])
- startCountStr := fmt.Sprintf("%v", w["count"])
- star, _ := strconv.Atoi(starStr)
- starCount, _ := strconv.Atoi(startCountStr)
- reply.List[i].StarStatistic[j] = &pb_v1.VoteResultStatisticStar{
- Star: int32(star),
- Count: int32(starCount),
- }
- stars += (star * starCount)
- }
- avg := int32(stars) / int32(count)
- if int32(stars)%int32(count) == 0 {
- reply.List[i].StarAvg = float64(avg)
- } else {
- reply.List[i].StarAvg = float64(avg) + 0.5
- }
- continue
- }
- choiceM := map[string]string{}
- for _, c := range v.ChoiceItems {
- choiceM[c.Flag] = c.Text
- }
- // 选择题统计
- filter := []bson.M{
- {"$project": bson.M{"answers": bson.M{"$filter": bson.M{"input": "$answers", "as": "answer", "cond": bson.M{"$eq": []interface{}{"$$answer.number", v.Number}}}}}},
- {"$unwind": "$answers"},
- {"$unwind": "$answers.choice_answer"},
- {"$group": bson.M{"_id": "$answers.choice_answer", "count": bson.M{"$sum": 1}}}}
- ret := []bson.M{}
- err = p.Pipe(collection, filter, &ret)
- if err != nil {
- logger.Error("mgo",
- zap.String("error", err.Error()))
- return nil, errors.DataBaseError
- }
- reply.List[i].ChoiceStatistic = make([]*pb_v1.VoteResultStatisticChoice, len(ret))
- for j, w := range ret {
- flag := fmt.Sprintf("%v", w["_id"])
- countStr := fmt.Sprintf("%v", w["count"])
- countInt, _ := strconv.Atoi(countStr)
- reply.List[i].ChoiceStatistic[j] = &pb_v1.VoteResultStatisticChoice{
- Flag: flag,
- Count: int32(countInt),
- Text: choiceM[flag],
- }
- }
- }
- if count > 0 {
- StatisticToCache(reply, req.GardenId, req.Id)
- }
- return reply, nil
- }
|