From 3662627241c795495249727ea2f28d08ed1149df Mon Sep 17 00:00:00 2001 From: 王家文 Date: Fri, 19 Apr 2024 16:16:14 +0800 Subject: [PATCH] feat✨:房间排行活动逻辑 --- models/roomrank.go | 4 +++- service-common/svmysql/dto.go | 3 +-- service/cardholder/dto-game.go | 87 --------------------------------------------------------------------------------------- service/cardholder/dto-player.go | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ service/cardholder/logic.go | 22 +++++++++++----------- service/cardholder/player.go | 42 +++++++++++++++++++++--------------------- service/init.go | 6 +++--- service/roomrank/consts.go | 8 ++++++++ service/roomrank/dto-player.go | 37 ++++++++++++++++++++++++++++++------- service/roomrank/dto-room.go | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- service/roomrank/handle.go | 28 +++++++++++++--------------- service/roomrank/logic.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ service/roomrank/player.go | 26 +++++++++++++++----------- service/roomrank/room.go | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- 14 files changed, 490 insertions(+), 175 deletions(-) delete mode 100644 service/cardholder/dto-game.go create mode 100644 service/cardholder/dto-player.go create mode 100644 service/roomrank/consts.go diff --git a/models/roomrank.go b/models/roomrank.go index 4209e65..c5f0ec7 100644 --- a/models/roomrank.go +++ b/models/roomrank.go @@ -14,13 +14,15 @@ type RspRoomRankGetConfig struct { // RoomRankInfo 房间排行信息 type RoomRankInfo struct { - RoomUid int64 `form:"room_uid" json:"room_uid"` // 房间唯一ID + SettleHas bool `form:"settle_has" json:"settle_has"` // 有结算内容未领取 + SettleAward string `form:"settle_award" json:"settle_award"` // 结算奖励内容 } // ReqRoomRankInfo 请求 房间排行信息 type ReqRoomRankInfo struct { BaseLoginInfo BaseSign + PlayerLevel int `form:"player_level" json:"player_level"` // 玩家等级 } // RspRoomRankInfo 返回 房间排行信息 diff --git a/service-common/svmysql/dto.go b/service-common/svmysql/dto.go index a87d282..8b8adc9 100644 --- a/service-common/svmysql/dto.go +++ b/service-common/svmysql/dto.go @@ -52,8 +52,7 @@ func First(obj IMysqlData, suffix string) (has bool, err error) { return } -func Find(obj IMysqlData, suffix string) (has bool, err error) { - info := obj.MysqlInfo(suffix) +func Find(obj any, info *MysqlInfo) (has bool, err error) { db := info.DbMysql result := db.Table(info.TableName).Find(obj) diff --git a/service/cardholder/dto-game.go b/service/cardholder/dto-game.go deleted file mode 100644 index e3bc1e7..0000000 --- a/service/cardholder/dto-game.go +++ /dev/null @@ -1,87 +0,0 @@ -package cardholder - -import ( - "apigame/service-common/svconst" - "apigame/service-common/svmysql" - "apigame/util/util-lx/lxalilog" - "apigame/util/util-lx/lxtime" - "encoding/json" - "fmt" -) - -// DataCardHolder 卡牌活动持久数据 -type DataCardHolder struct { - Uid int64 `gorm:"column:uid;primaryKey;comment:玩家唯一ID"` - ActivityId int64 `gorm:"comment:活动ID"` - - Details *DataCardHolderDetails `gorm:"-"` // 活动详情 - DetailsText string `gorm:"comment:活动详情封装"` - - CreateTime int64 `gorm:"comment:创建时间戳"` - UpdateTime int64 `gorm:"comment:修改时间戳"` -} - -func (d *DataCardHolder) MysqlInfo(suffix string) *svmysql.MysqlInfo { - tableName := svconst.MYSQL_TABLE_S_CARDHOLDER_DATA - return &svmysql.MysqlInfo{ - DbMysql: svconst.DbCommon, - TableName: fmt.Sprintf("%s_%s", tableName, suffix), - } -} - -// DataCardHolderDetails 卡牌活动详情 -type DataCardHolderDetails struct { - Cards map[int]int // 每张卡集了多少张 k=卡牌ID v=数量 - Album map[int]int // 卡组奖励领取 k=卡组ID v=数量 - StarSequenceScales map[string]int // 星级序列刻度 k=ID_用户序列_用户分组 v=刻度 - CardSequenceScales map[string]int // 卡牌序列刻度 k=ID_用户序列_用户分组 v=刻度 - Round int // 卡册当前轮次 - StarCount int // 星星点数 - LastStarCount int // 上期活动剩余星星点数 - AutoExchangeHolder []int // 活动切换时自动兑换的卡包列表 -} - -func NewDataCardHolder(uid int64) *DataCardHolder { - d := &DataCardHolder{ - Uid: uid, - Details: NewDataCardHolderDetails(), - } - d.Encode() - return d -} - -func NewDataCardHolderDetails() *DataCardHolderDetails { - return &DataCardHolderDetails{ - Cards: make(map[int]int), - Album: make(map[int]int), - StarSequenceScales: make(map[string]int), - CardSequenceScales: make(map[string]int), - Round: 1, - StarCount: 0, - AutoExchangeHolder: make([]int, 0), - } -} - -func (d *DataCardHolder) Init(uid int64) { - d.Uid = uid - d.CreateTime = lxtime.NowUninx() -} - -// Encode 打包数据 -func (d *DataCardHolder) Encode() { - details, err := json.Marshal(d.Details) - if err != nil { - lxalilog.Errors(err, "DataCardHolder Encode Error", d.Uid, d.ActivityId) - return - } - d.DetailsText = string(details) -} - -// Decode 分包数据 -func (d *DataCardHolder) Decode() { - err := json.Unmarshal([]byte(d.DetailsText), d.Details) - if err != nil { - lxalilog.Errors(err, "DataCardHolder Decode Error", d.Uid, d.ActivityId) - return - } -} diff --git a/service/cardholder/dto-player.go b/service/cardholder/dto-player.go new file mode 100644 index 0000000..b5f0155 --- /dev/null +++ b/service/cardholder/dto-player.go @@ -0,0 +1,87 @@ +package cardholder + +import ( + "apigame/service-common/svconst" + "apigame/service-common/svmysql" + "apigame/util/util-lx/lxalilog" + "apigame/util/util-lx/lxtime" + "encoding/json" + "fmt" +) + +// Player 卡牌活动持久数据 +type Player struct { + Uid int64 `gorm:"column:uid;primaryKey;comment:玩家唯一ID"` + ActivityId int64 `gorm:"comment:活动ID"` + + Details *PlayerDetails `gorm:"-"` // 详情 + DetailsText string `gorm:"comment:详情封装"` + + CreateTime int64 `gorm:"comment:创建时间戳"` + UpdateTime int64 `gorm:"comment:修改时间戳"` +} + +func (d *Player) MysqlInfo(suffix string) *svmysql.MysqlInfo { + tableName := svconst.MYSQL_TABLE_S_CARDHOLDER_DATA + return &svmysql.MysqlInfo{ + DbMysql: svconst.DbCommon, + TableName: fmt.Sprintf("%s_%s", tableName, suffix), + } +} + +func NewPlayer(uid int64) *Player { + d := &Player{ + Uid: uid, + Details: NewPlayerDetails(), + } + d.Encode() + return d +} + +// PlayerDetails 详情 +type PlayerDetails struct { + Cards map[int]int // 每张卡集了多少张 k=卡牌ID v=数量 + Album map[int]int // 卡组奖励领取 k=卡组ID v=数量 + StarSequenceScales map[string]int // 星级序列刻度 k=ID_用户序列_用户分组 v=刻度 + CardSequenceScales map[string]int // 卡牌序列刻度 k=ID_用户序列_用户分组 v=刻度 + Round int // 卡册当前轮次 + StarCount int // 星星点数 + LastStarCount int // 上期活动剩余星星点数 + AutoExchangeHolder []int // 活动切换时自动兑换的卡包列表 +} + +func NewPlayerDetails() *PlayerDetails { + return &PlayerDetails{ + Cards: make(map[int]int), + Album: make(map[int]int), + StarSequenceScales: make(map[string]int), + CardSequenceScales: make(map[string]int), + Round: 1, + StarCount: 0, + AutoExchangeHolder: make([]int, 0), + } +} + +func (d *Player) Init(uid int64) { + d.Uid = uid + d.CreateTime = lxtime.NowUninx() +} + +// Encode 打包数据 +func (d *Player) Encode() { + details, err := json.Marshal(d.Details) + if err != nil { + lxalilog.Errors(err, "Player Encode Error", d.Uid, d.ActivityId) + return + } + d.DetailsText = string(details) +} + +// Decode 分包数据 +func (d *Player) Decode() { + err := json.Unmarshal([]byte(d.DetailsText), d.Details) + if err != nil { + lxalilog.Errors(err, "Player Decode Error", d.Uid, d.ActivityId) + return + } +} diff --git a/service/cardholder/logic.go b/service/cardholder/logic.go index 5fc1d44..b2e77b1 100644 --- a/service/cardholder/logic.go +++ b/service/cardholder/logic.go @@ -31,7 +31,7 @@ func CheckStatus(conf *confcardholder.ActivityConfig) string { } // CheckGameData 检查游戏数据 轮次等 -func CheckGameData(d *DataCardHolder, conf *confcardholder.ActivityConfig) string { +func CheckGameData(d *Player, conf *confcardholder.ActivityConfig) string { if d.Details.Round > conf.Round { return code_msg.RECODE_MERGE_CARDHOLDER_ROUNDFINISH_ERROR } @@ -74,7 +74,7 @@ func GetListFromArray(array []string, scale, count int) []string { } // GetNewCard 按顺序查找数目最少的一张卡抽取 -func GetNewCard(player *DataCardHolder, conf *confcardholder.ActivityConfig) int { +func GetNewCard(player *Player, conf *confcardholder.ActivityConfig) int { if len(conf.CardConfig) < 1 { return 0 } @@ -91,7 +91,7 @@ func GetNewCard(player *DataCardHolder, conf *confcardholder.ActivityConfig) int } // CheckAlbumFinish 判断卡组是否已集齐 -func CheckAlbumFinish(albumId int, player *DataCardHolder, config *confcardholder.ActivityConfig) bool { +func CheckAlbumFinish(albumId int, player *Player, config *confcardholder.ActivityConfig) bool { for _, conf := range config.CardConfig { if conf.SetId == albumId { count := player.Details.Cards[conf.Id] @@ -104,7 +104,7 @@ func CheckAlbumFinish(albumId int, player *DataCardHolder, config *confcardholde } // CheckRoundFinish 判断轮次是否已集齐(所有卡组集齐) -func CheckRoundFinish(player *DataCardHolder, config *confcardholder.ActivityConfig) bool { +func CheckRoundFinish(player *Player, config *confcardholder.ActivityConfig) bool { for _, conf := range config.AlbumConfig { count := player.Details.Album[conf.SetId] if count < 1 { @@ -115,14 +115,14 @@ func CheckRoundFinish(player *DataCardHolder, config *confcardholder.ActivityCon } // HandleNextRound 处理轮次完成 星级序列刻度 卡牌序列刻度 -func HandleNextRound(player *DataCardHolder) { +func HandleNextRound(player *Player) { player.Details.Round += 1 player.Details.Cards = make(map[int]int) player.Details.Album = make(map[int]int) } // GetInfo 玩家卡牌活动信息 -func GetInfo(player *DataCardHolder, conf *confcardholder.ActivityConfig) models.CardHolderInfo { +func GetInfo(player *Player, config *confcardholder.ActivityConfig) models.CardHolderInfo { info := models.CardHolderInfo{ Cards: make(map[int]int), Album: make(map[int]int), @@ -142,7 +142,7 @@ func GetInfo(player *DataCardHolder, conf *confcardholder.ActivityConfig) models // DoOpen 封装的抽卡逻辑 // openMode:开包类型0客户端驱动1星星商店购买2剩余星星兑换 func DoOpen(gameId string, - player *DataCardHolder, + player *Player, config *confcardholder.ActivityConfig, confCardholder confcardholder.OpenCardholderConfig, sequenceId, cohort string, @@ -206,7 +206,7 @@ func DoOpen(gameId string, // DoOpenCheckAward 封装的新卡判断是否出发卡组和轮次奖励的逻辑 func DoOpenCheckAward(gameId string, - player *DataCardHolder, + player *Player, config *confcardholder.ActivityConfig, sequenceId, cohort string, newCards []int, @@ -270,7 +270,7 @@ func DoOpenCheckAward(gameId string, } // CalculateStarCount 计算星星点数 -func CalculateStarCount(player *DataCardHolder, config *confcardholder.ActivityConfig) { +func CalculateStarCount(player *Player, config *confcardholder.ActivityConfig) { starCount := 0 for cardId, cardCount := range player.Details.Cards { if cardCount <= 1 { @@ -292,7 +292,7 @@ func CalculateStarCount(player *DataCardHolder, config *confcardholder.ActivityC } // GetStarCardList 按照规则扣除星星数找到需要扣除的卡牌列表 -func GetStarCardList(player *DataCardHolder, config *confcardholder.ActivityConfig, needStar int) (enough bool, cardList map[int]int) { +func GetStarCardList(player *Player, config *confcardholder.ActivityConfig, needStar int) (enough bool, cardList map[int]int) { enough = false cardList = make(map[int]int) starAmount := 0 @@ -361,7 +361,7 @@ func GetStarCardList(player *DataCardHolder, config *confcardholder.ActivityConf } // NextActivityAutoExchange 活动切换时自动兑换卡包 -func NextActivityAutoExchange(gameId string, player *DataCardHolder, config *confcardholder.ActivityConfig) { +func NextActivityAutoExchange(gameId string, player *Player, config *confcardholder.ActivityConfig) { starCount := player.Details.LastStarCount // 把星星的配置按照需要的星星数降序排列 list := lo.Values[int, confcardholder.StarShopConfig](config.StarShopConfig) diff --git a/service/cardholder/player.go b/service/cardholder/player.go index e83018d..aa26933 100644 --- a/service/cardholder/player.go +++ b/service/cardholder/player.go @@ -8,26 +8,26 @@ import ( ) // SavePlayer 存储数据 -func SavePlayer(gameId string, d *DataCardHolder) { - d.UpdateTime = lxtime.NowUninx() - d.Encode() +func SavePlayer(gameId string, player *Player) { + player.UpdateTime = lxtime.NowUninx() + player.Encode() - err := svmysql.Save(d, gameId) + err := svmysql.Save(player, gameId) if err != nil { - lxalilog.Errors(err, "cardholder.SavePlayer error", gameId, d.Uid, d.ActivityId) + lxalilog.Errors(err, "cardholder.SavePlayer error", gameId, player.Uid, player.ActivityId) } } -func _LoadPlayer(gameId string, playerUid int64) (d *DataCardHolder) { - d = NewDataCardHolder(playerUid) - has, err := svmysql.First(d, gameId) +func _LoadPlayer(gameId string, playerUid int64) (player *Player) { + player = NewPlayer(playerUid) + has, err := svmysql.First(player, gameId) if has { - d.Decode() + player.Decode() } else { - d.Init(playerUid) - err = svmysql.Create(d, gameId) + player.Init(playerUid) + err = svmysql.Create(player, gameId) if err != nil { - lxalilog.Errors(err, "cardholder._LoadPlayer Create error", gameId, d.Uid, d.ActivityId) + lxalilog.Errors(err, "cardholder._LoadPlayer Create error", gameId, player.Uid, player.ActivityId) return } } @@ -35,24 +35,24 @@ func _LoadPlayer(gameId string, playerUid int64) (d *DataCardHolder) { } // LoadPlayer 获取数据 外部接口 -func LoadPlayer(gameId string, playerUid int64, config *confcardholder.ActivityConfig) (d *DataCardHolder) { +func LoadPlayer(gameId string, playerUid int64, config *confcardholder.ActivityConfig) (player *Player) { configId := config.Id - d = _LoadPlayer(gameId, playerUid) + player = _LoadPlayer(gameId, playerUid) // 如果当前有上线活动(活动ID不为0),且活动ID和玩家数据不同,说明活动已切换 需更新 if configId != 0 && - configId != d.ActivityId { + configId != player.ActivityId { // 剩余的星星数 - starCount := d.Details.StarCount + starCount := player.Details.StarCount - d.ActivityId = configId - d.Details = NewDataCardHolderDetails() + player.ActivityId = configId + player.Details = NewPlayerDetails() // 使用剩余的星星数来自动兑换卡包 - d.Details.LastStarCount = starCount - NextActivityAutoExchange(gameId, d, config) + player.Details.LastStarCount = starCount + NextActivityAutoExchange(gameId, player, config) - SavePlayer(gameId, d) + SavePlayer(gameId, player) } return } diff --git a/service/init.go b/service/init.go index 0fc4b47..c396e24 100644 --- a/service/init.go +++ b/service/init.go @@ -12,14 +12,14 @@ func Init() { // create table // 卡牌卡包 for _, gameId := range svconst.GameListCardHolder { - svmysql.InitTable(new(cardholder.DataCardHolder), gameId, true) + svmysql.InitTable(new(cardholder.Player), gameId, true) svmysql.InitTable(new(cardholder.RecordCardHolderOpen), gameId, true) svmysql.InitTable(new(cardholder.RecordCardHolderRewardAlbum), gameId, true) svmysql.InitTable(new(cardholder.RecordCardHolderRewardRound), gameId, true) } - // 卡牌卡包 + // 房间排行 for _, gameId := range svconst.GameListRoomRank { - svmysql.InitTable(new(roomrank.DataRoomRankPlayer), gameId, true) + svmysql.InitTable(new(roomrank.Player), gameId, true) } } diff --git a/service/roomrank/consts.go b/service/roomrank/consts.go new file mode 100644 index 0000000..0112881 --- /dev/null +++ b/service/roomrank/consts.go @@ -0,0 +1,8 @@ +package roomrank + +const ( + UserClassMin = 1 // 最小评级 + UserClassMax = 5 // 最大评级 + + RoomCloseSecond = 180 // 房间关闭时间 +) diff --git a/service/roomrank/dto-player.go b/service/roomrank/dto-player.go index 410926e..7d72eab 100644 --- a/service/roomrank/dto-player.go +++ b/service/roomrank/dto-player.go @@ -4,10 +4,11 @@ import ( "apigame/service-common/svconst" "apigame/service-common/svmysql" "apigame/util/util-lx/lxtime" + "fmt" ) -// DataRoomRankPlayer 房间排行持久数据 -type DataRoomRankPlayer struct { +// Player 房间排行持久数据 +type Player struct { Uid int64 `gorm:"column:uid;primaryKey;comment:玩家唯一ID"` ActivityId int64 `gorm:"comment:活动ID"` @@ -17,26 +18,48 @@ type DataRoomRankPlayer struct { RoomUid int64 `gorm:"comment:所在房间唯一ID"` + SettleHas bool `gorm:"comment:有结算内容未领取"` + SettleAward string `gorm:"comment:结算奖励内容"` + CreateTime int64 `gorm:"comment:创建时间戳"` UpdateTime int64 `gorm:"comment:修改时间戳"` } -func (d *DataRoomRankPlayer) MysqlInfo(suffix string) *svmysql.MysqlInfo { +func (d *Player) MysqlInfo(suffix string) *svmysql.MysqlInfo { tableName := svconst.MYSQL_TABLE_S_ROOMRANK_PLAYER return &svmysql.MysqlInfo{ DbMysql: svconst.DbCommon, - TableName: tableName + suffix, + TableName: fmt.Sprintf("%s_%s", tableName, suffix), } } -func NewDataRoomRankPlayer(uid int64) *DataRoomRankPlayer { - d := &DataRoomRankPlayer{ +func NewPlayer(uid int64) *Player { + d := &Player{ Uid: uid, } return d } -func (d *DataRoomRankPlayer) Init(uid int64) { +func (d *Player) Init(uid int64) { d.Uid = uid d.CreateTime = lxtime.NowUninx() } + +func (d *Player) AddUserScore(count int) { + d.UserScore += count + userScoreMin := UserClassMin * 10 + userScoreMax := UserClassMax*10 + 20 + if d.UserScore < userScoreMin { + d.UserScore = userScoreMin + } + if d.UserScore > userScoreMax { + d.UserScore = userScoreMax + } + d.UserClass = d.UserScore / 10 + if d.UserClass < UserClassMin { + d.UserClass = UserClassMin + } + if d.UserClass > UserClassMax { + d.UserClass = UserClassMax + } +} diff --git a/service/roomrank/dto-room.go b/service/roomrank/dto-room.go index 483483f..ce05049 100644 --- a/service/roomrank/dto-room.go +++ b/service/roomrank/dto-room.go @@ -3,23 +3,111 @@ package roomrank import ( "apigame/service-common/svconst" "apigame/service-common/svmysql" + "apigame/util/util-lx/lxalilog" + "apigame/util/util-lx/lxtime" + "encoding/json" "fmt" + "github.com/samber/lo" ) -// DataRoomRankRoom 房间排行持久数据 -type DataRoomRankRoom struct { +// Room 房间排行持久数据 +type Room struct { Id int64 `gorm:"column:id;primaryKey;comment:房间唯一ID"` - Uid int64 `gorm:"comment:玩家唯一ID"` ActivityId int64 `gorm:"comment:活动ID"` + ConfigId int `gorm:"comment:房间配置ID"` + + Details *RoomDetails `gorm:"-"` // 详情 + DetailsText string `gorm:"comment:详情封装"` + + Closed bool `gorm:"comment:房间已关闭"` CreateTime int64 `gorm:"comment:创建时间戳"` UpdateTime int64 `gorm:"comment:修改时间戳"` } -func (d *DataRoomRankRoom) MysqlInfo(suffix string) *svmysql.MysqlInfo { +func (d *Room) MysqlInfo(suffix string) *svmysql.MysqlInfo { tableName := svconst.MYSQL_TABLE_S_ROOMRANK_ROOM return &svmysql.MysqlInfo{ DbMysql: svconst.DbCommon, TableName: fmt.Sprintf("%s_%s_%d", tableName, suffix, d.ActivityId), } } + +// RoomPlayer 房间玩家 +type RoomPlayer struct { + Uid int64 // 玩家唯一ID + Score int64 // 玩家排行分数 + JoinTime int64 // 加入时间 + UserType int // 用户类型 + RobotConfigId int // 0=玩家 +} + +func NewRoomRobot(robotConfigId int, userType int) *RoomPlayer { + d := &RoomPlayer{ + Uid: 0, + Score: 0, + JoinTime: lxtime.NowUninx(), + UserType: userType, + RobotConfigId: robotConfigId, + } + return d +} + +func NewRoomPlayer(player *Player) *RoomPlayer { + d := &RoomPlayer{ + Uid: player.Uid, + Score: 0, + JoinTime: lxtime.NowUninx(), + UserType: player.UserType, + RobotConfigId: 0, + } + return d +} + +// RoomDetails 详情 +type RoomDetails struct { + Players []*RoomPlayer // 房间玩家列表 +} + +// Encode 打包数据 +func (d *Room) Encode() { + details, err := json.Marshal(d.Details) + if err != nil { + lxalilog.Errors(err, "Player Encode Error", d.Id, d.ActivityId) + return + } + d.DetailsText = string(details) +} + +// Decode 分包数据 +func (d *Room) Decode() { + d.Details = &RoomDetails{ + Players: make([]*RoomPlayer, 0), + } + err := json.Unmarshal([]byte(d.DetailsText), d.Details) + if err != nil { + lxalilog.Errors(err, "Player Decode Error", d.Id, d.ActivityId) + return + } +} + +// FindPlayer 找到玩家排名 -1=没找到 +func (d *Room) FindPlayer(playerUid int64) int { + count := len(d.Details.Players) + if count > 0 { + for i := 0; i < count; i++ { + p := d.Details.Players[i] + if p.Uid == playerUid { + return i + } + } + } + + return -1 +} + +func (d *Room) GetPlayerTypeCount(userType int) int { + return lo.CountBy(d.Details.Players, func(p *RoomPlayer) bool { + return p.UserType == userType + }) +} diff --git a/service/roomrank/handle.go b/service/roomrank/handle.go index 2015fbc..44208c7 100644 --- a/service/roomrank/handle.go +++ b/service/roomrank/handle.go @@ -27,31 +27,29 @@ func HandleInfo(req *models.ReqRoomRankInfo) (code string, rsp models.RspRoomRan code = code_msg.RECODE_OK gameId := req.GameID playerUid := req.UID + playerLevel := req.PlayerLevel // 尝试更新配置 config, hasConfig := confroomrank.GetCurrent(gameId) if !hasConfig { - code = code_msg.RECODE_MERGE_ROOMRANK_NOTOPEN_ERROR - return + config = new(confroomrank.ActivityConfig) } - // todo 检查是否在结算中 - //// 判断预告时间 - //sec := lxtime.NowUninx() - //if sec < config.StartTime { - // code = code_msg.RECODE_MERGE_CARDHOLDER_NOTOPEN_ERROR - // return - //} - // 读取游戏数据 player := LoadPlayer(gameId, playerUid) - // todo 检查是否有领取的结算奖励 + // 尝试判断结算 + hasSettle := TrySettle(gameId, player, config) + + // 尝试加入房间 + room, hasRoom := TryGetRoom(gameId, player, config, playerLevel) - //hasRoom := player.RoomUid != 0 - //if hasRoom { - // room, has := LoadRoom(gameId, player.RoomUid,) - //} + if hasSettle || hasRoom { + SavePlayer(gameId, player) + } + if hasRoom { + SaveRoom(gameId, room) + } rsp.RoomRankInfo = GetInfo(player, config) diff --git a/service/roomrank/logic.go b/service/roomrank/logic.go index 281f76e..9d73bde 100644 --- a/service/roomrank/logic.go +++ b/service/roomrank/logic.go @@ -1 +1,50 @@ package roomrank + +import ( + "apigame/configs/confroomrank" +) + +// TrySettle 尝试判断结算 +func TrySettle(gameId string, player *Player, config *confroomrank.ActivityConfig) (hasChange bool) { + hasChange = false + if player.SettleHas { + return + } + if player.ActivityId == 0 { + return + } + if player.ActivityId == config.Id { + return + } + // 查找玩家所在的房间 + room, hasRoom := LoadRoom(gameId, player.ActivityId, player.RoomUid) + if !hasRoom { + return + } + // 找到玩家在房间里的名次 + rankIndex := room.FindPlayer(player.Uid) + if rankIndex < 0 { + return + } + confActivity, hasConfActivity := confroomrank.GetConfig(gameId, room.ActivityId) + if !hasConfActivity { + return + } + // 设置玩家奖励等数据 + hasChange = true + player.SettleHas = true + confRoom, hasConfRoom := confActivity.Room[room.ConfigId] + if !hasConfRoom { + return + } + if len(confRoom.Awards) > rankIndex { + player.SettleAward = confRoom.Awards[rankIndex] + } + if len(confRoom.SettleScores) > rankIndex { + player.AddUserScore(confRoom.SettleScores[rankIndex]) + } + if len(confRoom.SettleUserType) > rankIndex { + player.UserType = confRoom.SettleUserType[rankIndex] + } + return +} diff --git a/service/roomrank/player.go b/service/roomrank/player.go index 306704c..1b999a0 100644 --- a/service/roomrank/player.go +++ b/service/roomrank/player.go @@ -9,26 +9,26 @@ import ( ) // SavePlayer 存储数据 -func SavePlayer(gameId string, d *DataRoomRankPlayer) { - d.UpdateTime = lxtime.NowUninx() +func SavePlayer(gameId string, player *Player) { + player.UpdateTime = lxtime.NowUninx() - err := svmysql.Save(d, gameId) + err := svmysql.Save(player, gameId) if err != nil { - lxalilog.Errors(err, "roomrank.SavePlayer error", gameId, d.Uid, d.ActivityId) + lxalilog.Errors(err, "roomrank.SavePlayer error", gameId, player.Uid, player.ActivityId) return } } // LoadPlayer 获取数据 外部接口 -func LoadPlayer(gameId string, playerUid int64) (d *DataRoomRankPlayer) { - d = NewDataRoomRankPlayer(playerUid) - has, err := svmysql.First(d, gameId) +func LoadPlayer(gameId string, playerUid int64) (player *Player) { + player = NewPlayer(playerUid) + has, err := svmysql.First(player, gameId) if has { } else { - d.Init(playerUid) - err = svmysql.Create(d, gameId) + player.Init(playerUid) + err = svmysql.Create(player, gameId) if err != nil { - lxalilog.Errors(err, "roomrank._LoadPlayer Create error", gameId, d.Uid, d.ActivityId) + lxalilog.Errors(err, "roomrank._LoadPlayer Create error", gameId, player.Uid, player.ActivityId) return } } @@ -36,7 +36,11 @@ func LoadPlayer(gameId string, playerUid int64) (d *DataRoomRankPlayer) { } // GetInfo 活动信息 -func GetInfo(player *DataRoomRankPlayer, conf *confroomrank.ActivityConfig) models.RoomRankInfo { +func GetInfo(player *Player, conf *confroomrank.ActivityConfig) models.RoomRankInfo { info := models.RoomRankInfo{} + if player.SettleHas { + info.SettleHas = player.SettleHas + info.SettleAward = player.SettleAward + } return info } diff --git a/service/roomrank/room.go b/service/roomrank/room.go index e75f897..b20bc04 100644 --- a/service/roomrank/room.go +++ b/service/roomrank/room.go @@ -1,39 +1,183 @@ package roomrank import ( + "apigame/configs/confroomrank" "apigame/service-common/svmysql" "apigame/util/util-lx/lxalilog" "apigame/util/util-lx/lxtime" ) -func tryInitTable(gameId string, d *DataRoomRankRoom) { - svmysql.InitTable(d, gameId, false) +func tryInitTable(gameId string, room *Room) { + svmysql.InitTable(room, gameId, false) } // SaveRoom 存储数据 -func SaveRoom(gameId string, d *DataRoomRankRoom) { - tryInitTable(gameId, d) +func SaveRoom(gameId string, room *Room) { + tryInitTable(gameId, room) - d.UpdateTime = lxtime.NowUninx() + room.UpdateTime = lxtime.NowUninx() + room.Encode() - err := svmysql.Save(d, gameId) + err := svmysql.Save(room, gameId) if err != nil { - lxalilog.Errors(err, "roomrank.SaveRoom error", gameId, d.Uid, d.ActivityId) + lxalilog.Errors(err, "roomrank.SaveRoom error", gameId, room.Id, room.ActivityId) return } } -// LoadRoom 获取数据 外部接口 -func LoadRoom(gameId string, id int64, activityId int64) (d *DataRoomRankRoom, has bool) { - d = &DataRoomRankRoom{Id: id, ActivityId: activityId} - tryInitTable(gameId, d) +// LoadRoom 获取数据 +func LoadRoom(gameId string, activityId int64, roomUid int64) (room *Room, has bool) { + room = &Room{Id: roomUid, ActivityId: activityId} + if roomUid == 0 { + has = false + return + } + tryInitTable(gameId, room) var err error - has, err = svmysql.First(d, gameId) + has, err = svmysql.First(room, gameId) if err != nil { - lxalilog.Errors(err, "roomrank.LoadRoom error", gameId, id, activityId) + lxalilog.Errors(err, "roomrank.LoadRoom error", gameId, roomUid, activityId) return } + room.Decode() + + return +} +func CreateRoom(gameId string, activityId int64, roomConfigId int) (room *Room, has bool) { + room = new(Room) + room.ActivityId = activityId + room.ConfigId = roomConfigId + room.Closed = false + room.CreateTime = lxtime.NowUninx() + details := new(RoomDetails) + details.Players = make([]*RoomPlayer, 0) + room.Details = details + + err := svmysql.Save(room, gameId) + if err != nil { + has = false + } else { + has = true + } return } + +// FindRoom 查找 +func FindRoom(gameId string, activityId int64, roomConfigId int) (rooms []*Room, has bool) { + roomDemo := &Room{ActivityId: activityId} + tryInitTable(gameId, roomDemo) + info := roomDemo.MysqlInfo(gameId) + + info.DbMysql = info.DbMysql.Where("config_id = ? AND closed = false", roomConfigId) + has, _ = svmysql.Find(&rooms, info) + for _, room := range rooms { + room.Decode() + } + + return +} + +// TryGetRoom 尝试获取房间 +func TryGetRoom(gameId string, player *Player, config *confroomrank.ActivityConfig, playerLevel int) (room *Room, hasRoom bool) { + hasRoom = false + if player.SettleHas { + return + } + if player.ActivityId != config.Id { + player.ActivityId = config.Id + } + // 查找玩家所在的房间 + room, hasRoom = LoadRoom(gameId, config.Id, player.RoomUid) + if hasRoom { + return + } + + // 根据等级和分数范围查找合适的房间配置ID + roomConfigId := 0 + roomConfig := confroomrank.RoomConfig{} + for _, i2 := range config.Room { + if playerLevel >= i2.Levels[0] && + playerLevel <= i2.Levels[1] && + player.UserClass == i2.UserClass { + roomConfigId = i2.Id + roomConfig = i2 + } + } + if roomConfigId == 0 { + lxalilog.Errors("TryGetRoom find roomConfigId error", playerLevel, player.UserClass) + return + } + // 数据库查找合适条件的房间列表 + rooms, has := FindRoom(gameId, config.Id, roomConfigId) + if has { + for i := 0; i < len(rooms); i++ { + roomTemp := rooms[i] + TryCloseRoom(gameId, roomTemp, roomConfig) + if roomTemp.Closed { + continue + } + // 可容纳玩家类型数量 + canJoinCount := GetTypeCanJoinCount(roomTemp, roomConfig, player.UserType) + if canJoinCount > 0 { + room = roomTemp + hasRoom = true + break + } + } + } + if hasRoom { + // 如果有 就加入 + PlayerJoinRoom(room, player) + } else { + // 如果没有合适条件的房间 创建一个 + roomCreate, hasCreate := CreateRoom(gameId, config.Id, roomConfigId) + if hasCreate { + room = roomCreate + PlayerJoinRoom(room, player) + hasRoom = hasCreate + } + } + + return +} + +func PlayerJoinRoom(room *Room, player *Player) { + roomPlayer := NewRoomPlayer(player) + room.Details.Players = append(room.Details.Players, roomPlayer) + player.RoomUid = room.Id +} + +// TryCloseRoom 尝试关闭房间 +func TryCloseRoom(gameId string, room *Room, roomConfig confroomrank.RoomConfig) { + secNow := lxtime.NowUninx() + if secNow > room.CreateTime+RoomCloseSecond { + room.Closed = true + // 根据缺口自动填充机器人 + for i := 0; i < len(roomConfig.PlayerTypeCount); i++ { + pair := roomConfig.PlayerTypeCount[i] + userType := pair[0] + canJoinCount := pair[1] - room.GetPlayerTypeCount(userType) + robotConfigId := roomConfig.AutoRobot[i] + for i := 0; i < canJoinCount; i++ { + roomPlayer := NewRoomRobot(robotConfigId, userType) + room.Details.Players = append(room.Details.Players, roomPlayer) + } + } + SaveRoom(gameId, room) + } +} + +// GetTypeCanJoinCount 房间获取某种类型玩家可加入数量 +func GetTypeCanJoinCount(room *Room, roomConfig confroomrank.RoomConfig, userType int) int { + maxCount := 0 + for i := 0; i < len(roomConfig.PlayerTypeCount); i++ { + pair := roomConfig.PlayerTypeCount[i] + if pair[0] == userType { + maxCount = pair[1] + break + } + } + return maxCount - room.GetPlayerTypeCount(userType) +} -- libgit2 0.21.0