Commit 471da943 authored by chenweijian's avatar chenweijian

group support

parents 03dc4a92 1c13f8e5
package groupPower_k
// groupPower等级
const (
GroupPowerGradeExpQueue = "group_power_grade_exp_queue"
)
func GetGroupPowerGradeExpQueue() string {
return GroupPowerGradeExpQueue
}
...@@ -10,9 +10,17 @@ import ( ...@@ -10,9 +10,17 @@ import (
const ( const (
MicPrefix = "mic:" MicPrefix = "mic:"
MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H MicDayInvite = MicPrefix + "day:invite:${userId}:${date}" // string 自动被邀请上麦,1天一次,TTL:24H
MicGroupPowerOnMic = MicPrefix + "groupPower:${userId}:${date}" // 家族内群上麦分钟数
) )
func GetUserMicDayInvite(userId mysql.ID) string { func GetUserMicDayInvite(userId mysql.ID) string {
date := time.Now().Format("2006-01-02") date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date) return redis_key.ReplaceKey(MicDayInvite, fmt.Sprintf("%d", userId), date)
} }
// 家族内群上麦分钟数
func GetMicGroupPowerOnMic(userId uint64) string {
date := time.Now().Format("2006-01-02")
return redis_key.ReplaceKey(MicGroupPowerOnMic, fmt.Sprintf("%d", userId), date)
}
package mic_k
// onMic异步入库
const (
OnMicQueue = "onMic:hilo_group"
)
func GetOnMicQueue() string {
return OnMicQueue
}
...@@ -15,10 +15,10 @@ func Init() { ...@@ -15,10 +15,10 @@ func Init() {
//gift_cron.GiftRemark() // 礼物消息补偿 //gift_cron.GiftRemark() // 礼物消息补偿
gift_cron.SendGiftEvent() // 礼物事件 gift_cron.SendGiftEvent() // 礼物事件
mic_cron.OnMicCheck() // 检查上麦 mic_cron.OnMicCheck() // 检查上麦
mic_cron.OnMicQueue() // 检查上麦-队列操作
group_cron.GroupPowerExpClear() // 清理家族经验/等级 group_cron.GroupPowerExpClear() // 清理家族经验/等级
group_cron.GroupPowerMonthRankAct() group_cron.GroupPowerMonthRankAct()
//group_cron.GroupInEventInit() // 进房事件 //group_cron.GroupInEventInit() // 进房事件
group_cron.GroupPowerGradeExp() // 家族升级(上麦事件会用到) todo
group_cron.CreateGroup() // group_cron.CreateGroup() //
group_cron.CalcGroupSupport() // 群组扶持计算 group_cron.CalcGroupSupport() // 群组扶持计算
} }
package group_cron
import (
"git.hilo.cn/hilo-common/domain"
"hilo-group/domain/cache/groupPower_c"
"hilo-group/domain/model/groupPower_m"
)
func GroupPowerGradeExp() {
go func() {
for true {
model := domain.CreateModelNil()
if data := groupPower_c.BLPopGroupPowerGradeExp(model); data != nil {
if err := model.Transaction(func(model *domain.Model) error {
return groupPower_m.IncrGroupPowerExp(model, data.GroupPowerId, data.Exp, data.UserId, data.Remark)
}); err != nil {
model.Log.Errorf("IncrGroupPowerExp fail,data:%v-err:%v", data, err)
} else {
model.Log.Infof("IncrGroupPowerExp success,data:%v", data)
}
}
}
}()
}
...@@ -3,8 +3,10 @@ package mic_cron ...@@ -3,8 +3,10 @@ package mic_cron
import ( import (
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"github.com/robfig/cron" "github.com/robfig/cron"
"hilo-group/domain/cache/mic_c"
"hilo-group/domain/event/mic_ev" "hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/service/group_mic_s"
) )
func OnMicCheck() { func OnMicCheck() {
...@@ -27,7 +29,7 @@ func OnMicCheck() { ...@@ -27,7 +29,7 @@ func OnMicCheck() {
model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err) model.Log.Errorf("cron micIn group_m.GetMicUser err:%v", err)
} }
if micUser != nil { if micUser != nil {
if err := mic_ev.PublishOnMicEvent(model, &mic_ev.OnMicEvent{ if err := mic_c.QueueOnMic(model, &mic_ev.OnMicEvent{
GroupUuid: micUser.GroupUuid, GroupUuid: micUser.GroupUuid,
I: micUser.I, I: micUser.I,
ExternalId: micUser.ExternalId, ExternalId: micUser.ExternalId,
...@@ -35,7 +37,7 @@ func OnMicCheck() { ...@@ -35,7 +37,7 @@ func OnMicCheck() {
Forbid: micUser.Forbid, Forbid: micUser.Forbid,
Timestamp: micUser.Timestamp, Timestamp: micUser.Timestamp,
}); err != nil { }); err != nil {
model.Log.Errorf("PublishOnMicEvent fail:%v", err) model.Log.Errorf("QueueOnMic fail:%v", err)
} }
} }
} }
...@@ -43,3 +45,26 @@ func OnMicCheck() { ...@@ -43,3 +45,26 @@ func OnMicCheck() {
}) })
c.Start() c.Start()
} }
func OnMicQueue() {
go func() {
for true {
model := domain.CreateModelNil()
if onMic := mic_c.BLPopQueueOnMic(model); onMic != nil {
// 群组上麦经验
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(onMic.GroupUuid, onMic.UserId, onMic.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v", onMic.GroupUuid, onMic.UserId)
}
// 用户上麦
//if err := mic_m.IncrUserOnMic(model, onMic.UserId, onMic.Timestamp); err != nil {
// model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
//} else {
// model.Log.Infof("cron micIn IncrUserOnMic success,userId:%v", onMic.UserId)
//}
}
}
}()
}
package groupPower_c package mic_c
import ( import (
"encoding/json" "encoding/json"
"git.hilo.cn/hilo-common/domain" "git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"hilo-group/_const/redis_key/groupPower_k" "hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/mic_ev"
"time" "time"
) )
type GroupPowerGradeExp struct { // redis queue on mic
GroupPowerId mysql.ID func QueueOnMic(model *domain.Model, onMic *mic_ev.OnMicEvent) error {
Exp mysql.Num queue := mic_k.GetOnMicQueue()
UserId mysql.ID onMic.Ts = time.Now().UnixNano() // 给一个时间戳
Remark string body, _ := json.Marshal(onMic)
Ts int64
}
// redis队列缓冲GroupPowerGradeExp升级内容
func QueueGroupPowerGradeExp(model *domain.Model, groupPowerId mysql.ID, exp mysql.Num, userId mysql.ID, remark string) error {
queue := groupPower_k.GetGroupPowerGradeExpQueue()
data := GroupPowerGradeExp{
GroupPowerId: groupPowerId,
Exp: exp,
UserId: userId,
Remark: remark,
Ts: time.Now().Unix(),
}
body, _ := json.Marshal(data)
return model.Redis.RPush(model, queue, string(body)).Err() return model.Redis.RPush(model, queue, string(body)).Err()
} }
// redis弹出GroupPowerGradeExp升级内容 // redis pop on mic
func BLPopGroupPowerGradeExp(model *domain.Model) *GroupPowerGradeExp { func BLPopQueueOnMic(model *domain.Model) *mic_ev.OnMicEvent {
var res *GroupPowerGradeExp var res *mic_ev.OnMicEvent
queue := groupPower_k.GetGroupPowerGradeExpQueue() queue := mic_k.GetOnMicQueue()
strs, err := model.Redis.BLPop(model, time.Second, queue).Result() strs, err := model.Redis.BLPop(model, time.Second, queue).Result()
if err != nil { if err != nil {
if err != redis.Nil { if err != redis.Nil {
model.Log.Errorf("BLPopGroupPowerGradeExp fail:%v", err) model.Log.Errorf("BLPopQueueOnMic fail:%v", err)
} }
return nil return nil
} }
if len(strs) >= 2 { if len(strs) >= 2 {
content := strs[1] content := strs[1]
res = new(GroupPowerGradeExp) res = new(mic_ev.OnMicEvent)
if err := json.Unmarshal([]byte(content), res); err != nil { if err := json.Unmarshal([]byte(content), res); err != nil {
model.Log.Errorf("BLPopGroupPowerGradeExp json fail:%v", err) model.Log.Errorf("BLPopQueueOnMic json fail:%v", err)
return nil return nil
} }
return res return res
......
...@@ -14,6 +14,8 @@ type OnMicEvent struct { ...@@ -14,6 +14,8 @@ type OnMicEvent struct {
UserId uint64 // 麦中的人 UserId uint64 // 麦中的人
Forbid bool // 静音 true:静音,false:没有静音 Forbid bool // 静音 true:静音,false:没有静音
Timestamp int64 // 上麦的的时间戳 Timestamp int64 // 上麦的的时间戳
Ts int64
} }
func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) { func AddOnMicEventSync(callback func(model *domain.Model, event interface{}) error) {
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"hilo-group/_const/enum/groupPower_e" "hilo-group/_const/enum/groupPower_e"
"hilo-group/domain/cache/groupPower_c" "hilo-group/_const/redis_key/mic_k"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"time" "time"
) )
...@@ -41,25 +41,6 @@ type GroupPowerExpDetail struct { ...@@ -41,25 +41,6 @@ type GroupPowerExpDetail struct {
Remark string Remark string
} }
type GroupPowerOnMic struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Seconds int64
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
type GroupPowerOnMicDetail struct {
Date string
GroupPowerId mysql.ID
UserId mysql.ID
Minute int
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
}
// 增加家族经验 // 增加家族经验
// 达到经验值之后升级 // 达到经验值之后升级
// 单进程同步执行,不考虑并发 // 单进程同步执行,不考虑并发
...@@ -153,155 +134,70 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N ...@@ -153,155 +134,70 @@ func IncrGroupPowerExp(txModel *domain.Model, groupPowerId mysql.ID, exp mysql.N
return nil return nil
} }
// 获取势力用户上麦加经验记录
func GetGroupPowerUserOnMicDetails(model *domain.Model, groupPowerId, userId mysql.ID) ([]*GroupPowerOnMicDetail, error) {
var res []*GroupPowerOnMicDetail
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMicDetail{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).Find(&res).Error; err != nil {
return res, err
}
return res, nil
}
// 获取势力用户上麦记录
func GetGroupPowerOnMic(model *domain.Model, groupPowerId, userId mysql.ID) (*GroupPowerOnMic, error) {
gpom := new(GroupPowerOnMic)
date := time.Now().Format("2006-01-02")
if err := model.DB().Model(GroupPowerOnMic{}).Where("date = ? AND group_power_id = ? AND user_id = ?", date, groupPowerId, userId).First(gpom).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return &GroupPowerOnMic{Date: date, GroupPowerId: groupPowerId, UserId: userId}, nil
}
return nil, err
}
return gpom, nil
}
const MaxMinuteTimes = 18
// 增加势力上麦经验 // 增加势力上麦经验
// 事务操作 // 事务操作
func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { func IncrGroupPowerExpOnMic(model *domain.Model, groupPowerId, userId mysql.ID) error {
return model.Transaction(func(model *domain.Model) error { key := mic_k.GetMicGroupPowerOnMic(userId)
// 获取用户上麦奖励历史 minutes, err := model.Redis.IncrBy(model, key, 1).Result()
onMicDetails, err := GetGroupPowerUserOnMicDetails(model, groupPowerId, userId) if err != nil {
if err != nil { model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
return err return err
} }
numDetails := len(onMicDetails) model.Redis.Expire(model, key, time.Hour*24) // ttl 一天
if numDetails >= MaxMinuteTimes { // 每日最多1800经验 = 18个10分钟 = 180分钟
// 上麦经验贡献值最多1800,1分钟100 if minutes > 180 {
return nil
}
onMic, err := GetGroupPowerOnMic(model, groupPowerId, userId)
if err != nil {
return err
}
nowTs := time.Now().Unix()
curTs := joinMicTimestamp
day0Ts := utils.GetZeroTime(time.Now()).Unix()
if joinMicTimestamp < onMic.LastCalTs {
curTs = onMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
onMicSeconds := nowTs - curTs
var moreDetails []*GroupPowerOnMicDetail
totalMinuteTimes := int((onMic.Seconds + onMicSeconds) / 600) // 今天实际能加经验次数
if totalMinuteTimes >= MaxMinuteTimes {
totalMinuteTimes = MaxMinuteTimes
}
if totalMinuteTimes > numDetails {
// 续上上一次的时间,从numDetails开始
for mt := numDetails + 1; mt <= totalMinuteTimes; mt++ {
moreDetails = append(moreDetails, &GroupPowerOnMicDetail{
Date: time.Now().Format("2006-01-02"),
GroupPowerId: groupPowerId,
UserId: userId,
Minute: mt * 10, // 转换分钟
})
}
}
// 有更多麦上10分钟,可以加经验
if len(moreDetails) > 0 {
for _, detail := range moreDetails {
// 添加明细,避免重复计算
if err := model.DB().Model(GroupPowerOnMicDetail{}).Create(detail).Error; err != nil {
return err
}
// 每10分钟增加100点经验
//if err := IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
if err := groupPower_c.QueueGroupPowerGradeExp(model, groupPowerId, 100, userId, "上麦10分钟"); err != nil {
return err
}
}
// 更新micExp信息
onMic.Seconds = onMic.Seconds + onMicSeconds
onMic.LastCalTs = nowTs
if err := model.DB().Model(GroupPowerOnMic{}).Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "date"}, {Name: "group_power_id"}},
DoUpdates: clause.Assignments(
map[string]interface{}{
"seconds": onMic.Seconds,
"last_cal_ts": nowTs,
},
)}).
Create(onMic).Error; err != nil {
return err
}
}
return nil return nil
}) }
if minutes%10 == 0 {
return IncrGroupPowerExp(model, groupPowerId, 100, userId, "上麦10分钟")
}
return nil
} }
// 增加势力上麦时长-家族之星 // 增加势力上麦时长-家族之星
// 事务操作 // 事务操作
func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { func IncrGroupPowerStarOnMicMonth(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error { // 月统计
// 月统计 star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
star, err := GetGroupPowerMonthStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive) curTs := joinMicTimestamp
curTs := joinMicTimestamp nowTs := time.Now().Unix()
nowTs := time.Now().Unix() month0Ts := now.BeginningOfMonth().Unix()
month0Ts := now.BeginningOfMonth().Unix() if err != nil && err != gorm.ErrRecordNotFound {
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err return err
}) }
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨月
if curTs < month0Ts {
curTs = month0Ts
}
score := nowTs - curTs
err = IncrGroupPowerMonthStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
} }
// 增加势力上麦时长-家族之星 // 增加势力上麦时长-家族之星
// 事务操作 // 事务操作
func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error { func IncrGroupPowerStarOnMicDay(model *domain.Model, groupPowerId, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error { // 日统计
// 日统计 star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive)
star, err := GetGroupPowerDayStar(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive) curTs := joinMicTimestamp
curTs := joinMicTimestamp nowTs := time.Now().Unix()
nowTs := time.Now().Unix() day0Ts := now.BeginningOfDay().Unix()
day0Ts := now.BeginningOfDay().Unix() if err != nil && err != gorm.ErrRecordNotFound {
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
err = IncrGroupPowerDayStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err return err
}) }
if star != nil && joinMicTimestamp < star.LastCalTs { // 加入的时间比上次计算时间小
curTs = star.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
err = IncrGroupPowerDayStarScore(model, groupPowerId, userId, groupPower_e.GroupPowerStarTypeActive, mysql.Num(score), nowTs)
return err
} }
// 清理所有家族的经验 // 清理所有家族的经验
......
...@@ -12,15 +12,12 @@ import ( ...@@ -12,15 +12,12 @@ import (
"hilo-group/domain/cache/group_c" "hilo-group/domain/cache/group_c"
"hilo-group/domain/event/group_ev" "hilo-group/domain/event/group_ev"
"hilo-group/domain/event/group_power_ev" "hilo-group/domain/event/group_power_ev"
"hilo-group/domain/event/mic_ev"
"hilo-group/domain/model/diamond_m" "hilo-group/domain/model/diamond_m"
"hilo-group/domain/model/groupPower_m" "hilo-group/domain/model/groupPower_m"
"hilo-group/domain/model/group_m" "hilo-group/domain/model/group_m"
"hilo-group/domain/model/mic_m"
"hilo-group/domain/model/msg_m" "hilo-group/domain/model/msg_m"
"hilo-group/domain/model/task_m" "hilo-group/domain/model/task_m"
"hilo-group/domain/model/user_m" "hilo-group/domain/model/user_m"
"hilo-group/domain/service/group_mic_s"
"hilo-group/myerr" "hilo-group/myerr"
"strconv" "strconv"
"time" "time"
...@@ -33,7 +30,6 @@ func EventInit() { ...@@ -33,7 +30,6 @@ func EventInit() {
GroupImMass() GroupImMass()
GroupTheme() GroupTheme()
//SendGift() // 送礼事件 //SendGift() // 送礼事件
OnMic() // 在麦上事件
GroupInMicChangeEvent() // 用户进房推送mic位置信息 GroupInMicChangeEvent() // 用户进房推送mic位置信息
} }
...@@ -535,36 +531,3 @@ func SendGift() { ...@@ -535,36 +531,3 @@ func SendGift() {
// return nil // return nil
//}) //})
} }
func OnMic() {
// 上麦经验/上麦时长
mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*mic_ev.OnMicEvent)
if !ok {
model.Log.Errorf("AddOnMicEventSync event type err")
return nil
}
if err := group_mic_s.NewGroupPowerService(model.MyContext).IncrGroupPowerOnMicExpAndTime(event.GroupUuid, event.UserId, event.Timestamp); err != nil {
model.Log.Errorf("cron micIn GroupPowerOnMicExp err:%v", err)
} else {
model.Log.Infof("cron micIn GroupPowerOnMicExp success, groupId:%v, userId:%v", event.GroupUuid, event.UserId)
}
return nil
})
// 用户上麦时长
mic_ev.AddOnMicEventAsync(func(model *domain.Model, e interface{}) error {
event, ok := e.(*mic_ev.OnMicEvent)
if !ok {
model.Log.Errorf("AddOnMicEventSync event type err")
return nil
}
if err := mic_m.IncrUserOnMic(model, event.UserId, event.Timestamp); err != nil {
model.Log.Errorf("cron micIn IncrUserOnMic err:%v", err)
} else {
model.Log.Infof("cron micIn IncrUserOnMic success,userId:%v", event.UserId)
}
// 处理活动数据 活动已经结束
//go rpc.AddActPoint(model, event.UserId, 1, 0)
return nil
})
}
...@@ -317,7 +317,7 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u ...@@ -317,7 +317,7 @@ func (s *GroupMicService) IncrGroupPowerOnMicExpAndTime(groupId string, userId u
return nil return nil
} }
// 增加势力上麦经验 // 增加势力上麦经验
if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId, joinMicTimestamp); err != nil { if err := groupPower_m.IncrGroupPowerExpOnMic(model, groupPowerId, userId); err != nil {
model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err) model.Log.Errorf("IncrGroupPowerExpOnMic fail:%v", err)
} }
// 增加势力上麦时长-月 // 增加势力上麦时长-月
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment