From efb4f5c8db872b6cfd2c7755c843ac735583b1ba Mon Sep 17 00:00:00 2001 From: 王家文 Date: Sat, 11 May 2024 11:31:55 +0800 Subject: [PATCH] feat✨:排行榜结算方式改为每天结算 --- service/roomrank/dto-player.go | 22 ++++++++++++---------- service/roomrank/dto-room.go | 12 +++++++----- service/roomrank/handle.go | 25 ++++++++++++++++++------- service/roomrank/logic.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++------ service/roomrank/room.go | 19 ++++++++++--------- util/ztime/external.go | 20 ++++++++++++++++++++ util/ztime/time.go | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 245 insertions(+), 37 deletions(-) create mode 100644 util/ztime/external.go create mode 100644 util/ztime/time.go diff --git a/service/roomrank/dto-player.go b/service/roomrank/dto-player.go index b240fd4..140d138 100644 --- a/service/roomrank/dto-player.go +++ b/service/roomrank/dto-player.go @@ -9,11 +9,12 @@ import ( // Player 房间排行持久数据 type Player struct { - Uid int64 `gorm:"column:uid;primaryKey;comment:玩家唯一ID"` - TopType int `gorm:"comment:排行榜类型"` - Name string `gorm:"-"` // 玩家名字 - Icon string `gorm:"-"` // 玩家头像 - ActivityId int64 `gorm:"comment:活动ID"` + Uid int64 `gorm:"column:uid;primaryKey;comment:玩家唯一ID"` + TopType int `gorm:"comment:排行榜类型"` + Name string `gorm:"-"` // 玩家名字 + Icon string `gorm:"-"` // 玩家头像 + ActivityId int64 `gorm:"comment:活动ID"` + ActivityTime int64 `gorm:"comment:当前活动周期时间"` UserType int `gorm:"comment:用户类型"` // 0=新手用户 1=优质用户 2=普通用户 3=垃圾用户 UserScore int `gorm:"comment:用户评级分"` @@ -23,11 +24,12 @@ type Player struct { RoomUid int64 `gorm:"comment:所在房间唯一ID"` - SettleActivityId int64 `gorm:"comment:上次结算的活动ID"` - SettleRank int `gorm:"comment:结算名次"` - SettleScore int64 `gorm:"comment:结算分数"` - SettleUserClass int `gorm:"comment:结算用户评级"` - SettleAward string `gorm:"comment:结算奖励内容"` + SettleActivityId int64 `gorm:"comment:上次结算的活动ID"` + SettleActivityTime int64 `gorm:"comment:上次结算的活动时间戳"` + SettleRank int `gorm:"comment:结算名次"` + SettleScore int64 `gorm:"comment:结算分数"` + SettleUserClass int `gorm:"comment:结算用户评级"` + SettleAward string `gorm:"comment:结算奖励内容"` CreateTime int64 `gorm:"comment:创建时间戳"` UpdateTime int64 `gorm:"comment:修改时间戳"` diff --git a/service/roomrank/dto-room.go b/service/roomrank/dto-room.go index bd92bfb..55d87d2 100644 --- a/service/roomrank/dto-room.go +++ b/service/roomrank/dto-room.go @@ -11,10 +11,11 @@ import ( // Room 房间排行持久数据 type Room struct { - Id int64 `gorm:"column:id;primaryKey;comment:房间唯一ID"` - TopType int `gorm:"comment:排行榜类型"` - ActivityId int64 `gorm:"comment:活动ID"` - ConfigId int `gorm:"comment:房间配置ID"` + Id int64 `gorm:"column:id;primaryKey;comment:房间唯一ID"` + TopType int `gorm:"comment:排行榜类型"` + ActivityId int64 `gorm:"comment:活动ID"` + ActivityTime int64 `gorm:"comment:当前活动周期时间"` + ConfigId int `gorm:"comment:房间配置ID"` Details *RoomDetails `gorm:"-"` // 详情 DetailsText string `gorm:"comment:详情封装"` @@ -29,9 +30,10 @@ type Room struct { func (d *Room) MysqlInfo(suffix string) *svmysql.MysqlInfo { tableName := svconst.MYSQL_TABLE_S_ROOMRANK_ROOM + tableName = fmt.Sprintf("%s_%s_%d_%d", tableName, suffix, d.TopType, d.ActivityId) return &svmysql.MysqlInfo{ DbMysql: svconst.DbCommon, - TableName: fmt.Sprintf("%s_%s_%d_%d", tableName, suffix, d.TopType, d.ActivityId), + TableName: tableName, } } diff --git a/service/roomrank/handle.go b/service/roomrank/handle.go index cbca1c2..9090a04 100644 --- a/service/roomrank/handle.go +++ b/service/roomrank/handle.go @@ -52,8 +52,10 @@ func HandleInfo(req *models.ReqRoomRankInfo) (code string, rsp models.RspRoomRan } defer lock.Release() + activityTime := GetActivityTime(config) + // 尝试判断结算 - hasSettleChange := TrySettle(gameId, req.TopType, player, config) + hasSettleChange := TrySettle(gameId, req.TopType, player, config, activityTime) if hasSettleChange { SavePlayer(gameId, player) @@ -75,9 +77,11 @@ func HandleInfo(req *models.ReqRoomRankInfo) (code string, rsp models.RspRoomRan SavePlayer(gameId, player) } }() - if player.ActivityId != config.Id { + if player.ActivityId != config.Id && player.ActivityTime != activityTime { player.ActivityId = config.Id + player.ActivityTime = activityTime player.RoomUid = 0 + player.Score = 0 needSavePlayer = true } @@ -88,7 +92,7 @@ func HandleInfo(req *models.ReqRoomRankInfo) (code string, rsp models.RspRoomRan } // 尝试加入房间 - room, hasRoom, firstJoin := TryGetRoom(gameId, req.TopType, player, config, playerLevel) + room, hasRoom, firstJoin := TryGetRoom(gameId, req.TopType, player, config, playerLevel, activityTime) if !hasRoom { code = code_msg.RECODE_MERGE_CONFIG_ERROR @@ -135,8 +139,10 @@ func HandleGetSettleAward(req *models.ReqRoomRankGetSettleAward) (code string, r } defer lock.Release() + activityTime := GetActivityTime(config) + // 尝试判断结算 - _ = TrySettle(gameId, req.TopType, player, config) + _ = TrySettle(gameId, req.TopType, player, config, activityTime) if !player.SettleHas() { code = code_msg.RECODE_MERGE_ROOMRANK_NOTHASSETTLE_ERROR return @@ -150,6 +156,7 @@ func HandleGetSettleAward(req *models.ReqRoomRankGetSettleAward) (code string, r rsp.AwardText = player.SettleAward player.SettleAward = "" player.ActivityId = config.Id + player.ActivityTime = 0 player.RoomUid = 0 player.Score = 0 SavePlayer(gameId, player) @@ -192,8 +199,10 @@ func HandleAddScore(req *models.ReqRoomRankAddScore) (code string, rsp models.Rs } defer lock.Release() + activityTime := GetActivityTime(config) + // 尝试判断结算 - hasSettleChange := TrySettle(gameId, req.TopType, player, config) + hasSettleChange := TrySettle(gameId, req.TopType, player, config, activityTime) if hasSettleChange { SavePlayer(gameId, player) } @@ -216,9 +225,11 @@ func HandleAddScore(req *models.ReqRoomRankAddScore) (code string, rsp models.Rs SavePlayer(gameId, player) } }() - if player.ActivityId != config.Id { + if player.ActivityId != config.Id && player.ActivityTime != activityTime { player.ActivityId = config.Id + player.ActivityTime = activityTime player.RoomUid = 0 + player.Score = 0 needSavePlayer = true } @@ -237,7 +248,7 @@ func HandleAddScore(req *models.ReqRoomRankAddScore) (code string, rsp models.Rs } // 尝试加入房间 - room, hasRoom, firstJoin := TryGetRoom(gameId, req.TopType, player, config, playerLevel) + room, hasRoom, firstJoin := TryGetRoom(gameId, req.TopType, player, config, playerLevel, activityTime) if !hasRoom { code = code_msg.RECODE_MERGE_CONFIG_ERROR diff --git a/service/roomrank/logic.go b/service/roomrank/logic.go index 745edda..2c175c6 100644 --- a/service/roomrank/logic.go +++ b/service/roomrank/logic.go @@ -3,33 +3,75 @@ package roomrank import ( "apigame/configs/confroomrank" "apigame/service-common/svconst" + "apigame/util/util-lx/lxtime" "apigame/util/utstring" - "apigame/util/zjson" + "apigame/util/ztime" "fmt" + "time" ) func getLockKey(gameId string, topType int, activityId int64) string { return fmt.Sprintf("%s:lock:roomrank:%s:%d:%d", svconst.REDIS_CACHEP_REFIX, gameId, topType, activityId) } +// GetActivityTime 根据当前时间获取当前次的结算时间戳 +func GetActivityTime(config *confroomrank.ActivityConfig) int64 { + dtNow := time.Now() + nowYear, nowMonth, nowDay := dtNow.Date() + hour, min, sec := ztime.TimeClock(config.ReleaseTime) + dt := time.Date(nowYear, nowMonth, nowDay, hour, min, sec, 0, time.Local) + if dtNow.After(dt) { + dt = dt.AddDate(0, 0, 1) + } + dtYear, dtMonth, dtDay := dt.Date() + activityTime := int64(dtYear)*1_0000 + int64(dtMonth)*100 + int64(dtDay) + return activityTime +} + +func ActivityTimeToDate(activityTime int64) (year int, month time.Month, day int) { + year = int(activityTime / 1_0000) + month = time.Month((activityTime % 1_0000) / 100) + day = int(activityTime % 100) + return +} + // TrySettle 尝试判断结算 -func TrySettle(gameId string, topType int, player *Player, config *confroomrank.ActivityConfig) (hasChange bool) { +func TrySettle(gameId string, topType int, player *Player, config *confroomrank.ActivityConfig, activityTime int64) (hasChange bool) { hasChange = false - if player.SettleActivityId == config.Id { + if player.ActivityId == 0 { return } - if player.ActivityId == 0 { + if player.SettleActivityId == config.Id && player.SettleActivityTime == activityTime { return } - if player.ActivityId == config.Id { + if player.ActivityId == config.Id && player.ActivityTime == activityTime { return } - fmt.Println(zjson.Str(player)) + //if player.ActivityId == 0 { + // return + //} + //if player.ActivityId == config.Id { + // return + //} + //fmt.Println(zjson.Str(player)) // 查找玩家所在的房间 room, hasRoom := LoadRoom(gameId, topType, player.ActivityId, player.RoomUid) if !hasRoom { return } + + if room.HasSettle { + return + } + // 未到结算时间不结算 + dtYear, dtMonth, dtDay := ActivityTimeToDate(room.ActivityTime) + hour, min, sec := ztime.TimeClock(config.ReleaseTime) + dt := time.Date(dtYear, dtMonth, dtDay, hour, min, sec, 0, time.Local) + dtNow := lxtime.NowUninx() + if dtNow < dt.Unix() { + return + } + confActivity, hasConfActivity := confroomrank.GetConfig(gameId, room.ActivityId) if !hasConfActivity { return @@ -47,6 +89,7 @@ func TrySettle(gameId string, topType int, player *Player, config *confroomrank. // 设置玩家奖励等数据 hasChange = true player.SettleActivityId = config.Id + player.SettleActivityTime = activityTime confRoom, hasConfRoom := confActivity.Room[room.ConfigId] if !hasConfRoom { return diff --git a/service/roomrank/room.go b/service/roomrank/room.go index 491bd04..5d6389e 100644 --- a/service/roomrank/room.go +++ b/service/roomrank/room.go @@ -49,14 +49,15 @@ func LoadRoom(gameId string, topType int, activityId int64, roomUid int64) (room return } -func CreateRoom(gameId string, topType int, activityId int64, roomConfigId int) (room *Room, has bool) { +func CreateRoom(gameId string, topType int, config *confroomrank.ActivityConfig, roomConfigId int, activityTime int64) (room *Room, has bool) { room = new(Room) room.TopType = topType - room.ActivityId = activityId + room.ActivityId = config.Id room.ConfigId = roomConfigId room.Closed = false room.HasSettle = false room.CreateTime = lxtime.NowUninx() + room.ActivityTime = activityTime details := new(RoomDetails) details.Players = make([]*RoomPlayer, 0) details.IndexNames = make([]int, 0) @@ -72,12 +73,12 @@ func CreateRoom(gameId string, topType int, activityId int64, roomConfigId int) } // FindRoom 查找 -func FindRoom(gameId string, topType int, activityId int64, roomConfigId int) (rooms []*Room, has bool) { - roomDemo := &Room{TopType: topType, ActivityId: activityId} +func FindRoom(gameId string, topType int, activityId int64, roomConfigId int, activityTime int64) (rooms []*Room, has bool) { + roomDemo := &Room{TopType: topType, ActivityId: activityId, ActivityTime: activityTime} tryInitRoom(gameId, roomDemo) info := roomDemo.MysqlInfo(gameId) - info.DbMysql = info.DbMysql.Where("config_id = ? AND closed = false", roomConfigId) + info.DbMysql = info.DbMysql.Where("config_id = ? AND activity_time = ? AND closed = false", roomConfigId, activityTime) has, _ = svmysql.Find(&rooms, info) for _, room := range rooms { room.Decode() @@ -87,7 +88,7 @@ func FindRoom(gameId string, topType int, activityId int64, roomConfigId int) (r } // TryGetRoom 尝试获取房间 -func TryGetRoom(gameId string, topType int, player *Player, config *confroomrank.ActivityConfig, playerLevel int) (room *Room, hasRoom bool, firstJoin bool) { +func TryGetRoom(gameId string, topType int, player *Player, config *confroomrank.ActivityConfig, playerLevel int, activityTime int64) (room *Room, hasRoom bool, firstJoin bool) { hasRoom = false firstJoin = false // 查找玩家所在的房间 @@ -115,7 +116,7 @@ func TryGetRoom(gameId string, topType int, player *Player, config *confroomrank return } // 数据库查找合适条件的房间列表 - rooms, has := FindRoom(gameId, topType, config.Id, roomConfigId) + rooms, has := FindRoom(gameId, topType, config.Id, roomConfigId, activityTime) if has { for i := 0; i < len(rooms); i++ { roomTemp := rooms[i] @@ -138,7 +139,7 @@ func TryGetRoom(gameId string, topType int, player *Player, config *confroomrank firstJoin = true } else { // 如果没有合适条件的房间 创建一个 - roomCreate, hasCreate := CreateRoom(gameId, topType, config.Id, roomConfigId) + roomCreate, hasCreate := CreateRoom(gameId, topType, config, roomConfigId, activityTime) if hasCreate { room = roomCreate @@ -168,7 +169,7 @@ func TryCloseRoom(gameId string, room *Room, roomConfig confroomrank.RoomConfig) return } secNow := lxtime.NowUninx() - if secNow > room.CreateTime+RoomCloseSecond { + if secNow > room.ActivityTime-RoomCloseSecond { room.Closed = true // 根据缺口自动填充机器人 for i := 0; i < len(roomConfig.PlayerTypeCount); i++ { diff --git a/util/ztime/external.go b/util/ztime/external.go new file mode 100644 index 0000000..1b110fe --- /dev/null +++ b/util/ztime/external.go @@ -0,0 +1,20 @@ +package ztime + +import ( + "strconv" + "strings" +) + +func TimeClock(text string) (hour, min, sec int) { + list := strings.Split(text, ":") + if len(list) >= 1 { + hour, _ = strconv.Atoi(list[0]) + } + if len(list) >= 2 { + min, _ = strconv.Atoi(list[1]) + } + if len(list) >= 3 { + sec, _ = strconv.Atoi(list[2]) + } + return +} diff --git a/util/ztime/time.go b/util/ztime/time.go new file mode 100644 index 0000000..6049d62 --- /dev/null +++ b/util/ztime/time.go @@ -0,0 +1,129 @@ +package ztime + +import "time" + +const ( + DtFormatDate = "2006-01-02" + DtFormatTime = "2006-01-02 15:04:05" + DtFormatMonth = "2006-01" +) + +// Unix 获取当前秒时间戳 +func Unix() int64 { + return time.Now().Unix() +} + +// UnixMilli 获取当前毫秒时间戳 +func UnixMilli() int64 { + return time.Now().UnixMilli() +} + +// TimeToDateString +// @Description: 时间转日期字符串 +// @param dt +// @return string +func TimeToDateString(dt time.Time) string { + return dt.Format(DtFormatDate) +} + +// TimeToTimeString +// @Description: 时间转时间字符串 +// @param dt +// @return string +func TimeToTimeString(dt time.Time) string { + return dt.Format(DtFormatTime) +} + +// TimeToMonthString +// @Description: 时间转月份字符串 +// @param dt +// @return string +func TimeToMonthString(dt time.Time) string { + return dt.Format(DtFormatMonth) +} + +// TimeToMonth +// @Description: 时间转月份字符串 +// @param dt +// @return string +func TimeToMonth(dt time.Time) int { + return dt.Year()*100 + int(dt.Month()) +} + +// DateStringToTimeE +// @Description: 日期字符串转时间 +// @param dt +// @return time.Time +// @return error +func DateStringToTimeE(dt string) (time.Time, error) { + return time.Parse(DtFormatDate, dt) +} + +// DateStringToTime +// @Description: 时间字符串转时间 +// @param dt +// @return time.Time +// @return error +func DateStringToTime(dt string) time.Time { + if t, err := time.Parse(DtFormatDate, dt); err == nil { + return t + } else { + return time.Now() + } +} + +// TimeStringToTimeE +// @Description: 时间字符串转时间 +// @param dt +// @return time.Time +// @return error +func TimeStringToTimeE(dt string) (time.Time, error) { + return time.Parse(DtFormatTime, dt) +} + +// TimeStringToTime +// @Description: 时间字符串转时间 +// @param dt +// @return time.Time +// @return error +func TimeStringToTime(dt string) time.Time { + if t, err := time.Parse(DtFormatTime, dt); err == nil { + return t + } else { + return time.Now() + } +} + +// TimeTextInt64 把时间转换成数字字符串 比如 20240510113130 +func TimeTextInt64(dt time.Time) int64 { + date := int64(dt.Year())*1_0000 + int64(dt.Month())*100 + int64(dt.Day()) + t := int64(dt.Hour())*1_0000 + int64(dt.Minute())*100 + int64(dt.Second()) + return date*1_000000 + t +} + +// SameMonth +// @Description: 判断同一月 +// @param dt1 +// @param dt2 +// @return bool +func SameMonth(dt1, dt2 time.Time) bool { + return dt1.Year() == dt2.Year() && dt1.Month() == dt2.Month() +} + +// SameDay +// @Description: 判断同一天 +// @param dt1 +// @param dt2 +// @return bool +func SameDay(dt1, dt2 time.Time) bool { + return dt1.Year() == dt2.Year() && dt1.Month() == dt2.Month() && dt1.Day() == dt2.Day() +} + +// SameHour +// @Description: 判断同一小时 +// @param dt1 +// @param dt2 +// @return bool +func SameHour(dt1, dt2 time.Time) bool { + return dt1.Year() == dt2.Year() && dt1.Month() == dt2.Month() && dt1.Day() == dt2.Day() && dt1.Hour() == dt2.Hour() +} -- libgit2 0.21.0