/*
 * 由SharpDevelop创建。
 * 用户： Administrator
 * 日期: 2019-03-28
 * 时间: 14:23
 * 
 * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
 */
using System;
using System.Collections.Concurrent;
using Server.DB.Sql;
using System.Data;
using MrWu.Debug;
using System.Collections.Generic;
using MrWu.Time;
using MrWu.Binary;
using MrWu.Basic;
using System.Threading;
using System.Threading.Tasks;
using MrWu.DB;
using GameData;
using Server.Data.ClubDef;
using Server.Data;
using System.Data.SqlClient;
using System.Text;
using Server.DB.Redis;
using StackExchange.Redis;
using System.Data.SqlTypes;
using GameData.Club;
using GameMessage;

namespace GameDAL
{
    /// <summary>
    /// 竞技比赛数据管理
    /// </summary>
    public static class ClubDataManager
    {

        /// <summary>
        /// 竞技比赛表名称
        /// </summary>
        public const string tb_clubs = "clubs";

        /// <summary>
        /// id列名
        /// </summary>
        public const string fd_id = "id";

        /// <summary>
        /// 竞技比赛名称列名
        /// </summary>
        public const string fd_clubname = "clubname";

        /// <summary>
        /// 公告列名
        /// </summary>
        public const string fd_notice = "notice";

        /// <summary>
        /// 竞技比赛会长列名
        /// </summary>
        public const string fd_leadername = "leadername";

        /// <summary>
        /// 玩法版本
        /// </summary>
        public const string fd_wayVer = "wayVer";

        /// <summary>
        /// 时间小时部分列名
        /// </summary>
        public const string fd_createtimeh = "createtimeh";

        /// <summary>
        /// 时间分钟部分列名
        /// </summary>
        public const string fd_createtimem = "createtimem";

        /// <summary>
        /// 时间秒部分列名
        /// </summary>
        public const string fd_createtimes = "createtimes";

        /// <summary>
        /// 关闭时间小时部分列名
        /// </summary>
        public const string fd_closetimeh = "closetimeh";

        /// <summary>
        /// 关闭时间分钟部分列名
        /// </summary>
        public const string fd_closetimem = "closetimem";

        /// <summary>
        /// 关闭时间秒钟部分列名
        /// </summary>
        public const string fd_closetimes = "closetimes";

        /// <summary>
        /// 房卡 列名
        /// </summary>
        public const string fd_cards = "cards";

        /// <summary>
        /// 玩家数量 列名
        /// </summary>
        public const string fd_manCnt = "manCnt";

        /// <summary>
        /// 所有的竞技比赛玩家数据 列名
        /// </summary>
        public const string fd_mans = "mans";

        /// <summary>
        /// 俱乐部密码
        /// </summary>
        public const string fd_Password = "password";

        /// <summary>
        /// 新玩法列
        /// </summary>
        public const string fd_newways = "newways";
        
        /// <summary>
        /// 设置
        /// </summary>
        public const string fd_setting = "setting";

        /// <summary>
        /// 积分 消耗一张房卡得1积分
        /// </summary>
        public const string fd_integral = "integral";

        /// <summary>
        /// 竞技比赛所有玩家表
        /// </summary>
        public const string tb_players = "players";

        /// <summary>
        /// userid列
        /// </summary>
        public const string fd_userid2018 = "userid2018";

        /// <summary>
        /// 用户名
        /// </summary>
        public const string fd_nickname2018 = "nickname2018";

        /// <summary>
        /// 联系方式-没用上
        /// </summary>
        //public const string fd_contact = "contact";

        /// <summary>
        /// 我的竞技比赛信息_老的
        /// </summary>
        public const string fd_myclubinfo = "myclubinfo";

        /// <summary>
        /// 我的竞技比赛信息 新的
        /// </summary>
        public const string fd_myclubinfodata = "myclubinfodata";

        /// <summary>
        /// 我加入的竞技比赛信息 老的
        /// </summary>
        public const string fd_joinclubinfo = "joinclubinfo";

        /// <summary>
        /// 我加入的竞技比赛信息 新的
        /// </summary>
        public const string fd_joinclubinfodata = "joinclubinfodata";

        /// <summary>
        /// 战斗记录id 老的
        /// </summary>
        public const string fd_fightcord = "fightrecordid";

        /// <summary>
        /// 战斗记录 新的
        /// </summary>
        public const string fd_fightcorddata = "fightrecordiddata";

        /// <summary>
        /// 竞技比赛消息白哦
        /// </summary>
        public const string tb_message = "clubmsg";

        /// <summary>
        /// 消息类型字段
        /// </summary>
        public const string fd_style = "style";

        /// <summary>
        /// 消息状态
        /// </summary>
        public const string fd_state = "state";

        /// <summary>
        /// 内容
        /// </summary>
        public const string fd_strcontent = "strcontent";

        /// <summary>
        /// 接收时间
        /// </summary>
        public const string fd_sendTime = "sendTime";

        /// <summary>
        /// 处理时间
        /// </summary>
        public const string fd_dotime = "dotime";

        /// <summary>
        /// 处理者
        /// </summary>
        public const string fd_doman = "doman";

        /// <summary>
        /// 处理人名称
        /// </summary>
        public const string fd_domanname = "domanname";

        /// <summary>
        /// 接收人id  转变为竞技比赛id
        /// </summary>
        public const string fd_receiveid = "receiveid";

        /// <summary>
        /// 发送者id  转变为用户id
        /// </summary>
        public const string fd_sendid = "sendid";

        /// <summary>
        /// 发送者名称
        /// </summary>
        public const string fd_sendname = "sendname";

        /// <summary>
        /// 竞技比赛战斗记录表
        /// </summary>
        public const string tb_ClubFightRecord = "club_FightRecord";

        /// <summary>
        /// 竞技比赛大赢家表
        /// </summary>
        public const string tb_ClubBigWiner = "Club_BigWiner";

        /// <summary>
        /// 竞技比赛id
        /// </summary>
        public const string fd_clubid = "clubid";

        /// <summary>
        /// 玩法id
        /// </summary>
        public const string fd_wayid = "wayid";

        /// <summary>
        /// 房间的唯一码
        /// </summary>
        public const string fd_weiyima = "weiyima";

        /// <summary>
        /// 游戏服务器id
        /// </summary>
        public const string fd_gameserid = "gameserid";

        /// <summary>
        /// 房间号
        /// </summary>
        public const string fd_roomnum = "roomnum";

        /// <summary>
        /// 房间战斗次数 
        /// </summary>
        public const string fd_warcnt = "warcnt";

        /// <summary>
        /// 开始时间
        /// </summary>
        public const string fd_startTime = "startTime";

        /// <summary>
        /// 结束时间
        /// </summary>
        public const string fd_endTime = "endTime";

        /// <summary>
        /// 玩家分值信息
        /// </summary>
        public const string fd_scores = "scores";

        /// <summary>
        /// userid
        /// </summary>
        public const string fd_userid = "userid";

        /// <summary>
        /// 昵称
        /// </summary>
        public const string fd_nickname = "nickname";

        /// <summary>
        /// 备注
        /// </summary>
        public const string fd_remark = "remark";

        /// <summary>
        /// 头像
        /// </summary>
        public const string fd_photo = "photo";

        /// <summary>
        /// id增量
        /// </summary>
        public const int idIncrement = 100000;

        /// <summary>
        /// 创建竞技比赛存储过程
        /// </summary>
        public const string pr_createclubnew = "createclubnew";

        /// <summary>
        /// 创建竞技比赛玩家
        /// </summary>
        public const string pr_createplayer = "CreateClubPlayer";

        /// <summary>
        /// 加载所有的竞技比赛数据
        /// </summary>
        public static List<Club_Base> LoadClubs()
        {
            List<Club_Base> clubs = new List<Club_Base>();
            DataTable dt = GameDB.Instance.selectDb(dbbase.game2018, tb_clubs);
            int len = dt.Rows.Count;
            for (int i = 0; i < len; i++)
            {
                clubs.Add(_LoadClub(dt.Rows[i]));
            }
            return clubs;
        }

        public static async Task<Club_Base> LoadClubAsync(int clubid)
        {
            return await Task.Run(()=>LoadClub(clubid));
        }

        public static Club_Base LoadClub(int clubid)
        {
            clubid = clubid -= 100000;
            DataTable dt = GameDB.Instance.selectDb(dbbase.game2018, tb_clubs, null, $"id={clubid}");
            if (dt.Rows.Count <= 0)
            {
                return null;
            }
            return _LoadClub(dt.Rows[0]);
        }

        public static bool ExistClub(int clubId)
        {
            clubId = clubId -= 100000;
            bool exists = GameDB.Instance.DapperExecuteScalar<int>(dbbase.game2018, 
                $"SELECT COUNT(1) FROM {tb_clubs} WHERE Id = @Id", 
                new { Id = clubId }) > 0;
            return exists;
        }

        /// <summary>
        /// 从行数据中加载竞技比赛数据
        /// </summary>
        /// <param name="row">行</param>
        /// <returns></returns>
        private static Club_Base _LoadClub(DataRow row)
        {
            Club_Base club = new Club_Base();
            club.Init();
            club.id = int.Parse(row[fd_id].ToString()) + idIncrement;
            club.clubname = row[fd_clubname].ToString();
            club.notice = row[fd_notice].ToString();
            club.leadername = row[fd_leadername].ToString();
            club.wayVer = (int)row[fd_wayVer];
            int timeh = int.Parse(row[fd_createtimeh].ToString());
            int timem = int.Parse(row[fd_createtimem].ToString());
            int times = int.Parse(row[fd_createtimes].ToString());

            //if (club.id > 100050)
            //    Console.WriteLine("1111");

            CustomTime custime = new CustomTime(timeh, (byte)timem, (byte)times, 0);
            club.createTime = TimeConvert.CustomTimeToDateTime(custime);
            club.card = int.Parse(row[fd_cards].ToString());
            club.mancnt = int.Parse(row[fd_manCnt].ToString());
            byte[] bts = row[fd_mans] as byte[];
            tr_clubMans mans = BinaryConvert.BytesToStruct<tr_clubMans>(bts, 0);
            if (mans.ids != null)
            {
                club.mansid.AddRange(mans.ids.GetNewArray(0, club.mancnt));
            }

            if (club.mancnt != club.mansid.Count)
            {
                Debug.Error($"数据错误，玩家数量与真实数量不一致! {club.id}");
            }
            
            string ways = row[fd_newways].ToString();

            if (club.wayVer == Club_Base.allServerVer)
            {
                PlayWay[] plways = JsonPack.GetData<PlayWay[]>(ways);
                if (plways != null)
                    club.ways.AddRange(plways);
            }

            club.PassWord = row[fd_Password].ToString();
            
            string setting = row[fd_setting].ToString();
            if (!string.IsNullOrEmpty(setting))
            {
                club.Setting = JsonPack.GetData<ClubSetting>(setting);
            }
            else
            {
                club.Setting = new ClubSetting();
            }
            Debug.Info("加载竞技比赛:" + club.clubname);
            //  Thread.Sleep(2);//不知为何要等待100ms, 单元测试，当数据较多时（大于200），将导致测试因超时失败，因此由原100修改为2
            return club;
        }

        /// <summary>
        /// 加载所有的拥有竞技比赛的玩家
        /// </summary>
        /// <returns></returns>
        public static List<ClubPlayer> LoadPlayers()
        {
            List<ClubPlayer> players = new List<ClubPlayer>();

            DataTable dt = GameDB.Instance.selectDb(dbbase.game2018, tb_players);
            int len = dt.Rows.Count;
            for (int i = 0; i < len; i++)
            {
                players.Add(_LoadPlayer(dt.Rows[i]));
            }
            return players;
        }

        public static ClubPlayer LoadPlayer(int userId)
        {
            DataTable dt = GameDB.Instance.selectDb(dbbase.game2018, tb_players, null, $"userid2018={userId}");
            int len = dt.Rows.Count;
            if (len > 0)
            {
                return _LoadPlayer(dt.Rows[0]);
            }
            return null;
        }

        /// <summary>
        /// 删除俱乐部玩家
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public static bool DeletePlayer(int userid)
        {
            string sql = $"delete from players where userid2018={userid}";
            return 1 == GameDB.Instance.ExceSql(dbbase.game2018, sql);
        }

        /// <summary>
        /// 删除俱乐部
        /// </summary>
        /// <param name="clubid"></param>
        /// <returns></returns>
        public static bool DeleteClub(int clubid)
        {
            string sql = $"DELETE FROM clubs WHERE ID = {clubid}";
            string leaguePowerSql = $"DELETE FROM LeagueClubLeaguePower WHERE ClubId = {clubid}";
            var ret = dbbase.game2018.ExecuteTransaction(t =>
            {
                t.ExecuteNonQuery(sql);
                t.ExecuteNonQuery(leaguePowerSql);
                
                return true;
            });
            return ret;
        }

        /// <summary>
        /// 删除俱乐部消息，申请加入之类的消息
        /// </summary>
        /// <param name="clubId">俱乐部Id，减去了100000的id，真实的俱乐部Id</param>
        /// <returns></returns>
        public static bool DeleteClubsByClubId(int clubId)
        {
            string sql = $"DELETE FROM clubmsg WHERE receiveid = {clubId}";
            var c = GameDB.Instance.ExceSql(dbbase.game2018, sql);
            Debug.ImportantLog($"删除俱乐部：{clubId} 的消息条数为：{c}");
            return c > 0;
        }

        public static Task<bool> PlayerIsInClubAsync(int userid)
        {
            return Task.Run(() => PlayerIsInClub(userid));
        }

        /// <summary>
        /// 玩家是否在俱乐部里面有数据
        /// </summary>
        /// <returns>true有数据 false没有数据</returns>
        public static bool PlayerIsInClub(int userid)
        {
            string sql = $"select top 1 * from players where userid2018={userid}";
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            var b = ds.Tables != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0;
            if (!b) return false;
            var myinfo = ds.Tables[0].Rows[0][fd_myclubinfodata] == DBNull.Value;
            var joinInfo = ds.Tables[0].Rows[0][fd_joinclubinfodata] == DBNull.Value;
            //Debug.ImportantLog($"b m:{myinfo} ,j:{joinInfo}");
            if (myinfo && joinInfo)
            {
                return false;
            }
            else
            {
                string myText = ds.Tables[0].Rows[0][fd_myclubinfodata] as string; //空数据一般是[]
                string joinText = ds.Tables[0].Rows[0][fd_joinclubinfodata] as string;
                //Debug.ImportantLog($"mytext:{myText},   join:{joinText}");
                if (myText.Length <= 3 && joinText.Length <= 3)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 加载竞技比赛玩家
        /// 
        /// 2020-06-21 修改竞技比赛的玩家表
        /// 原来存储的是二进制数据,完全没有办法拓展。
        /// 所以把我的竞技比赛信息,加入的竞技比赛信息，战斗记录的id，换成 josn 格式存储 新增数据库字段
        /// 也就是这个版本升级之contact 字段 myclubinfo 字段 joinclubinfo 字段 fightrecordid 字段 都废弃了
        /// 
        /// </summary>
        /// <param name="row">行</param>
        /// <returns>竞技比赛玩家</returns>
        private static ClubPlayer _LoadPlayer(DataRow row)
        {
            ClubPlayer player = new ClubPlayer();
            //userid
            player.userid = int.Parse(row[fd_userid2018].ToString());
            //用户昵称
            player.nickname = row[fd_nickname2018].ToString();
            if (row["sex"] != DBNull.Value)
            { //这是新加的字段
                player.sex = int.Parse(row["sex"].ToString());
            }
            bool isSave = false;

            //先去加载新的, 如果加载不到 就去加载老的
            if (row[fd_myclubinfodata] == DBNull.Value)
            { //新的是空 去加载老的, 并把这个数据存到新的里面去
                byte[] bts = row[fd_myclubinfo] as byte[];
                tr_clubsOfPlayer myclubinfo = BinaryConvert.BytesToStruct<tr_clubsOfPlayer>(bts);
                player.myClubs = tr_clubsOfPlayerToListPlayerofClub(ref myclubinfo);
                //存到新的里去
                isSave = true;
            }
            else
            {
                string text = row[fd_myclubinfodata] as string;
                player.myClubs = JsonPack.GetData<List<playerofClub>>(text);
                if (player.myClubs == null)
                {
                    Debug.Error("新表中没有存储到我的竞技比赛数据" + player.userid);
                    player.myClubs = new List<playerofClub>();
                }
            }

            if (row[fd_joinclubinfodata] == DBNull.Value)
            {  //新的是空 去加载老的，并把这个数据存到新的里面去
                byte[] bts = row[fd_joinclubinfo] as byte[];
                tr_clubsOfPlayer joinclubinfo = BinaryConvert.BytesToStruct<tr_clubsOfPlayer>(bts);
                player.joinClubs = tr_clubsOfPlayerToListPlayerofClub(ref joinclubinfo);
                //存到新的里面去
                isSave = true;
            }
            else
            {
                string text = row[fd_joinclubinfodata] as string;
                player.joinClubs = JsonPack.GetData<List<playerofClub>>(text);
                if (player.joinClubs == null)
                {
                    Debug.Error("新表中没有存储到我加入的竞技比赛数据:" + player.userid);
                    player.joinClubs = new List<playerofClub>();
                }
            }

            if (row[fd_fightcorddata] == DBNull.Value)
            {
                byte[] bts = row[fd_fightcord] as byte[];
                tr_playerFightRecordId fightrecord = BinaryConvert.BytesToStruct<tr_playerFightRecordId>(bts);
                player.fightRecordids = FightRecordidToListid(ref fightrecord);
                //存到新的里面去
                isSave = true;
            }
            else
            {
                string text = row[fd_fightcorddata] as string;
                player.fightRecordids = JsonPack.GetData<List<int>>(text);
                if (player.fightRecordids == null)
                {
                    Debug.Error("新表中没有存储到战斗记录数据的id:" + player.userid);
                    player.fightRecordids = new List<int>();
                }
            }

            if (isSave)
                UpdatePlayer(player);

            return player;

        }


        /// <summary>
        /// 时间转换
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        private static DateTime ConvertTime(ref tr_sifangdatetime time)
        {
            CustomTime ct = new CustomTime(time.hours, time.minute, time.second);
            return TimeConvert.CustomTimeToDateTime(ct);
        }

        /// <summary>
        /// 时间转换
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        private static tr_sifangdatetime ConvertTime(DateTime time)
        {
            CustomTime ct = TimeConvert.DateTimeToCustomTime(time);
            tr_sifangdatetime sftime;
            sftime.hours = ct.hours;
            sftime.minute = ct.minute;
            sftime.second = ct.second;
            return sftime;
        }

        /// <summary>
        /// 玩家的单个竞技比赛结构数据转类数据
        /// </summary>
        /// <returns></returns>
        private static playerofClub Tr_playerInfoOfClubToplayerofClub(ref tr_playerInfoOfClub tpic)
        {
            playerofClub item = new playerofClub();
            item.clubid = tpic.clubid;
            item.inGame = tpic.ingame;
            item.position = tpic.position;
            item.remark = BinaryConvert.BytesToShortString(tpic.remark, BinaryConvert.GB2312);
            if (item.remark.Length != 0)
                Console.WriteLine(item.remark);
            item.joinTime = ConvertTime(ref tpic.jointime);
            item.permission = tpic.bak1;
            return item;
        }

        /// <summary>
        /// 玩家的单个竞技比赛类数据转结构数据
        /// </summary>
        /// <param name="pc"></param>
        /// <returns></returns>
        private static tr_playerInfoOfClub PlayerofClubTotr_playerInfoOfClub(playerofClub pc)
        {
            tr_playerInfoOfClub tpic = tr_playerInfoOfClub.CreateTr_playerInfoOfClub();
            tpic.clubid = pc.clubid;
            tpic.ingame = (byte)pc.inGame;
            tpic.jointime = ConvertTime(pc.joinTime);
            tpic.position = (byte)pc.position;
            tpic.bak1 = (ushort)pc.permission;
            BinaryConvert.ShortStringToBytes(pc.remark, tpic.remark, 0, BinaryConvert.GB2312);
            return tpic;
        }


        /// <summary>
        /// 玩家的竞技比赛结构数据 转类数据
        /// </summary>
        /// <param name="tcp"></param>
        /// <returns></returns>
        private static List<playerofClub> tr_clubsOfPlayerToListPlayerofClub(ref tr_clubsOfPlayer tcp)
        {
            List<playerofClub> pc = new List<playerofClub>();
            for (int i = 0; i < tcp.cnt; i++)
            {
                pc.Add(Tr_playerInfoOfClubToplayerofClub(ref tcp.datas[i]));
            }
            return pc;
        }

        /// <summary>
        /// 玩家的竞技比赛类数据 转结构数据
        /// </summary>
        /// <param name="clubdata"></param>
        /// <returns></returns>
        private static tr_clubsOfPlayer ListPlayerofClubTotr_clubsOfPlayer(List<playerofClub> clubdata)
        {
            tr_clubsOfPlayer tcp = tr_clubsOfPlayer.CreateTr_clubsOfPlayer();//new tr_clubsOfPlayer();
            tcp.cnt = clubdata.Count;
            for (int i = 0; i < tcp.cnt; i++)
            {
                if (i < tcp.datas.Length)
                    tcp.datas[i] = PlayerofClubTotr_playerInfoOfClub(clubdata[i]);
            }
            return tcp;
        }

        /// <summary>
        /// 玩家战斗记录id结构体转链表
        /// </summary>
        /// <param name="pfr"></param>
        /// <returns></returns>
        private static List<int> FightRecordidToListid(ref tr_playerFightRecordId pfr)
        {
            List<int> records = new List<int>();
            for (int i = 0; i < pfr.cnt; i++)
            {
                records.Add(pfr.fightrecords[i]);
            }
            return records;
        }

        /// <summary>
        /// 玩家战斗记录id链表转结构体
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public static tr_playerFightRecordId ListidToFightRecordid(List<int> ids)
        {
            tr_playerFightRecordId tpfr = new tr_playerFightRecordId();
            tpfr.cnt = ids.Count;
            for (int i = 0; i < tpfr.cnt; i++)
            {
                tpfr.fightrecords[i] = ids[i];
            }
            return tpfr;
        }

        /// <summary>
        /// 数组转 竞技比赛 中的玩家数据
        /// </summary>
        /// <param name="mansid"></param>
        /// <returns></returns>
        public static tr_clubMans ArrayTotr_clubMans(List<int> mansid)
        {
            tr_clubMans mans = tr_clubMans.CreateClubMans();
            int len = mansid.Count;
            for (int i = 0; i < len; i++)
            {
                mans.ids[i] = mansid[i];
            }
            return mans;
        }
        
        /// <summary>
        /// 创建竞技比赛存储过程
        /// </summary>
        /// <param name="club">竞技比赛数据</param>
        /// <param name="myclubs">我的竞技比赛数据</param>
        /// <param name="createuser">创建者userid</param>
        /// <returns>0程序出错 -1未找到创建者 -2竞技比赛名称同名  -3表示已存在竞技比赛id</returns>
        public static int CreateClub(Club_Base club, List<playerofClub> myclubs, int createuser)
        {
            var spp = GameDB.Instance.BeginSetProcedureParameter(dbbase.game2018, pr_createclubnew);
            GameDB.Instance.AddProdureParameters(spp, "@clubid", SqlDbType.Int, club.id - ClubDataManager.idIncrement);
            GameDB.Instance.AddProdureParameters(spp, "@clubname", SqlDbType.NVarChar, club.clubname);
            GameDB.Instance.AddProdureParameters(spp, "@clubnotice", SqlDbType.NVarChar, club.notice);
            GameDB.Instance.AddProdureParameters(spp, "@createruser", SqlDbType.NVarChar, createuser);
            CustomTime ct = TimeConvert.DateTimeToCustomTime(club.createTime);
            GameDB.Instance.AddProdureParameters(spp, "@createH", SqlDbType.Int, ct.hours);
            GameDB.Instance.AddProdureParameters(spp, "@createM", SqlDbType.Int, ct.minute);
            GameDB.Instance.AddProdureParameters(spp, "@createS", SqlDbType.Int, ct.second);
            GameDB.Instance.AddProdureParameters(spp, "@cards", SqlDbType.Int, club.card);
            var ids = ArrayTotr_clubMans(club.mansid);
            byte[] bts = BinaryConvert.StructToBytes(ids);
            GameDB.Instance.AddProdureParameters(spp, "@mans", SqlDbType.Binary, bts);
            GameDB.Instance.AddProdureParameters(spp, "@mancnt", SqlDbType.Int, club.mancnt);
            GameDB.Instance.AddProdureParameters(spp, "@ways", SqlDbType.Text, JsonPack.GetJson(club.ways));
            var clubsinfo = JsonPack.GetJson(myclubs);
            /* 老的二进制方式
            var clubsinfo = ListPlayerofClubTotr_clubsOfPlayer(myclubs);
            bts = BinaryConvert.StructToBytes(clubsinfo);
            */
            GameDB.Instance.AddProdureParameters(spp, "@myclubinfo", SqlDbType.Text, clubsinfo);
            GameDB.Instance.AddProdureParameters(spp, "@result", SqlDbType.Int, 0, ParameterDirection.Output);
            DataSet ds = new DataSet();
            Dictionary<string, object> pars = GameDB.Instance.EndAddProdureParameters(spp, ds);
            return (int)pars["@result"];
        }

        /// <summary>
        /// 创建一个竞技比赛玩家
        /// </summary>
        /// <param name="player"></param>
        /// <returns></returns>
        public static bool CreatePlayer(ClubPlayer player)
        {
            var spp = GameDB.Instance.BeginSetProcedureParameter(dbbase.game2018, pr_createplayer);
            GameDB.Instance.AddProdureParameters(spp, "@userid", SqlDbType.Int, player.userid);

            /* 老的
            var clubsinfo = ListPlayerofClubTotr_clubsOfPlayer(player.myClubs);
            byte[] bts = BinaryConvert.StructToBytes(clubsinfo);
            GameDB.Instance.AddProdureParameters(spp, "@myclubinfo", SqlDbType.Binary, bts);
            */

            var clubsinfo = JsonPack.GetJson(player.myClubs);
            GameDB.Instance.AddProdureParameters(spp, "@myclubinfo", SqlDbType.Text, clubsinfo);

            /* 老的
            clubsinfo = ListPlayerofClubTotr_clubsOfPlayer(player.joinClubs);
            bts = BinaryConvert.StructToBytes(clubsinfo);
            GameDB.Instance.AddProdureParameters(spp, "@joinclubinfo", SqlDbType.Binary, bts);
            */

            clubsinfo = JsonPack.GetJson(player.joinClubs);
            GameDB.Instance.AddProdureParameters(spp, "@joinclubinfo", SqlDbType.Text, clubsinfo);

            /* 老的
            var pfr = ListidToFightRecordid(player.fightRecordids);
            bts = BinaryConvert.StructToBytes(pfr);
            GameDB.Instance.AddProdureParameters(spp, "@fightrecordids", SqlDbType.Binary, bts);
            */

            var pfr = JsonPack.GetJson(player.fightRecordids);
            GameDB.Instance.AddProdureParameters(spp, "@fightrecordids", SqlDbType.Text, pfr);


            GameDB.Instance.AddProdureParameters(spp, "@result", SqlDbType.Int, 0, ParameterDirection.Output);
            DataSet ds = new DataSet();
            Dictionary<string, object> pars = GameDB.Instance.EndAddProdureParameters(spp, ds);
            if (ds.Tables.Count > 0)
            {
                player.nickname = ds.Tables[0].Rows[0][fd_nickname].ToString();
            }

            return (int)pars["@result"] == 1;
        }

        /// <summary>
        /// 更新玩家   修改玩家权限，设置小黑屋都需要调用更新 玩家数据
        /// </summary>
        /// <param name="player"></param>
        public static bool UpdatePlayer(ClubPlayer player)
        {
            string sql = string.Format("update Top(1) {0} set {1}=@nickname,{2}=@myclubinfo,{3}=@joinclubinfo,{4}=@fightrecord where {5}={6};",
                                       tb_players, fd_nickname2018, fd_myclubinfodata, fd_joinclubinfodata, fd_fightcorddata, fd_userid2018, player.userid);

            //List<ISqlAloneParameter<SqlDbType>> sqlpms = new List<ISqlAloneParameter<SqlDbType>>();

            /* 老的存储
            var clubsinfo = ListPlayerofClubTotr_clubsOfPlayer(player.myClubs);
            byte[] bts1 = BinaryConvert.StructToBytes(clubsinfo);
            var param1 = new SqlParameter("@myclubinfo", SqlDbType.Binary, bts1.Length) { Value = bts1 };//sqlpms.Add(new SqlAloneParameter("@myclubinfo", bts, bts.Length));
            */
            var paramNick = new SqlParameter("@nickname", SqlDbType.Text) { Value = player.nickname };

            var clubsinfo = JsonPack.GetJson(player.myClubs);
            var param1 = new SqlParameter("@myclubinfo", SqlDbType.Text) { Value = clubsinfo };

            /* 老的存储
            var clubsinfo2 = ListPlayerofClubTotr_clubsOfPlayer(player.joinClubs);
            var bts2 = BinaryConvert.StructToBytes(clubsinfo2);
            var param2 = new SqlParameter("@joinclubinfo", SqlDbType.Binary, bts2.Length) { Value = bts2 };//sqlpms.Add(new SqlAloneParameter("@joinclubinfo", bts, bts.Length));
            */
            var clubsinfo2 = JsonPack.GetJson(player.joinClubs);
            var param2 = new SqlParameter("@joinclubinfo", SqlDbType.Text) { Value = clubsinfo2 };

            /* 老的存储
            var pfr = ListidToFightRecordid(player.fightRecordids);
            var bts3 = BinaryConvert.StructToBytes(pfr);
            var param3 = new SqlParameter("@fightrecord", SqlDbType.Binary, bts3.Length) { Value = bts3 };//sqlpms.Add(new SqlAloneParameter("@fightrecord", bts, bts.Length));
            */
            var pfd = JsonPack.GetJson(player.fightRecordids);
            var param3 = new SqlParameter("@fightrecord", SqlDbType.Text) { Value = pfd };

            var sqlpms = new SqlParameter[] { paramNick, param1, param2, param3 };
            return 1 == GameDB.Instance.ExceSql(dbbase.game2018, sql, sqlpms);
        }

        public static bool UpdatePlayers(IEnumerable<ClubPlayer> players)
        {
            var transaction = GameDB.Instance.BeginTransaction(dbbase.game2018);
            var succ = false;
            try
            {
                foreach (var player in players)
                {
                    string sql = string.Format("update Top(1) {0} set {1}=@nickname,{2}=@myclubinfo,{3}=@joinclubinfo,{4}=@fightrecord where {5}={6};",
                                           tb_players, fd_nickname2018, fd_myclubinfodata, fd_joinclubinfodata, fd_fightcorddata, fd_userid2018, player.userid);
                    var paramNick = new SqlAloneParameter("@nickname", player.nickname, player.nickname.Length, SqlDbType.Text);
                    var clubsinfo = JsonPack.GetJson(player.myClubs);
                    var param1 = new SqlAloneParameter("@myclubinfo", clubsinfo, clubsinfo.Length, SqlDbType.Text);
                    var clubsinfo2 = JsonPack.GetJson(player.joinClubs);
                    var param2 = new SqlAloneParameter("@joinclubinfo", clubsinfo2, clubsinfo2.Length, SqlDbType.Text);
                    var pfd = JsonPack.GetJson(player.fightRecordids);
                    var param3 = new SqlAloneParameter("@fightrecord", pfd, pfd.Length, SqlDbType.Text);
                    var sqlpms = new List<ISqlAloneParameter<SqlDbType>> { paramNick, param1, param2, param3 };
                    succ = GameDB.Instance.TransactionAddSql(transaction, sql, sqlpms) == 1;
                    if (transaction.isException)
                    {
                        throw transaction.exception;//发生异常，抛出
                    }
                    if (!succ)
                    {
                        throw new Exception($"UpdatePlayers failed, sql: {sql}");
                    }
                }
                succ = true;
            }
            catch (Exception ex)
            {
                Debug.Error($"UpdatePlayers ex：{ex}");
            }
            finally
            {
                succ &= GameDB.Instance.SubTransaction(transaction);
            }
            return succ;
        }

        /// <summary>
        /// 获取下一个竞技比赛id
        /// </summary>
        /// <returns></returns>
        public static int GetNextClubId()
        {
            string sql = string.Format("select top(1) id from {0} order by {1} desc", tb_clubs, fd_id);
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            if (ds.Tables.Count == 0 || ds.Tables[0].Rows.Count < 1) return 1;
            return int.Parse(ds.Tables[0].Rows[0]["id"].ToString()) + 1;
        }

        /// <summary>
        /// 查看公告格式
        /// </summary>
        /// <param name="notice"></param>
        /// <returns></returns>
        private static bool CheckNotice(string notice)
        {
            return BaseFun.CheckStringLength(notice, 0, 32, true, Encoding.GetEncoding("gb2312"))
                && BaseFun.ProcessSqlStr(notice);
        }

        /// <summary>
        /// 执行sql语句修改竞技比赛公告
        /// </summary>
        /// <param name="clubid"></param>
        /// <param name="notice"></param>
        public static void ExceSqlSetClubNotice(int clubid, string notice)
        {
            //string sql = string.Format("update top(1) {2} set {3} = '{0}' where {4} = {1}", notice, clubid, tb_clubs, fd_notice, fd_id);
            //                            update top(1) {tb_clubs} set {fd_notice} = '{notice}' where {fd_id} = {clubid}

            string sql = string.Format("update top(1) {0} set {1} = @notice where [ID] = @p2", tb_clubs, fd_notice);
            GameDB.Instance.ExceSql(dbbase.game2018, sql, new SqlParameter[]{
                new SqlParameter("@p2", SqlDbType.Int){ Value = clubid - ClubDataManager.idIncrement },
                new SqlParameter("@notice",notice ?? (object)DBNull.Value)
                });
        }

        /// <summary>
        /// 保存俱乐部密码
        /// </summary>
        /// <param name="clubid"></param>
        /// <param name="notice"></param>
        public static void SaveClubPassword(int clubid, string password)
        {
            string sql = string.Format("update top(1) {0} set {1} = @password where [ID] = @p2", tb_clubs, fd_Password);
            GameDB.Instance.ExceSql(dbbase.game2018, sql, new SqlParameter[]{
                new SqlParameter("@p2", SqlDbType.Int){ Value = clubid - ClubDataManager.idIncrement },
                new SqlParameter("@password",password ?? string.Empty)
                });
        }

        /// <summary>
        /// 修改俱乐部群主的名字
        /// </summary>
        /// <param name="clubid"></param>
        /// <param name="nickName"></param>
        public static void UpdateLeaderName(int clubid, string nickName)
        {
            string sql = string.Format("update top(1) {0} set {1} = @nickName where [ID] = @p2", tb_clubs, fd_leadername);
            GameDB.Instance.ExceSql(dbbase.game2018, sql, new SqlParameter[]{
                new SqlParameter("@p2", SqlDbType.Int){ Value = clubid - ClubDataManager.idIncrement },
                new SqlParameter("@nickName",nickName ?? string.Empty)
                });
        }

        /// <summary>
        /// 设置竞技比赛公告
        /// </summary>
        /// <param name="clubid">竞技比赛id</param>
        /// <param name="notice">公告</param>
        /// <returns>公告符不符合格式</returns>
        public static bool SetClubNotice(int clubid, string notice)
        {
            bool r = CheckNotice(notice);

            if (r)
            {
                ExceSqlSetClubNotice(clubid, notice);
            }

            return r;
        }

        /// <summary>
        /// 设置竞技比赛公告
        /// </summary>
        /// <param name="clubid">竞技比赛id</param>
        /// <param name="notice">公告</param>
        /// <returns></returns>
        public static bool SetClubNoticeAsyn(int clubid, string notice)
        {
            bool r = CheckNotice(notice);

            if (r)
            {
                Task.Factory.StartNew(
                    () =>
                    {
                        ExceSqlSetClubNotice(clubid, notice);
                    }
                );
            }

            return r;
        }

        /// <summary>
        /// 计算带折扣房卡的最终值
        /// </summary>
        public static int CalClubCardWithDiscount(int clubId, int cardCnt)
        {
            var discount = ClubRCDiscountRedisUtil.GetClub(clubId);
            return (int)Math.Round(cardCnt / discount);
        }

        public static Task<bool> AddClubCardAsync(int clubId,int cardCnt)
        {
            return Task.Run(() => AddClubCard(clubId, cardCnt));
        }

        /// <summary>
        /// 添加竞技比赛房卡
        /// </summary>
        /// <param name="clubid">竞技比赛id</param>
        /// <param name="cardCnt">房卡数量</param>
        public static bool AddClubCard(int clubid, int cardCnt)
        {
            string sql;
            int cnt = Math.Abs(cardCnt);

            if (cardCnt >= 0) //返还房卡
                sql = $"update top(1) {tb_clubs} set {fd_cards} = {fd_cards} + {cnt},{fd_integral} = {fd_integral} - {cnt} where {fd_id} = {clubid - idIncrement}";
            //sql = string.Format("update Top(1) {0} set {1} = {1} + {2}, {5} = {5} - {2} where {3} = {4}", tb_clubs, fd_cards, cardCnt, fd_id, , (clubid - idIncrement));
            else
                sql = $"update top(1) {tb_clubs} set {fd_cards} = {fd_cards} - {cnt},{fd_integral} = {fd_integral} + {cnt} where {fd_id} = {clubid - idIncrement}";
            //sql = string.Format("update Top(1) {0} set {1} = {1}  {2} where {3} = {4}", tb_clubs, fd_cards, cardCnt, fd_id, (clubid - idIncrement));

            Debug.ImportantLog(sql);
            return GameDB.Instance.ExceSql(dbbase.game2018, sql) > 0;
        }

        /// <summary>
        /// 异步添加竞技比赛房卡
        /// </summary>
        /// <param name="clubid"></param>
        /// <param name="cardCnt"></param>
        public static async Task<bool> AddClubCardAsyn(int clubid, int cardCnt)
        {
            return await Task.Factory.StartNew(
                () =>
                {
                    return AddClubCard(clubid, cardCnt);
                }
            );
        }

        /*
        /// <summary>
        /// 获取竞技比赛消息_未处理的
        /// </summary>
        /// <param name="clubid">竞技比赛id</param>
        /// <param name="count">最大接收数量</param>
        /// <returns></returns>
        public static List<ClubMessage> GetClubMessage(int clubid, int count) {
            List<ClubMessage> msgs = new List<ClubMessage>();
            string sql = string.Format("select Top({0}) * from {1} where {2}={3} and {4}=0 Order By sendTime desc;",
                                       count, tb_message, fd_receiveid, clubid - idIncrement, fd_state);
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            if (ds.Tables.Count == 0)
                return msgs;
            DataTable dt = ds.Tables[0];
            for (int i = 0; i < dt.Rows.Count; i++) {
                msgs.Add(LoadClubMessage(dt.Rows[i]));
            }
            return msgs;
        }
        */

        /// <summary>
        /// 加载竞技比赛消息
        /// </summary>
        /// <param name="row">行</param>
        /// <returns></returns>
        public static ClubMessage LoadClubMessage(DataRow row)
        {
            ClubMessage clubmsg = new ClubMessage();
            clubmsg.id = (int)row[fd_id];
            clubmsg.style = (int)row[fd_style];
            clubmsg.state = (int)row[fd_state];
            clubmsg.content = row[fd_strcontent].ToString();
            clubmsg.sendTime = DateTime.Parse(row[fd_sendTime].ToString());
            string doTime = row[fd_dotime].ToString();
            if (!string.IsNullOrEmpty(doTime))
            {
                clubmsg.doTime = DateTime.Parse(doTime);
            }
            if (row[fd_doman] != DBNull.Value)
                clubmsg.doman = (int)row[fd_doman];
            if (row[fd_domanname] != DBNull.Value)
                clubmsg.domanname = row[fd_domanname].ToString();
            if (row[fd_receiveid] != DBNull.Value)
                clubmsg.reciveid = (int)row[fd_receiveid] + idIncrement;
            clubmsg.sendid = (int)row[fd_sendid];
            clubmsg.sendname = row[fd_sendname].ToString();
            if (row.Table.Columns.Contains("Sex"))
                if (row["Sex"] != DBNull.Value)
                    clubmsg.SendSex = (int)row["Sex"];
            clubmsg.param1 = (int)row["param1"];
            clubmsg.param2 = row["param2"] is DBNull ? null : (string)row["param2"];
            return clubmsg;
        }

        public static Task<ClubMessage> GetClubMessageAsync(int msgid)
        {
            return Task.Run(
                () => GetClubMessage(msgid)
            );
        }
        
        /// <summary>
        /// 获取竞技比赛消息
        /// </summary>
        /// <param name="msgid"></param>
        /// <returns></returns>
        public static ClubMessage GetClubMessage(int msgid)
        {
            string sql = string.Format($"select Top(1) * from {tb_message} where {fd_id} = {msgid}");

            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            if (ds.Tables.Count == 0)
                return null;

            DataTable dt = ds.Tables[0];
            return LoadClubMessage(dt.Rows[0]);
        }

        public static Task<List<ClubMessage>> GetClubMessageByClubAsync(int clubId)
        {
            return Task.Run(() => GetClubMessageByClub(clubId));
        }

        /// <summary>
        /// 获取竞技比赛未处理的消息
        /// </summary>
        /// <param name="club"></param>
        /// <returns></returns>
        public static List<ClubMessage> GetClubMessageByClub(int clubid)
        {
            List<ClubMessage> lst = new List<ClubMessage>();
            string sql = $"SELECT TOP 500 c.[id],c.[style],c.[state],c.[sendTime],c.[dotime],c.[doman],c.[domanname],c.[receiveid],c.[sendid],c.[sendname],c.[strcontent],c.[param1],c.[param2],us.Sex  FROM [game2018].[dbo].[clubmsg] c INNER JOIN jnxdgame.dbo.tbUserBaseInfo us on c.sendid=us.UserID  where c.receiveid= {clubid - idIncrement} and (((c.style=0 or c.style=2) and c.state=0) or (c.style=1 and c.state=4)) order by c.id desc";//and (c.style=0 or c.style=2) 
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            if (BaseFun.DataSetIsNullOrEmpty(ds) || BaseFun.DataTableIsNullOrEmpty(ds.Tables[0]))
                return lst;

            var dt = ds.Tables[0];
            int len = dt.Rows.Count;
            for (int i = 0; i < len; i++)
            {
                lst.Add(LoadClubMessage(dt.Rows[i]));
            }

            return lst;
        }

        /// <summary>
        /// 获取个人的消息记录
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        public static List<ClubMessage> GetClubMessageByPerson(int userid)
        {
            List<ClubMessage> lst = new List<ClubMessage>();
            string sql = string.Format($"select * from {tb_message} where {fd_sendid} = {userid} order by {fd_id} desc");
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            if (BaseFun.DataSetIsNullOrEmpty(ds) || BaseFun.DataTableIsNullOrEmpty(ds.Tables[0]))
                return lst;

            var dt = ds.Tables[0];
            int len = dt.Rows.Count;
            for (int i = 0; i < len; i++)
            {
                lst.Add(LoadClubMessage(dt.Rows[i]));
            }
            return lst;
        }

        public static Task<int> DoClubMessageAsync(ClubMessage clubmsg)
        {
            return Task.Run(() => DoClubMessage(clubmsg));
        }

        /// <summary>
        /// 更新竞技比赛消息
        /// </summary>
        /// <param name="clubmsg"></param>
        public static int DoClubMessage(ClubMessage clubmsg)
        {
            string sql = string.Format($"update top(1) {tb_message} set {fd_state}={clubmsg.state},{fd_doman}='{clubmsg.doman}',{fd_dotime}='{clubmsg.doTime}',{fd_domanname}=@domanname where {fd_id}={clubmsg.id} and ((({fd_style}=0 or {fd_style}=2) and {fd_state} = 0) or ({fd_style}=1 and {fd_state} = 4))");
            return GameDB.Instance.ExceSql(dbbase.game2018, sql, new[] { new SqlParameter("@domanname", clubmsg.domanname ?? (object)DBNull.Value) });
        }

        public static Task<bool> InsertClubMessageAsync(ClubMessage clubmsg)
        {
            return Task.Run(() => InsertClubMessage(clubmsg));
        }

        /// <summary>
        /// 插入一条消息
        /// </summary>
        /// <param name="clubmsg"></param>
        /// <returns></returns>
        public static bool InsertClubMessage(ClubMessage clubmsg)
        {

            if (clubmsg.domanname == null)
                clubmsg.domanname = string.Empty;

            if (clubmsg.content == null)
                clubmsg.content = string.Empty;


            string sql = $"insert into {tb_message}({fd_style},{fd_state},{fd_sendTime},{fd_receiveid},{fd_sendid},{fd_sendname},{fd_strcontent})" +
                $"  values({clubmsg.style},{clubmsg.state},'{clubmsg.sendTime}',{clubmsg.reciveid},{clubmsg.sendid},@sendname,@content)";

            return GameDB.Instance.ExceSql(dbbase.game2018, sql, new[] {
                new SqlParameter("@content", clubmsg.content ?? (object)DBNull.Value),
                new SqlParameter("@sendname", clubmsg.sendname ?? (object)string.Empty)//clubmsg 的sendname字段不允许为null
            }) == 1;

        }

        public static Task<bool> AskForJoinClubMessageAsync(ClubMessage clubmsg)
        {
            return Task.Run(() => AskForJoinClubMessage(clubmsg));
        }

        /// <summary>
        /// 请求加入竞技比赛
        /// </summary>
        /// <param name="clubmsg"></param>
        public static bool AskForJoinClubMessage(ClubMessage clubmsg)
        {
            string sql = string.Empty;
            try
            {
                if (clubmsg.domanname == null)
                    clubmsg.domanname = string.Empty;

                if (clubmsg.content == null)
                    clubmsg.content = string.Empty;

                //如果不存在 这个竞技比赛的申请 就可以去申请
                sql = string.Format($"if not exists(select Top(1) 1 from {tb_message} where {fd_receiveid} = {clubmsg.reciveid - idIncrement} and {fd_sendid} = {clubmsg.sendid} and {fd_style} = {clubmsg.style} and {fd_state} = {clubmsg.state}) begin{Environment.NewLine}");
                sql += string.Format($"insert into {tb_message}({fd_style},{fd_state},{fd_sendTime},{fd_doman},{fd_domanname},{fd_receiveid},{fd_sendid},{fd_sendname},{fd_strcontent}, param1, param2) " +
                                     $"values({clubmsg.style},{clubmsg.state},'{clubmsg.sendTime}',{clubmsg.doman},@domanname,{clubmsg.reciveid - idIncrement},{clubmsg.sendid},@sendname,@content, {clubmsg.param1}, @param2);");//{(clubmsg.param2 == null ? "NULL" : string.Format("'{0}'", clubmsg.param2))}
                sql += " end;";

                //Debug.Warning("AskForJoinClubMessage:" + sql);

                /*
                 * 0724 帮看下，这里有语法错误，输出日志看下 --over
                 * 
                 * 
                 * */

                return GameDB.Instance.ExceSql(dbbase.game2018, sql, new[]{
                    new SqlParameter("@domanname", clubmsg.domanname),
                    new SqlParameter("@sendname", clubmsg.sendname),
                    new SqlParameter("@content", clubmsg.content),
                    new SqlParameter("@param2", clubmsg.param2 ?? (object)DBNull.Value)
                }) == 1;
            }
            catch (Exception ex)
            {
                throw new Exception("AskForJoinClubMessage: " + sql, ex);
            }
        }

        /// <summary>
        /// 加入竞技比赛数据处理_异步的
        /// </summary>
        /// <param name="club"></param>
        /// <param name="clubPlayer"></param>
        /// <returns></returns>
        public static Task ClubPlayerChange_Asyn(Club_Base club, ClubPlayer clubPlayer)
        {
            return Task.Factory.StartNew(
                () => ClubPlayerChange(club, clubPlayer)
                );
        }

        /// <summary>
        /// 加入竞技比赛数据处理
        /// </summary>
        /// <param name="club"></param>
        /// <param name="clubPlayer"></param>
        public static void ClubPlayerChange(Club_Base club, ClubPlayer clubPlayer)
        {
            //保存竞技比赛数据以及玩家数据
            var spp = GameDB.Instance.BeginTransaction(dbbase.game2018);
            string sql = string.Format("update Top(1) {0} set {1} = {2}, {3}=@mans where {4} = {5};"   //更改竞技比赛
                                       , tb_clubs, fd_manCnt, club.mancnt, fd_mans, fd_id, club.id - idIncrement);

            var ids = ArrayTotr_clubMans(club.mansid);
            byte[] bts = BinaryConvert.StructToBytes(ids);
            List<ISqlAloneParameter<SqlDbType>> sqlpms = new List<ISqlAloneParameter<SqlDbType>>();
            sqlpms.Add(new SqlAloneParameter("@mans", bts, bts.Length));
            GameDB.Instance.TransactionAddSql(spp, sql, sqlpms);

            sql = string.Format("update Top(1) {0} set {1} = @joinclub,{4}=@joinclubnew where {2} = {3};",
                                tb_players, fd_joinclubinfo, fd_userid2018, clubPlayer.userid, fd_joinclubinfodata);

            var clubsinfo = ListPlayerofClubTotr_clubsOfPlayer(clubPlayer.joinClubs);
            bts = BinaryConvert.StructToBytes(clubsinfo);
            var strJoin = JsonPack.GetJson(clubPlayer.joinClubs);
            sqlpms = new List<ISqlAloneParameter<SqlDbType>>();
            sqlpms.Add(new SqlAloneParameter("joinclub", bts, bts.Length));
            sqlpms.Add(new SqlAloneParameter("joinclubnew", strJoin, strJoin.Length, SqlDbType.Text));
            GameDB.Instance.TransactionAddSql(spp, sql, sqlpms);

            if (!GameDB.Instance.SubTransaction(spp))
                throw spp.exception;
        }

        /// <summary>
        /// 保存玩法
        /// </summary>
        /// <param name="clubid"></param>
        /// <param name="ways"></param>
        static void SavePlayWay(int clubid, string ways)
        {
            string sql = string.Format("update Top(1) {0} set {1}={2},{3}=@way where {4}={5};",
                                       tb_clubs, fd_wayVer, Club_Base.allServerVer, fd_newways, fd_id, clubid - idIncrement);

            //List<ISqlAloneParameter<SqlDbType>> sqlpms = new List<ISqlAloneParameter<SqlDbType>>();
            //sqlpms.Add(new SqlAloneParameter("@way", ways, ways.Length, SqlDbType.Text));

            GameDB.Instance.ExceSql(dbbase.game2018, sql, new SqlParameter[] { new SqlParameter("@way", SqlDbType.Text, ways.Length) { Value = ways } });
        }

        /// <summary>
        /// 保存玩法
        /// </summary>
        /// <param name="club"></param>
        public static void SavePlayWay(Club_Base club)
        {
            int clubid = club.id;
            string ways = JsonPack.GetJson(club.ways);

            SavePlayWay(clubid, ways);
        }

        /// <summary>
        /// 保存玩法_异步操作
        /// </summary>
        /// <param name="club"></param>
        public static void SavePlayWayAysn(Club_Base club)
        {
            int clubid = club.id;
            string ways = JsonPack.GetJson(club.ways);

            Task.Factory.StartNew(
                () => SavePlayWay(clubid, ways)
            );
        }
        
        /// <summary>
        /// 分页查询
        /// </summary>
        public static List<FightScore> GetFightScoresByPage(int clubId, DateTime startDateTime, DateTime endDateTime,
            int pageSize, int pageIndex)
        {
            var sqlclubId = clubId - ClubDataManager.idIncrement;
            string subSql = "(SELECT ROW_NUMBER() OVER (ORDER BY id ASC) AS rownumber, * FROM club_FightRecord";
            subSql += $" WHERE clubid={sqlclubId} AND endtime BETWEEN '{startDateTime}' and '{endDateTime}')";
            string sql = $"SELECT TOP {pageSize} * FROM {subSql} AS temp_row WHERE rownumber > {pageSize * pageIndex}";
            Debug.Info($"sql:{sql}");
            return GetFightScoreBySql(sql, sqlclubId);
        }
        
        private static List<FightScore> GetFightScoreBySql(string sql,int clubId=0)
        {
            List<FightScore> fights = new List<FightScore>();
            DataSet ds = new DataSet();
            GameDB.Instance.ExceSql(dbbase.game2018, sql, null, ds);
            if (ds.Tables == null || ds.Tables.Count == 0)
            {
                //没有记录               
                return fights;
            }
            DataTable dt = ds.Tables[0];
            if (dt.Rows != null && dt.Rows.Count > 0)
            {
                int len = dt.Rows.Count;
                for (int i = 0; i < len; i++)
                {
                    fights.Add(GetFightScore(clubId, dt.Rows[i]));
                }
            }
            return fights;
        }

        /// <summary>
        /// 获取某个俱乐部的某个玩法的前多少条战斗记录
        /// </summary>
        /// <param name="clubid">界面显示的俱乐部ID</param>
        /// <param name="wayId">玩法ID</param>
        /// <param name="top">前多少条</param>
        /// <returns></returns>
        public static List<FightScore> GetFightScoreByWayId(int clubid,string wayId,int top = 100)
        {
            var sql = $"select top {top}  * from  club_FightRecord where clubid = {clubid- idIncrement} and wayid='{wayId}'  order by id desc";
             return GetFightScoreBySql(sql);
        }

        /// <summary>
        /// 加载战斗记录
        /// </summary>
        /// <param name="clubid"></param>
        /// <param name="weiyima"></param>
        /// <returns></returns>
        public static FightScore LoadFightScore(int clubid, string weiyima)
        {
            DataTable dt = GameDB.Instance.selectDb(dbbase.game2018, tb_ClubFightRecord, null, string.Format("clubid={0} and weiyima='{1}'", clubid - idIncrement, weiyima));
            if (dt.Rows != null && dt.Rows.Count > 0)
            {
                return GetFightScore(clubid, dt.Rows[0]);
            }
            return null;
        }

        /// <summary>
        /// 根据id获取战绩记录
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static FightScore GetFightScoreById(int id)
        {
            DataTable dt = GameDB.Instance.selectDb(dbbase.game2018, tb_ClubFightRecord, null, string.Format("id={0}", id));
            if (dt.Rows != null && dt.Rows.Count > 0)
            {
                return GetFightScore(-1, dt.Rows[0]);
            }
            return null;
        }

        /// <summary>
        /// 获取战斗记录
        /// </summary>
        /// <param name="row"></param>
        /// <returns></returns>
        public static FightScore GetFightScore(int clubid, DataRow row)
        {
            FightScore fs = new FightScore();
            fs.clubid = clubid > 0 ? clubid : (idIncrement + (int)row["clubid"]);
            fs.id = (int)row[fd_id];
            fs.roomnum = (int)row[fd_roomnum];
            fs.warCnt = (int)row[fd_warcnt];
            fs.wayid = row[fd_wayid].ToString();  //未使用
            fs.game_serid = (int)row[fd_gameserid];
            fs.weiyima = row[fd_weiyima].ToString();
            string json = row[fd_scores].ToString();
            fs.scores = JsonPack.GetData<FightScore.Player[]>(json);
            fs.startTime = DateTime.Parse(row[fd_startTime].ToString());
            fs.endTime = DateTime.Parse(row[fd_endTime].ToString());
            if (row["CardNum"] != DBNull.Value)
            {
                fs.CardNum = (int)row["CardNum"];
            }
            if (row["style"] != DBNull.Value)
            {
                fs.Style = (short)row["style"];
            }
            if (row["disUserId"] != DBNull.Value)
            {
                fs.DisUserId = (int)row["disUserId"];
            }
            //if (row["playclub"] != DBNull.Value)
            //{
            //    string strp = row["playclub"].ToString();
            //    if (!string.IsNullOrEmpty(strp) && strp.Length > 2)
            //    {
            //        if (strp.IndexOf("Name") >= 0)
            //        {
            //            fs.PlayInClubInfo = JsonPack.GetData<Dictionary<int, IdName>>(strp);
            //        }
            //        else
            //        {
            //            fs.PlayInClub = JsonPack.GetData<Dictionary<int, int>>(strp);
            //        }
            //    }
            //}
            return fs;
        }

        static string GetHidesKey(int clubid)
        {
            return $"HidesWay:{clubid}";
        }
        
        /// <summary>
        /// 保存俱乐部隐藏玩法
        /// </summary>
        /// <param name="clubId"></param>
        /// <param name="list"></param>
        public static void SaveHideWays(int clubId, List<string> list,bool isSync = false)
        {
            if (clubId <= 0 || list == null) return;
            var key = GetHidesKey(clubId);
            var str = JsonPack.GetJson(list);
            
            Debug.Info($"保存隐藏:{clubId}{str}");
            if (isSync)
            {
                redisManager.GetBiSaidb(6).StringSetAsync(key, str);
            }
            else
            {
                redisManager.GetBiSaidb(6).StringSet(key, str);
            }
        }

        /// <summary>
        /// 删除隐藏玩法
        /// </summary>
        public static void RemoveHideWays(int clubId)
        {
            var key = GetHidesKey(clubId);
            redisManager.GetBiSaidb(6).KeyDelete(key);
        }

        public static Task<List<string>> GetHidesAsync(int clubId)
        {
            return Task.Run(() => GetHides(clubId));
        }

        /// <summary>
        /// 读取俱乐部隐藏玩法
        /// </summary>
        /// <param name="clubid"></param>
        /// <returns></returns>
        public static List<string> GetHides(int clubid)
        {
            if (clubid <= 0) return new List<string>();
            var key = GetHidesKey(clubid);
            string str = redisManager.GetBiSaidb(6).StringGet(key);
            if (!string.IsNullOrWhiteSpace(str) && str.Length > 2)
            {
                Debug.Info($"读取隐藏:{clubid}{str}");
                return JsonPack.GetData<List<string>>(str);
            }
            else
            {
                return new List<string>();
            }
        }

        static string GetPlayerHideWayKey(int clubId)
        {
            return $"GetPlayerHideWayKey:{clubId}";
        }

        /// <summary>
        /// 保存玩家不能玩哪些玩法
        /// </summary>
        /// <param name="clubId"></param>
        /// <param name="data"></param>
        public static void SavePlayerHideWay(int clubId, Dictionary<int, List<string>> data)
        {
            if (clubId <= 0 || data == null) return;
            var key = GetPlayerHideWayKey(clubId);
            var str = JsonPack.GetJson(data);
            redisManager.GetBiSaidb(6).StringSet(key, str);
        }

        /// <summary>
        /// 获取玩家不能玩哪些玩法
        /// </summary>
        /// <param name="clubId"></param>
        /// <returns></returns>
        public static Dictionary<int, List<string>> GetPlayerHideWay(int clubId)
        {
            if (clubId <= 0) return new Dictionary<int, List<string>>();
            var key = GetPlayerHideWayKey(clubId);
            string str = redisManager.GetBiSaidb(6).StringGet(key);
            if (!string.IsNullOrWhiteSpace(str) && str.Length > 2)
            {
                return JsonPack.GetData<Dictionary<int, List<string>>>(str);
            }
            else
            {
                return new Dictionary<int, List<string>>();
            }
        }

        static string GetClubFightRecordKey()
        {
            return "GetClubFightRecordKey";
        }

        /// <summary>
        /// 游戏报错战斗结束数据到reids，俱乐部服务器去redis里面去拿
        /// </summary>
        /// <param name="jsonData"></param>
        /// <returns>true保存成功 false保存失败</returns>
        public static bool SaveClubFightRecord(string jsonData)
        {
            if (string.IsNullOrWhiteSpace(jsonData)) return true;
            try
            {
                redisManager.Getdb(9).ListRightPush(GetClubFightRecordKey(), jsonData); //从尾部添加
            }
            catch (Exception e)
            {
                Debug.Error($"保存战绩数据失败，msg:{e.Message},code:{e.StackTrace}");
                return false;
            }
            return true;
        }

        public static string GetOneClubFightRecord()
        {
            return redisManager.Getdb(9).ListLeftPop(GetClubFightRecordKey()); //从头部取
        }
    }
}
