package roommgr

import (
	"World/common"
	"World/conf"
	"World/db"
	pb "World/pb"
	"net"
	"strconv"
	"time"

	pmgr "World/playermgr"
	"World/utils"
	"common/beegomap"
	"common/logger"
	"common/redis"
	"common/rpc_world"
	stat "common/statistic"
	"math/rand"
	"sync"

	"World/resume"
	"encoding/json"

	"github.com/goSnowFlake"
	"github.com/satori/go.uuid"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

const (
	SevenDays   = (3600 * 24 * 7)
	PROXY_ID    = 1
	PLATFORM_ID = 1
)

var (
	randSeek = int64(1)
	mu       sync.Mutex
)

func getRandSeek() int64 {
	mu.Lock()

	if randSeek >= 100000000 {
		randSeek = 0
	}

	randSeek++

	mu.Unlock()

	return int64(time.Now().UnixNano()) + randSeek
}

type AllianceClubIds struct {
	Locker *sync.RWMutex
	Ids    []uint32
}

type UserRoomIds struct {
	Locker *sync.RWMutex
	Ids    []uint32
}

type RoomInfos struct {
	Locker *sync.RWMutex
	Rooms  []*rpc_world.CreateRoomRequest
}

type ValRoomInfos struct {
	Locker *sync.RWMutex
	Rooms  []*rpc_world.CreateRoomRequest
}

type ActivityInfo struct {
	BuyinCnt  int
	TimeStamp int
}

type Activity struct {
	Locker     *sync.RWMutex
	Activities []*ActivityInfo
}

type MapActivity struct {
	MapActivitys *beegomap.BeeMap //map[int]*Activity
}

var (
	m_mapClubGame   *beegomap.BeeMap // = make(map[int32][]*rpc_world.CreateRoomRequest) //key:俱乐部id value:房间信息 通过俱乐部创建的牌局
	m_UserGame      RoomInfos        //= make([]*rpc_world.CreateRoomRequest, 0)        //slice:不是通过俱乐部创建的牌局,存储房间信息
	m_mapUserRoomId *beegomap.BeeMap //= make(map[int32][]int32) //key:用户id，value：房间id列表 用户加入的不是通过俱乐部创建房间列表

	m_mapAllianceClubIds *beegomap.BeeMap //= make(map[int32][]int) //key:房间id，value：俱乐部id列表
)

func Init() {
	//	log.Println("begin Init-RoomIdInit")
	RoomIdInit()
	//	log.Println("after Init-RoomIdInit")

	GetClubGameFromRedis()
	//	log.Println("end roommgr-Init()")
}

func init() {
	m_mapClubGame = beegomap.NewBeeMap()
	m_UserGame.Locker = new(sync.RWMutex)
	m_mapUserRoomId = beegomap.NewBeeMap()
	m_mapAllianceClubIds = beegomap.NewBeeMap()

}

type server struct{}

func getDrawinNum(clubId uint32, blindLevel int32) (int64, int64) {
	jackpotInfo, _ := db.GetJackpotInfo(clubId, int(blindLevel))
	if jackpotInfo != nil {
		return jackpotInfo.ProfitScale, jackpotInfo.DrawinAmout
	} else {
		blind := conf.GetBlindByIndex(uint32(blindLevel))
		return blind.Scale, blind.DrawinAmout
	}
}

func RemoveDuplicateAllianceClubIds(elements []uint32) []uint32 {
	encountered := map[uint32]bool{}
	result := []uint32{}

	for v := range elements {
		if encountered[elements[v]] == true {
		} else {
			encountered[elements[v]] = true
			result = append(result, elements[v])
		}
	}
	return result
}

func (s *server) CreateRoom(ctx context.Context, in *rpc_world.CreateRoomRequest) (*rpc_world.CreateRoomReply, error) {
	roomInfo := new(rpc_world.CreateRoomRequest)
	roomInfo = in

	logger.Info("****rpc CreateRoom in:%+v", in)

	var r rpc_world.CreateRoomReply
	r.MapAllianceClubIds = make(map[uint32]*rpc_world.AllianceItem)

	if len(in.AllianceIds) == 0 { //非联盟牌局
		if in.ClubId == 0 { //不是从俱乐部创建的牌局
			m_UserGame.Locker.Lock()
			m_UserGame.Rooms = append(m_UserGame.Rooms, roomInfo)
			m_UserGame.Locker.Unlock()
			vv := m_mapUserRoomId.Get(uint32(in.CreatePlayerId))
			if vv != nil {
				userRoomIds, _ := vv.(*UserRoomIds)
				if userRoomIds != nil {
					userRoomIds.Locker.Lock()
					userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
					userRoomIds.Locker.Unlock()
				} else {
					userRoomIds := new(UserRoomIds)
					userRoomIds.Locker = new(sync.RWMutex)
					userRoomIds.Locker.Lock()
					userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
					userRoomIds.Locker.Unlock()
					m_mapUserRoomId.Set(uint32(in.CreatePlayerId), userRoomIds)
				}
			} else {
				userRoomIds := new(UserRoomIds)
				userRoomIds.Locker = new(sync.RWMutex)
				userRoomIds.Locker.Lock()
				userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
				userRoomIds.Locker.Unlock()
				m_mapUserRoomId.Set(uint32(in.CreatePlayerId), userRoomIds)
			}
		} else {
			roomInfo.IsNeedStatistic = true
			vv := m_mapClubGame.Get(uint32(in.ClubId))
			if vv != nil {
				valRoomInfos, _ := vv.(*ValRoomInfos)
				if valRoomInfos != nil {
					valRoomInfos.Locker.Lock()
					valRoomInfos.Rooms = append(valRoomInfos.Rooms, roomInfo)
					valRoomInfos.Locker.Unlock()
				}
			} else {
				valRoomInfos := new(ValRoomInfos)
				valRoomInfos.Locker = new(sync.RWMutex)
				valRoomInfos.Locker.Lock()
				valRoomInfos.Rooms = append(valRoomInfos.Rooms, roomInfo)
				valRoomInfos.Locker.Unlock()
				m_mapClubGame.Set(uint32(in.ClubId), valRoomInfos)
			}
		}
	} else { //联盟牌局
		var allianceClubIds []uint32
		//增加联盟俱乐部对应的roomInfo
		for i := 0; i < len(in.AllianceIds); i++ {
			ids, t_list, e := db.GetAllianceMemberList(in.AllianceIds[i])
			if e == nil {
				for j := 0; j < len(ids); j++ {
					allianceClubIds = append(allianceClubIds, ids[j])
				}
				pItem := new(rpc_world.AllianceItem)
				if AlliCreaterUid, er := db.GetAllianceCreaterUID(in.AllianceIds[i]); er == nil {
					pItem.AlliCreaterUid = AlliCreaterUid
				}

				if name, err := db.GetAllianceName(in.AllianceIds[i]); err == nil {
					pItem.AllianceName = name
				}

				for _, clubid := range ids {
					pItem.Clubids = append(pItem.Clubids, clubid)
				}

				for k := 0; k < len(ids); k++ {
					pInfo := new(rpc_world.JoinAllianceInfo)
					pInfo.ClubId = ids[k]
					pInfo.JoinTime = t_list[k]
					pItem.Infos = append(pItem.Infos, pInfo)
				}

				r.MapAllianceClubIds[in.AllianceIds[i]] = pItem
			}
		}

		allianceClubIds = RemoveDuplicateAllianceClubIds(allianceClubIds)

		logger.Info("allianceClubIds:%v", allianceClubIds)

		vv := m_mapAllianceClubIds.Get(uint32(in.RoomId))
		if vv != nil {
			allianceCids, _ := vv.(*AllianceClubIds)
			allianceCids.Locker.Lock()
			allianceCids.Ids = allianceClubIds[0:len(allianceClubIds)]
			logger.Info("allianceCids.Ids:%v", allianceCids.Ids)
			allianceCids.Locker.Unlock()
		} else {
			allianceCids := new(AllianceClubIds)
			allianceCids.Locker = new(sync.RWMutex)
			allianceCids.Locker.Lock()
			allianceCids.Ids = allianceClubIds[0:len(allianceClubIds)]
			logger.Info("allianceCids.Ids:%v", allianceCids.Ids)
			allianceCids.Locker.Unlock()
			m_mapAllianceClubIds.Set(uint32(in.RoomId), allianceCids)
		}

		for k := 0; k < len(allianceClubIds); k++ {
			if roomInfo.ClubId == uint32(allianceClubIds[k]) {
				roomInfo.IsNeedStatistic = true
			} else {
				roomInfo.IsNeedStatistic = false
			}
			vv := m_mapClubGame.Get(uint32(allianceClubIds[k]))
			if vv != nil {
				valRoomInfos, _ := vv.(*ValRoomInfos)
				if valRoomInfos != nil {
					valRoomInfos.Locker.Lock()
					valRoomInfos.Rooms = append(valRoomInfos.Rooms, roomInfo)
					valRoomInfos.Locker.Unlock()
				}
			} else {
				valRoomInfos := new(ValRoomInfos)
				valRoomInfos.Locker = new(sync.RWMutex)
				valRoomInfos.Locker.Lock()
				valRoomInfos.Rooms = append(valRoomInfos.Rooms, roomInfo)
				valRoomInfos.Locker.Unlock()
				m_mapClubGame.Set(uint32(allianceClubIds[k]), valRoomInfos)
			}
		}

		var allianceCIDs []uint32
		for _, cid := range allianceClubIds {
			allianceCIDs = append(allianceCIDs, cid)
		}
		r.AllianceClubIds = allianceCIDs[0:len(allianceCIDs)]

		for _, clubId := range allianceClubIds {
			adminIds, err := db.GetClubAdmins(clubId)
			if err == nil {
				for _, adminId := range adminIds {
					r.ClubAdminids = append(r.ClubAdminids, adminId)
				}
			}
		}
	}

	SetClubGame2Redis()

	if in.IsAssociatedJackpot {
		profitScale, drawinAmout := getDrawinNum(in.ClubId, in.RuleBlindEnum)
		r.ProfitScale = profitScale
		r.DrawinAmout = drawinAmout
	}

	logger.Info("rpc CreateRoom reply:%+v", r)

	return &r, nil
}

func (s *server) JoinRoom(ctx context.Context, in *rpc_world.JoinRoomRequest) (*rpc_world.JoinRoomReply, error) {
	logger.Info("****rpc JoinRoom in:%+v", in)

	bExist := false

	vv := m_mapUserRoomId.Get(uint32(in.UserId))
	if vv != nil {
		userRoomIds, _ := vv.(*UserRoomIds)
		if userRoomIds != nil {
			if len(userRoomIds.Ids) == 0 {
				userRoomIds.Locker.Lock()
				userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
				userRoomIds.Locker.Unlock()
			} else {
				userRoomIds.Locker.RLock()
				for _, rid := range userRoomIds.Ids {
					if in.RoomId == rid {
						bExist = true
						break
					}
				}
				userRoomIds.Locker.RUnlock()

				if !in.IsAlliance && !bExist {
					userRoomIds.Locker.Lock()
					userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
					userRoomIds.Locker.Unlock()
				}
			}
		} else {
			userRoomIds := new(UserRoomIds)
			userRoomIds.Locker = new(sync.RWMutex)
			userRoomIds.Locker.Lock()
			userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
			userRoomIds.Locker.Unlock()
		}
	} else {
		userRoomIds := new(UserRoomIds)
		userRoomIds.Locker = new(sync.RWMutex)
		userRoomIds.Locker.Lock()
		userRoomIds.Ids = append(userRoomIds.Ids, in.RoomId)
		userRoomIds.Locker.Unlock()
		m_mapUserRoomId.Set(uint32(in.UserId), userRoomIds)
	}

	return &rpc_world.JoinRoomReply{Message: strconv.Itoa(int(in.RoomId)) + strconv.Itoa(int(in.UserId))}, nil
}

func (s *server) DestroyRoom(ctx context.Context, in *rpc_world.DestroyRoomRequest) (*rpc_world.DestroyRoomReply, error) {
	logger.Info("****rpc DestroyRoom in:%+v", in)

	m_UserGame.Locker.Lock()
	for i := len(m_UserGame.Rooms) - 1; i >= 0; i-- {
		game := m_UserGame.Rooms[i]
		if in.Id == game.RoomId {
			m_UserGame.Rooms = append(m_UserGame.Rooms[:i], m_UserGame.Rooms[i+1:]...)
		}
	}
	m_UserGame.Locker.Unlock()

	items := m_mapUserRoomId.Items()
	for userId, vv := range items {
		userRoomIds, _ := vv.(*UserRoomIds)
		if userRoomIds != nil {
			userRoomIds.Locker.Lock()
			for i := len(userRoomIds.Ids) - 1; i >= 0; i-- {
				if in.Id == userRoomIds.Ids[i] {
					userRoomIds.Ids = append(userRoomIds.Ids[:i], userRoomIds.Ids[i+1:]...)
				}
				if len(userRoomIds.Ids) == 0 {
					m_mapUserRoomId.Delete(userId)
				}
			}
			userRoomIds.Locker.Unlock()
		}
	}

	for clubId, vv := range m_mapClubGame.Items() {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.Lock()
			for i := len(valRoomInfos.Rooms) - 1; i >= 0; i-- {
				if in.Id == valRoomInfos.Rooms[i].RoomId {
					valRoomInfos.Rooms = append(valRoomInfos.Rooms[:i], valRoomInfos.Rooms[i+1:]...)
				}
				if len(valRoomInfos.Rooms) == 0 {
					m_mapClubGame.Delete(clubId)
					logger.Info("DestroyRoom-clubId:%v", clubId)
				}
			}
			valRoomInfos.Locker.Unlock()
		}
	}

	SetClubGame2Redis()

	//删除联盟房间对应的俱乐部
	m_mapAllianceClubIds.Delete(uint32(in.Id))

	return &rpc_world.DestroyRoomReply{Message: "DestroyRoom! " + strconv.Itoa(int(in.Id))}, nil
}

func (s *server) ModifyRoomInfo(ctx context.Context, in *rpc_world.ModifyRoomInfoRequest) (*rpc_world.ModifyRoomInfoReply, error) {
	logger.Info("****rpc ModifyRoomInfo in:%+v", in)

	m_UserGame.Locker.Lock()
	for j, game := range m_UserGame.Rooms {
		if in.Id == game.RoomId {
			m_UserGame.Rooms[j].PlayerCount = in.PlayerCount
			m_UserGame.Rooms[j].GameStatus = in.GameStatus
			m_UserGame.Rooms[j].StartTime = in.StartTime
			m_UserGame.Rooms[j].ExtraTime = in.ExtraTime
		}
	}
	m_UserGame.Locker.Unlock()

	for _, vv := range m_mapClubGame.Items() {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.Lock()
			for i, game := range valRoomInfos.Rooms {
				if in.Id == game.RoomId {
					valRoomInfos.Rooms[i].PlayerCount = in.PlayerCount
					valRoomInfos.Rooms[i].GameStatus = in.GameStatus
					valRoomInfos.Rooms[i].StartTime = in.StartTime
					valRoomInfos.Rooms[i].ExtraTime = in.ExtraTime
				}
			}
			valRoomInfos.Locker.Unlock()
		}
	}

	SetClubGame2Redis()

	return &rpc_world.ModifyRoomInfoReply{Message: "ModifyRoomInfo! " + strconv.Itoa(int(in.Id))}, nil
}

func (s *server) GetNewRoomID(ctx context.Context, in *rpc_world.GetRoomIDRequest) (*rpc_world.GetRoomIDReply, error) {
	logger.Info("****rpc GetNewRoomID in:%+v", in)

	//获取房间uuid
	u1 := uuid.NewV1()
	//获取房间id
	roomid := GetRoomid()

	rand.Seed(getRandSeek())
	randWoker := rand.Intn(1023)

	iw, err := goSnowFlake.NewIdWorker(int64(randWoker))
	var sql_id uint64
	var snowflake_id int64
	if err == nil {
		if snowflake_id, err = iw.NextId(); err == nil {
			return &rpc_world.GetRoomIDReply{RoomUuid: u1.String(), Roomid: roomid, UuidInt: uint64(snowflake_id)}, nil
		}
	}

	id, _ := db.GetMaxRoomId()
	sql_id = id

	logger.Info("rpc GetNewRoomID RoomUuid:%v roomid:%v sql_id:%v", u1.String(), roomid, sql_id)

	return &rpc_world.GetRoomIDReply{RoomUuid: u1.String(), Roomid: roomid, UuidInt: sql_id}, nil
}

func (s *server) CheckClubManager(ctx context.Context, in *rpc_world.CheckClubManagerRequest) (*rpc_world.CheckClubManagerReply, error) {
	logger.Info("****rpc CheckClubManager in:%+v", in)
	result := db.HasPrivilege(in.Clubid, in.Playerid)

	logger.Info("rpc CheckClubManager result:%v Clubid:%v Playerid:%v", result, in.Clubid, in.Playerid)
	return &rpc_world.CheckClubManagerReply{Result: result}, nil
}

func (s *server) CheckClubMember(ctx context.Context, in *rpc_world.CheckClubMemberRequest) (*rpc_world.CheckClubMemberReply, error) {
	logger.Info("****rpc CheckClubMember in:%+v", in)
	var result bool = false
	result, _ = db.IsPlayerInClub(in.Clubid, in.Playerid)

	logger.Info("rpc CheckClubMember result:%v", result)
	return &rpc_world.CheckClubMemberReply{Result: result}, nil
}

func PlayerBuyin(UserId int, ClubId int, buyTime int) {
}

func getOperateGoldClubId(rid uint64) uint32 {
	var clubId uint32
	clubId = 0
	for id, vv := range m_mapClubGame.Items() {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.RLock()
			for _, game := range valRoomInfos.Rooms {
				if rid == uint64(game.RoomId) {
					clubId = id
				}
			}
			valRoomInfos.Locker.RUnlock()
		}

	}
	return clubId
}

func isNeedOperateGold(rid uint64, feetype rpc_world.FeeType) bool {
	opreateGold := true
	if feetype == rpc_world.FeeType_Enum_game {
		clubId := getOperateGoldClubId(rid)
		if clubId != 0 {
			opreateGold = db.IsNeedOperateGold(clubId)
		}
	}

	return opreateGold
}

func (s *server) PlayerBuyin(ctx context.Context, in *rpc_world.PlayerBuyinRequest) (*rpc_world.PlayerBuyinReply, error) {
	logger.Info("****rpc PlayerBuyin in:%+v", in)
	PlayerBuyin(int(in.UserId), int(in.ClubId), int(time.Now().Unix()))

	return &rpc_world.PlayerBuyinReply{Message: strconv.Itoa(int(in.UserId))}, nil
}

func (s *server) GetUserData(ctx context.Context, in *rpc_world.GetUserDataRequest) (*rpc_world.GetUserDataReply, error) {
	logger.Info("****rpc GetUserData in:%+v", in)
	if uInfo, err := db.GetUserInfo(in.UserId); err == nil {
		logger.Info("rpc GetUserData UserId:%v UserName:%v Gender:%v DiamondNum:%v UserGold:%v AvatarThumb:%v Marks:%v",
			uInfo.UserId, uInfo.UserName, uInfo.Gender, uInfo.DiamondNum, uInfo.UserGold, uInfo.AvatarThumb, uInfo.Marks)
		return &rpc_world.GetUserDataReply{UserId: uInfo.UserId, UserName: uInfo.UserName, Gender: uInfo.Gender, DiamondNum: uInfo.DiamondNum, UserGold: uInfo.UserGold, AvatarThumb: uInfo.AvatarThumb, Marks: uInfo.Marks}, nil
	}

	logger.Info("rpc GetUserData UserId:%v failed!", in.UserId)

	return &rpc_world.GetUserDataReply{UserId: in.UserId}, nil
}

func (s *server) GetUserAllianceClubs(ctx context.Context, in *rpc_world.GetUserAllianceClubsRequest) (*rpc_world.GetUserAllianceClubsReply, error) {
	logger.Info("****rpc GetUserAllianceClubs in:%+v", in)
	var clubIds []uint32
	var allianceClubids []uint32 //联盟对应的俱乐部的集合
	vv := m_mapAllianceClubIds.Get(uint32(in.RoomId))
	if vv != nil {
		allianceCids, _ := vv.(*AllianceClubIds)
		if allianceCids != nil {
			userClubIds, _ := db.GetUserClubIds(in.UserId)
			allianceCids.Locker.RLock()
			allianceClubids = append(allianceClubids, allianceCids.Ids...)
			for i := 0; i < len(allianceCids.Ids); i++ {
				for j := 0; j < len(userClubIds); j++ {
					if allianceCids.Ids[i] == userClubIds[j] {
						clubIds = append(clubIds, userClubIds[j])
					}
				}
			}
			allianceCids.Locker.RUnlock()
		}
	}

	clubIds = common.RemoveDuplicates(clubIds)
	allianceClubids = common.RemoveDuplicates(allianceClubids)

	var clubInfos []*rpc_world.ClubInfo
	var clubcreatorids []uint32
	for i := 0; i < len(allianceClubids); i++ {
		if clubname, createrId, err := db.GetClubInfo(allianceClubids[i]); err == nil && createrId != 0 {
			if common.IsIdExist(clubIds, allianceClubids[i]) {
				clubInfo := new(rpc_world.ClubInfo)
				clubInfo.ClubName = clubname
				clubInfo.CreaterId = createrId
				clubInfo.ClubId = allianceClubids[i]
				clubInfos = append(clubInfos, clubInfo)
			}
			clubcreatorids = append(clubcreatorids, createrId)
		}
	}

	//clubcreatorids = common.RemoveDuplicateIds(clubcreatorids)
	logger.Info("rpc GetUserAllianceClubs clubInfos:%+v clubcreatorids:%+v", clubInfos, clubcreatorids)

	return &rpc_world.GetUserAllianceClubsReply{ClubInfos: clubInfos, ClubCreaterids: clubcreatorids}, nil
}

func (s *server) NotifyWorldGameRestart(ctx context.Context, in *rpc_world.NotifyWorldGameRestartRequest) (*rpc_world.NotifyWorldGameRestartReply, error) {
	logger.Info("****rpc NotifyWorldGameRestart in:%+v", in)

	//恢复金币
	var err_num int32 = 1
	err := db.RecoverPlayerGold()
	if err != nil {
		err_num = 2
	}

	//清空发现列表
	m_mapClubGame.Clear()
	SetClubGame2Redis()

	logger.Info("rpc NotifyWorldGameRestart err_num:%v ", err_num)
	return &rpc_world.NotifyWorldGameRestartReply{Error: err_num}, nil
}

func (s *server) WorldOperateUserLeftGold(ctx context.Context, in *rpc_world.WorldOperateUserLeftGoldRequest) (*rpc_world.WorldOperateUserLeftGoldReply, error) {
	logger.Info("****rpc WorldOperateUserLeftGold in:%+v", in)

	var err_num int32 = 1
	err := db.UpdatePlayLeftGold(in.UserId, in.LeftGold, in.Roomid)
	if err != nil {
		err_num = 2
	}

	logger.Info("rpc WorldOperateUserLeftGold err_num:%v ", err_num)
	return &rpc_world.WorldOperateUserLeftGoldReply{Error: err_num}, nil
}

func (s *server) WorldOprateUserGold(ctx context.Context, in *rpc_world.WorldOprateUserGoldRequest) (*rpc_world.WorldOprateUserGoldReply, error) {
	logger.Info("****rpc WorldOprateUserGold in:%+v", in)

	var err_num int32 = 0

	var goldBefore int64 = 0
	var goldAfter int64 = 0
	var changeNum int64 = 0
	isNeed := isNeedOperateGold(in.RoomId, in.FeeType)
	if isNeed {
		if in.OperateType == db.Add {
			goldBefore, goldAfter, _ = db.OperateRequesterGold(in.UserId, in.GoldNum, db.Add)
			changeNum = in.GoldNum
			err_num = 1
		} else if in.OperateType == int32(db.Subtract) {
			var curGoldNum int64
			var err error
			if curGoldNum, err = db.GetUserGoldNum(in.UserId); err == nil {
				if curGoldNum < in.GoldNum {
					err_num = 2
					logger.Info("rpc WorldOprateUserGold err_num:%v uid:%v curGoldNum:%v in.GoldNum:%v ", err_num, in.UserId, curGoldNum, in.GoldNum)
					return &rpc_world.WorldOprateUserGoldReply{ErrNum: err_num}, nil
				}
				err_num = 1
				goldBefore, goldAfter, _ = db.OperateRequesterGold(in.UserId, in.GoldNum, db.Subtract)
				changeNum = -in.GoldNum
			}
		}
	} else {
		err_num = 1
	}

	logger.Info("rpc WorldOprateUserGold err_num:%v goldBefore:%v goldAfter:%v", err_num, goldBefore, goldAfter)

	//发送金币变动通知
	player, err := pmgr.GetPlayerFromMap(in.UserId)
	if err == nil {
		common.SendGoldNumNotify(player, uint32(in.RoomId), uint32(in.UserId), int64(goldAfter), int64(changeNum))
	} else {
		logger.Notic("Player not found uid:%v", in.UserId)
	}

	return &rpc_world.WorldOprateUserGoldReply{ErrNum: err_num, GoldBefore: goldBefore, GoldAfter: goldAfter}, nil
}

func (s *server) GetAllianceBuyinLimit(ctx context.Context, in *rpc_world.GetAllianceBuyinLimitRequest) (*rpc_world.GetAllianceBuyinLimitReply, error) {
	logger.Info("****rpc GetAllianceBuyinLimit in:%+v", in)
	var maxBuyinLimit int64 = 0
	var curBuyinLimit int64 = 0
	var bOpen bool = true
	var err error = nil

	if maxBuyinLimit, curBuyinLimit, bOpen, err = db.GetAllianceClubInfo(in.AllianceId, in.ClubId); err == nil {
		logger.Info("rpc GetAllianceBuyinLimit maxBuyinLimit:%v curBuyinLimit:%v ContorlBuyin:%v ErrNum: 1 err:%v", maxBuyinLimit, curBuyinLimit, bOpen, err)
		return &rpc_world.GetAllianceBuyinLimitReply{MaxBuyinLimit: maxBuyinLimit, CurBuyinLimit: curBuyinLimit, ContorlBuyin: bOpen, ErrNum: 1}, err
	}

	logger.Info("rpc GetAllianceBuyinLimit maxBuyinLimit:%v curBuyinLimit:%v ContorlBuyin:%v ErrNum: 2 err:%v", maxBuyinLimit, curBuyinLimit, bOpen, err)
	return &rpc_world.GetAllianceBuyinLimitReply{MaxBuyinLimit: maxBuyinLimit, CurBuyinLimit: curBuyinLimit, ContorlBuyin: bOpen, ErrNum: 2}, err
}

func (s *server) SetAllianceCurBuyinLimit(ctx context.Context, in *rpc_world.SetAllianceCurBuyinLimitRequest) (*rpc_world.SetAllianceCurBuyinLimitReply, error) {
	logger.Info("****rpc SetAllianceCurBuyinLimit in:%+v", in)
	var err error = nil

	if err = db.ModifyAllianceCurBuyinLimit(in.AllianceId, in.ClubId, int(in.CurBuyinLimit)); err == nil {
		logger.Info("rpc SetAllianceCurBuyinLimit ErrNum:1 err:%v AllianceId:%v ClubId:%v CurBuyinLimit:%v", err, in.AllianceId, in.ClubId, in.CurBuyinLimit)
		return &rpc_world.SetAllianceCurBuyinLimitReply{ErrNum: 1}, err
	}

	logger.Info("rpc SetAllianceCurBuyinLimit result ErrNum:2 err:%v in:%+v", err, in)
	return &rpc_world.SetAllianceCurBuyinLimitReply{ErrNum: 2}, err
}

func GetClubBoardNum(clubId int32) int {
	var num int
	vv := m_mapClubGame.Get(uint32(clubId))
	if vv != nil {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.RLock()
			for _, game := range valRoomInfos.Rooms {
				if game.IsNeedStatistic == true {
					num++
				}
			}
			valRoomInfos.Locker.RUnlock()
		}

	}

	return num
}

func ClubhasBoardRunning(clubId uint32) bool {
	var bExist bool = false
	vv := m_mapClubGame.Get(clubId)
	if vv != nil {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.RLock()
			if len(valRoomInfos.Rooms) > 0 {
				bExist = true
			}
			valRoomInfos.Locker.RUnlock()
		}
	}

	return bExist
}

func GetUserCreatBoardNum(userId uint32) int {
	var curNum int
	m_UserGame.Locker.RLock()
	for _, game := range m_UserGame.Rooms {
		if game.CreatePlayerId == userId {
			curNum = curNum + 1
		}
	}
	m_UserGame.Locker.RUnlock()

	return curNum
}

//错误码 1：成功，可以创建；74：不是俱乐部管理员，不能创建；75：俱乐部等级不够开启更多房间；76：其他错误
func (s *server) CheckCreateClubRoom(ctx context.Context, in *rpc_world.CheckCreateClubRoomRequest) (*rpc_world.CheckCreateClubRoomReply, error) {
	logger.Info("****rpc CheckCreateClubRoom in:%+v", in)

	var err_num common.ErrorType = common.Error_OK

	for {
		//检查是否有创建房间权限
		if in.ClubId != 0 && !db.HasPrivilege(in.ClubId, in.UserId) {
			err_num = common.Error_CreateRoom_Privilege_Not_Enough
			logger.Info("HasPrivilege err_num:%v in:%+v", err_num, in)
			break
		}

		var err error
		var gameMax int32
		if in.ClubId != 0 { //俱乐部创建的牌局
			var level int32

			//获取俱乐部等级
			if level, err = db.GetCurrentClubLevel(in.ClubId); err == nil {
				//获取可创建的最大的牌局数
				if gameMax, err = db.GetClubGameMax(int(level)); err == nil {
					//获取当前俱乐部牌局数量
					curNum := GetClubBoardNum(int32(in.ClubId))
					if int32(curNum) >= gameMax {
						err_num = common.Error_CreateRoom_Level_Not_Enough
						logger.Info("GetClubBoardNum err_num:%v in:%+v", err_num, in)
					}
				}
			} else {
				err_num = common.Error_CreateRoom_Other
				logger.Info("GetCurrentClubLevel err_num:%v in:%+v", err_num, in)
			}

			break
		} else { //非俱乐部创建的牌局
			//获取可创建的最大的牌局数
			if gameMax, err = db.GetUserGameMax(in.UserId); err == nil {
				//获取当前俱乐部牌局数量
				curNum := GetUserCreatBoardNum(in.UserId)
				if int32(curNum) >= gameMax {
					err_num = common.Error_CreateRoom_Level_Not_Enough
					logger.Info("GetUserCreatBoardNum err_num:%v in:%+v", err_num, in)
				}
			} else {
				err_num = common.Error_CreateRoom_Other
				logger.Info("GetUserGameMax err_num:%v in:%+v", err_num, in)
			}

			//当前已创建的牌局数
			break
		}

		break
	}

	logger.Info("CheckCreateClubRoom result err_num:%v in:%+v", err_num, in)

	return &rpc_world.CheckCreateClubRoomReply{ErrNum: int32(err_num)}, nil
}

func (s *server) HitCardType(ctx context.Context, in *rpc_world.HitCardTypeRequest) (*rpc_world.HitCardTypeReply, error) {
	logger.Info("****rpc HitCardType in:%+v", in)
	var JackPotAwardInfos []*pb.NoticeJackPotAwardInfo

	var err_num common.ErrorType
	err_num = common.Error_OK

	var notiJackpotAmout pb.NoticeJackpotAmout
	var reply rpc_world.HitCardTypeReply
	for {
		//查询奖池金额
		amount, err := db.GetJackpotAmount(in.ClubId, int(in.BlindLevel))
		if err != nil {
			err_num = common.Error_Get_JackpotAward_Failed
			logger.Info("GetJackpotAmount err_num:%v in:%+v", err_num, in)
			break
		}

		//用户设置奖励比例map
		awardTypeMap := make(map[int32]int32)

		//查询奖励比例
		awardTypes, err := db.GetAwardTypeList(in.ClubId)
		for _, awardType := range awardTypes {
			awardTypeMap[awardType.HandLevel] = awardType.AwardPercent
		}

		var totalPercent int64
		for _, cardinfo := range in.Cards {
			totalPercent += int64(awardTypeMap[cardinfo.CardLevel])

			awardInfo := new(pb.NoticeJackPotAwardInfo)
			awardInfo.AwardPlayid = cardinfo.AwardPlayerId
			awardInfo.HandLevel = cardinfo.CardLevel

			if subUserInfo, err := db.GetSubUserInfo(awardInfo.AwardPlayid); err == nil {
				if subUserInfo != nil {
					awardInfo.AwardPlayerName = subUserInfo.Name
				}
			}

			JackPotAwardInfos = append(JackPotAwardInfos, awardInfo)

			//构造反馈的结构体，为中奖者桌面加码用
			userCardAwardInfo := new(rpc_world.UserCardAward)
			userCardAwardInfo.AwardPlayerId = cardinfo.AwardPlayerId
			userCardAwardInfo.SeatId = cardinfo.SeatId
			userCardAwardInfo.CardLevel = cardinfo.CardLevel

			reply.CardAwards = append(reply.CardAwards, userCardAwardInfo)

		}

		if totalPercent > 100 {
			//用来存db
			for _, info := range JackPotAwardInfos {
				info.AwardAmount = amount * int64(awardTypeMap[info.HandLevel]) / int64(totalPercent)
			}

			for _, inf := range reply.CardAwards {
				inf.AwardAmount = amount * int64(awardTypeMap[inf.CardLevel]) / int64(totalPercent)
			}
		} else {
			for _, info := range JackPotAwardInfos {
				info.AwardAmount = amount * int64(awardTypeMap[info.HandLevel]) / 100
			}

			for _, inf := range reply.CardAwards {
				inf.AwardAmount = amount * int64(awardTypeMap[inf.CardLevel]) / 100
			}
		}

		//修改数据库值
		var subtractAmount int64 = 0
		for _, awardInfo := range JackPotAwardInfos {
			subtractAmount += awardInfo.AwardAmount
		}

		//尝试计算成员奖励时应该抽到俱乐部基金的总金币数
		var preAllAward2Club int64

		//从db读取俱乐部抽水比例 默认10%
		var Award2ClubPercent int
		Award2ClubPercent, _, err = db.GetAward2ClubPercent(in.ClubId)
		if err != nil {
			Award2ClubPercent = conf.GetAward2ClubPercent()
		}
		for _, inf := range reply.CardAwards {
			awardAmount := amount * int64(awardTypeMap[inf.CardLevel]) / 100
			preAllAward2Club += awardAmount * int64(Award2ClubPercent) / 100 //如果剩余奖池够抽水入所有俱乐部则用此值，否则此值会被覆盖
		}

		curAmount := amount - subtractAmount // 扣除每个玩家奖励后的奖池金额
		if curAmount >= preAllAward2Club {
			curAmount -= preAllAward2Club
			for _, inf := range reply.CardAwards {
				inf.Award2ClubFund = inf.AwardAmount * int64(Award2ClubPercent) / 100
			}
		} else {
			//彩池剩余金额不够比例分成
			var allAward2Club int64
			for _, inf := range reply.CardAwards {
				inf.Award2ClubFund = amount * int64(awardTypeMap[inf.CardLevel]) / totalPercent * int64(Award2ClubPercent) / 100
				allAward2Club += inf.Award2ClubFund
			}
			curAmount -= allAward2Club
		}

		err = db.UpdateJackpotAmount(in.ClubId, int(in.BlindLevel), curAmount)
		if err == nil {
			notiJackpotAmout.ClubId = in.ClubId
			notiJackpotAmout.BlindLevel = in.BlindLevel
			notiJackpotAmout.PrevAmount = amount
			notiJackpotAmout.CurrentAmout = curAmount
		}

		break
	}

	var total_award int64 = 0
	for {
		//查询此俱乐部对应的牌局
		var memberIds []uint32
		var AllClubIds []uint32
		allianceClubids := GetJackpotClubIds(in.ClubId)
		AllClubIds = append(allianceClubids, in.ClubId)
		AllClubIds = common.RemoveDuplicates(AllClubIds)
		for _, cid := range AllClubIds {
			pIds, _ := db.GetClubMemberList(cid)
			memberIds = append(memberIds, pIds...)
		}

		if len(memberIds) != 0 {
			for _, noti := range JackPotAwardInfos {
				//奖励存入奖励记录表
				//AddJackpotRecord(clubId int, room_creater_uid int, room_uintid int, card_uintid int, blindLevel int, hand_level int, award_amount int, award_uid int) error {
				db.AddJackpotRecord(in.ClubId, in.CreatePlayerId, int(in.Room_UUIDInt), int(in.Game_UUIDInt), int(in.BlindLevel), int(noti.HandLevel), int(noti.AwardAmount), int(noti.AwardPlayid))

				utils.SendEventReport(uint32(noti.AwardPlayid), in.ClubId, stat.Event_Type_Jackpot_Awardinfo, int(in.BlindLevel), int(noti.HandLevel), int(noti.AwardAmount), "")

				total_award += noti.AwardAmount
				for _, memberId := range memberIds {
					player, er := pmgr.GetPlayerFromMap(memberId)
					if er == nil {
						common.SendNoti(player, uint32(in.RoomId), uint32(memberId), pb.MSGID_MsgID_JackPotAwardInfo_Notice, noti)
						logger.Info("noti to memberId:%v HitCardType AwardPlayid:%v AwardAmount:%v HandLevel:%v AwardPlayerName:%v ClubId:%v", memberId, noti.AwardPlayid, noti.AwardAmount, noti.HandLevel, noti.AwardPlayerName, in.ClubId)
					}
				}
			}

			for _, memberId := range memberIds {
				player, er := pmgr.GetPlayerFromMap(memberId)
				if er == nil {
					common.SendNoti(player, uint32(in.RoomId), uint32(memberId), pb.MSGID_MsgID_JackpotAmout_Notice, &notiJackpotAmout)
				}
			}
		}
		break
	}

	reply.TotalAwardAmount = total_award
	reply.ErrNum = int32(err_num)

	logger.Info("rpc HitCardType reply:%+v", reply)

	return &reply, nil
}

func Drawin(ClubId uint32, BlindLevel int, Amount int64) {
	//活跃度存库
	db.AddJackpotAmount(ClubId, BlindLevel, Amount)
}

func (s *server) DrawinJackpot(ctx context.Context, in *rpc_world.DrawinJackpotRequest) (*rpc_world.DrawinJackpotReply, error) {
	logger.Info("****rpc DrawinJackpot in:%+v", in)
	preAmount, _ := db.GetJackpotAmount(in.ClubId, int(in.BlindLevel))

	var noti pb.NoticeJackpotAmout

	noti.ClubId = in.ClubId
	noti.BlindLevel = in.BlindLevel
	noti.PrevAmount = preAmount
	noti.CurrentAmout = preAmount + in.DrawinAmout

	Drawin(in.ClubId, int(in.BlindLevel), int64(in.DrawinAmout))

	//查询此俱乐部对应的牌局
	var memberIds []uint32
	var AllClubIds []uint32
	allianceClubids := GetJackpotClubIds(in.ClubId)
	AllClubIds = append(allianceClubids, in.ClubId)
	AllClubIds = common.RemoveDuplicates(AllClubIds)
	for _, cid := range AllClubIds {
		pIds, _ := db.GetClubMemberList(cid)
		memberIds = append(memberIds, pIds...)
	}

	if len(memberIds) != 0 {
		for _, memberId := range memberIds {
			player, er := pmgr.GetPlayerFromMap(memberId)
			if er == nil {
				common.SendNoti(player, uint32(in.RoomId), uint32(memberId), pb.MSGID_MsgID_JackpotAmout_Notice, &noti)
			}
		}
	}

	logger.Info("rpc DrawinJackpot ErrNum: 1 in:%+v", in)

	return &rpc_world.DrawinJackpotReply{ErrNum: 1}, nil
}

func DoCommunicate() {
	logger.Info("DoCommunicate begin")
	addr := conf.GetRpcListenAddr()
	//	lis, err := net.Listen("tcp", port)
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		logger.Fatal("failed to listen: %v", err)
	}
	logger.Info("DoCommunicate mid")
	s := grpc.NewServer()
	rpc_world.RegisterRoomServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		logger.Fatal("failed to serve: %v", err)
	}
	logger.Info("DoCommunicate end")
}

func IsRoomExist(list []*pb.ClubGameSnapshot, id uint32) bool {
	bExist := false

	for _, Info := range list {
		if Info.RoomId == id {
			bExist = true
			break
		}
	}
	return bExist
}

func GetClubGameInfo(cid uint32) []*pb.ClubGameSnapshot {
	var list []*pb.ClubGameSnapshot
	vv := m_mapClubGame.Get(uint32(cid))
	if vv != nil {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.RLock()
			for _, gameInfo := range valRoomInfos.Rooms {
				info := new(pb.ClubGameSnapshot)
				info.CreatePlayerId = gameInfo.CreatePlayerId
				info.CreatorName = gameInfo.CreatorName
				info.ClubId = gameInfo.ClubId
				info.GameMode = gameInfo.GameMode
				info.RoomName = gameInfo.RoomName

				info.PlayerCount = gameInfo.PlayerCount
				info.SmallBlind = gameInfo.SmallBlind
				info.BigBlind = gameInfo.BigBlind
				info.BuyinMin = gameInfo.BuyinMin
				info.BuyinMax = gameInfo.BuyinMax

				info.CreateTime = gameInfo.CreateTime
				info.BuyinControl = gameInfo.BuyinControl
				info.Insurance = gameInfo.Insurance
				info.AntiCheating = gameInfo.AntiCheating
				info.Straddle = gameInfo.Straddle

				info.RandSeat = gameInfo.RandSeat
				info.Ante = gameInfo.Ante
				info.PlayerCountMax = gameInfo.PlayerCountMax
				info.OwnerType = gameInfo.OwnerType
				info.RuleTimeLimit = gameInfo.RuleTimeLimit

				info.RoomId = gameInfo.RoomId
				info.GameStatus = gameInfo.GameStatus
				info.StartTime = gameInfo.StartTime

				info.JackpotIsopen = gameInfo.IsAssociatedJackpot
				info.IsAllinAllfold = gameInfo.IsAllinAllfold
				info.ShortFullhouseFlushStraightThree = gameInfo.ShortFullhouseFlushStraightThree
				info.IsOpenedDrawback = gameInfo.IsOpenedDrawback
				info.IsForceShowcard = gameInfo.IsForceShowcard

				info.ExtraTime = gameInfo.ExtraTime

				list = append(list, info)
			}
			logger.Info("getClubGameInfo-list:", list)
			valRoomInfos.Locker.RUnlock()
		}
	}
	return list
}

func GetClubBoard(clubIds []uint32) []*pb.ClubGameSnapshot {
	var gameList []*pb.ClubGameSnapshot
	for _, cid := range clubIds {
		list := GetClubGameInfo(cid)
		for _, GameSnapshot := range list {
			SubInfo, _ := db.GetSubClubInfo(cid)
			if SubInfo != nil {
				GameSnapshot.PicPath = SubInfo.PicPath
				GameSnapshot.ClubName = SubInfo.ClubName
			}
		}
		logger.Info("GetClubBoard-cid:%v list:%+v:", cid, list)
		gameList = append(gameList, list...)
		logger.Info("GetClubBoard-clubIds:%v gameList:%+v:", clubIds, gameList)
	}

	return gameList
}

func GetAllianceClubIds() *beegomap.BeeMap {
	return m_mapAllianceClubIds
}

func CleanAllianceDeletedBoard(cid int) {
	//牌局进行暂不允许退出联盟
	//	logger.Info("CleanAllianceDeletedBoard-ClubId:%v", cid)
	//	items := m_mapAllianceClubIds.Items()
	//	for _, vv := range items {
	//		allianceCids, _ := vv.(*AllianceClubIds)
	//		if allianceCids != nil {
	//			allianceCids.Locker.Lock()
	//			for j := len(allianceCids.Ids) - 1; j >= 0; j-- {
	//				if allianceCids.Ids[j] == cid {
	//					allianceCids.Ids = append(allianceCids.Ids[:j], allianceCids.Ids[j+1:]...)
	//				}
	//			}
	//			allianceCids.Locker.Unlock()
	//		}
	//	}

	//	vv := m_mapClubGame.Get(uint32(cid))
	//	if vv != nil {
	//		valRoomInfos, _ := vv.(*ValRoomInfos)
	//		if valRoomInfos != nil {
	//			valRoomInfos.Locker.Lock()
	//			for i := len(valRoomInfos.Rooms) - 1; i >= 0; i-- {
	//				if len(valRoomInfos.Rooms[i].AllianceIds) != 0 {
	//					valRoomInfos.Rooms = append(valRoomInfos.Rooms[:i], valRoomInfos.Rooms[i+1:]...)
	//				}
	//				if len(valRoomInfos.Rooms) == 0 {
	//					m_mapClubGame.Delete(clubId)
	//					logger.Info("CleanAllianceDeletedBoard-clubId:%v", clubId)
	//				}
	//			}
	//			valRoomInfos.Locker.Unlock()
	//		}
	//	}
}

func getUserGameInfo(roomId uint32) *pb.ClubGameSnapshot {
	var info *pb.ClubGameSnapshot = nil
	m_UserGame.Locker.RLock()
	for _, gameInfo := range m_UserGame.Rooms {
		if gameInfo.RoomId == roomId {
			info = new(pb.ClubGameSnapshot)

			info.CreatePlayerId = gameInfo.CreatePlayerId
			info.CreatorName = gameInfo.CreatorName
			info.ClubId = gameInfo.ClubId
			info.GameMode = gameInfo.GameMode
			info.RoomName = gameInfo.RoomName

			info.PlayerCount = gameInfo.PlayerCount
			info.SmallBlind = gameInfo.SmallBlind
			info.BigBlind = gameInfo.BigBlind
			info.BuyinMin = gameInfo.BuyinMin
			info.BuyinMax = gameInfo.BuyinMax

			info.CreateTime = gameInfo.CreateTime
			info.BuyinControl = gameInfo.BuyinControl
			info.Insurance = gameInfo.Insurance
			info.AntiCheating = gameInfo.AntiCheating
			info.Straddle = gameInfo.Straddle

			info.RandSeat = gameInfo.RandSeat
			info.Ante = gameInfo.Ante
			info.PlayerCountMax = gameInfo.PlayerCountMax
			info.OwnerType = gameInfo.OwnerType
			info.RuleTimeLimit = gameInfo.RuleTimeLimit

			info.GameStatus = gameInfo.GameStatus
			info.StartTime = gameInfo.StartTime

			info.RoomId = gameInfo.RoomId
			info.IsAllinAllfold = gameInfo.IsAllinAllfold
			info.ShortFullhouseFlushStraightThree = gameInfo.ShortFullhouseFlushStraightThree
			info.IsOpenedDrawback = gameInfo.IsOpenedDrawback
			info.IsForceShowcard = gameInfo.IsForceShowcard

			info.ExtraTime = gameInfo.ExtraTime
		}
	}
	m_UserGame.Locker.RUnlock()
	return info
}

func GetNotClubBoard(uid int) []*pb.ClubGameSnapshot {
	var list []*pb.ClubGameSnapshot
	var rids []uint32

	vv := m_mapUserRoomId.Get(uint32(uid))
	if vv != nil {
		userRoomIds, _ := vv.(*UserRoomIds)
		if userRoomIds != nil {
			userRoomIds.Locker.RLock()
			rids = make([]uint32, len(userRoomIds.Ids))
			copy(rids, userRoomIds.Ids)
			userRoomIds.Locker.RUnlock()
		}
	}

	for _, roomId := range rids {
		info := getUserGameInfo(roomId)
		if info == nil {
			continue
		}
		if !IsRoomExist(list, info.RoomId) {
			SubInfo, _ := db.GetSubGameInfo(info.CreatePlayerId)
			if SubInfo != nil {
				info.PicPath = SubInfo.PicPath
			}

			list = append(list, info)
		}
	}

	return list
}

func GetJackpotClubIds(clubId uint32) []uint32 {
	var jackClubIds []uint32
	v := m_mapClubGame.Get(uint32(clubId))
	if v != nil {
		valRoomInfos, _ := v.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.RLock()
			for _, game := range valRoomInfos.Rooms {
				vv := m_mapAllianceClubIds.Get(uint32(game.RoomId))
				if vv != nil {
					allianceCids, _ := vv.(*AllianceClubIds)
					if allianceCids != nil {
						allianceCids.Locker.RLock()
						jackClubIds = append(jackClubIds, allianceCids.Ids...)
						allianceCids.Locker.RUnlock()
					}

				}
			}
			valRoomInfos.Locker.RUnlock()
		}
	}

	//根据房间找到联盟相关的俱乐部
	return jackClubIds
}

func (s *server) CheckClubsMember(ctx context.Context, in *rpc_world.CheckClubsMemberRequest) (*rpc_world.CheckClubsMemberReply, error) {
	logger.Info("****rpc CheckClubsMember in:%+v", in)
	var err_num int32 = 0
	var isMember bool = false
	for {
		//1.查看创建的俱乐部集合
		cids, err := db.GetCreatedClubs(in.ClubCreaterid)
		if err != nil {
			err_num = int32(common.Error_Club_Other)
			logger.Notic("GetCreatedClubs:ClubCreaterid%v  failed:%v", in.ClubCreaterid, err_num)
			break
		}

		//2.俱乐部集合所包含的成员集
		var memberIds []uint32
		for _, cid := range cids {
			pIds, _ := db.GetClubMemberList(cid)
			memberIds = append(memberIds, pIds...)
		}

		//3.玩家是否在成员集中
		if common.IsIdExist(memberIds, in.UserId) {
			isMember = true
			err_num = 1
			break
		}

		break
	}

	logger.Info("rpc CheckClubsMember result:%v Clubid:%v Playerid:%v", isMember, in.ClubCreaterid, in.UserId)

	return &rpc_world.CheckClubsMemberReply{IsClubMember: isMember, ErrNum: err_num}, nil
}

func (s *server) StoreIncome(ctx context.Context, in *rpc_world.StoreIncomeRequest) (*rpc_world.StoreIncomeReply, error) {
	logger.Info("****rpc StoreIncome in:%+v", in)

	for _, cIncome := range in.CcuidIncome {
		db.ClubIncome_locker.Lock()
		db.CheckAndLoadClubIncome(cIncome.UID)
		ccuidIncome, _ := db.GetClubIncome(int(cIncome.UID))
		if ccuidIncome == nil {
			ccuidIncome = new(common.ClubCreaterIncomeInfo)
		}
		ccuidIncome.UID = cIncome.UID
		ccuidIncome.Fee += cIncome.Fee
		ccuidIncome.Insurance += cIncome.Insurance
		ccuidIncome.Jackpot += cIncome.Jackpot

		ccuidIncome.Total = ccuidIncome.Total + ccuidIncome.Fee + ccuidIncome.Insurance + ccuidIncome.Jackpot

		db.UpdateClubIncome(int(ccuidIncome.UID), ccuidIncome)
		db.SyncClubIncomeToDB(int(cIncome.UID))
		db.ClubIncome_locker.Unlock()
		//glog.Info(" roomid:", mp.RoomID, " uuid:", mp.UUID, " playerid:", player.UID, " total buyin:", player.TotalBuyin, " after total buyin:", user.Total_buyin, " total end room count:", user.Total_end_room_count)
	}

	for _, aIncome := range in.AcuidIncome {
		db.CheckAndLoadAlliIncome(aIncome.UID)
		acuidIncome, _ := db.GetAlliIncome(int(aIncome.UID))
		if acuidIncome == nil {
			acuidIncome = new(common.AlliCreaterIncomeInfo)
		}
		acuidIncome.UID = aIncome.UID
		acuidIncome.Fee += aIncome.Fee
		acuidIncome.Insurance += aIncome.Insurance
		acuidIncome.Jackpot += aIncome.Jackpot

		acuidIncome.Total = acuidIncome.Total + acuidIncome.Fee + acuidIncome.Insurance + acuidIncome.Jackpot

		db.UpdateAlliIncome(int(acuidIncome.UID), acuidIncome)

		//glog.Info(" roomid:", mp.RoomID, " uuid:", mp.UUID, " playerid:", player.UID, " total buyin:", player.TotalBuyin, " after total buyin:", user.Total_buyin, " total end room count:", user.Total_end_room_count)

		db.SyncAlliIncomeToDB(int(aIncome.UID))
	}

	if in.ProxyIncome != nil {
		proxyIncome, _ := db.GetProxyIncome(int(PROXY_ID))
		if proxyIncome == nil {
			proxyIncome = new(common.ProxyIncomeInfo)
		}
		proxyIncome.UID = PROXY_ID
		proxyIncome.Fee += in.ProxyIncome.Fee
		proxyIncome.Insurance += in.ProxyIncome.Insurance
		proxyIncome.Jackpot += in.ProxyIncome.Jackpot

		db.UpdateProxyIncome(int(PROXY_ID), proxyIncome)

		db.SyncProxyIncomeToDB(int(PROXY_ID))
	}

	if in.PlatformIncome != nil {
		platformIncome, _ := db.GetPlatformIncome(int(PLATFORM_ID))
		if platformIncome == nil {
			platformIncome = new(common.PlatformIncomeInfo)
		}
		platformIncome.UID = PLATFORM_ID
		platformIncome.Fee = in.PlatformIncome.Fee
		platformIncome.Insurance = in.PlatformIncome.Insurance
		platformIncome.Jackpot = in.PlatformIncome.Jackpot

		db.UpdatePlatformIncome(int(PLATFORM_ID), platformIncome)
		db.SyncPlatformIncomeToDB(int(PLATFORM_ID))
	}

	reply := new(rpc_world.StoreIncomeReply)
	return reply, nil
}

func SetClubGame2Redis() {
	cli := resume.GetRedisClient()
	cli.Delete(redis.Map_ClubGame)
	for k, vv := range m_mapClubGame.Items() {
		valRoomInfos, _ := vv.(*ValRoomInfos)
		if valRoomInfos != nil {
			valRoomInfos.Locker.Lock()
			//sRoomInfos, _ := json.Marshal(valRoomInfos.Rooms)
			//..
			var info_value []rpc_world.CreateRoomRequest
			for _, value := range valRoomInfos.Rooms {
				info_value = append(info_value, *value)
			}
			//..
			sRoomInfos, _ := json.Marshal(info_value)
			cli.HSet(redis.Map_ClubGame, strconv.Itoa(int(k)), string(sRoomInfos))
			valRoomInfos.Locker.Unlock()
		}
	}
}

func GetClubGameFromRedis() {
	logger.Info("GetClubGameFromRedis!")
	cli := resume.GetRedisClient()
	v, err := cli.HMGets(redis.Map_ClubGame)
	if err != nil {
		logger.Warn("redis get Map_ClubGame failed")
	} else {
		for i := 0; i < len(v); i += 2 {
			k := v[i].([]byte)
			val := v[i+1].([]byte)
			//..
			kv := string(k)
			ks := string(val)
			logger.Info("GetClubGameFromRedis recvd currency message:%+v +%v", kv, ks)
			//..
			var roomInfo []rpc_world.CreateRoomRequest
			err := json.Unmarshal([]byte(val), &roomInfo)
			if err != nil {
				logger.Warn("GetClubGameFromRedis Unmarshal failed err:%v", err)
				break
			}

			RInfos := new(ValRoomInfos)
			RInfos.Locker = new(sync.RWMutex)
			RInfos.Locker.Lock()
			for _, value := range roomInfo {
				RInfos.Rooms = append(RInfos.Rooms, &value)
			}
			RInfos.Locker.Unlock()

			ik, _ := strconv.Atoi(string(k))
			m_mapClubGame.Set(uint32(ik), RInfos)
			logger.Info("recover club game %v", uint32(ik))
		}
	}
}
