123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 |
- package service
- import (
- "fmt"
- "gadmin/config"
- "gadmin/internal/admin/consts"
- "gadmin/internal/admin/forms"
- "gadmin/internal/elastic/eapi"
- "gadmin/internal/gorm/model"
- "gadmin/internal/gorm/query"
- "gadmin/utility"
- "github.com/gin-gonic/gin"
- "github.com/sirupsen/logrus"
- "os"
- "strings"
- )
- // Chapter 章节服务
- var Chapter = new(sChapter)
- type sChapter struct{}
- //func (s *sChapter) OrdinaryList(ctx *gin.Context, req forms.ChapterOrdinaryListReq) (resp serializer.Response) {
- // type passData struct {
- // Id int32 `json:"id"`
- // Name string `json:"name"`
- // RoomCount int32 `json:"roomCount"`
- // Count int64 `json:"count"`
- // Difficulty int64 `json:"difficulty"`
- // Pass bool `json:"pass"`
- // IsActivity bool `json:"isActivity"`
- // }
- //
- // DB, err := player.GetDBByUserId(req.PlayerId)
- // if err != nil {
- // return serializer.Err(consts.CodeParamErr, "GetDBByUserId err", err)
- // }
- //
- // var (
- // p = query.Use(config.GDBGroup[DB]).PlayerMaterial
- // passDatas []passData
- // models forms.ListRes
- // )
- // material, err := p.WithContext(ctx).Where(p.Playerid.Eq(req.PlayerId)).First()
- // if err != nil {
- // return serializer.Err(consts.CodeParamErr, "查询出错 Find", err)
- // }
- //
- // if material == nil || material.ID == 0 || material.PassRoom == "null" {
- // return serializer.Suc(models)
- // }
- //
- // if err := json.Unmarshal([]byte(material.PassRoom), &passDatas); err != nil {
- // return serializer.Err(consts.CodeParamErr, "Unmarshal err", err)
- // }
- //
- // tmp := make([]passData, 0)
- // for k, v := range passDatas {
- // if v.Id == 0 || v.Id > 99 {
- // continue
- // }
- // data := gmdata.GetChapterById(v.Id)
- // if data == nil {
- // data = &gmdata.Chapter{
- // Name: `未知`,
- // }
- // }
- // passDatas[k].Name = data.Name
- // passDatas[k].RoomCount = data.RoomCount
- // tmp = append(tmp, passDatas[k])
- // }
- //
- // // 使用自定义的 Less 函数来指定排序规则
- // sort.SliceStable(tmp, func(i, j int) bool {
- // if tmp[i].Id != tmp[j].Id {
- // return tmp[i].Id < tmp[j].Id // 根据 Id 升序排列
- // }
- // return tmp[i].Difficulty < tmp[j].Difficulty // 如果 Id 相同,则根据 Difficulty 升序排列
- // })
- //
- // models.List = tmp
- //
- // return serializer.Suc(models)
- //}
- //func (s *sChapter) ActivityList(ctx *gin.Context, req forms.ChapterActivityListReq) (resp serializer.Response) {
- // type passData struct {
- // Id int32 `json:"id"`
- // Difficulty int32 `json:"difficulty"`
- // DifficultyName string `json:"difficultyName"`
- // Name string `json:"name"`
- // Degree int32 `json:"degree"`
- // RewardMulti float64 `json:"rewardMulti"`
- // RewardEffectTime int64 `json:"rewardEffectTime"`
- // ChallengeCount int64 `json:"challenge_count"`
- // ClearanceCount int64 `json:"clearance_count"`
- // FailCount int64 `json:"fail_count"`
- // }
- //
- // DB, err := player.GetDBByUserId(req.PlayerId)
- // if err != nil {
- // return serializer.Err(consts.CodeParamErr, "GetDBByUserId err", err)
- // }
- //
- // var (
- // c = query.Use(config.DB).Chapter
- // passDatas []passData
- // models forms.ListRes
- // z = query.Use(config.GDBGroup[DB]).ZoneActivity
- // )
- // chapters, err := c.WithContext(ctx).Where(c.PlayerID.Eq(req.PlayerId)).Find()
- // if err != nil {
- // return serializer.Err(consts.CodeParamErr, "查询出错 Find", err)
- // }
- //
- // if len(chapters) == 0 {
- // return serializer.Suc(models)
- // }
- //
- // zone, err := z.WithContext(ctx).Where(z.Playerid.Eq(req.PlayerId)).First()
- // if err != nil {
- // return serializer.Err(consts.CodeParamErr, "查询出错 Find", err)
- // }
- //
- // // BonusProperties 加成属性
- // type BonusProperties struct {
- // DifScale int `json:"difScale"` // 难度系数
- // RewardMulti float64 `json:"rewardMulti"` // 奖励倍数
- // RewardEffectTime int64 `json:"rewardEffectTime"` // 奖励倍数生效时间
- // }
- //
- // bonusProperties := make(map[string]*BonusProperties)
- // //difficulty := make(map[string]int32)
- // if zone != nil {
- // if err = json.Unmarshal([]byte(zone.BonusProperties), &bonusProperties); err != nil {
- // return serializer.Err(consts.CodeParamErr, "Unmarshal err", err)
- // }
- // }
- //
- // logrus.Warnf("bonusProperties:%+v", bonusProperties)
- //
- // //chapterIds := []int64{100, 101, 102, 103}
- // //var difficultys = []int32{0, 1, 2}
- //
- // for _, v := range chapters {
- // var data = gmdata.GetChapterById(v.ChapterID)
- // if data == nil {
- // data = &gmdata.Chapter{
- // Name: `未知`,
- // }
- // }
- //
- // //var ds = []int32{0, 1, 2}
- // //if v.ChapterID == 103 {
- // // ds = []int32{0}
- // //}
- // //
- // //for _, difficulty := range ds {
- // //
- // //
- // //}
- //
- // bs, ok := bonusProperties[fmt.Sprintf("%v_%v", v.ChapterID, v.Difficulty)]
- // if ok {
- // passDatas = append(passDatas, passData{
- // Id: v.ChapterID,
- // Difficulty: v.Difficulty,
- // DifficultyName: gmdata.GetDifficultName(int64(v.Difficulty)),
- // Name: data.Name,
- // Degree: int32(bs.DifScale),
- // RewardMulti: bs.RewardMulti,
- // RewardEffectTime: bs.RewardEffectTime,
- // ChallengeCount: int64(v.ClearanceCount + v.FailCount),
- // ClearanceCount: int64(v.ClearanceCount),
- // FailCount: int64(v.FailCount),
- // })
- // } else {
- // // 没有数据视为没有参与过,直接不显示
- // //passDatas = append(passDatas, passData{
- // // Id: v.ChapterID,
- // // Difficulty: difficulty,
- // // Name: data.Name,
- // // Degree: 100, // 这里写死了100,其实有的初始值并不是100,需要知道
- // // RewardMulti: 1,
- // // RewardEffectTime: 0,
- // // ChallengeCount: int64(v.ClearanceCount + v.FailCount),
- // // ClearanceCount: int64(v.ClearanceCount),
- // // FailCount: int64(v.FailCount),
- // //})
- // }
- //
- // }
- //
- // // 远征
- // var (
- // cf = query.Use(config.GDBGroup[DB]).Climbfloor
- // )
- // cfd, _ := cf.WithContext(ctx).Where(cf.Playerid.Eq(req.PlayerId)).First()
- // //if err != nil {
- // // return serializer.Err(consts.CodeParamErr, "查询出错 Climbfloor Find", err)
- // //}
- //
- // if cfd == nil {
- // passDatas = append(passDatas, passData{
- // Id: 105,
- // Name: "远征",
- // Degree: 0,
- // DifficultyName: gmdata.GetDifficultName(int64(0)),
- // //ChallengeCount: int64(v.ClearanceCount + v.FailCount),
- // //ClearanceCount: int64(v.ClearanceCount),
- // //FailCount: int64(v.FailCount),
- // })
- // } else {
- // passDatas = append(passDatas, passData{
- // Id: 105,
- // Name: "远征",
- // Degree: cfd.MaxFloor,
- // DifficultyName: gmdata.GetDifficultName(int64(0)),
- // //ChallengeCount: int64(v.ClearanceCount + v.FailCount),
- // //ClearanceCount: int64(v.ClearanceCount),
- // //FailCount: int64(v.FailCount),
- // })
- // }
- //
- // models.List = passDatas
- //
- // return serializer.Suc(models)
- //}
- func (s *sChapter) doReconnectFromDB(ctx *gin.Context, params forms.ChapterReconnectReq, chapterId, difficulty int32, isNew bool) (count, userCount int64, err error) {
- type Result struct {
- TotalCount int64 `gorm:"total_count"`
- UserCount int64 `gorm:"user_count"`
- }
- begin, end, _ := utility.GetBeginAndEndOfDay2(params.Day, params.EndDay)
- end = end + 1
- table := model.GetChapterTable2(chapterId)
- var (
- q = query.Use(config.DB).ChapterLog.Table(table)
- db = q.UnderlyingDB()
- )
- db = db.Where("event_id = 2 and extra like '%0%' and difficulty = ? and event_at >= ? and event_at <= ?", difficulty, begin, end)
- if params.ServerId > 0 {
- db = db.Where("server_id = ?", params.ServerId)
- }
- switch params.ChannelId {
- case consts.ChannelIdNone:
- // 不选择渠道
- case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
- // 所有广告渠道
- db = db.Where("channel_id in (?)", Channel.GetIdsByType(params.ChannelId))
- default:
- // 选择指定渠道
- db = db.Where("channel_id = ?", params.ChannelId)
- }
- res := make([]*Result, 0)
- if isNew {
- err = db.Select("count(*) AS total_count, count( DISTINCT user_id ) AS user_count, DATE (FROM_UNIXTIME( user_created_at )) AS d").Where("user_created_at >= ? and user_created_at <= ?", begin, end).Group("d").Find(&res).Error
- } else {
- err = db.Select("count(*) AS total_count, count( DISTINCT user_id ) AS user_count").Find(&res).Error
- }
- if err != nil {
- logrus.Errorf("查询出错:%+v", err)
- if strings.Contains(err.Error(), "1146") {
- createSql := "CREATE TABLE IF NOT EXISTS `%s` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`channel_id` varchar(128) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '渠道ID',`flag` int DEFAULT '0',`user_id` bigint unsigned NOT NULL COMMENT '用户id',`server_id` int NOT NULL DEFAULT '1' COMMENT '服务器ID',`event_id` tinyint unsigned NOT NULL COMMENT '埋点id',`chapter_id` smallint unsigned NOT NULL COMMENT '关卡id',`difficulty` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '困难度',`room_id` bigint NOT NULL COMMENT '房间id',`user_created_at` int unsigned NOT NULL COMMENT '用户注册时间',`event_at` int unsigned NOT NULL COMMENT '埋点事件触发的时间',`event_at_ns` bigint unsigned NOT NULL,`token` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '登陆的token',`extra` text COLLATE utf8mb4_general_ci COMMENT '其他参数',PRIMARY KEY (`id`),UNIQUE KEY `user_event_ns` (`user_id`,`event_at_ns`),KEY `created_chapter_event_event_at_idx` (`user_created_at`,`chapter_id`,`event_id`,`event_at`),KEY `event_id_event_at_idx` (`event_id`,`event_at`),KEY `server_id` (`server_id`),KEY `channel_id` (`channel_id`),KEY `idx_event_id` (`event_id`) USING BTREE,KEY `server_id_difficulty_user_id_event_id_extra_index` (`server_id`,`difficulty`,`user_id`,`event_id`),KEY `chapter_logs_100_event_at_index` (`event_at`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='关卡信息埋点日志';"
- if err := q.UnderlyingDB().Exec(fmt.Sprintf(createSql, table)).Error; err != nil {
- logrus.Errorf("创建表%s错误:%+v", table, err)
- }
- }
- return 0, 0, err
- }
- for _, v := range res {
- count += v.TotalCount
- userCount += v.UserCount
- }
- return
- }
- func (s *sChapter) doReconnect(ctx *gin.Context, params forms.ChapterReconnectReq, chapterId, difficulty int32, isNew bool) (count, userCount int64, err error) {
- begin, end, _ := utility.GetBeginAndEndOfDay2(params.Day, params.EndDay)
- end = end + 1
- index := fmt.Sprintf("%s%s", os.Getenv("ELASTIC_TOPIC"), model.GetChapterTable2(chapterId))
- var (
- mustNot []eapi.M
- where eapi.M
- )
- must := []eapi.M{
- {
- "term": eapi.M{
- "event_id": "2",
- },
- },
- {
- "match": eapi.M{
- "extra": "0",
- },
- },
- {
- "term": eapi.M{
- "chapter_id": chapterId,
- },
- },
- {
- "term": eapi.M{
- "difficulty": difficulty,
- },
- },
- {
- "range": eapi.M{
- "event_at": eapi.M{
- "gte": begin,
- "lte": end,
- },
- },
- },
- }
- if params.ServerId > 0 {
- must = append(must, eapi.M{
- "term": eapi.M{
- "server_id": params.ServerId,
- },
- })
- }
- switch params.ChannelId {
- case consts.ChannelIdNone:
- // 不选择渠道
- case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
- // 所有广告渠道
- must = append(must, eapi.M{
- "terms": eapi.M{
- "channel_id": Channel.GetIdsByType(params.ChannelId),
- },
- })
- default:
- // 选择指定渠道
- must = append(must, eapi.M{
- "term": eapi.M{
- "channel_id": params.ChannelId,
- },
- })
- }
- //if params.ChannelId != "" {
- // if params.ChannelId == "1" {
- // mustNot = append(mustNot, eapi.M{
- // "term": eapi.M{
- // "channel_id": "0",
- // },
- // })
- // } else {
- // must = append(must, eapi.M{
- // "term": eapi.M{
- // "channel_id": params.ChannelId,
- // },
- // })
- // }
- //
- //}
- // 新用户
- if isNew {
- // 同一天
- if begin+86400 == end {
- must = append(must, eapi.M{
- "range": eapi.M{
- "user_created_at": eapi.M{
- "gte": begin,
- "lte": end,
- },
- },
- })
- } else {
- // 多天的,分析每天的新用户
- for i := begin; i < end; i += 86400 {
- var newMust = must
- newMust = append(newMust, eapi.M{
- "range": eapi.M{
- "user_created_at": eapi.M{
- "gte": i,
- "lte": i + 86400,
- },
- },
- })
- if len(mustNot) > 0 {
- where = eapi.M{
- "query": eapi.M{
- "bool": eapi.M{
- "must": newMust,
- "must_not": mustNot,
- },
- },
- }
- } else {
- where = eapi.M{
- "query": eapi.M{
- "bool": eapi.M{
- "must": newMust,
- },
- },
- }
- }
- res, err := eapi.Count(ctx, index, where)
- if err != nil {
- return 0, 0, err
- }
- if res > 0 {
- count += res
- }
- res2, err := eapi.Cardinality(ctx, index, where, "user_id")
- if err != nil {
- return 0, 0, err
- }
- if res2 > 0 {
- userCount += res2
- }
- }
- return
- }
- }
- if len(mustNot) > 0 {
- where = eapi.M{
- "query": eapi.M{
- "bool": eapi.M{
- "must": must,
- "must_not": mustNot,
- },
- },
- }
- } else {
- where = eapi.M{
- "query": eapi.M{
- "bool": eapi.M{
- "must": must,
- },
- },
- }
- }
- //logrus.Warnf("doReconnect index:%v\n where:%v\n", index, utility.DumpToJSON(where))
- res, err := eapi.Count(ctx, index, where)
- if err != nil {
- return 0, 0, err
- }
- res2, err := eapi.Cardinality(ctx, index, where, "user_id")
- if err != nil {
- return 0, 0, err
- }
- return res, res2, nil
- }
- //func (s *sChapter) Reconnect(ctx *gin.Context, params forms.ChapterReconnectReq) (resp serializer.Response) {
- // chapterMap := gmdata.GetChaptersMap()
- // var (
- // wg sync.WaitGroup
- // errCh = make(chan error, len(chapterMap))
- // )
- //
- // list := make([]forms.ChapterReconnectItem, 0)
- // for _, v := range chapterMap {
- // wg.Add(1)
- // go func(v *gmdata.Chapter) {
- // defer wg.Done()
- // //count, users, err := s.doReconnect(ctx, params, int32(v.ID), int32(v.Difficulty), false)
- // count, users, err := s.doReconnectFromDB(ctx, params, int32(v.ID), int32(v.Difficulty), false)
- // if err != nil {
- // errCh <- err
- // return
- // }
- //
- // //newCount, newUsers, err := s.doReconnect(ctx, params, int32(v.ID), int32(v.Difficulty), true)
- // newCount, newUsers, err := s.doReconnectFromDB(ctx, params, int32(v.ID), int32(v.Difficulty), true)
- // if err != nil {
- // errCh <- err
- // return
- // }
- //
- // list = append(list, forms.ChapterReconnectItem{
- // Id: len(list),
- // ChapterId: int(v.ID),
- // Chapter: Dash.GetChapterName(v.ID, v.Difficulty),
- // DifficultyIndex: int(v.Difficulty),
- // Difficulty: gmdata.GetDifficultName(v.Difficulty),
- // DieCount: count,
- // DieUserCount: users,
- // NewDieCount: newCount,
- // NewDieUserCount: newUsers,
- // })
- // }(v)
- // }
- //
- // wg.Wait()
- //
- // select {
- // case err1 := <-errCh:
- // return serializer.Err(consts.CodeParamErr, err1.Error(), err1)
- // default:
- //
- // }
- //
- // for k, v := range list {
- // list[k].Index = v.ChapterId*1000 + v.DifficultyIndex
- // }
- // sort.Sort(forms.ChapterReconnectItemSlice(list))
- //
- // pageCount := int64(len(list))
- // models := new(forms.ChapterReconnectRespData)
- // models.Page = params.Page
- // models.PerPage = params.PerPage
- // models.PageCount = int64(math.Ceil(float64(pageCount) / float64(params.PerPage)))
- //
- // startInx := (models.Page - 1) * models.PerPage
- // endInx := (models.Page) * models.PerPage
- // if startInx < 0 {
- // startInx = 0
- // }
- // if endInx > pageCount {
- // endInx = pageCount
- // }
- // subList := list[startInx:endInx]
- //
- // models.List = subList
- // return serializer.Suc(models)
- //}
|