package user_m import ( "gorm.io/gorm" "hilo-user/_const/enum/user_e" "hilo-user/common" "hilo-user/domain" "hilo-user/domain/event/user_ev" "hilo-user/myerr" "hilo-user/myerr/bizerr" "hilo-user/resource/mysql" "math/rand" "strconv" "time" ) type GameInfo struct { Id uint64 `json:"id"` MgId string `json:"mg_id"` GameType user_e.GameType `json:"user_type"` Mode int32 `json:"mode"` Piece int32 `json:"piece"` OnOff1 uint8 `json:"on_off1"` Diamond uint64 `json:"diamond"` CreateId uint64 `json:"create_id"` Status uint8 `json:"status"` // '0.未开始 1.游戏中 2.结束' TxGroupId string `json:"tx_group_id"` GameRoundId string `json:"user_round_id"` BattleStartAt uint32 `json:"battle_start_at"` BattleEndAt uint32 `json:"battle_end_at"` BattleDuration uint32 `json:"battle_duration"` AutoMatch uint8 `json:"auto_match"` // 是否开启自动匹配,0否1是 CreatedTime time.Time `json:"created_time"` UpdatedTime time.Time `json:"updated_time"` } type GamePlayer struct { Id uint64 `json:"id"` GameId uint64 `json:"user_id"` UserId uint64 `json:"user_id"` Status uint8 `json:"status"` // '0.未开始 1.游戏中 2.游戏结束 3.逃跑 4.创建者关闭游戏', UserCode string `json:"user_code"` ExternalId string `json:"external_id"` Rank uint32 `json:"rank"` IsEscaped uint8 `json:"is_escaped"` IsAi uint8 `json:"is_ai"` Role int32 `json:"role"` Score int32 `json:"score"` IsWin uint8 `json:"is_win"` Award uint32 `json:"award"` Extras string `json:"extras"` IsManaged uint8 `json:"is_managed"` EndAt uint32 `json:"end_at"` SeatIdx int8 `json:"seat_idx"` Diamond int64 `json:"diamond"` // 黄钻收益,有可能负数 CreatedTime time.Time `json:"created_time"` UpdatedTime time.Time `json:"updated_time"` } type GameAddParam struct { GameId uint64 `form:"userId"` GameType user_e.GameType `form:"userType" binding:"required"` Mode user_e.GameMode `form:"mode" binding:"required"` Piece int `form:"piece" binding:"required"` OnOff1 int `form:"onOff1" binding:"required"` Diamond uint64 `form:"diamond" binding:"required"` AutoMatch int `form:"autoMatch" binding:"required"` TxGroupId string `form:"groupId" binding:"required"` GameCode string `form:"userCode"` } type GamePlayerOptLog struct { Id uint64 `json:"id"` GameId uint64 `json:"user_id"` UserId uint64 `json:"user_id"` Opt uint8 `json:"opt"` TxGroupId string `json:"tx_group_id"` CreateAt time.Time `json:"create_at"` } type GameSdkReport struct { Id uint64 `json:"id"` GameRoundId string `json:"user_round_id"` TxGroupId string `json:"tx_group_id"` ReportType string `json:"report_type"` ReportMsg string `json:"report_msg"` ExternalId string `json:"external_id"` SsToken string `json:"ss_token"` CreateAt time.Time `json:"create_at"` } func GetGameInfo(model *domain.Model, userId uint64, txGroupId, roundId string, battleEndAt, status int64) (*GameInfo, error) { res := new(GameInfo) db := model.Db if userId != 0 { db = db.Where("id = ?", userId) } if txGroupId != "" { db = db.Where("tx_group_id = ?", txGroupId) } if roundId != "" { db = db.Where("user_round_id = ?", roundId) } if battleEndAt != -1 { db = db.Where("battle_end_at = ?", battleEndAt) } if status != -1 { db = db.Where("status = ?", status) } err := db.First(&res).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } return res, nil } func GetGamingInfo(model *domain.Model, txGroupId string) (*GameInfo, error) { res := new(GameInfo) db := model.Db if txGroupId != "" { db = db.Where("tx_group_id = ?", txGroupId) } err := db.Where("status in (0,1)").First(&res).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } return res, nil } func Add(model *domain.Model, info *GameInfo) error { nowTime := time.Now() info.CreatedTime = nowTime info.UpdatedTime = nowTime err := model.Db.Save(info).Error if err != nil { return myerr.WrapErr(err) } return nil } func Edit(model *domain.Model, id uint64, para *GameAddParam) error { if id == 0 { model.Log.Infof("GameDao Edit id = 0") return nil } err := model.Db.Exec("update user_info set mode=?,piece=?,on_off1=?,diamond=?,auto_match=? where id = ? and battle_start_at = 0", para.Mode, para.Piece, para.OnOff1, para.Diamond, para.AutoMatch, id).Error if err != nil { return myerr.WrapErr(err) } return nil } func GameCloseUpdate(model *domain.Model, info *GameInfo) error { if info.Id == 0 { model.Log.Infof("GameCloseUpdate Id = 0") return bizerr.GameNotFound } result := model.Db.Exec("update user_info set status=?,battle_end_at=? where id = ? and status != 2", user_e.GameStatusEnd, time.Now().Unix(), info.Id) if result.Error != nil { model.Log.Errorf("GameCloseUpdate info.Id:%v, err:%v", info.Id, result.Error) return myerr.WrapErr(result.Error) } if result.RowsAffected <= 0 { model.Log.Errorf("GameCloseUpdate info.Id:%v, err:%v", info.Id, result.Error) return bizerr.GameCloseWrong } return nil } func GameCloseUpdatePlayer(model *domain.Model, info *GameInfo) error { if info.Id == 0 { model.Log.Infof("GameCloseUpdatePlayer Id = 0") return nil } err := model.Db.Exec("update user_player set status=?,end_at=? where user_id = ?", user_e.GamerStatusEnd, time.Now().Unix(), info.Id).Error if err != nil { return myerr.WrapErr(err) } return nil } func GameStartUpdate(model *domain.Model, info *user_ev.GameStartObject) error { //var initGameRoundId bool userInfo := new(GameInfo) infoKey, err := strconv.Atoi(info.ReportGameInfoKey) if err != nil { model.Log.Errorf("GameStartUpdate err:%v, info:%v", err, info) return myerr.WrapErr(err) } err = model.Db.Where("id = ?", infoKey).First(&userInfo).Error if err != nil { model.Log.Errorf("GameStartUpdate err:%v, info:%v", err, info) return myerr.WrapErr(err) //if err != gorm.ErrRecordNotFound { // model.Log.Errorf("GameStartUpdate err:%v, info:%v", err, info) // return myerr.WrapErr(err) //} //userInfo = new(GameInfo) //err = model.Db.Where("tx_group_id = ? and user_round_id = ''", info.RoomId).First(&userInfo).Error //if err != nil { // if err != gorm.ErrRecordNotFound { // model.Log.Errorf("GameStartUpdate err:%v, info:%v", err, info) // return myerr.WrapErr(err) // } // model.Log.Infof("GameStartUpdate 找不到可以更新的记录 info:%v", info) // return nil //} //initGameRoundId = true } if userInfo.Id == 0 { model.Log.Errorf("GameStartUpdate 记录id为0 userInfo:%v", userInfo) return myerr.WrapErr(bizerr.GameNotFound) } //if initGameRoundId { // err = model.Db.Exec("update user_info set mode=?,user_round_id=?,battle_start_at=? where id = ? and user_round_id='' limit 1", // info.GameMode, info.GameRoundId, info.BattleStartAt, userInfo.Id).Error //} else { // err = model.Db.Exec("update user_info set mode=?,user_round_id=?,battle_start_at=? where id = ? limit 1", // info.GameMode, info.GameRoundId, info.BattleStartAt, userInfo.Id).Error //} err = model.Db.Exec("update user_info set mode=?,user_round_id=?,battle_start_at=? where id = ? limit 1", info.GameMode, info.GameRoundId, info.BattleStartAt, userInfo.Id).Error if err != nil { model.Log.Errorf("GameStartUpdate err:%v", err) return myerr.WrapErr(err) } err = model.Db.Exec("update user_player set status=? where user_id = ?", user_e.GamerStatusGaming, userInfo.Id).Error if err != nil { model.Log.Errorf("GameStartUpdate err:%v", err) return myerr.WrapErr(err) } return nil } // 标记游戏已经开始 func GameStartMark(model *domain.Model, userId mysql.ID) error { if err := model.DB().Model(GameInfo{}).Where("id = ?", userId).Update("status", user_e.GameStatusGaming).Error; err != nil { model.Log.Errorf("GameStartMark fail:userId:%v,err:%v", userId, err) return err } return nil } // 标记游戏已经结束 func GameEndMark(model *domain.Model, userId mysql.ID) error { if err := model.DB().Model(GameInfo{}).Where("id = ?", userId).Update("status", user_e.GameStatusEnd).Error; err != nil { model.Log.Errorf("GameStartMark fail:userId:%v,err:%v", userId, err) return err } return nil } func GameSettleUpdate(model *domain.Model, info *user_ev.GameSettleObject) error { //if info.GameRoundId == "" { // model.Log.Infof("GameSettleUpdate GameRoundId = 0") // return nil //} infoKey, err := strconv.Atoi(info.ReportGameInfoKey) if err != nil { model.Log.Errorf("GameSettleUpdate err:%v, info:%v", err, info) return myerr.WrapErr(err) } userInfo := new(GameInfo) err = model.Db.Where("id = ?", infoKey).First(&userInfo).Error if err != nil { model.Log.Errorf("GameSettleUpdate err:%v", err) return myerr.WrapErr(err) } result := model.Db.Exec("update user_info set status=?,battle_end_at=?,battle_duration=? where id = ? and status=1", user_e.GameStatusEnd, info.BattleEndAt, info.BattleDuration, userInfo.Id) if result.Error != nil { model.Log.Errorf("GameSettleUpdate err:%v", err) return myerr.WrapErr(err) } if result.RowsAffected <= 0 { model.Log.Errorf("GameSettleUpdate 修改失败, userInfo.Id:%v", userInfo.Id) return myerr.WrapErr(bizerr.GameSettleWrong) } for _, v := range info.Results { err = model.Db.Exec("update user_player set status=?,`rank`=?,is_escaped=?,is_ai=?,`role`=?,score=?,is_win=?,"+ "award=?,extras=?,end_at=?,diamond=?,is_managed=? where user_id = ? and external_id = ?", user_e.GamerStatusEnd, v.Rank, v.IsEscaped, v.IsAi, v.Role, v.Score, v.IsWin, v.Award, v.Extras, info.BattleEndAt, v.Diamond, v.IsManaged, userInfo.Id, v.Uid).Error if err != nil { model.Log.Errorf("GameSettleUpdate err:%v", err) return myerr.WrapErr(err) } } err = model.Db.Exec("update user_player set status=?,end_at=? where user_id=? and end_at=0", user_e.GamerStatusEnd, time.Now().Unix(), userInfo.Id).Error if err != nil { model.Log.Errorf("GameSettleUpdate err:%v", err) return myerr.WrapErr(err) } return nil } func GetGamePlayers(model *domain.Model, userId uint64) ([]*GamePlayer, error) { res := make([]*GamePlayer, 0) err := model.Db.Where("user_id = ?", userId).Order("created_time").Find(&res).Error if err != nil { return nil, err } return res, nil } func DelGamePlayers(model *domain.Model, userId uint64) error { if userId <= 0 { return bizerr.InvalidParameter } err := model.Db.Exec("delete from user_player where user_id = ?", userId).Error if err != nil { return myerr.WrapErr(err) } return nil } func GetGamePlayersMap(model *domain.Model, userId uint64, userExtIds []string) (map[string]*GamePlayer, error) { list := make([]*GamePlayer, 0, len(userExtIds)) err := model.Db.Where("user_id = ? and external_id in (?)", userId, userExtIds).Find(&list).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } res := make(map[string]*GamePlayer, 0) for _, v := range list { res[v.ExternalId] = v } return res, nil } func GetGamePlayer(model *domain.Model, userId, userId uint64) (*GamePlayer, error) { res := new(GamePlayer) err := model.Db.Where("user_id = ? and user_id = ?", userId, userId).First(res).Error if err != nil && err != gorm.ErrRecordNotFound { return nil, err } return res, nil } func SaveGamePlayer(model *domain.Model, info *GamePlayer) error { err := model.Db.Save(info).Error if err != nil { return myerr.WrapErr(err) } return nil } func DelGamePlayer(model *domain.Model, id uint64) error { result := model.Db.Exec("delete from user_player where id = ? and status=0", id) if result.Error != nil { return result.Error } if result.RowsAffected <= 0 { return myerr.WrapErr(bizerr.GameExitWrong) } return nil } func UpdateGamePlayerExit(model *domain.Model, id uint64) error { err := model.Db.Exec("update user_player set end_at=? where id = ?", time.Now().Unix(), id).Error if err != nil { return err } return nil } func SaveGameOptLog(model *domain.Model, userId, userId uint64, opt user_e.GameOpt, txGroupId string) error { defer common.CheckGoPanic() err := model.Db.Save(&GamePlayerOptLog{GameId: userId, UserId: userId, Opt: uint8(opt), TxGroupId: txGroupId, CreateAt: time.Now()}).Error if err != nil { model.Log.Errorf("SaveGameOptLog err:%v", err) return err } return nil } func SaveGameSdkReport(model *domain.Model, userRoundId, roomId, reportType, reportMsg, externalId, ssToken string) error { defer common.CheckGoPanic() err := model.Db.Save(&GameSdkReport{TxGroupId: roomId, GameRoundId: userRoundId, ReportType: reportType, ReportMsg: reportMsg, ExternalId: externalId, SsToken: ssToken, CreateAt: time.Now()}).Error if err != nil { model.Log.Errorf("SaveGameSdkReport err:%v", err) return err } return nil } // 获取一个正在进行游戏的房间id(房间没有密码,没有下注的游戏房间) func GetGamingTxGroupId(model *domain.Model, userType user_e.GameType) (txGroupId string, err error) { // 游戏类型,游戏未满人,游戏未开始 infos := make([]*GameInfo, 0) sql := "select s1.* from (select * from user_info where user_type=? and status=0 and diamond=0 limit 50) s1 left join group_info on s1.tx_group_id=group_info.tx_group_id where group_info.password='' and group_info.tourist_mic=1" err = model.Db.Raw(sql, userType).Find(&infos).Error //err = model.Db.Where("status = 0 and user_type = ?", userType).Limit(10).Find(&infos).Error if err != nil { return } if len(infos) == 0 { return } if len(infos) == 1 { txGroupId = infos[0].TxGroupId return } // 打乱 rand.Shuffle(len(infos), func(i, j int) { t := infos[i] infos[i] = infos[j] infos[j] = t }) txGroupId = infos[0].TxGroupId return } // 获取用户在该房间已经加入的未结束的游戏 func GetGamingInfoByUserId(model *domain.Model, userId uint64, txGroupId string) (*GameInfo, error) { res := new(GameInfo) db := model.Db err := db.Where("id in (select user_id from user_player where user_id=? and end_at=0) and tx_group_id = ? and status in (0,1)", userId, txGroupId).First(&res).Error //err := db.Where("status in (0,1)").First(&res).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil } return nil, err } return res, nil }