handle.go 8.24 KB
package roomrank

import (
	"apigame/configs-db/confroomrank"
	"apigame/models"
	"apigame/service/code-msg"
	"apigame/util/util-lx/lxtime"
	"apigame/util/zredislock"
)

// HandleGetConfig 活动配置
func HandleGetConfig(req *models.ReqRoomRankGetConfig) (code string, rsp models.RspRoomRankGetConfig) {
	rsp = models.RspRoomRankGetConfig{Config: make([]any, 0)}
	code = code_msg.RECODE_OK
	gameId := req.GameID

	// 尝试更新配置
	configs := confroomrank.GetCurrentConfigs(gameId)
	for _, config := range configs {
		rsp.Config = append(rsp.Config, config.GenerateConfigClient())
	}
	return
}

// HandleInfo 房间排行信息
func HandleInfo(req *models.ReqRoomRankInfo) (code string, rsp models.RspRoomRankInfo) {
	rsp = models.RspRoomRankInfo{}
	code = code_msg.RECODE_OK
	gameId := req.GameID
	playerUid := req.UID
	playerLevel := req.PlayerLevel

	// 读取游戏数据
	player := LoadPlayer(gameId, playerUid, req.TopType)
	player.Name = req.PlayerName
	player.Icon = req.PlayerIcon

	// 采用分布式锁
	lockKey := getLockKey(gameId, req.TopType)
	opt := zredislock.GetOptionLimitRetry(RoomLockLinearBackoff, RoomLockMaxCount)
	lock := zredislock.Obtain(lockKey, RoomLockMillisecond, opt)
	if lock.Err != nil {
		code = code_msg.RECODE_CAOZUOPINFAN_ERROR
		return
	}
	defer lock.Release()

	/* ----- 结算 Start -----*/
	// 尝试判断结算
	hasSettleChange := TrySettle(gameId, req.TopType, player)

	if hasSettleChange {
		SavePlayer(gameId, player)
	}
	if player.SettleHas() {
		rsp.RoomRankInfo = GetInfoFromSettle(player)
		return
	}
	/* ----- 结算 End -----*/

	// 尝试更新配置
	config, hasConfig := confroomrank.GetCurrent(gameId, req.TopType)
	if !hasConfig {
		config = new(confroomrank.ActivityConfig)
		code = code_msg.RECODE_MERGE_ROOMRANK_NOTOPEN_ERROR
		return
	}
	activityTime := GetActivityTime(config)

	// 判断玩家等级
	if req.PlayerLevel < config.OpenLevel {
		code = code_msg.RECODE_MERGE_ROOMRANK_LEVEL_ERROR
		return
	}

	needSavePlayer := false
	defer func() {
		if needSavePlayer {
			SavePlayer(gameId, player)
		}
	}()
	if player.ActivityId != config.Id || player.ActivityTime != activityTime {
		player.ActivityId = config.Id
		player.ActivityTime = activityTime
		player.RoomUid = 0
		player.Score = 0
		needSavePlayer = true
	}

	// 找到原房间
	roomOld, hasOldRoom := TryGetRoom(gameId, req.TopType, player, config)
	if hasOldRoom {
		rsp.RoomRankInfo = GetInfoFromRoom(gameId, player, roomOld, config)
		return
	}

	// 于此同时,如果活动倒计时 < 关门时间 * 2,则不再允许报名
	secNow := lxtime.NowUninx()
	dtEnd := GetTimeEnd(activityTime, config.ReleaseTime).Unix()
	if secNow > dtEnd-RoomCloseSecond*2 {
		code = code_msg.RECODE_MERGE_ROOMRANK_CANTSIGN_ERROR
		return
	}

	// 判断玩家积分
	if player.Score < config.OpenScore {
		rsp.RoomRankInfo = GetInfoFromPlayer(gameId, player, config)
		return
	}

	// 尝试加入房间
	room, hasRoom, firstJoin := TryFindRoom(gameId, req.TopType, player, config, playerLevel, activityTime)

	if !hasRoom {
		code = code_msg.RECODE_MERGE_CONFIG_ERROR
		return
	}

	needSavePlayer = true
	TryReSort(room, config)
	SavePlayer(gameId, player)
	SaveRoom(gameId, room)
	rsp.RoomRankInfo = GetInfoFromRoom(gameId, player, room, config)
	rsp.RoomRankInfo.FirstJoin = firstJoin

	return
}

// HandleGetSettleAward 领取上期结算奖励
func HandleGetSettleAward(req *models.ReqRoomRankGetSettleAward) (code string, rsp models.RspRoomRankGetSettleAward) {
	rsp = models.RspRoomRankGetSettleAward{}
	code = code_msg.RECODE_OK
	gameId := req.GameID
	playerUid := req.UID

	// 读取游戏数据
	player := LoadPlayer(gameId, playerUid, req.TopType)
	player.Name = req.PlayerName
	player.Icon = req.PlayerIcon

	// 采用分布式锁
	lockKey := getLockKey(gameId, req.TopType)
	opt := zredislock.GetOptionLimitRetry(RoomLockLinearBackoff, RoomLockMaxCount)
	lock := zredislock.Obtain(lockKey, RoomLockMillisecond, opt)
	if lock.Err != nil {
		code = code_msg.RECODE_CAOZUOPINFAN_ERROR
		return
	}
	defer lock.Release()

	/* ----- 结算 Start -----*/
	// 尝试判断结算
	hasSettleChange := TrySettle(gameId, req.TopType, player)

	if hasSettleChange {
		SavePlayer(gameId, player)
	}
	if !player.SettleHas() {
		code = code_msg.RECODE_MERGE_ROOMRANK_NOTHASSETTLE_ERROR
		return
	}
	/* ----- 结算 End -----*/

	// 尝试发送已结算的排行榜信息
	{
		confActivity, hasConfActivity := confroomrank.GetConfig(gameId, player.ActivityId)
		if hasConfActivity {
			// 查找玩家所在的房间
			room, hasRoom := TryGetRoom(gameId, req.TopType, player, confActivity)
			if hasRoom {
				rsp.Tops = GetTopsInfoFromRoom(room, confActivity)
			}
		}
	}

	oldActivityId := player.ActivityId

	// 领取奖励
	rsp.SettleRank = player.SettleRank
	rsp.SettleScore = player.SettleScore
	rsp.UserClass = player.SettleUserClass
	rsp.AwardText = player.SettleAward
	player.SettleAward = ""
	player.ActivityId = 0
	player.ActivityTime = 0
	player.RoomUid = 0
	player.Score = 0
	SavePlayer(gameId, player)

	// 记录日志
	recordBase := NewRecordBase(player.Uid, req.TopType, oldActivityId)
	SaveRecordGetSettleAward(gameId, NewRecordGetSettleAward(recordBase, rsp.AwardText))

	return
}

// HandleAddScore 房间排行增加积分
func HandleAddScore(req *models.ReqRoomRankAddScore) (code string, rsp models.RspRoomRankAddScore) {
	rsp = models.RspRoomRankAddScore{}
	code = code_msg.RECODE_OK
	gameId := req.GameID
	playerUid := req.UID
	playerLevel := req.PlayerLevel

	// 读取游戏数据
	player := LoadPlayer(gameId, playerUid, req.TopType)
	player.Name = req.PlayerName
	player.Icon = req.PlayerIcon

	// 采用分布式锁
	lockKey := getLockKey(gameId, req.TopType)
	opt := zredislock.GetOptionLimitRetry(RoomLockLinearBackoff, RoomLockMaxCount)
	lock := zredislock.Obtain(lockKey, RoomLockMillisecond, opt)
	if lock.Err != nil {
		code = code_msg.RECODE_CAOZUOPINFAN_ERROR
		return
	}
	defer lock.Release()

	/* ----- 结算 Start -----*/
	// 尝试判断结算
	hasSettleChange := TrySettle(gameId, req.TopType, player)

	if hasSettleChange {
		SavePlayer(gameId, player)
	}
	if player.SettleHas() {
		rsp.RoomRankInfo = GetInfoFromSettle(player)
		code = code_msg.RECODE_MERGE_ROOMRANK_HASSETTLE_ERROR
		return
	}
	/* ----- 结算 End -----*/

	// 尝试更新配置
	config, hasConfig := confroomrank.GetCurrent(gameId, req.TopType)
	if !hasConfig {
		config = new(confroomrank.ActivityConfig)
		code = code_msg.RECODE_MERGE_ROOMRANK_NOTOPEN_ERROR
		return
	}
	activityTime := GetActivityTime(config)

	// 判断玩家等级
	if req.PlayerLevel < config.OpenLevel {
		code = code_msg.RECODE_MERGE_ROOMRANK_LEVEL_ERROR
		return
	}

	needSavePlayer := false
	defer func() {
		if needSavePlayer {
			SavePlayer(gameId, player)
		}
	}()
	if player.ActivityId != config.Id || player.ActivityTime != activityTime {
		player.ActivityId = config.Id
		player.ActivityTime = activityTime
		player.RoomUid = 0
		player.Score = 0
		needSavePlayer = true
	}

	oldScore := player.Score
	player.Score += req.AddScore
	newScore := player.Score
	needSavePlayer = true
	// 记录日志
	recordBase := NewRecordBase(player.Uid, req.TopType, config.Id)
	SaveRecordAddScore(gameId, NewRecordAddScore(recordBase, req.AddScore, oldScore, newScore))

	// 找到原房间
	roomOld, hasOldRoom := TryGetRoom(gameId, req.TopType, player, config)
	if hasOldRoom {
		// 房间排行增加积分
		UpdatePlayerScore(roomOld, player)
		TryReSort(roomOld, config)
		SaveRoom(gameId, roomOld)

		rsp.RoomRankInfo = GetInfoFromRoom(gameId, player, roomOld, config)
		return
	}

	// 于此同时,如果活动倒计时 < 关门时间 * 2,则不再允许报名
	secNow := lxtime.NowUninx()
	dtEnd := GetTimeEnd(activityTime, config.ReleaseTime).Unix()
	if secNow > dtEnd-RoomCloseSecond*2 {
		code = code_msg.RECODE_MERGE_ROOMRANK_CANTSIGN_ERROR
		return
	}

	// 判断玩家积分
	if player.Score < config.OpenScore {
		rsp.RoomRankInfo = GetInfoFromPlayer(gameId, player, config)
		return
	}

	// 尝试加入房间
	room, hasRoom, firstJoin := TryFindRoom(gameId, req.TopType, player, config, playerLevel, activityTime)

	if !hasRoom {
		code = code_msg.RECODE_MERGE_CONFIG_ERROR
		return
	}

	// 房间排行增加积分
	UpdatePlayerScore(room, player)
	TryReSort(room, config)
	SaveRoom(gameId, room)

	rsp.RoomRankInfo = GetInfoFromRoom(gameId, player, room, config)
	rsp.RoomRankInfo.FirstJoin = firstJoin

	return
}