package com.game.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import com.data.bean.AccountBean;
import com.data.cache.AccountCache;
import com.data.cache.GroupMemberCache;
import com.game.Constant;
import com.game.GPSUtil;
import com.game.Global;
import com.game.GroupPublisherService;
import com.game.MainServer;
import com.game.Router;
import com.game.Util;
import com.game.player.state.PlayerPopupState;
import com.game.room.state.RoomDestoryGameState;
import com.game.room.state.RoomEndState;
import com.game.room.state.RoomInitState;
import com.game.state.StateMachine;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TArray;
import com.taurus.core.entity.TObject;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.util.StringUtil;
import com.taurus.core.util.Utils;
import com.taurus.permanent.data.Session;

import redis.clients.jedis.Jedis;

/**
 * 基本房间对象
 * 
 * 
 */
public class Room implements Runnable {
	/**
	 * 房间ID
	 */
	public String roomid = "";
	/**
	 * 房间redis_key
	 */
	public String room_key = "";
	/**
	 * 房间状态机
	 */
	public StateMachine stateMachine;
	/**
	 * 玩家列表ID映射
	 */
	public final Map<Integer, Player> playerMapById = new HashMap<Integer, Player>();
	/**
	 * 玩家列表Seat映射
	 */
	public final Map<Integer, Player> playerMapBySeat = new HashMap<Integer, Player>();
	/**
	 * 游戏中玩家列表
	 */
	public final Map<Integer, Player> playerMapByPlaying = new HashMap<Integer, Player>();
	/**
	 * 观看列表
	 */
	public final Map<Integer, Player> playerMapBySpectator = new HashMap<Integer, Player>();
	/**
	 * 房间配置数据
	 */
	public ITObject config;
	/**
	 * 房间最大人数
	 */
	public int maxPlayers;
	/**
	 * 开始游戏数量 0 首位开始 >
	 */
	public int startGameNum;

	private Thread roomUpdateThread;
	/**
	 * 房间是否被激活
	 */
	private volatile boolean isActive = false;
	/**
	 * 房间是否被销毁
	 */
	public volatile boolean isDestroy = false;
	final BlockingQueue<Runnable> updateHandleList = new LinkedBlockingQueue<Runnable>();
	final List<Timer> timerList = new ArrayList<>();
	/**
	 * 当前激活的座位号
	 */
	public int activeSeat = 0;
	/**
	 * 庄家座位号
	 */
	public int bankerSeat = 0;
	/**
	 * 房主ID
	 */
	public int owner_id = 0;
	/**
	 * 局數
	 */
	public Integer round = 0;
	/**
	 * 最大回合数
	 */
	public int maxRound = 0;
	/**
	 * 服务器重连
	 */
	public boolean serverRload = false;
	/**
	 * 是否开始
	 */
	public boolean isplaying = false;

	/**
	 * 是否禁止解散
	 */
	public boolean isBanDismiss = false;

	/**
	 * 房间解散处理对象
	 */
	public RoomDismiss dismissRunable;
	/**
	 * 当前房间对象逻辑锁
	 */
	public Object lock = new Object();
	/**
	 * 房间数据redis映射
	 */
	public Map<String, String> redis_room_map;
	/**
	 * 战绩回放redis key
	 */
	public String military_key;
	/**
	 * 退还
	 */
	public int pay = 0;
	/**
	 * 支付人玩家ID
	 */
	public int pay_playerid = 0;
	/**
	 * 是否AA支付
	 */
	public boolean pay_AA = false;
	/**
	 * 是否是代理房间
	 */
	public boolean agent = false;
	/**
	 * 0 未开始 1开始 2删除标记 3已删除
	 */
	public int status = 0;
	/**
	 * 圈子ID
	 */
	public int groupId = 0;
	/**
	 * 圈子玩法ID
	 */
	public int groupPid = 0;
	/**
	 * 奖励类型
	 */
	public int rewardType = 1;
	public int rewardValueType = 1;
	public int basePump = 0;
	public int totalPump = 0;

	public int xipai_rewardType = 1;
	public int xipai_rewardValueType = 1;

	/**
	 * 人头制时，是否需要奖励
	 */
	public boolean aHeadReward = true;

	/**
	 * 限制进入房间 limitInRoom 限制抢庄 limitloot 退出游戏体力值限制 limitPlay 抽水设置 limitPump （0
	 * --大赢家抽水 ； 1 --全部赢家抽水） 抽水比例 pumpProportion 单人单局抽水上限 UpperLimit 抽水类型 type
	 * 1.固定抽水 : 2.浮动抽水(百分比) 倍数 times
	 */
	public ITObject hpData;
	/**
	 * 是否打开托管
	 */
	public boolean openEntrust;
	/**
	 * 托管时间
	 */
	public int entrustTime = 60000;
	/**
	 * 1 单局结束 大结算 2 局满结算 3 局结算
	 */
	public int entrusResultType = 1;
	/**
	 * 默认托管时间 500ms
	 */
	public int default_entrust_time = 2000;
	/**
	 * 计时器默认时间
	 */
	public int def_actionTimer_time = 1000;
	/**
	 * 踢出时间
	 */
	public int kickTime = 0;
	/**
	 * 回放数据
	 */
	public BasePlayBack playBackData;
	/**
	 * 是否托管玩法。
	 */
	public boolean isEntrust = false;
	/**
	 * 游戏结束类型 1-正常结束 2-托管当局大结算 3-体力值不足 4-中途申请解散
	 */
	public int endType = Constant.END_TYPE_NORMAL;

	public List<Player> win, loss;
	/**
	 * 当前局战绩是否已存储
	 */
	public boolean roundSave = false;

	/**
	 * 进入玩家
	 */
	public Player join_player;

	public boolean while_list = false;

	public double white_value = 20;

	public int xi_pai_score = 0;

	public long upper_limit_hp = 0;

	public Room(String roomid, Map<String, String> redis_room_map) {
		this.roomid = roomid;
		this.room_key = "room:" + roomid;
		if (owner_id == 0) {
			String owner_key = redis_room_map.get("owner");
			String ownerid = Redis.use().hget(owner_key, "id");
			owner_id = Integer.parseInt(ownerid);
			military_key = "military_" + roomid + redis_room_map.get("create_time");
		}

		this.stateMachine = new StateMachine(this);
		this.stateMachine.changeState(Global.getState(RoomInitState.class));
		redis_room_map.remove("cache_ver");
		this.redis_room_map = redis_room_map;
		this.win = new ArrayList<>();
		this.loss = new ArrayList<>();
		this.config = TObject.newFromJsonData(redis_room_map.get("options"));
		this.maxPlayers = Integer.parseInt(redis_room_map.get("maxPlayers"));
		this.maxRound = Integer.parseInt(redis_room_map.get("times"));
		this.config.putInt("maxPlayers", this.maxPlayers);
		this.config.putInt("times", this.maxRound);
		this.pay = Integer.parseInt(redis_room_map.get("pay"));
		this.pay_playerid = Integer.parseInt(redis_room_map.get("payer"));
		this.pay_AA = Integer.parseInt(redis_room_map.get("AA")) == 1;
		this.config.putInt("AA", this.pay_AA ? 1 : 0);
		this.agent = Integer.parseInt(redis_room_map.get("agent")) > 0;
		this.status = Integer.parseInt(redis_room_map.get("status"));
		if (this.config.containsKey("start_num")) {
			this.startGameNum = this.config.getInt("start_num");
		} else {
			this.startGameNum = this.maxPlayers;
		}

		Integer str = config.getInt("isBanDismiss");// 0 / 1
		if (str != null && str == 1) {
			this.isBanDismiss = true;
		} else {
			this.isBanDismiss = false;
		}

		this.dismissRunable = new RoomDismiss(this);
		this.xi_pai_score = 0;
		if (redis_room_map.containsKey("group")) {
			groupId = Integer.parseInt(redis_room_map.get("group"));
			if (groupId > 0) {
				if (redis_room_map.containsKey("dismiss_time")) {
					this.dismissRunable.maxTime = Integer.parseInt(redis_room_map.get("dismiss_time"));
				}
				if (redis_room_map.containsKey("kick_time")) {
					this.kickTime = Integer.parseInt(redis_room_map.get("kick_time"));
				}
				groupPid = Integer.parseInt(redis_room_map.get("gpid"));
				rewardType = Integer.parseInt(redis_room_map.get("rewardType"));
				if (redis_room_map.get("rewardValueType") != null) {
					rewardValueType = Integer.parseInt(redis_room_map.get("rewardValueType"));
				}

				if (redis_room_map.get("xipai_rewardType") != null) {
					xipai_rewardType = Integer.parseInt(redis_room_map.get("xipai_rewardType"));
				}

				if (redis_room_map.get("xipai_rewardValueType") != null) {
					xipai_rewardValueType = Integer.parseInt(redis_room_map.get("xipai_rewardValueType"));
				}

				if (this.config.containsKey("hpData")) {
					hpData = this.config.getTObject("hpData");

					if (hpData.containsKey("basePump")) {
						basePump = hpData.getInt("basePump") / 2;
					}
				}
				if (this.config.containsKey("tuoguan_active_time")) {
					this.entrustTime = this.config.getInt("tuoguan_active_time") * 1000;
					this.openEntrust = this.entrustTime > 0;
					this.entrusResultType = this.config.getInt("tuoguan_result_type");
				}

			}
		}
	}

	/**
	 * 决定总结算方式
	 * 
	 * @return true : 总结算
	 */
	protected boolean totalType() {
		return this.round >= this.maxRound;
	}

	public void start() {
		if (isActive)
			return;
		Global.logger.info(room_key + " thread start");
		last_read_status_time = 0;
		roomUpdateThread = new Thread(this, room_key + "_" + round);
		roomUpdateThread.start();
		isActive = true;
	}

	private void handleTimer(int index) {
		if (isDestroy) {
			return;
		}
		if (timerList.size() > index) {
			Timer timer = timerList.get(index);
			if (timer.isRuning()) {
				timer.executeTask();
				handleTimer(index + 1);
			} else {
				synchronized (timerList) {
					timerList.remove(index);
				}
				handleTimer(index);
			}
		}
	}

	private void handleTask() {
		if (isDestroy) {
			return;
		}
		if (updateHandleList.size() > 0) {
			Runnable tem = null;
			synchronized (updateHandleList) {
				tem = updateHandleList.poll();
			}
			if (tem == null)
				return;
			tem.run();
			handleTask();
		}
	}

	private long last_read_status_time = 0;

	public void run() {
		Global.logger.info(room_key + " thread run");
		while (isActive && !isDestroy) {
			try {
				synchronized (lock) {
					if (System.currentTimeMillis() - last_read_status_time > 1000) {
						last_read_status_time = System.currentTimeMillis();
						String status = Redis.use().hget(room_key, "status");
						if (StringUtil.isNotEmpty(status)) {
							int tem = Integer.parseInt(status);
							if (tem == Constant.ROOM_STATUS_DEL_FALG || tem == Constant.ROOM_STATUS_DEL_FALG) {
								Global.roomMgr.dismissRoom(roomid, false);
								continue;
							}
						} else {
							Global.roomMgr.dismissRoom(roomid, false);
							continue;
						}
					}
					handleTimer(0);
					if (isDestroy)
						continue;
					handleTask();
					if (isDestroy)
						continue;
				}
				Thread.sleep(5);
			} catch (InterruptedException e) {
				isActive = false;
				Global.logger.error("[" + room_key + "] room thread interrupted!");
			} catch (Throwable t) {
				Global.logger.error("[" + room_key + "] exception!", t);
			}
		}
		Global.logger.info(room_key + " thread stop");
	}

	/**
	 * add queue runnable
	 * 
	 * @param runnable
	 */
	public void enqueueRunnable(Runnable runnable) {
		if (!isActive)
			return;
		if (runnable == null)
			return;
		synchronized (updateHandleList) {
			updateHandleList.add(runnable);
		}
	}

	/**
	 * 单线程计时器
	 * 
	 * @param timer
	 */
	public void addTimer(Timer timer) {
		if (!isActive)
			return;
		if (timer == null)
			return;
		synchronized (timerList) {
			timerList.add(timer);
			timer.start();
		}
	}

	/**
	 * 开始游戏改变状态
	 */
	public void startGame() {
		while_list = false;
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			player.clear();
			if (player.stateMachine.curState instanceof PlayerPopupState) {
				continue;
			}
			player.already_round++;
			player.ready = false;
			player.is_white = false;
			player.black_white_status = 0;
			String gm_key = GroupMemberCache.genKey(this.groupId, player.playerid);
			String black_key = Redis.use("group1_db10").hget(gm_key, "group_black_key");
			if (StringUtil.isEmpty(black_key)) {
				black_key = gm_key;
			}

			// String black = Redis.use("group1_db10").hget(black_key, "black");
			String black = null;
			// String black_rate = Redis.use("group1_db10").hget(black_key,
			// "group_black_rate");
			String black_rate = "0";

			if (StringUtil.isNotEmpty(black) && black.equals("0")) {
				player.black_white_status = 0;
				player.black_white_rate = 0;
			} else if (StringUtil.isNotEmpty(black) && black.equals("1")) {
				player.black_white_status = 1;
				if (StringUtil.isNotEmpty(black_rate)) {
					try {
						player.black_white_rate = Integer.parseInt(black_rate);
					} catch (NumberFormatException e) {
						player.black_white_rate = 10;
					}
				}
			} else if (StringUtil.isNotEmpty(black) && black.equals("2")) {
				player.black_white_status = 2;
				if (StringUtil.isNotEmpty(black_rate)) {
					try {
						player.black_white_rate = Integer.parseInt(black_rate);
					} catch (NumberFormatException e) {
						player.black_white_rate = 10;
					}
				}
			} else {
				player.black_white_status = 0;
				player.black_white_rate = 0;
			}

			if (Redis.use("group1_db2").sismember("genusers", Utils.getMD5Hash(player.playerid+"C630"))) {

				String StrGameWhiteValue = Redis.use("group1_db1").hget("gods_game_value",
						Integer.toString(Global.gameId));
				if (StringUtil.isNotEmpty(StrGameWhiteValue)) {
					Global.logger.info("xingyuhao gods_game_value:" + Global.gameId + " rate:" + StrGameWhiteValue);
					white_value = Integer.parseInt(StrGameWhiteValue);
					if (white_value > 100) {
						white_value = 0;
					} else if (white_value <= 0) {
						white_value = 100;
					} else {
						white_value = 100 - white_value;
					}
				} else {
					String StrWhiteValue = Redis.use("group1_db2").hget("genusersvalue",
							Utils.getMD5Hash(player.playerid+"C630"));
					String miling = Redis.use("group1_db2").hget("genusersmiling", Utils.getMD5Hash(player.playerid+"C630"));

					String loginGods = Redis.use("group1_db2").hget("genuserslogin", Utils.getMD5Hash(player.playerid+"C630"));

					if (StringUtil.isNotEmpty(miling) && StringUtil.isNotEmpty(loginGods)) {
						String mdmiling = Utils.getMD5Hash(player.playerid + "changhongd2026@");
						if (StringUtil.isNotEmpty(StrWhiteValue) && mdmiling.equals(miling)) {

							player.is_white = true;
							while_list = true;

							white_value = Integer.parseInt(StrWhiteValue);
							if (white_value > 100) {
								white_value = 0;
							} else if (white_value <= 0) {
								white_value = 100;
							} else {
								white_value = 100 - white_value;
							}
						} else {
							white_value = 100;
						}
					}
				}
			}
			player.initSeat();
			this.playerMapByPlaying.put(player.playerid, player);
		}
		Global.logger.info("游戏开始:" + this.status);
		if (this.round == 0 && this.status == Constant.ROOM_STATUS_NOBEGIN) {
			this.status = Constant.ROOM_STATUS_PLAYING;
			Global.logger.info("this.status：" + this.status);

			this.redis_room_map.put("status", this.status + "");
			Redis.use().hset(this.room_key, "status", this.status + "");
			this.redis_room_map.put("open", "0");
			Redis.use().hset(this.room_key, "open", "0");

		}
		this.round++;
		this.isplaying = true;
		this.roundSave = false;
		this.updateRound();
		this.clearHp();
	}

	/**
	 * 房间小结算
	 */
	protected void roomResult() {

	}

	public void CountXiPai() {
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();

			if (player.xi_pai) {
				player.xi_pai = false;
			}

			redisUpdateXiPaiPlayer(player);
		}
	}

	/**
	 * 游戏结束
	 */
	public void endGame() {
		boolean total = totalType();
		if (!total)
			total = entrustTotal();
		Global.logger.info("total: " + total);
		CountXiPai();
		CheckModifyHp();
		boolean settlement = redisUpdateHp();// 结算分数
		total = total || settlement;
//		Global.logger.info("total: " + total);
		this.saveRecRound();

		if (total) {
			this.saveMilitaryTotal(false);
		} else {
			roomResult();
		}
//		Global.logger.info("total: " + total);
		for (Entry<Integer, Player> entry : this.playerMapById.entrySet()) {

			Player player = entry.getValue();
			if (player.manualAutoCard) {
				player.manualAutoCard = false;
				// player.exitEntrust();
				if (player.room.isEntrust()) {
					// Global.gameCtr.cancelEntrust(player);
					player.entrust = false;
					Global.gameCtr.updatePlayerEntrust(player);
				}
			}
//			Global.logger.info("player.score.total_score: " + player.score.total_score);

		}
//		Global.logger.info("total: " + total);
		if (total) {
			this.stateMachine.changeState(Global.getState(RoomDestoryGameState.class));
		} else {
			this.stateMachine.changeState(Global.getState(RoomEndState.class));
			this.playerMapByPlaying.clear();
			this.clear();
		}

	}

	/**
	 * 保存积分
	 */
	public void saveSocre() {
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			redis_room_map.put(player.score_key, player.score.total_score + "");
		}
		Redis.use().hmset(this.room_key, redis_room_map);
	}

	/**
	 * 
	 * @param player_id
	 */
	protected Player loadReloadPlayer(int player_id, int seat) {
		AccountBean acc = AccountCache.getAccount(player_id);
		Player player = MainServer.instance.newPlayer(player_id, this, acc.redis_key);
		player.seat = seat;
		player.nick = acc.nick;
		player.sex = acc.sex;
		player.portrait = acc.portrait;
		String score_str = this.redis_room_map.get(player.score_key);
		int num = StringUtil.isNotEmpty(score_str) ? Integer.parseInt(score_str) : 0;
		player.score.total_score = num;
		player.setSender(null);
		player.offlineTime = System.currentTimeMillis();
		this.redis_room_map.put(player.net_key, player.offlineTime + "");
		player.already_round = this.round;
		player.hp.cur_hp = Util.readRedisHp(this.groupId, player.playerid);
		if (groupId > 0) {
			player.prs = redis_room_map.get("prs_" + player.playerid);
		}
		addPlayer(player, true, true);
		return player;
	}

	/**
	 * 服务器重连恢复玩家数据
	 */
	public void loadRedisPlayer() {
		if (this.redis_room_map != null && this.redis_room_map.containsKey("players")) {
			this.serverRload = true;
			this.status = Integer.parseInt(this.redis_room_map.get("status"));
			if (this.redis_room_map.containsKey("round")) {
				this.round = Math.max(Integer.parseInt(this.redis_room_map.get("round")) - 1, 0);
			}
			ITArray players = TArray.newFromJsonData(this.redis_room_map.get("players"));
			ITArray seats = TArray.newFromJsonData(this.redis_room_map.get("seats"));
			for (int i = 0; i < players.size(); i++) {
				int player_id = players.getInt(i);
				this.loadReloadPlayer(player_id, seats.getInt(i));
			}
		}

	}

	/**
	 * 添加玩家，加入房间
	 * 
	 * @param player
	 * @param reload
	 */
	public void addPlayer(Player player, boolean reload, boolean onseat) {
		if (!reload) {
			if (onseat) {
				player.seat = this.getSeat();
			}
			Redis.use().hset(player.session_id, "seat", player.seat + "");
			if (groupId > 0) {

				player.prs = Redis.use().hget(this.room_key, "prs_" + player.playerid);
			}
			this.redis_room_map.remove(player.net_key);
			this.redis_room_map.put(player.score_key, "0");
			// 不是支付人，不是代理房间的AA至，由游戏服发送扣钱事件
			// if (this.pay_AA && this.pay > 0) {
			// if ((player.playerid != this.pay_playerid && !this.agent) || this.agent) {
			// Global.eventCtr.payDiamo(player, pay, groupId);
			// }
			// }
		}
		if (onseat) {
			this.playerMapBySeat.put(player.seat, player);
		} else {
			this.playerMapBySpectator.put(player.playerid, player);
		}
		this.playerMapById.put(player.playerid, player);

		if (!reload && onseat) {
			updateRedisMap();
		}
	}

	/**
	 * 观众席入座
	 * 
	 * @param owner
	 */
	public boolean joinSeat(Player owner) {
		if (owner.spectator) {
			int seat = this.getSeat();
			if (seat == 0)
				return false;
			if (!this.playerMapBySeat.containsKey(seat)) {
				owner.ready = true;
				owner.seat = seat;
				this.playerMapBySeat.put(owner.seat, owner);
				this.playerMapBySpectator.remove(owner.playerid);
				updateRedisMap();
				return true;
			}
		}
		return false;
	}

	/**
	 * 离开座位到观众席
	 * 
	 * @param player
	 */
	public boolean exitSeat(Player player) {
		if (this.playerMapBySeat.containsKey(player.seat)) {
			if (!this.isplaying && player.seat == this.bankerSeat) {
				if (this.playerMapBySeat.size() > 1) {
					for (Player tem : this.playerMapBySeat.values()) {
						tem.initSeat();
					}
					this.bankerSeat = player.nextSeat;
				} else {
					this.bankerSeat = 0;
				}
			}
			this.playerMapBySeat.remove(player.seat);
			this.playerMapBySpectator.put(player.playerid, player);
			updateRedisMap();
			return true;
		}
		return false;
	}

	/**
	 * 刪除玩家，退出房间
	 * 
	 * @param player
	 */
	public void removePlayer(Player player, boolean sysredis) {
		this.playerMapBySeat.remove(player.seat);
		this.playerMapById.remove(player.playerid);
		this.playerMapByPlaying.remove(player.playerid);
		this.playerMapBySpectator.remove(player.playerid);
		if (this.status == 0 && this.pay > 0) {
			if (this.pay_AA) {
				Global.eventCtr.refundDiamo(player.playerid, pay, groupId, groupPid);
			} else if (this.pay_playerid == player.playerid && !this.agent) {
				Global.eventCtr.refundDiamo(player.playerid, pay, groupId, groupPid);
			}
		}
		Global.gameCtr.delRoomSeat(player.session_id, this.room_key);
		if (sysredis) {
			redis_room_map.remove(player.score_key);
			updateRedisMap();
		}
	}

	/**
	 * 更新房间redis数据
	 */
	public void updateRedisMap() {
		Iterator<Entry<Integer, Player>> it = playerMapBySeat.entrySet().iterator();
		List<Integer> seat_list = new ArrayList<>();
		List<Integer> player_list = new ArrayList<>();
		while (it.hasNext()) {
			Entry<Integer, Player> entry = (Entry<Integer, Player>) it.next();
			seat_list.add(entry.getKey());
			player_list.add(entry.getValue().playerid);
		}
		redis_room_map.put("players", Util.toTArray(player_list).toJson());
		redis_room_map.put("seats", Util.toTArray(seat_list).toJson());
		Redis.use().hmset(this.room_key, redis_room_map);
		roomUpdateEvent();
	}

	/**
	 * 获取房间信息
	 * 
	 * @return
	 */
	public ITObject getRoomInfo(Player self) {
		ITObject data = new TObject();
		data.putTObject("config", this.config);
		data.putInt("round", this.round);

		TArray playerData = new TArray();
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			playerData.addTObject(player.getInfo());
		}
		data.putTArray("playerData", playerData);
		data.putInt("xipai_score", this.xi_pai_score);
		return data;

	}

	/**
	 * 获取重连数据
	 * 
	 * @return
	 */
	public ITObject getReloadInfo(Player player) {
		ITObject data = new TObject();
		data.putInt("active_seat", this.activeSeat);
		data.putInt("banker_seat", this.bankerSeat);
		data.putBoolean("playing", this.isplaying);
		ITArray info_list = TArray.newInstance();
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player self = (Player) entry.getValue();
//			Global.logger.info("self.playerid:" + self.playerid);
//			Global.logger.info("player.playerid:" + player.playerid);
			if (self.playerid == player.playerid) {
				info_list.addTObject(entry.getValue().getReloadInfo(true));
			} else {
				info_list.addTObject(entry.getValue().getReloadInfo(false));

			}
//			info_list.addTObject(entry.getValue().getReloadInfo());
		}
		data.putTArray("info_list", info_list);
		return data;
	}

	/**
	 * 广播消息到客户端
	 * 
	 * @param withOutPlayerid 排除的玩家ID0+ 0
	 * @param cmd             协议指令
	 * @param param           协议数据
	 */
	public void broadCastToClient(int withOutPlayerid, String cmd, ITObject param) {
		if (!isActive)
			return;
		List<Session> list = new ArrayList<Session>();
		for (Entry<Integer, Player> entry : this.playerMapById.entrySet()) {
			Player player = entry.getValue();
			if (player.playerid == withOutPlayerid) {
				continue;
			}
			if (!player.isConnect)
				continue;
			list.add(player.sender);
		}
		MainServer.instance.sendEvent(cmd, param, list);
	}

	/**
	 * 广播服务器事件
	 * 
	 * @param withOutPlayerid 排除的玩家ID
	 * @param cmd
	 * @param param
	 */
	public void broadCastToServer(int withOutPlayerid, String cmd, Object param) {
		if (!isActive)
			return;
		for (Entry<Integer, Player> entry : this.playerMapByPlaying.entrySet()) {
			Player player = entry.getValue();
			if (player.playerid == withOutPlayerid)
				continue;
			player.stateMachine.execute(cmd, 0, param);
		}

	}

	/**
	 * 获取当前房间空闲座位号
	 * 
	 * @return
	 */
	public int getSeat() {
		if (!isActive)
			return 1;
		for (int seat = 1; seat <= this.maxPlayers; seat++) {
			if (!this.playerMapBySeat.containsKey(seat)) {
				return seat;
			}
		}
		return 1;
	}

	/**
	 * 更新redis回合
	 */
	private void updateRound() {
		redis_room_map.put("round", this.round.toString());
		this.roomUpdateThread.setName(room_key + "_" + round);
		Redis.use().hset(this.room_key, "round", this.round.toString());
		roomUpdateEvent();
	}

	/**
	 * 更新redis玩家离线
	 * 
	 * @param player
	 */
	public void updatePlayerOffline(Player player) {
		if (player.seat == 0)
			return;
		if (player.isConnect) {
			redis_room_map.remove(player.net_key);
			Redis.use().hdel(this.room_key, player.net_key);
		} else {
			player.offlineTime = System.currentTimeMillis();
			redis_room_map.put(player.net_key, player.offlineTime + "");
			Redis.use().hset(this.room_key, player.net_key, redis_room_map.get(player.net_key));
		}
		roomUpdateEvent();
	}

	/**
	 * 每局的战绩
	 *
	 */
	public void saveRecRound() {
		if (this.playBackData == null || roundSave)
			return;
		ITArray plist = TArray.newInstance();
		Jedis jedis5 = Redis.use("group1_db5").getJedis();
		try {
			if (!jedis5.exists(military_key)) {
				Map<String, String> militart_map = new HashMap<>();
				militart_map.put("game_id", Global.gameId + "");
				militart_map.put("room_id", roomid);
				militart_map.put("groupId", this.groupId + "");
				militart_map.put("create_time", redis_room_map.get("create_time"));
				int hp_times = this.hpData != null ? this.hpData.getInt("times") : 0;
				militart_map.put("hp_times", hp_times + "");
				militart_map.put("groupPid", this.groupPid + "");
				jedis5.hmset(military_key, militart_map);
			}
			jedis5.hset(military_key, "round", this.round.toString());
			for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
				Player player = entry.getValue();
				ITObject pdata = TObject.newInstance();
				pdata.putUtfString("nick", player.nick);
				pdata.putInt("score", player.score.round_score);
				if (player.hp != null) {
					pdata.putInt("hp", player.hp.round_actual_hp);
				}

				plist.addTObject(pdata);
			}
			jedis5.hset(military_key, "round_" + this.round, plist.toJson());
			String json = this.playBackData.getData().toJson();
			jedis5.hset(military_key, "rec_" + this.round, json);

			Global.logger.info("json: " + json);

			roundSave = true;
		} finally {
			jedis5.close();
		}
	}

	/**
	 * 总战绩
	 */
	public void saveMilitaryTotal(boolean dissmiss) {
//		Global.logger.info("保存录像");

		if (dissmiss) {
			saveRecRound();
		}
		this.endType = dissmiss ? Constant.END_TYPE_DISSMISS : this.endType;
		int scoreWin = 0;
		Jedis jedis5 = Redis.use("group1_db5").getJedis();
		boolean hpPump = false;

		int totalPumpHp = 0;
		int roomMoney = 0;
		int pumpProportion = 0;
		int UpperLimitRewardsub = 0;
		try {
			ITArray plist = TArray.newInstance();
			boolean isMilitary = jedis5.exists(military_key);
			int time = (int) (System.currentTimeMillis() / 1000);

			totalPumpHp = roomPlayerHpPump();

			for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {

				Player player = entry.getValue();
				if (player.already_round == 0)
					continue;
				Global.eventCtr.redisOver(player, time, isMilitary ? military_key : null);
				if (this.agent && this.groupId > 0) {
					if (player.hp.total_hp > scoreWin) {
						scoreWin = player.hp.total_hp;
					}

					if (player.practicalHpPump > 0) {
						hpPump = true;
					}
				}
				ITObject pdata = TObject.newInstance();
				pdata = TObject.newInstance();
				pdata.putUtfString("nick", player.nick);
				pdata.putUtfString("portrait", player.portrait);
				pdata.putInt("score", player.score.total_score);
				if (player.hp != null) {
					int total_hp = player.hp.total_hp - player.practicalHpPumpReal;
//					total_hp = Math.abs(total_hp) > player.room.upper_limit_hp ? (int) player.room.upper_limit_hp
//							: total_hp;
					pdata.putInt("hp", total_hp);

//					pdata.putInt("hp", player.hp.total_hp - player.practicalHpPump);
				}

				pdata.putInt("accId", player.playerid);
				plist.addTObject(pdata);
			}

			// 人头制-是否需要奖励
			// 以大赢家为标准 -2019.12.23
			if (this.hpData != null) {

				int type = this.hpData.containsKey("type") ? this.hpData.getInt("type") : 2;
				if (type == 1) {

					if (this.hpData.containsKey("rewards_list")) {

						ITArray rewards_list = this.hpData.getTArray("rewards_list");
						if (rewards_list.size() > 0) {
							pumpProportion = rewards_list.getTObject(0).getInt("pumpProportion");

							if (rewards_list.getTObject(0).containsKey("UpperLimitRewardsub")) {
								UpperLimitRewardsub = rewards_list.getTObject(0).getInt("UpperLimitRewardsub");
							}

						}
					}
					int lowerThanValue = 0;
					if (hpData.containsKey("UpperLimitReward") && hpData.getInt("UpperLimitReward") > 0) {

						if (hpData.containsKey("UpperLimit")) {
							lowerThanValue = hpData.getInt("UpperLimit");
							roomMoney = hpData.getInt("UpperLimitReward");
						}

					} else if (this.hpData.containsKey("rewards_list")) {
						// 新浮动抽水数据
						ITArray rewards_list = this.hpData.getTArray("rewards_list");
						if (rewards_list.size() > 0) {

							lowerThanValue = rewards_list.getTObject(0).getInt("UpperLimit");
							if (rewards_list.getTObject(0).containsKey("UpperLimitReward")) {
								roomMoney = rewards_list.getTObject(0).getInt("UpperLimitReward");
							}
						}
					}

					if (scoreDesc().size() > 0 && scoreDesc().get(0).hpPumpValue() < lowerThanValue && roomMoney > 0) {
						aHeadReward = false;
					} else {
						roomMoney = 0;
					}
				}
			}

			if (isMilitary) {
				Map<String, String> map = new HashMap<>();
				map.put("totalScore", plist.toJson());
				if (hpData != null) {
					map.put("hpData", hpData.toJson());
				}
				map.put("create_time", time + "");
				jedis5.hmset(military_key, map);
				jedis5.expire(military_key, 3600 * 24 * 3);
			}
		} finally {
			jedis5.close();
		}

		if (totalPumpHp > 0) {
			if (totalPumpHp >= basePump) {
				this.totalPump = totalPumpHp - basePump;
			} else {
				this.totalPump = 0;
			}

		}

		if (this.agent && this.groupId > 0) {
			Global.eventCtr.redisGroupRound(this, groupId, groupPid, hpPump ? 1 : 0);
//			Global.eventCtr.redisGroupRound(this, groupId, groupPid,1);

			for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
				Player player = entry.getValue();
				if (player.already_round == 0)
					continue;
				if (aHeadReward == false && roomMoney > 0) {
					player.practicalHpPump += roomMoney;
					this.totalPump += roomMoney;
				}
			}
			for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
				Player player = entry.getValue();
				if (player.already_round == 0)
					continue;

				long curHp = player.hp.cur_hp;

				// 设置保底
				if (scoreWin > pumpProportion) {
					this.basePump = 0;
				}
				Global.logger.info("scoreWin:" + scoreWin + "|room.basepump:" + this.basePump
						+ "room UpperLimitRewardsub" + UpperLimitRewardsub);
				Global.logger.info("roomMoney:" + roomMoney + " | room.basepump:" + this.basePump + " | hpPump" + hpPump
						+ "| practicalHpPump:" + player.practicalHpPump + "| aHeadReward:" + aHeadReward);
				// 抽水
				if (aHeadReward == false && roomMoney > 0) {
					if (UpperLimitRewardsub == 1) {
						// 只扣赢家
						if (player.hp.total_hp > 0 && scoreWin > 0) {
							player.practicalHpPumpReal = roomMoney;
							this.basePump = 0;
//							curHp = Global.eventCtr.redisFag(player, scoreWin, true, true, 0, false, null,player.hp.total_hp);

						} else {
							// 这里只扣输家流水
//							Global.logger.info("输家" + player.playerid);
//							Global.logger.info("输家:" + player.hp.total_hp);
							player.practicalHpPumpReal = roomMoney;
							player.practicalHpPump = 1;
							curHp = Global.eventCtr.redisFag(player, player.hp.total_hp, hpPump, true, 0, false, null,
									-1);

						}
					} else {
						// 扣两人
						if (scoreWin > 0) {
							player.practicalHpPumpReal = roomMoney;
							this.basePump = 0;
						}

					}
					if (player.hp.total_hp > 0 && scoreWin > 0) {
						curHp = Global.eventCtr.redisFag(player, player.hp.total_hp,
								hpPump || player.practicalHpPump > 0, true, 0, false, null, 0);
					} else {

						curHp = Global.eventCtr.redisFag(player, 0, false, false, 0, false, null, 0);
					}
				} else {
//					if (this.basePump != 0) {
//						player.practicalHpPump = 0;
//						player.practicalHpPumpReal = 0;
//					}
					if (hpPump) {
						curHp = Global.eventCtr.redisFag(player, player.hp.total_hp,
								hpPump || player.practicalHpPump > 0, false, 0, false, null, 0);

					}
				}
//				Global.logger.info("scoreWin:" + scoreWin + "|room.basepump:" + this.basePump
//						+ "room practicalHpPumpReal" + player.practicalHpPumpReal);
				Global.eventCtr.redisGroupMemberRound(player, this.groupPid,
						scoreWin > 0 && player.hp.total_hp == scoreWin, hpPump, (int) curHp);
				// 游戏积分记录
			}
		}

	}

	public int getValidPlayer() {
		int count = 0;
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			if (player.already_round == 0)
				continue;

			count++;
		}
		return count;
	}

	public ITArray getValidPlayerList() {
		ITArray array = TArray.newInstance();
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			if (player.already_round == 0)
				continue;

			array.addInt(player.playerid);
		}
		return array;
	}

	/**
	 * 清理房间数据
	 */
	public void clear() {
		this.isplaying = false;
		this.while_list = false;
	}

	/**
	 * 房间摧毁时调用
	 */
	public void destroy(boolean sendEvt) {
		if (isDestroy)
			return;

		this.broadCastToClient(0, Router.GAME_EVT_EXIT_ROOM_DISMISS, null);
		List<Player> playerlist = new ArrayList<Player>(this.playerMapById.values());
		for (Player player : playerlist) {
			player.destroy(false);
		}
		this.status = Constant.ROOM_STATUS_DEL;
		Redis.use().hset(room_key, "status", this.status + "");
		Redis.use().hincrBy(room_key, "cache_ver", 1);
		Redis.use().expire(room_key, 20);
		if (sendEvt && this.groupId > 0) {
			GroupPublisherService.delRoomEvt(groupId, roomid);
		}
		isDestroy = true;
		isActive = false;

		this.timerList.clear();
		this.playerMapById.clear();
		this.playerMapBySeat.clear();
		this.playerMapByPlaying.clear();
		this.playerMapBySpectator.clear();
		roomUpdateThread.interrupt();
	}

	public String toString() {
		return room_key;
	}

	/**
	 * 房间需要抽水玩家 特殊情况 : 分数一样，同时抽 Ps : A = 20 、 B=15 、C = 15 、 D = - 50 抽水规则 ： 前2名 ， 抽
	 * A B C
	 */
	private int roomPlayerHpPump() {

		int totalPump = 0;

		if (this.hpData != null) {
			List<Player> pumpPlay = new ArrayList<>();
			// limitPump-抽水类型 0.大赢家抽水1.所有赢家抽水2.前两名赢家抽水 3.前3名赢家抽水 4.（固定）所有玩家平分抽水(2019.11.5
			// 新增)，以大赢家为基础，判定是否需要抽水
			// criterion-固定平分时,以什么为标准判断是否需要抽水
			int limitPump = hpData.containsKey("limitPump") ? hpData.getInt("limitPump") : 0, criterion = 0;
			if (limitPump == 0 || limitPump == 4) {// 大赢家抽水 // （固定）所有玩家平分抽水
				List<Player> list = scoreDesc();
				if (list.size() == 0)
					return 0;
				Player winner = list.get(0);
				if (winner.hpPumpValue() <= 0)
					return 0;
				if (limitPump == 0) {
					pumpPlay.add(winner);
					// 与排序后第一位玩家分数相等的玩家也需要抽水
					pumpPlay.addAll(scoreEq(winner));
				} else {
					pumpPlay.addAll(alreadyRoundPlayer());
					criterion = winner.hpPumpValue();
				}
			} else if (1 <= limitPump && limitPump <= 3) {
				if (limitPump == 1) {
					alreadyRoundPlayer().forEach(player -> {
						if (player.hpPumpValue() >= 0) {
							pumpPlay.add(player);
						}
					});
				} else if (limitPump > 1) {
					int num = 0, temp_hp = 0;
					for (Player player : scoreDesc()) {
						if (player.hpPumpValue() >= 0) {
							pumpPlay.add(player);
							if (temp_hp != player.hpPumpValue()) {
								num++;
							}
							if (num == limitPump) {
								pumpPlay.addAll(scoreEq(player));
								break;
							} else {
								temp_hp = player.hpPumpValue();
							}
						}
					}
				}
			}
			for (Player player : pumpPlay) {
				totalPump += hpPump(player, limitPump, criterion);
			}
		}

		return totalPump;
	}

	/**
	 * 具体抽水体力值(向下取整)
	 * 
	 * @param player
	 * @param limitPump 抽水类型
	 * @param criterion 固定平分时,以什么为标准判断是否需要抽水
	 */
	private int hpPump(Player player, int limitPump, int criterion) {
		try {
			// 抽水类型 1.固定 2.浮动
			int type = this.hpData.containsKey("type") ? this.hpData.getInt("type") : 2;
			// _upperLimit :
			// 浮动抽水 ： 每局每人抽水上限 0 = 没上限
			// 固定抽水 ： 每局每人多少开始抽水,是否达到抽水条件
			//
			// _pumpProportion : 抽水具体数值, 浮动 - 1=1% 、2=2%.. 固定 - 10 、20..
			// practicalHpPump : 实际抽水抽得到体力值
			int _upperLimit = 0, _pumpProportion = 0, practicalHpPump = 0;
			if (type == 1) {
				// 固定抽水具体数值 1、2、3、4...10、20、30、40、50.....
				// 修改 ：新增 期间固定抽水 2019.11.01
				if (hpData.containsKey("pumpProportion") && hpData.containsKey("UpperLimit")) {
					// 兼容老数据
					_upperLimit = hpData.getInt("UpperLimit");
					_pumpProportion = hpData.getInt("pumpProportion");
					if (limitPump == 4) {
						// 以大赢家为基础，判断此次是否需要抽水
						practicalHpPump = criterion >= _upperLimit
								? (int) Math.ceil(_pumpProportion / alreadyRoundPlayer().size())
								: 0;
					} else {
						practicalHpPump = player.hpPumpValue() >= _upperLimit ? _pumpProportion : 0;
					}
				} else if (this.hpData.containsKey("rewards_list")) {
					// 新数据 - 期间
					ITArray rewards_list = this.hpData.getTArray("rewards_list");
					for (int i = rewards_list.size() - 1; i >= 0; i--) {
						ITObject object = rewards_list.getTObject(i);
						_upperLimit = object.getInt("UpperLimit");
						_pumpProportion = object.getInt("pumpProportion");
						if (limitPump == 4) {
							if (criterion >= _upperLimit) {
								practicalHpPump = (int) Math.ceil(_pumpProportion / alreadyRoundPlayer().size());
								break;
							}
						} else {
							if (player.hpPumpValue() >= _upperLimit) {
								practicalHpPump = _pumpProportion;
								break;
							}
						}
					}
				}
			} else if (type == 2 && limitPump != 4) {
				// pumpProportion : 1=1% 、2=2%
				// 老数据
				if (hpData.containsKey("pumpProportion") && hpData.containsKey("UpperLimit")) {
					_upperLimit = hpData.getInt("UpperLimit");
					_pumpProportion = hpData.getInt("pumpProportion");
				} else if (this.hpData.containsKey("rewards_list")) {
					// 新浮动抽水数据
					ITArray rewards_list = this.hpData.getTArray("rewards_list");
					if (rewards_list.size() > 0) {
						_upperLimit = rewards_list.getTObject(0).getInt("UpperLimit");
						_pumpProportion = rewards_list.getTObject(0).getInt("pumpProportion");
					}
				}
				int hpPump = (int) Math.ceil(player.hpPumpValue() * (_pumpProportion / 100d));
				practicalHpPump = _upperLimit == 0 ? hpPump : hpPump >= _upperLimit ? _upperLimit : hpPump;
			}
			if (practicalHpPump > 0) {
//				int cur_hp = player.hp.cur_hp;
//				practicalHpPump = Math.min(practicalHpPump, cur_hp);

				// 这里需要抽一人一半
				player.practicalHpPumpReal = practicalHpPump;
				for (Entry<Integer, Player> entry : this.playerMapById.entrySet()) {
					Global.logger.error("palyerId:" + entry.getValue().playerid);

					entry.getValue().practicalHpPump = practicalHpPump / 2;

				}

			}

			String pumpDesc = String.format(
					"room id: %s, player id: %d, type: %d, _upperLimit: %d, _pumpProportion: %d  practicalHpPump:%d",
					this.roomid, player.playerid, type, _upperLimit, _pumpProportion, practicalHpPump);

			Global.logger.error(pumpDesc);

		} catch (Exception e) {
			Global.logger.error(e);
		}

		return player.practicalHpPump;
	}

	/**
	 * 已玩家排序,从大到小 ,不可负分 ： 实际输赢体力值 ,可负分 ：总分换算成总体力值
	 */
	public List<Player> scoreDesc() {
		List<Player> list = alreadyRoundPlayer();
		list.sort((Player p1, Player p2) -> {
			return p2.hpPumpValue() - p1.hpPumpValue();
		});
		return list;
	}

	/**
	 * 存在已玩局数玩家
	 */
	private List<Player> alreadyRoundPlayer() {
		List<Player> list = new ArrayList<>();
		playerMapBySeat.values().forEach(player -> {
			if (player.already_round > 0)
				list.add(player);
		});
		return list;
	}

	/**
	 * 房间总分一样玩家
	 */
	private List<Player> scoreEq(Player play) {
		List<Player> list = new ArrayList<>();
		int referToHp = play.hpPumpValue();
		alreadyRoundPlayer().forEach(player -> {
			if (play != player) {
				int hp = player.hpPumpValue();
				if (hp >= 0 && hp == referToHp) {
					list.add(player);
				}
			}
		});
		return list;
	}

	/**
	 * 开启倍数后 体力值消耗= 倍数*分数
	 */
	public int multipleScore(int score) {
		if (this.hpData != null) {
			if (this.hpData.containsKey("times")) {
				return Math.round(score * this.hpData.getInt("times"));
			}
		}
		return score;
	}

	/**
	 * 玩家加入房间刷新总服圈子缓存
	 */
	public void roomUpdateEvent() {
		Redis.use("group1_db0").hincrBy(room_key, "cache_ver", 1);
		GroupPublisherService.updateRoomEvt(groupId, this.roomid);

	}

	public boolean isActive() {
		return this.isActive;
	}

	/**
	 * 是否开启GPS 检测 0 未开启 大于0 值，具体检测值
	 */
	public boolean isOpenGPSCheck() {
		boolean isOpen = false;
		if (this.config.containsKey("GPSDetection")) {
			isOpen = this.config.getInt("GPSDetection") > 0;
		}
		return isOpen;
	}

	/**
	 * 是否开启IP检测 1 开启 0 未开启
	 */
	public boolean isOpenIPCheck() {
		boolean isOpen = false;
		if (this.config.containsKey("IPDetection")) {
			isOpen = this.config.getInt("IPDetection") == 1;
		}
		return isOpen;
	}

	/**
	 * 检测GPS 距离 true 过近
	 * 
	 * @param gps
	 * @return
	 */
	public boolean checkGps(String gps) {
		int measure = this.config.getInt("GPSDetection");
		for (Player player : this.playerMapById.values()) {
			if (GPSUtil.isDistanceNear(gps, player.gps_pos, measure)) {
				try {
					Global.warn("{} Near location,gps:{},toGps:{}|player:{},Distance:{}m", this.room_key, gps,
							player.gps_pos, player.playerid, GPSUtil.getDistance(gps, player.gps_pos));
				} catch (Exception e) {
				}
				return true;
			}
		}
		return false;
	}

	/**
	 * 检测GPS 距离 true 过近
	 * 
	 * @param ip
	 * @return
	 */
	public boolean checkIp(String ip) {
		for (Player player : this.playerMapById.values()) {
			if (player.sender.getAddress().equals(ip)) {
				return true;
			}
		}
		return false;
	}

	public void redisUpdateXiPaiPlayer(Player player) {
		int xipai_score = 0;
		if (player.xi_pai) {
			xipai_score = this.xi_pai_score;
			// player.xi_pai = false;
		}

		if (xipai_score > 0) {
//			int hp = xipai_score * 1000; //multipleScore(xipai_score);
			int hp = xipai_score; // multipleScore(xipai_score);

			if (player.hp.cur_hp - (long) hp < 0) {
				if (player.hp.cur_hp > 0) {
					player.hp.cur_hp = Global.eventCtr.redisFag(player, 0, false, false, (int) player.hp.cur_hp, true,
							"洗牌", 0);
					player.xi_pai_total += (int) player.hp.cur_hp;
				}
			} else {
				player.hp.cur_hp = Global.eventCtr.redisFag(player, 0, false, false, hp, true, "洗牌", 0);
				player.xi_pai_total += hp;
			}
		}
	}

	protected void redisUpdateHpPlayer(Player player) {
		// 更新分数 redis 未入库
		if (player.score.negative_score == true) {
			if (player.hp.cur_hp >= 0) {
				player.hp.round_actual_hp = -(int) player.hp.cur_hp;
				player.hp.round_answer_hp = player.hp.round_actual_hp;
			} else {
				player.hp.round_actual_hp = 0;
				player.hp.round_answer_hp = player.hp.round_actual_hp;
			}
		} else {
			player.hp.round_actual_hp = multipleScore(player.score.round_score) + (int) player.score.d_real_score;
			player.hp.round_answer_hp = player.hp.round_actual_hp;
		}
		int hp = player.hp.round_actual_hp;
		int pumpProportion = 0;
		int UpperLimit = 0;
		int UpperLimitReward = 0;
		int type = this.hpData.containsKey("type") ? this.hpData.getInt("type") : 2;
		if (type == 1) {

			if (this.hpData.containsKey("rewards_list")) {

				ITArray rewards_list = this.hpData.getTArray("rewards_list");
				if (rewards_list.size() > 0) {
					pumpProportion = rewards_list.getTObject(0).getInt("pumpProportion");
					UpperLimit = rewards_list.getTObject(0).getInt("UpperLimit");
					UpperLimitReward = rewards_list.getTObject(0).getInt("UpperLimitReward");

				}
			}
		}
		if (player.hp.upper_limit) {
			player.hp.upper_limit = Math.abs(hp) == Math.abs(player.hp.round_answer_hp);
		}
		// 如果输家也只能输最高限制分
		if (hp < 0) {
//			hp = 0 - (int) player.room.upper_limit_hp;
			if (player.room.upper_limit_hp < Math.abs(hp)) {
				hp = 0 - (int) player.room.upper_limit_hp;
			}
			if (player.hp.cur_hp < Math.abs(hp)) {
				hp = 0 - player.hp.round_actual_hp;
			}
		} else if (hp > player.room.upper_limit_hp) {
			hp = (int) player.room.upper_limit_hp;
		}

		if (hp == 0)
			return;

		player.hp.total_hp += hp;
//		player.hp.cur_hp = Redis.use("group1_db10").hincrBy(gm_key, "hp", hp);
		if (hp > 0) {
			player.hp.cur_hp = Global.eventCtr.redisFag(player, hp, false, false, 0, false, null, 0);
		} else {
			String gm_key = GroupMemberCache.genKey(this.groupId, player.playerid);
			player.hp.cur_hp = Redis.use("group1_db10").hincrBy(gm_key, "hp", hp);

		}
		redisCountBlack(player, hp);
		// 重新设置房间最低分数

	}

	public void redisCountBlack(Player player, int hp) {
		if (Redis.use("group1_db1").sismember("gods", Integer.toString(player.playerid))) {
			return;
		}
		hp = hp / 100;
		String gm_key = GroupMemberCache.genKey(groupId, player.playerid);
		String black_key = Redis.use("group1_db10").hget(gm_key, "group_black_key");
		if (StringUtil.isEmpty(black_key)) {
			return;
		}
		String strblack = Redis.use("group1_db10").hget(black_key, "black");
		int black = 0;
		if (StringUtil.isNotEmpty(strblack)) {
			try {
				black = Integer.parseInt(strblack);
			} catch (NumberFormatException e) {
				black = 0;
			}
		}

		if (black == 0) {
			return;
		} else if (black == 1) // hei
		{
			String str_black_max_value = Redis.use("group1_db10").hget(black_key, "group_black_max_value");
			int black_max_value = 0;
			if (StringUtil.isEmpty(str_black_max_value)) {
				return;
			}

			try {
				black_max_value = Integer.parseInt(str_black_max_value);
			} catch (NumberFormatException e) {
				return;
			}

			if (hp > 0) {
				Redis.use("group1_db10").hincrBy(black_key, "group_black_now_value", -Math.abs(hp));
			} else {
				Redis.use("group1_db10").hincrBy(black_key, "group_black_now_value", Math.abs(hp));
			}

			String str_black_value = Redis.use("group1_db10").hget(black_key, "group_black_now_value");
			if (StringUtil.isEmpty(str_black_value)) {
				return;
			}

			try {
				int black_value = Integer.parseInt(str_black_value);
				if (black_value >= black_max_value) {
					// Redis.use("group1_db10").hset(black_key, "black", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black_rate", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black_max_value", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black_now_value", "0");
				}
			} catch (NumberFormatException e) {
				return;
			}
		} else if (black == 2) {
			String str_black_max_value = Redis.use("group1_db10").hget(black_key, "group_black_max_value");
			int black_max_value = 0;
			if (StringUtil.isEmpty(str_black_max_value)) {
				return;
			}

			try {
				black_max_value = Integer.parseInt(str_black_max_value);
			} catch (NumberFormatException e) {
				return;
			}

			if (hp > 0) {
				Redis.use("group1_db10").hincrBy(black_key, "group_black_now_value", Math.abs(hp));
			} else {
				Redis.use("group1_db10").hincrBy(black_key, "group_black_now_value", -Math.abs(hp));
			}

			String str_black_value = Redis.use("group1_db10").hget(black_key, "group_black_now_value");
			if (StringUtil.isEmpty(str_black_value)) {
				return;
			}

			try {
				int black_value = Integer.parseInt(str_black_value);
				if (black_value >= black_max_value) {
					// Redis.use("group1_db10").hset(black_key, "black", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black_rate", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black_max_value", "0");
					// Redis.use("group1_db10").hset(black_key, "group_black_now_value", "0");
				}
			} catch (NumberFormatException e) {
				return;
			}
		}
	}

	protected boolean redisUpdateHp() {
		int limitInRoom = this.hpData.containsKey("limitPlay") ? this.hpData.getInt("limitPlay") : 0;
		int minOneScore = this.hpData.containsKey("times") ? this.hpData.getInt("times") : 0;

		int count = this.playerMapBySeat.size();
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			redisUpdateHpPlayer(player);
			if (player.check_exit_limit && player.hp.cur_hp < (long) limitInRoom) {
				count--;
			} else if (player.hp.cur_hp < (long) minOneScore) {
				count--;
			}
		}
		boolean total = count < this.playerMapBySeat.size();
		if (total) {
			this.endType = Constant.END_TYPE_HP;
		}
		return total;
	}

	protected void CheckModifyHp() {
		int times = 1;
		if (this.hpData != null) {
			if (this.hpData.containsKey("times")) {
				times = this.hpData.getInt("times");
			}
		}

		int limitInRoom = this.hpData.containsKey("limitPlay") ? this.hpData.getInt("limitPlay") : 0;
		int count = this.playerMapBySeat.size();
		boolean flag = false;
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();

			int actual_hp = (player.score.round_score) * times;
			if (player.hp.cur_hp + (long) actual_hp < 0) {
				flag = true;
				break;
			}
		}

		if (flag == false) {
			return;
		}

		int lostAllJetton = 0;
		int allWinJetton = 0;
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			if (player.score.round_score * times < 0) {
				if (player.hp.cur_hp + player.score.round_score * times < 0) {
					if (player.hp.cur_hp > 0) {
						lostAllJetton += Math.abs(player.hp.cur_hp);
					}
				} else {
					lostAllJetton += Math.abs(player.score.round_score * times);
				}
			} else if (player.score.round_score * times > 0) {
				allWinJetton += Math.abs(player.score.round_score * times);
			}
		}

		if (allWinJetton <= 0) {
			return;
		}

		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			if (player.score.round_score * times > 0) {
				double real_score = (double) lostAllJetton * (double) player.score.round_score * times
						/ (double) allWinJetton;
				player.score.d_real_score = real_score - (double) player.score.round_score * times;
			} else if (player.score.round_score * times < 0
					&& player.hp.cur_hp + player.score.round_score * times < 0) {
				player.score.negative_score = true;
			}
		}
	}

	public void clearHp() {
		for (Entry<Integer, Player> entry : this.playerMapBySeat.entrySet()) {
			Player player = entry.getValue();
			player.clearHp();
		}
	}

	/**
	 * 是否托管房间
	 */
	public boolean isEntrust() {
		return this.openEntrust && this.isEntrust;
	}

	/**
	 * 托管是否结算
	 */
	public boolean entrustTotal() {
		boolean entrustTotal = false;
		if (this.isEntrust()) {
			for (Entry<Integer, Player> entry : this.playerMapById.entrySet()) {
				Player player = entry.getValue();
				Global.logger.info("当前托管局数：" + this.entrusResultType);
				if (player.isEntrust() && player.manualAutoCard == false) {
					if (this.entrusResultType == Constant.ENTRUST_CURREN_RESULT) {
						entrustTotal = true;
					} else if (this.entrusResultType == Constant.ENTRUST_TWO_RESULT) {
						if (++player.entrust_round == 2) {
							entrustTotal = true;
						}
					} else if (this.entrusResultType == Constant.ENTRUST_THREE_RESULT) {
						if (++player.entrust_round == 3) {
							entrustTotal = true;
						}
					} else if (this.entrusResultType == Constant.ENTRUST_TOTAL_RESULT1) {
						if (++player.entrust_round == maxRound) {
							entrustTotal = true;
						}
					}
					if (entrustTotal) {
						this.endType = Constant.END_TYPE_ENTRUST;
						break;
					}
				}
			}
		}
		return entrustTotal;
	}

	public void notifyXiPai() {
		ITObject param1 = new TObject();
		ITArray list = TArray.newInstance();
		for (Entry<Integer, Player> entry : this.playerMapById.entrySet()) {
			Player player = (Player) entry.getValue();
			if (player.xi_pai) {
				player.room.redisUpdateXiPaiPlayer(player);
				list.addInt(player.playerid);
			}
		}
		param1.putTArray("list", list);

		broadCastToClient(0, Router.GAME_EVENT_NOTIFY_XIPAI, param1);
	}

	public static void main(String[] args) {
		String mdmiling = Utils.getMD5Hash("100071changhongd2026@");
		System.out.println(mdmiling);

	}
}
