package thirteen

import (
	"fmt"
	"math"
	"math/rand"
	"sort"
	"strings"
	"time"

	"mongo.games.com/goserver/core/logger"

	"mongo.games.com/game/common"
	rule "mongo.games.com/game/gamerule/thirteen"
	"mongo.games.com/game/gamesrv/base"
	"mongo.games.com/game/proto"
	"mongo.games.com/game/protocol/thirteen"
)

type PlayerData struct {
	SnId             int32
	cards            [13]int       //手牌信息
	cardsO           *rule.Group   //确定的牌型信息
	isDP             bool          // 是否倒排
	gainCoin         int64         //本局赢的金币
	taxCoin          int64         //本局税收
	clubPump         int64         //俱乐部抽水
	deterMine        bool          //玩家是否确定牌
	score            [7]int64      //玩家每墩的得分 0:头 1中 2尾 3:特殊牌型分数 4打枪 5全垒打 6离场补偿分
	tableScore       [6]int64      // 客户端展示
	winThreePos      map[int]int64 //只包含打枪玩家位置和总赢分
	winAllPlayers    map[int]int64 //玩家位置和输赢分
	isStand          bool          //玩家站起 true打开 本局结束后自动离开房间 false未打开
	isBilled         bool          // 是否结算
	IsRob            bool
	Pos              int
	Coin             int64
	StartCoin        int64
	Head             int32 //头像
	flag             int
	Platform         string //平台
	Channel          string //渠道信息
	PackageID        string //推广包标识 对应客户端的packagetag
	PromoterTree     int32
	InviterId        int32  //邀请人Id
	WBLevel          int32  //黑白名单 白:[1,10] 黑:[-1,-10]
	CurIsWin         int64  //当局输赢   负数：输  0：平局  正数：赢
	BeUnderAgentCode string //隶属经销商（推广人）
	Name             string //名字
	Sex              int32  //性别
	City             string //城市
	Longitude        int32  //经纬度
	Latitude         int32  //经纬度
	AgentCode        string //代理商编号
	HeadOutLine      int32  //头像框
	VIP              int32  //VIP帐号 等级
	allGroup         map[int]*rule.Group
	TestLog          []string
	RoleId           int32
}

type SceneEx struct {
	*base.Scene                        //场景
	poker          *rule.Pokers        // 扑克牌对象
	logic          *rule.Logic         // 十三张算法
	players        map[int32]*PlayerEx // 玩家信息
	seats          []*PlayerEx         // 本局游戏中的玩家状态数据
	isCanAllHitPos int                 // 全垒打玩家坐标 =4人 并且没有特殊牌型
	currOpPos      int                 // 当前操作的玩家
	hitTime        time.Duration       // 打枪阶段按打枪人数加时间
	specialTime    time.Duration       // 亮牌阶段有特殊牌型增加时间
	specialTypeNum int                 // 玩家有特殊牌的个数
	entryHitState  bool                // 是否可以进入打枪阶段
	robotNum       int                 // 参与游戏的机器人数量
	gamePlayerNum  int                 // 参与游戏的人数量

	r               int                   // 体验场测试数据
	cardsSlice      [][13]int             // 从大到小排列四副牌
	nowMaxCardsIsIn bool                  // 现在最大牌是否还在
	PlayerBackup    map[int32]*PlayerData // 本局离场玩家数据备份
	LeaveNum        int                   // 离场扣分人数
	testPokers      []int64               // 测试牌堆
	logid           string
}

func NewThirteenWaterSceneData(s *base.Scene) *SceneEx {
	sceneEx := &SceneEx{
		Scene:        s,
		logic:        new(rule.Logic),
		players:      make(map[int32]*PlayerEx),
		seats:        make([]*PlayerEx, s.GetPlayerNum()),
		PlayerBackup: make(map[int32]*PlayerData),
	}
	if s.GetPlayerNum() > 4 { // 两幅牌
		sceneEx.poker = rule.NewPokers(2, sceneEx.HasLaiZi())
	} else {
		sceneEx.poker = rule.NewPokers(1, sceneEx.HasLaiZi())
	}
	if sceneEx.HasLaiZi() {
		sceneEx.logic.LaiZi = []int{52, 53} // 目前只有大小王为癞子
	}
	return sceneEx
}

func (this *SceneEx) init() bool {
	this.Clear()
	return true
}

func (this *SceneEx) Clear() {
	this.poker.Init()
	this.isCanAllHitPos = -1
	this.currOpPos = -1
	this.hitTime = rule.ThirteenWaterHitTimeout
	this.specialTypeNum = 0
	this.entryHitState = false
	this.robotNum = 0
	this.gamePlayerNum = 0
	this.r = 1
	this.cardsSlice = nil
	this.nowMaxCardsIsIn = true
	this.PlayerBackup = make(map[int32]*PlayerData)
	this.LeaveNum = 0

	for i := 0; i < this.GetPlayerNum(); i++ {
		if this.seats[i] != nil {
			this.seats[i].Clear()
		}
	}
}

func (this *SceneEx) delPlayer(p *base.Player) {
	if p, exist := this.players[p.SnId]; exist {
		this.seats[p.GetPos()] = nil
		delete(this.players, p.SnId)
	}
}

func (this *SceneEx) BroadcastPlayerLeave(p *base.Player, reason int) {
	scLeavePack := &thirteen.SCThirteenPlayerLeave{
		Pos: proto.Int(p.GetPos()),
	}
	proto.SetDefaults(scLeavePack)

	this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerLeave), scLeavePack, p.GetSid())
}

func (this *SceneEx) OnPlayerLeave(p *base.Player, reason int) {
	this.delPlayer(p)
	this.BroadcastPlayerLeave(p, reason)
}

func (this *SceneEx) SceneDestroy(force bool) {
	//销毁房间
	this.Scene.Destroy(force)
}

func (this *SceneEx) CanStart() bool {
	//房间人数>=2自动开始,并且有真人或者是预创建房间
	if len(this.players) >= 2 && (this.GetRealPlayerNum() > 0 || this.IsPreCreateScene()) {
		return true
	}
	return false
}

func (this *SceneEx) ThirteenWaterCreateRoomInfoPacket(s *base.Scene, p *base.Player) interface{} {
	pack := &thirteen.SCThirteenRoomInfo{
		RoomId:      proto.Int(s.GetSceneId()),
		Creator:     proto.Int32(s.GetCreator()),
		GameId:      proto.Int(s.GetGameId()),
		RoomMode:    proto.Int(s.GetSceneMode()),
		AgentId:     proto.Int32(s.GetAgentor()),
		SceneType:   s.GetDBGameFree().SceneType,
		State:       proto.Int(s.GetSceneState().GetState()),
		TimeOut:     proto.Int(s.GetSceneState().GetTimeout(s)),
		DisbandGen:  proto.Int(this.GetDisbandGen()),
		BaseScore:   proto.Int32(this.GetBaseScore()),
		LeaveDeduct: this.GetDBGameFree().GetLeaveDeduct(),
		LeaveCombat: this.GetDBGameFree().GetLeaveCombat(),
		Params:      this.Params,
	}
	// 玩家信息
	for _, playerEx := range this.players {
		pd := &thirteen.ThirteenPlayerData{
			SnId:        proto.Int32(playerEx.SnId),
			Name:        proto.String(playerEx.Name),
			Head:        proto.Int32(playerEx.Head),
			Sex:         proto.Int32(playerEx.Sex),
			Coin:        proto.Int64(playerEx.Coin),
			Pos:         proto.Int(playerEx.Pos),
			Flag:        proto.Int(playerEx.GetFlag()),
			Longitude:   proto.Int32(playerEx.Longitude),
			Latitude:    proto.Int32(playerEx.Latitude),
			City:        proto.String(playerEx.City),
			AgentCode:   proto.String(playerEx.AgentCode),
			HeadOutLine: proto.Int32(playerEx.HeadOutLine),
			VIP:         proto.Int32(playerEx.VIP),
			IsStand:     proto.Bool(playerEx.isStand),
			IsConfirm:   proto.Bool(playerEx.deterMine),
			RoleId:      playerEx.PlayerData.GetRoleId(),
		}
		ppp := &thirteen.Poker{}
		ppp.IndexType = -1
		pd.CardsO = ppp
		if playerEx.cardsO != nil {
			if playerEx.cardsO.PokerType > 0 {
				//确定之后为特殊牌型
				ppp := &thirteen.Poker{}
				ppp.Head = common.CopySliceIntToInt32(playerEx.cards[:3])
				ppp.Mid = common.CopySliceIntToInt32(playerEx.cards[3:8])
				ppp.End = common.CopySliceIntToInt32(playerEx.cards[8:])
				ppp.IndexType = proto.Int32(int32(playerEx.cardsO.PokerType * 1000000))
				pd.CardsO = ppp
				pd.IsDP = playerEx.isDP
			} else if playerEx.cardsO.PokerType == 0 {
				//确定之后为普通牌型
				ppp := &thirteen.Poker{}
				ppp.Head = common.CopySliceIntToInt32(playerEx.cardsO.Head[:])
				ppp.Mid = common.CopySliceIntToInt32(playerEx.cardsO.Mid[:])
				ppp.End = common.CopySliceIntToInt32(playerEx.cardsO.End[:])
				ppp.IndexType = proto.Int32(int32(this.FormatCards(playerEx.cardsO)))
				pd.CardsO = ppp
				pd.IsDP = playerEx.isDP
			}
		}
		if playerEx.cards[0] != -1 {
			pd.Cards = common.CopySliceIntToInt32(playerEx.cards[:])
		}
		if playerEx.allGroup != nil {
			pd.AllCardsO, _ = AllGroupToProto(playerEx.allGroup)
		}
		if p == nil || playerEx.SnId != p.SnId {
			if s.SceneState.GetState() == rule.ThirteenWaterSceneStateSendCards ||
				s.SceneState.GetState() == rule.ThirteenWaterSceneStateOptCard {
				pd.Cards = nil
				pd.AllCardsO = nil
				if pd.CardsO.IndexType > 0 {
					ppp := &thirteen.Poker{}
					ppp.IndexType = 0
					pd.CardsO = ppp
					pd.IsDP = false
				}
			}
		}
		if s.SceneState.GetState() == rule.ThirteenWaterSceneStateShowCards ||
			s.SceneState.GetState() == rule.ThirteenWaterSceneStateHit ||
			s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
			pd.Score = playerEx.score[:]
			pd.TableScore = playerEx.tableScore[:]
			var hitScore []*thirteen.HitScore
			for k, v := range playerEx.winThreePos {
				pck := &thirteen.HitScore{
					Pos:   proto.Int32(int32(k)),
					Score: proto.Int64(v),
				}
				hitScore = append(hitScore, pck)
			}
			pd.Hit = hitScore
		}
		if s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
			pd.WinCoin = playerEx.gainCoin
		}
		pack.Players = append(pack.Players, pd)
	}
	// 备份的玩家信息
	for _, playerEx := range this.PlayerBackup {
		if playerEx != nil || !playerEx.isBilled {
			continue
		}
		pd := &thirteen.ThirteenPlayerData{
			SnId:        proto.Int32(playerEx.SnId),
			Name:        proto.String(playerEx.Name),
			Head:        proto.Int32(playerEx.Head),
			Sex:         proto.Int32(playerEx.Sex),
			Coin:        proto.Int64(playerEx.Coin),
			Pos:         proto.Int(playerEx.Pos),
			Flag:        proto.Int(playerEx.flag),
			Longitude:   proto.Int32(playerEx.Longitude),
			Latitude:    proto.Int32(playerEx.Latitude),
			City:        proto.String(playerEx.City),
			AgentCode:   proto.String(playerEx.AgentCode),
			HeadOutLine: proto.Int32(playerEx.HeadOutLine),
			VIP:         proto.Int32(playerEx.VIP),
			IsStand:     proto.Bool(playerEx.isStand),
			IsConfirm:   proto.Bool(playerEx.deterMine),
			IsLeave:     true,
			RoleId:      playerEx.RoleId,
		}
		ppp := &thirteen.Poker{}
		ppp.IndexType = -1
		pd.CardsO = ppp
		if playerEx.cardsO != nil {
			if playerEx.cardsO.PokerType > 0 {
				//确定之后为特殊牌型
				ppp := &thirteen.Poker{}
				ppp.Head = common.CopySliceIntToInt32(playerEx.cards[:3])
				ppp.Mid = common.CopySliceIntToInt32(playerEx.cards[3:8])
				ppp.End = common.CopySliceIntToInt32(playerEx.cards[8:])
				ppp.IndexType = proto.Int32(int32(playerEx.cardsO.PokerType * 1000000))
				pd.CardsO = ppp
				pd.IsDP = playerEx.isDP
			} else if playerEx.cardsO.PokerType == 0 {
				//确定之后为普通牌型
				ppp := &thirteen.Poker{}
				ppp.Head = common.CopySliceIntToInt32(playerEx.cardsO.Head[:])
				ppp.Mid = common.CopySliceIntToInt32(playerEx.cardsO.Mid[:])
				ppp.End = common.CopySliceIntToInt32(playerEx.cardsO.End[:])
				ppp.IndexType = proto.Int32(int32(this.FormatCards(playerEx.cardsO)))
				pd.CardsO = ppp
				pd.IsDP = playerEx.isDP
			}
		}
		if playerEx.cards[0] != -1 {
			pd.Cards = common.CopySliceIntToInt32(playerEx.cards[:])
		}
		if playerEx.allGroup != nil {
			pd.AllCardsO, _ = AllGroupToProto(playerEx.allGroup)
		}
		if p == nil || playerEx.SnId != p.SnId {
			if s.SceneState.GetState() == rule.ThirteenWaterSceneStateSendCards ||
				s.SceneState.GetState() == rule.ThirteenWaterSceneStateOptCard {
				pd.Cards = nil
				pd.AllCardsO = nil
				if pd.CardsO.IndexType > 0 {
					ppp := &thirteen.Poker{}
					ppp.IndexType = 0
					pd.CardsO = ppp
					pd.IsDP = false
				}
			}
		}
		if s.SceneState.GetState() == rule.ThirteenWaterSceneStateShowCards ||
			s.SceneState.GetState() == rule.ThirteenWaterSceneStateHit ||
			s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
			pd.Score = playerEx.score[:]
			pd.TableScore = playerEx.tableScore[:]
			var hitScore []*thirteen.HitScore
			for k, v := range playerEx.winThreePos {
				pck := &thirteen.HitScore{
					Pos:   proto.Int32(int32(k)),
					Score: proto.Int64(v),
				}
				hitScore = append(hitScore, pck)
			}
			pd.Hit = hitScore
		}
		if s.SceneState.GetState() == rule.ThirteenWaterSceneStateBilled {
			pd.WinCoin = playerEx.gainCoin
		}
		pack.Players = append(pack.Players, pd)
	}

	proto.SetDefaults(pack)
	if p != nil {
		p.SyncFlag()
	}
	logger.Logger.Trace("SCThirteenWaterRoomInfo:", pack)
	return pack
}

func (this *SceneEx) GetBaseScore() int32 { //游戏底分
	if this.DbGameFree.FreeMode == 1 {
		baseScore := this.GetParam(rule.ParamBaseScore)
		if baseScore > 0 {
			return baseScore
		}
	}

	if this.DbGameFree != nil {
		return this.DbGameFree.GetBaseScore()
	}
	return 1
}

func (this *SceneEx) GetBaiPai() time.Duration {
	s := this.GetParam(rule.ParamBaiPai)
	if s > 0 {
		return time.Duration(s) * time.Second
	}
	return rule.ThirteenWaterOptCardTimeout
}

func (this *SceneEx) HasLaiZi() bool {
	s := this.GetParam(rule.ParamLaiZi)
	if s >= 0 {
		return s == 1
	}
	return false
}

func (this *SceneEx) AutoCombine() bool {
	s := this.GetParam(rule.ParamAuto)
	if s >= 0 {
		return s == 0
	}
	return true
}

// GetLeaveDeductCoin 离场扣分
func (this *SceneEx) GetLeaveDeductCoin() int64 {
	return int64(this.GetDBGameFree().GetLeaveDeduct()) * int64(this.GetBaseScore())
}

func (this *SceneEx) GetScore(player *PlayerEx) {
	if player == nil || player.isDP {
		return
	}
	// 计算特殊牌型分数
	ptRate := int64(0)
	//清龙* 一条龙* 十二皇族 三同花顺* 三分天下 全大 全小 凑一色* 四套三条 五对三条 六对半* 三顺子* 三同花
	if player.cardsO.PokerType != 0 {
		this.specialTypeNum++
		//特殊牌处理
		if player.cardsO.PokerType >= 1 && player.cardsO.PokerType <= 13 {
			ptRate = rule.SpecialScore[player.cardsO.PokerType]
		}
	}
	if this.specialTypeNum > 0 {
		for _, p := range this.players {
			if p != nil && p.IsGameing() && player.cardsO.PokerType != 0 {
				if player.Pos == p.Pos {
					continue
				}
				if p.cardsO.PokerType == 0 || p.isDP {
					player.score[3] += ptRate
					p.score[3] -= ptRate
					player.winAllPlayers[p.Pos] += ptRate
					p.winAllPlayers[player.Pos] -= ptRate
				} else if p.cardsO.PokerType != 0 {
					//多个特殊牌型处理
					if player.cardsO.PokerType < p.cardsO.PokerType {
						player.score[3] += ptRate
						p.score[3] -= ptRate
						player.winAllPlayers[p.Pos] += ptRate
						p.winAllPlayers[player.Pos] -= ptRate
					}
				}
			}
		}
	}
	// 计算普通牌型分数
	for _, p := range this.players {
		if p != nil && p.IsGameing() && player.cardsO.PokerType == 0 {
			if player.Pos == p.Pos || p.cardsO.PokerType != 0 {
				continue
			}
			s := 0
			score := int64(0) //赢的分数
			//头墩
			rate := int64(1)
			n := this.logic.CompareHead(player.cardsO.Head, p.cardsO.Head)
			h := this.logic.GetType(player.cardsO.Head[:])
			if h == rule.PokersTypeThree {
				rate += 2
			}
			if n == 1 || p.isDP {
				player.score[0] += rate
				p.score[0] -= rate
				score += rate
				s++
				player.winAllPlayers[p.Pos] += rate
				p.winAllPlayers[player.Pos] -= rate
				player.tableScore[3] += rate - 1
			}
			//中墩
			rate = int64(1)
			n = this.logic.CompareFive(player.cardsO.Mid, p.cardsO.Mid)
			m := this.logic.GetType(player.cardsO.Mid[:])
			if m == rule.PokersTypeFullHouse {
				rate += 1
			} else if m == rule.PokersTypeFour {
				rate += 6
			} else if m == rule.PokersTypeStraightFlush {
				rate += 8
			} else if m == rule.PokersTypeFive {
				rate += 10
			}
			if n == 1 || p.isDP {
				player.score[1] += rate
				p.score[1] -= rate
				score += rate
				s++
				player.winAllPlayers[p.Pos] += rate
				p.winAllPlayers[player.Pos] -= rate
				player.tableScore[4] += rate - 1
			}
			//尾墩
			rate = int64(1)
			n = this.logic.CompareFive(player.cardsO.End, p.cardsO.End)
			e := this.logic.GetType(player.cardsO.End[:])
			if e == rule.PokersTypeFour {
				rate += 3
			} else if e == rule.PokersTypeStraightFlush {
				rate += 4
			} else if e == rule.PokersTypeFive {
				rate += 5
			}
			if n == 1 || p.isDP {
				player.score[2] += rate
				p.score[2] -= rate
				score += rate
				s++
				player.winAllPlayers[p.Pos] += rate
				p.winAllPlayers[player.Pos] -= rate
				player.tableScore[5] += rate - 1
			}
			if s == 3 {
				player.winThreePos[p.Pos] = score
			}
		}
	}
}

// 发送玩家的所有牌和所有牌型
func (this *SceneEx) SendToPlayerCards(s *base.Scene) {
	for _, player := range this.players {
		if player != nil && player.IsGameing() {
			all, k := AllGroupToProto(player.allGroup)
			pack := &thirteen.SCThirteenPlayerCards{
				Cards:     common.CopySliceIntToInt32(player.cards[:]),
				Pos:       proto.Int32(int32(player.Pos)),
				AllCardsO: all,
			}
			// 记录默认牌型
			if k > 0 {
				player.defGroup = player.allGroup[k]
			}
			if len(pack.AllCardsO) == 0 {
				logger.Logger.Warnf("no poker suggest: %v %v", player.cards, rule.PokersShow(player.cards[:]))
				// 没有推荐牌，随便给个数据
				pack.AllCardsO = []*thirteen.Poker{
					{
						IndexType: 90909,
						Head:      common.CopySliceIntToInt32(player.cards[:3]),
						Mid:       common.CopySliceIntToInt32(player.cards[3:8]),
						End:       common.CopySliceIntToInt32(player.cards[8:]),
					},
				}
			}
			proto.SetDefaults(pack)
			logger.Logger.Trace("SCThirteenWaterPlayerCards:", pack)
			player.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerCards), pack)
			Send := &thirteen.SCThirteenPlayerCards{
				Pos: proto.Int32(int32(player.Pos)),
			}
			proto.SetDefaults(Send)
			logger.Logger.Trace("SCThirteenWaterPlayerCards:", Send)
			s.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerCards), Send, player.GetSid())
		}
	}
}

func AllGroupToProto(allGroup map[int]*rule.Group) ([]*thirteen.Poker, int) {
	var pack []*thirteen.Poker
	for k, v := range allGroup {
		p := &thirteen.Poker{
			Head:      common.CopySliceIntToInt32(v.Head[:]),
			Mid:       common.CopySliceIntToInt32(v.Mid[:]),
			End:       common.CopySliceIntToInt32(v.End[:]),
			IndexType: proto.Int32(int32(k)),
		}
		pack = append(pack, p)
	}

	sort.Slice(pack, func(i, j int) bool {
		ii := pack[i]
		jj := pack[j]
		// 特殊牌在前面
		if ii.IndexType >= 1000000 && jj.IndexType >= 1000000 {
			return ii.IndexType < jj.IndexType
		}
		if ii.IndexType >= 1000000 {
			return true
		}
		if jj.IndexType >= 1000000 {
			return false
		}
		// 普通牌型，从尾墩到头墩大的在前面
		if ii.IndexType%100 < jj.IndexType%100 {
			return true
		} else if ii.IndexType%100 > jj.IndexType%100 {
			return false
		}

		if ii.IndexType%10000/100 < jj.IndexType%10000/100 {
			return true
		} else if ii.IndexType%10000/100 > jj.IndexType%10000/100 {
			return false
		}

		if ii.IndexType/10000 < jj.IndexType/10000 {
			return true
		} else if ii.IndexType/10000 > jj.IndexType/10000 {
			return false
		}
		return false
	})

	//for _, v := range pack {
	//	logger.Logger.Tracef("AllGroupToProto: %v %v %v %v", v.IndexType, rule.PokersShow(common.CopySliceInt32ToInt(v.Head)), rule.PokersShow(common.CopySliceInt32ToInt(v.Mid)), rule.PokersShow(common.CopySliceInt32ToInt(v.End)))
	//}
	if len(pack) > 0 {
		return pack, int(pack[0].IndexType)
	}

	return pack, 0
}

// CheckIsCanHit 检查是否可以打枪
func (this *SceneEx) CheckIsCanHit() bool {
	pt := 0    //特殊牌型数量
	isHit := 0 //几个人可以打枪
	for _, v := range this.players {
		if v != nil && v.IsGameing() {
			if v.cardsO.PokerType != 0 {
				pt++
			}
			//全垒打: 打枪所有人并且至少打3人
			if len(v.winThreePos) >= 3 && len(v.winThreePos) == this.gamePlayerNum-1 {
				this.isCanAllHitPos = v.Pos
			}
			if len(v.winThreePos) > 0 {
				isHit++
			}
		}
	}
	// 人数至少2人
	if /*pt == 0 &&*/ this.gamePlayerNum >= 2 && isHit > 0 {
		return true
	}
	this.isCanAllHitPos = -1
	return false
}

func (this *SceneEx) SelectCards(p *PlayerEx, indexType int) *rule.Group {
	switch indexType {
	case -1: // 使用特殊牌型
		for k, v := range p.allGroup {
			if k >= 1000000 {
				p.cardsO = v
				break
			}
		}
	case -2: // 使用牌值最大的牌型
		this.GetMaxCardsO(p)

		// 真人默认选牌规则
		if !p.IsRob && p.defGroup != nil {
			p.cardsO = p.defGroup
		}
	}

	if indexType > 10000 { // 从推荐牌中选一个
		c := p.allGroup[indexType]
		if c != nil {
			p.cardsO = c
		}
	}

	// 还没有确认就随机推荐一个
	if p.cardsO == nil || p.cardsO.PokerType == -1 {
		for k, v := range p.allGroup {
			p.cardsO = v
			if k >= 1000000 {
				break
			}
		}
		logger.Logger.Tracef("随机推荐：SnId(%v) %v", p.SnId, p.cardsO)
	}
	return p.cardsO
}

// SendSelectCards 玩家选择特定的牌显示
func (this *SceneEx) SendSelectCards(player *PlayerEx, indexType int, opcode int64) {
	ShowCardsO := this.SelectCards(player, indexType)

	pack := &thirteen.SCThirteenPlayerOp{
		OpRetCode: thirteen.OpResultCode_OPRC_Sucess,
		OpCode:    int32(opcode),
		Pos:       proto.Int32(int32(player.Pos)),
		Cards:     &thirteen.Poker{},
	}

	if indexType == -1 || indexType >= 1000000 { // 特殊牌
		pack.Cards.Head = common.CopySliceIntToInt32(player.cards[:3])
		pack.Cards.Mid = common.CopySliceIntToInt32(player.cards[3:8])
		pack.Cards.End = common.CopySliceIntToInt32(player.cards[8:])
	} else {
		// 自动组牌或玩家自选
		pack.Cards.Head = common.CopySliceIntToInt32(ShowCardsO.Head[:])
		pack.Cards.Mid = common.CopySliceIntToInt32(ShowCardsO.Mid[:])
		pack.Cards.End = common.CopySliceIntToInt32(ShowCardsO.End[:])
		pack.Cards.IsDP = this.logic.IsDP(ShowCardsO.Head, ShowCardsO.Mid, ShowCardsO.End)
	}
	pack.Cards.IndexType = proto.Int32(int32(this.FormatCards(ShowCardsO)))
	pack.Cards.Pos = int32(player.GetPos())
	proto.SetDefaults(pack)
	logger.Logger.Trace("SCThirteenPlayerOp1:", pack)
	player.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)

	pack.Cards.Head = nil
	pack.Cards.Mid = nil
	pack.Cards.End = nil
	pack.Cards.IndexType = 0
	pack.Cards.IsDP = false
	logger.Logger.Trace("SCThirteenPlayerOp2:", pack)
	this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack, player.GetSid())
	for _, v := range this.seats {
		if v == nil {
			continue
		}
		if v.SnId != player.SnId && v.IsRobot() {
			logger.Logger.Trace("SCThirteenPlayerOpRobot:", pack)
			v.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenPlayerOp), pack)
		}
	}
}

func (this *SceneEx) FormatCards(cardsO *rule.Group) int {
	num := 0
	if cardsO != nil && cardsO.PokerType != 0 {
		num = cardsO.PokerType * 1000000
	} else if cardsO != nil && cardsO.PokerType == 0 && cardsO.Head[0] != -1 {
		num += this.logic.GetType(cardsO.Head[:]) * 10000
		num += this.logic.GetType(cardsO.Mid[:]) * 100
		num += this.logic.GetType(cardsO.End[:])
	}
	return num
}

// GetMinCards 默认获取玩家最小牌值的类型
func (this *SceneEx) GetMinCards(player *PlayerEx) {
	min := 1000000
	for v, m := range player.allGroup {
		sum := 0
		if v >= 1000000 {
			continue
		}
		a := v / 10000
		b := (v - a*10000) / 100
		c := v - a*10000 - b*100
		s := []int{a, b, c}
		for _, k := range s {
			if k >= 1 && k <= 20 {
				sum += 20 - k
			}
		}
		if min >= sum {
			min = sum
			player.cardsO = m
		}
	}
}

func (this *SceneEx) GetRandsType() (playerCards [13]int) {
	//r := rand.Intn(15) + 1
	//全垒打
	//playerCards = [13]int{9, 9 + 13, 9 + 13*2, 2, 3, 4, 5, 6, 3 + 13, 4 + 13, 5 + 13, 6 + 13, 7 + 13}
	//return
	c := [][13]int{
		//清龙
		{39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51},
		//一条龙
		{13, 14, 28, 29, 30, 44, 45, 7, 34, 9, 23, 11, 51},
		//十二皇族
		{9, 10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51},
		//三同花顺
		{1, 2, 3, 4, 5, 15, 16, 17, 18, 19, 27, 28, 29},
		//三分天下
		{10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51, 13},
		//全大
		{7, 21, 35, 23, 11, 38, 51, 33, 48, 49, 50, 12, 25},
		//全小
		{14, 27, 40, 15, 28, 41, 4, 17, 5, 18, 6, 19, 32},
		//凑一色
		{13, 14, 40, 16, 42, 18, 44, 19, 46, 47, 23, 49, 25},
		//四套三条
		{5, 18, 44, 6, 19, 32, 7, 33, 46, 10, 23, 36, 50},
		//五对三条
		{17, 30, 5, 31, 6, 32, 8, 47, 23, 36, 12, 25, 38},
		//六对半
		{17, 30, 5, 31, 6, 32, 8, 47, 23, 36, 38, 51, 39},
		//三顺子
		{1, 28, 16, 17, 18, 30, 31, 45, 20, 8, 36, 50, 12},
		//三同花
		{2, 3, 6, 4 + 13, 8 + 13, 9 + 13, 13, 25, 31, 34, 27, 28, 29},
	}
	if this.r < 12 {
		this.r++
	} else {
		this.r = 1
	}
	playerCards = c[this.r]
	return
}

// SortCards 把所有牌排序
//func (this *SceneEx) SortCards() {
//	//确定所有玩家拿可以拿到的最大牌型
//	for _, player := range this.players {
//		if player != nil && player.IsGameing() {
//			this.GetMaxCardsO(player)
//		}
//	}
//	//计算总分数
//	this.CountScore()
//	scoreMap := make(map[int]int64)
//	for _, player := range this.seats {
//		if player != nil && player.IsGameing() {
//			score := int64(0)
//			//计算玩家输赢的分数
//			for _, v := range player.score {
//				score += v
//			}
//			scoreMap[player.Pos] = score
//		}
//	}
//	for i := 0; i < 6; i++ {
//		max := int64(-1000)
//		pos := -1
//		for k, v := range scoreMap {
//			if max <= v {
//				max = v
//				pos = k
//			}
//		}
//		if pos != -1 {
//			delete(scoreMap, pos)
//			this.cardsSlice = append(this.cardsSlice, this.seats[pos].cards)
//			this.seats[pos].cards = [13]int{-1}
//			if len(scoreMap) == 0 {
//				break
//			}
//		}
//	}
//}

// GetMaxCardsO 一副牌中拿最大牌值的方案
func (this *SceneEx) GetMaxCardsO(p *PlayerEx) {
	if p != nil {
		p.cardsO = rule.GetMaxCard(p.allGroup)
	}
}

// cardsSort 按从大到小的排列发牌
func (this *SceneEx) cardsSort(cardArr [][13]int, cardGroup []map[int]*rule.Group) {
	type P struct {
		i             int
		score         [6]int64
		cardsO        *rule.Group
		cards         [13]int
		group         map[int]*rule.Group
		winThreePos   map[int]int64
		winAllPlayers map[int]int64
	}

	var ps []*P
	for i := 0; i < len(cardArr); i++ {
		p := &P{
			i:             i,
			score:         [6]int64{0, 0, 0, 0, 0, 0},
			cardsO:        rule.GetMaxCard(cardGroup[i]),
			cards:         cardArr[i],
			group:         cardGroup[i],
			winThreePos:   map[int]int64{},
			winAllPlayers: map[int]int64{},
		}
		ps = append(ps, p)
	}

	var specialTypeNum int
	for i := 0; i < len(cardArr); i++ {
		player := ps[i]

		// 计算特殊牌型分数
		ptRate := int64(0)
		if player.cardsO.PokerType != 0 {
			specialTypeNum++
			//特殊牌处理
			if player.cardsO.PokerType >= 1 && player.cardsO.PokerType <= 13 {
				ptRate = rule.SpecialScore[player.cardsO.PokerType]
			}
		}

		if specialTypeNum > 0 {
			for _, p := range ps {
				if player.cardsO.PokerType != 0 {
					if player.i == p.i {
						continue
					}
					if p.cardsO.PokerType == 0 {
						player.score[3] += ptRate
						p.score[3] -= ptRate
						player.winAllPlayers[p.i] += ptRate
						p.winAllPlayers[player.i] -= ptRate
					} else if p.cardsO.PokerType != 0 {
						//多个特殊牌型处理
						if player.cardsO.PokerType < p.cardsO.PokerType {
							player.score[3] += ptRate
							p.score[3] -= ptRate
							player.winAllPlayers[p.i] += ptRate
							p.winAllPlayers[player.i] -= ptRate
						}
					}
				}
			}
		}

		// 计算普通牌型分数
		for _, p := range ps {
			if player.cardsO.PokerType == 0 {
				if player.i == p.i || p.cardsO.PokerType != 0 {
					continue
				}
				s := 0
				score := int64(0) //赢的分数
				//头墩
				rate := int64(1)
				n := this.logic.CompareHead(player.cardsO.Head, p.cardsO.Head)
				h := this.logic.GetType(player.cardsO.Head[:])
				if h == rule.PokersTypeThree {
					rate += 2
				}
				if n == 1 {
					player.score[0] += rate
					p.score[0] -= rate
					score += rate
					player.winAllPlayers[p.i] += rate
					p.winAllPlayers[player.i] -= rate
					s++
				}
				//中墩
				rate = int64(1)
				n = this.logic.CompareFive(player.cardsO.Mid, p.cardsO.Mid)
				m := this.logic.GetType(player.cardsO.Mid[:])
				if m == rule.PokersTypeFullHouse {
					rate += 1
				} else if m == rule.PokersTypeFour {
					rate += 6
				} else if m == rule.PokersTypeStraightFlush {
					rate += 8
				} else if m == rule.PokersTypeFive {
					rate += 10
				}
				if n == 1 {
					player.score[1] += rate
					p.score[1] -= rate
					score += rate
					player.winAllPlayers[p.i] += rate
					p.winAllPlayers[player.i] -= rate
					s++
				}
				//尾墩
				rate = int64(1)
				n = this.logic.CompareFive(player.cardsO.End, p.cardsO.End)
				e := this.logic.GetType(player.cardsO.End[:])
				if e == rule.PokersTypeFour {
					rate += 3
				} else if e == rule.PokersTypeStraightFlush {
					rate += 4
				} else if e == rule.PokersTypeFive {
					rate += 5
				}
				if n == 1 {
					player.score[2] += rate
					p.score[2] -= rate
					score += rate
					player.winAllPlayers[p.i] += rate
					p.winAllPlayers[player.i] -= rate
					s++
				}
				if s == 3 {
					player.winThreePos[p.i] = score
				}
			}
		}
	}

	// 打枪分
	isCanAllHitPos := -1
	pt := 0    //特殊牌型数量
	isHit := 0 //几个人可以打枪
	for _, v := range ps {
		if v.cardsO.PokerType != 0 {
			pt++
		}
		//全垒打: 打枪所有人并且至少打3人
		if len(v.winThreePos) >= 3 && len(v.winThreePos) == this.gamePlayerNum-1 {
			isCanAllHitPos = v.i
		}
		if len(v.winThreePos) > 0 {
			isHit++
		}
	}
	// 可以打枪:没有特殊牌型，人数至少2人
	if pt == 0 && this.gamePlayerNum >= 2 && isHit > 0 {
		for _, playerEx := range ps {
			if len(playerEx.winThreePos) > 0 {
				for k, v := range playerEx.winThreePos {
					// 打枪
					ps[k].score[4] -= v
					ps[k].winAllPlayers[playerEx.i] -= v
					playerEx.score[4] += v
					playerEx.winAllPlayers[k] += v
					// 全垒打分数
					if playerEx.i == isCanAllHitPos {
						ps[k].score[5] -= v
						ps[k].winAllPlayers[playerEx.i] -= v
						playerEx.score[5] += v
						playerEx.winAllPlayers[k] += v
					}
				}
			}
		}
	}

	sort.Slice(ps, func(i, j int) bool {
		var a, b int64
		for _, v := range ps[i].score {
			a += v
		}
		for _, v := range ps[j].score {
			b += v
		}
		return a > b
	})
	for i := 0; i < len(cardArr); i++ {
		cardArr[i] = ps[i].cards
		cardGroup[i] = ps[i].group
	}
}

// CountScore 计算总分数
func (this *SceneEx) CountScore() {
	//计算头、中、尾道、特殊牌分数
	for _, player := range this.seats {
		if player != nil && player.IsGameing() {
			this.GetScore(player)
			// 离场补偿分
			if this.LeaveNum > 0 {
				player.score[6] = int64(this.LeaveNum) * int64(this.GetDBGameFree().GetLeaveCombat())
			}
		}
	}
	for _, player := range this.seats {
		if player != nil && player.IsGameing() {
			for i := 0; i < 3; i++ {
				player.tableScore[i] = player.score[i] - player.tableScore[i+3]
			}
		}
	}

	this.entryHitState = this.CheckIsCanHit()

	if !this.entryHitState {
		//如果不能进入打枪阶段 不计算打枪和全垒打
		return
	}
	//计算打枪分数
	for _, playerEx := range this.players {
		if playerEx != nil && playerEx.IsGameing() {
			if len(playerEx.winThreePos) > 0 {
				for k, v := range playerEx.winThreePos {
					// 并且都不是特殊牌型
					if playerEx.cardsO.PokerType != 0 || this.seats[k].cardsO.PokerType != 0 {
						continue
					}
					// 打枪
					this.seats[k].score[4] -= v
					this.seats[k].winAllPlayers[playerEx.Pos] -= v
					playerEx.score[4] += v
					playerEx.winAllPlayers[k] += v
					// 全垒打分数
					if playerEx.Pos == this.isCanAllHitPos {
						this.seats[k].score[5] -= v
						this.seats[k].winAllPlayers[playerEx.Pos] -= v
						playerEx.score[5] += v
						playerEx.winAllPlayers[k] += v
					}
				}
			}
		}
	}
}

func (this *SceneEx) GetInGameNum() {
	for _, v := range this.players {
		if v != nil && v.IsGameing() {
			this.gamePlayerNum++
			if v.IsRob {
				this.robotNum++
			}
		}
	}
}

// 获取最小牌
func (this *SceneEx) GetAllMinCards() (a [13]int) {
	for i := len(this.cardsSlice) - 1; i >= 0; i-- {
		a = this.cardsSlice[i]
		this.cardsSlice[i] = [13]int{-1}
		this.cardsSlice = append(this.cardsSlice[:i], this.cardsSlice[i+1:]...)
		break
	}
	return [13]int{-1}
}

// 获取最大牌
func (this *SceneEx) GetAllMaxCards() (a [13]int) {
	if this.nowMaxCardsIsIn {
		this.nowMaxCardsIsIn = false
	}
	for i := 0; i < len(this.cardsSlice); i++ {
		a = this.cardsSlice[i]
		this.cardsSlice = append(this.cardsSlice[:i], this.cardsSlice[i+1:]...)
		break
	}
	return [13]int{-1}
}

// 随机拿牌
func (this *SceneEx) GetRandCards(b bool) (a [13]int) {
	n := len(this.cardsSlice)
	if n == 0 {
		return [13]int{-1}
	}
	r := rand.Intn(n)
	if !b {
		if this.nowMaxCardsIsIn {
			//最大牌还在
			//不带最大牌随机
			if n == 1 {
				//就剩一副牌
				return [13]int{-1}
			}
			if r == 0 {
				//随到最大牌
				r++
			}
		}
	} else {
		//带最大牌随机
		if this.nowMaxCardsIsIn {
			if r == 0 {
				this.nowMaxCardsIsIn = false
			}
		}
	}

	a = this.cardsSlice[r]
	this.cardsSlice = append(this.cardsSlice[:r], this.cardsSlice[r+1:]...)
	return
}

func (this *SceneEx) ShowCards() {
	var allCards []*thirteen.Poker
	for _, p := range this.players {
		if p != nil && p.IsGameing() && p.cardsO != nil {
			var hitScore []*thirteen.HitScore
			for k, v := range p.winThreePos {
				pck := &thirteen.HitScore{
					Pos:   proto.Int32(int32(k)),
					Score: proto.Int64(v),
				}
				hitScore = append(hitScore, pck)
			}
			pk := &thirteen.Poker{
				IndexType:  proto.Int32(int32(this.FormatCards(p.cardsO))),
				Head:       common.IntSliceToInt32(p.cardsO.Head[:]),
				Mid:        common.IntSliceToInt32(p.cardsO.Mid[:]),
				End:        common.IntSliceToInt32(p.cardsO.End[:]),
				IsDP:       p.isDP,
				Pos:        int32(p.GetPos()),
				Score:      p.score[:],
				Hit:        hitScore,
				TableScore: p.tableScore[:],
				Cards:      common.IntSliceToInt32(p.cards[:]),
			}
			allCards = append(allCards, pk)
		}
	}

	opCode := 0
	if this.GetSceneState().GetState() == rule.ThirteenWaterSceneStateHit {
		opCode = 1 // 打枪
	}

	pc := &thirteen.SCThirteenShowCards{
		OpCode:   proto.Int32(int32(opCode)),
		AllCards: allCards,
	}
	proto.SetDefaults(pc)
	logger.Logger.Trace("SCThirteenWaterShowCards is pc: ", pc)
	this.Broadcast(int(thirteen.TWMmoPacketID_PACKET_SCThirteenShowCards), pc, 0)
}

func (this *SceneEx) CountBilled() {
	var totalWinScore, totalLoseScore int64 // 总赢分
	for _, v := range this.players {
		if v != nil && v.IsGameing() {
			// 玩家总分
			v.totalScore = 0
			for _, vv := range v.score[:6] {
				v.totalScore += vv
			}
			v.totalScore *= int64(this.GetBaseScore())
			if v.totalScore > 0 {
				if v.totalScore > v.Coin {
					v.totalScore = v.Coin
				}
			} else if v.totalScore < 0 {
				if v.totalScore < -v.Coin {
					v.totalScore = -v.Coin
				}
			}
			// 总输赢分
			if v.totalScore > 0 {
				totalWinScore += v.totalScore
			} else if v.totalScore < 0 {
				totalLoseScore += -v.totalScore
			}
			logger.Logger.Tracef("玩家[%d]总赢分: %d", v.GetPos(), v.totalScore)
		}
	}

	if totalWinScore > totalLoseScore {
		// 赢分大，输分玩家分数不需要修改
		for _, v := range this.players {
			if v != nil && v.IsGameing() {
				if v.totalScore > 0 {
					v.gainCoin = int64(float64(v.totalScore) * float64(totalLoseScore) / float64(totalWinScore))
				} else if v.totalScore < 0 {
					v.gainCoin = v.totalScore
				}
			}
		}
	} else if totalWinScore < totalLoseScore {
		// 输分大，赢分玩家分数不需要修改
		for _, v := range this.players {
			if v != nil && v.IsGameing() {
				if v.totalScore > 0 {
					v.gainCoin = v.totalScore
				} else if v.totalScore < 0 {
					v.gainCoin = int64(float64(v.totalScore) * float64(totalLoseScore) / float64(totalWinScore))
				}
			}
		}
	} else {
		for _, v := range this.players {
			if v != nil && v.IsGameing() {
				v.gainCoin = v.totalScore
			}
		}
	}

	for _, playerEx := range this.players {
		if playerEx == nil || !playerEx.IsGameing() {
			continue
		}
		if playerEx.gainCoin > 0 {
			gainCoin := playerEx.gainCoin
			playerEx.gainCoin = playerEx.gainCoin * int64(10000-this.DbGameFree.GetTaxRate()) / 10000
			playerEx.taxCoin = gainCoin - playerEx.gainCoin
		}
		logger.Logger.Tracef("玩家分数 %v, coin:%v tax:%v win:%v", playerEx.SnId, playerEx.gainCoin, playerEx.taxCoin, playerEx.winAllPlayers)
	}
}

func (this *SceneEx) BackupPlayer(p *PlayerEx, isBilled bool) {
	testLog := make([]string, len(p.TestLog))
	copy(testLog, p.TestLog)
	this.PlayerBackup[p.SnId] = &PlayerData{
		SnId:             p.SnId,
		cards:            p.cards,
		cardsO:           p.cardsO,
		isDP:             p.isDP,
		gainCoin:         p.gainCoin,
		taxCoin:          p.taxCoin,
		deterMine:        p.deterMine,
		score:            p.score,
		tableScore:       p.tableScore,
		winThreePos:      p.winThreePos,
		winAllPlayers:    p.winAllPlayers,
		isStand:          p.isStand,
		isBilled:         isBilled,
		IsRob:            p.IsRob,
		Pos:              p.Pos,
		Coin:             p.Coin,
		StartCoin:        p.StartCoin,
		Head:             p.Head,
		flag:             p.GetFlag(),
		Platform:         p.Platform,
		Channel:          p.Channel,
		PackageID:        p.PackageID,
		PromoterTree:     p.PromoterTree,
		InviterId:        p.InviterId,
		WBLevel:          p.WBLevel,
		CurIsWin:         p.CurIsWin,
		BeUnderAgentCode: p.BeUnderAgentCode,
		Name:             p.Name,
		Sex:              p.Sex,
		City:             p.City,
		Longitude:        p.Longitude,
		Latitude:         p.Latitude,
		AgentCode:        p.AgentCode,
		HeadOutLine:      p.HeadOutLine,
		VIP:              p.VIP,
		allGroup:         p.allGroup,
		TestLog:          testLog,
		RoleId:           p.PlayerData.GetRoleId(),
	}
}

func (this *SceneEx) SendHandCardOdds() {
	var realPlayersGood, realPlayersBad, realPlayers, robotPlayers []*PlayerEx
	var G, B int32
	for _, seat := range this.seats {
		if seat != nil && seat.IsGameing() {
			if seat.IsRob {
				robotPlayers = append(robotPlayers, seat)
			} else {
				seat.odds = this.GetPlayerOdds(seat.Player, this.GameId, this.robotNum > 0)
				if seat.odds > 0 {
					realPlayersGood = append(realPlayersGood, seat)
					G += seat.odds
				} else if seat.odds < 0 {
					realPlayersBad = append(realPlayersBad, seat)
					B -= seat.odds
				} else {
					realPlayers = append(realPlayers, seat)
				}
			}
		}
	}

	this.poker.Init()

	cardsArr := make([][13]int, this.poker.N*4)
	cardsGroup := make([]map[int]*rule.Group, this.poker.N*4)
	for k := range cardsArr {
		cardsArr[k] = this.poker.Get13Crads()
		cardsGroup[k] = this.logic.Suggest(cardsArr[k])
	}

	f := func(players *[]*PlayerEx) {
		if players == nil || len(*players) == 0 {
			return
		}
		var p *PlayerEx // 发牌给这个玩家
		var a int
		for _, v := range *players {
			a += int(math.Abs(float64(v.odds)))
		}
		n := this.RandInt(a)
		total := 0
		for k, v := range *players {
			total += int(math.Abs(float64(v.odds)))
			if n < total {
				p = (*players)[k]
				*players = append((*players)[:k], (*players)[k+1:]...)
				break
			}
		}

		var cards [13]int
		var group map[int]*rule.Group
		if p.odds > 0 {
			// 拿好牌
			cards = cardsArr[0]
			cardsArr = cardsArr[1:]
			group = cardsGroup[0]
			cardsGroup = cardsGroup[1:]
		} else {
			// 拿坏牌
			cards = cardsArr[len(cardsArr)-1]
			cardsArr = cardsArr[:len(cardsArr)-1]
			group = cardsGroup[len(cardsGroup)-1]
			cardsGroup = cardsGroup[:len(cardsGroup)-1]
		}
		p.cards = cards
		p.allGroup = group
	}

	// 需要换牌
	isGood := len(realPlayersGood) > 0 && int32(this.RandInt(1000)) < G
	isBad := len(realPlayersBad) > 0 && int32(this.RandInt(1000)) < B
	logger.Logger.Tracef("Thirteen SendHandCardOdds Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B)
	if isGood || isBad {
		// 按从大到小排序
		this.cardsSort(cardsArr, cardsGroup)

		// 发好牌
		if isGood {
			l := len(realPlayersGood)
			for i := 0; i < l; i++ {
				f(&realPlayersGood)
			}
		}
		// 发坏牌
		if isBad {
			l := len(realPlayersBad)
			for i := 0; i < l; i++ {
				f(&realPlayersBad)
			}
		}
	}
	// 随机拿牌
	for _, v := range this.players { // map随机
		if v == nil || !v.IsGameing() || v.cards[0] != -1 {
			continue
		}
		v.cards = cardsArr[0]
		v.allGroup = cardsGroup[0]
		cardsArr = cardsArr[1:]
		cardsGroup = cardsGroup[1:]
	}

	for _, player := range this.players {
		if player.IsGameing() && !player.IsRob {
			logger.Logger.Trace("snid:", player.SnId)
			player.TestLog = append(player.TestLog, fmt.Sprintf("随机换牌 Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B))
			for _, v := range player.TestLog {
				logger.Logger.Trace(v)
			}
			pack := &thirteen.SCThirteenTest{}
			player.TestLog = append(player.TestLog, fmt.Sprintf("随机换牌 Good:%v G:%v Bad:%v B:%v", isGood, G, isBad, B))
			pack.Data = strings.Join(player.TestLog, "\n")
			proto.SetDefaults(pack)
			player.SendToClient(int(thirteen.TWMmoPacketID_PACKET_SCThirteenTest), pack)
			logger.Logger.Trace("SnId: ", player.SnId, ";SCThirteenTest: ", pack)
		}
	}
}
