diff --git a/internal/app/api/v1/statistics.go b/internal/app/api/v1/statistics.go new file mode 100644 index 0000000..c59d873 --- /dev/null +++ b/internal/app/api/v1/statistics.go @@ -0,0 +1,15 @@ +package v1 + +import ( + "github.com/gin-gonic/gin" +) + +// GetAddressChallengeCount 获取地址完成挑战/获得NFT的数量 +func GetAddressChallengeCount(c *gin.Context) { + address := c.Param("address") + if count, err := srv.GetAddressChallengeCount(address); err != nil { + FailWithMessage("获取失败:"+err.Error(), c) + } else { + OkWithData(count, c) + } +} diff --git a/internal/app/dao/statistics.go b/internal/app/dao/statistics.go new file mode 100644 index 0000000..8700352 --- /dev/null +++ b/internal/app/dao/statistics.go @@ -0,0 +1,81 @@ +package dao + +import "backend-go/internal/app/model/response" + +func (d *Dao) GetAddressChallengeCount(address string) (res response.GetAddressChallengeCountRes, err error) { + err = d.db.Table("users"). + Select("users.id as user_id, users.address, users.name,string_agg(tag.name, ',') as tags"). + Joins("LEFT JOIN users_tag ON users_tag.user_id = users.id"). + Joins("LEFT JOIN tag ON tag.id = users_tag.tag_id"). + Where("users.address = ?", address). + Group("users.id"). + Find(&res).Error + if err != nil { + return res, err + } + // 领取NFT数量 + d.db.Raw(`SELECT COUNT(1) FROM + ( + SELECT + quest.ID + FROM + "user_challenges" + LEFT JOIN quest ON quest.token_id = user_challenges.token_id + LEFT JOIN user_challenge_log ON user_challenge_log.token_id = user_challenges.token_id AND user_challenge_log.address = user_challenges.address + WHERE + user_challenges.address = ? AND quest.token_id IS NOT NULL AND user_challenge_log.token_id IS NOT NULL + GROUP BY + quest.ID + UNION + SELECT + quest_id + FROM + zcloak_card + LEFT JOIN quest ON quest.id = zcloak_card.quest_id + LEFT JOIN user_challenge_log ON user_challenge_log.token_id = quest.token_id AND user_challenge_log.address = zcloak_card.address + WHERE + zcloak_card.address = ? AND quest.token_id IS NOT NULL AND user_challenge_log.token_id IS NOT NULL + GROUP BY + quest_id ) AS f`, address, address).Scan(&res.ClaimNum) + // 挑战成功/失败数量 + type CountResult struct { + TokenId string `json:"token_id"` + PassCount int `json:"pass_count"` + NotPassCount int `json:"not_pass_count"` + } + var countResult []CountResult + if err := d.db.Raw(` + SELECT + token_id, + sum(pass_count) as pass_count, + sum(not_pass_count) as not_pass_count + FROM ( + (SELECT user_challenge_log.token_id, sum(case when pass then 1 else 0 end) as pass_count, sum(case when not pass then 1 else 0 end) as not_pass_count + FROM user_challenge_log + LEFT JOIN quest ON user_challenge_log.token_id=quest.token_id + WHERE address = ? AND quest.token_id IS NOT NULL + GROUP BY user_challenge_log.token_id) + UNION ALL + (SELECT user_open_quest.token_id, sum(case when pass then 1 else 0 end) as pass_count, sum(case when not pass then 1 else 0 end) as not_pass_count + FROM user_open_quest + LEFT JOIN quest ON user_open_quest.token_id=quest.token_id + WHERE address = ? AND quest.token_id IS NOT NULL + GROUP BY user_open_quest.token_id) + ) as combined + GROUP BY token_id + `, address, address).Scan(&countResult).Error; err != nil { + return res, err + } + for _, result := range countResult { + if result.PassCount == 0 { + res.FailNum += 1 + continue + } + res.SuccessNum += 1 + } + res.NotClaimNum = res.SuccessNum - res.ClaimNum + if res.NotClaimNum < 0 { + res.NotClaimNum = 0 + } + return res, nil +} diff --git a/internal/app/model/request/statistics.go b/internal/app/model/request/statistics.go new file mode 100644 index 0000000..725b8fc --- /dev/null +++ b/internal/app/model/request/statistics.go @@ -0,0 +1 @@ +package request diff --git a/internal/app/model/response/statistics.go b/internal/app/model/response/statistics.go new file mode 100644 index 0000000..17b7c75 --- /dev/null +++ b/internal/app/model/response/statistics.go @@ -0,0 +1,12 @@ +package response + +type GetAddressChallengeCountRes struct { + UserID int64 `gorm:"user_id" json:"user_id"` + Address string `gorm:"column:address;type:varchar(44);UNIQUE;comment:钱包地址" json:"address" form:"address"` + Name string `gorm:"name" json:"name"` + Tags string `json:"tags"` + SuccessNum int64 `json:"success_num"` // 挑战成功数量 + FailNum int64 `json:"fail_num"` // 挑战失败数量 + ClaimNum int64 `json:"claim_num"` // 领取NFT数量 + NotClaimNum int64 `json:"not_claim_num"` // 未领取NFT数量 +} diff --git a/internal/app/router/router.go b/internal/app/router/router.go index 4bf8a01..6e39854 100644 --- a/internal/app/router/router.go +++ b/internal/app/router/router.go @@ -92,6 +92,7 @@ func Routers(c *config.Config) *gin.Engine { InitSocialRouter(v1Group) InitOpenQuestRouter(v1Group) InitZcloakRouter(v1Group) + InitStatisticsRouter(v1Group) } V2Group := Router.Group("v2") V2Group.Use(middleware.I18n()) diff --git a/internal/app/router/statistics.go b/internal/app/router/statistics.go new file mode 100644 index 0000000..5e991e3 --- /dev/null +++ b/internal/app/router/statistics.go @@ -0,0 +1,13 @@ +package router + +import ( + v1 "backend-go/internal/app/api/v1" + "github.com/gin-gonic/gin" +) + +func InitStatisticsRouter(Router *gin.RouterGroup) { + router := Router.Group("statistics") + { + router.GET("/addressChallengeCount/:address", v1.GetAddressChallengeCount) // 获取地址完成挑战/获得NFT的数量 + } +} diff --git a/internal/app/service/statistics.go b/internal/app/service/statistics.go new file mode 100644 index 0000000..13969da --- /dev/null +++ b/internal/app/service/statistics.go @@ -0,0 +1,8 @@ +package service + +import "backend-go/internal/app/model/response" + +// GetAddressChallengeCount 获取地址完成挑战/获得NFT的数量 +func (s *Service) GetAddressChallengeCount(address string) (res response.GetAddressChallengeCountRes, err error) { + return s.dao.GetAddressChallengeCount(address) +}