package extend.pk.uitl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

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 extend.pk.CardGroup;
import extend.pk.CardObj;
import extend.pk.Config;
import extend.pk.RoomCard;


/**
 * 
 * 
 */
public class CardCheck {

	/**
	 * 服务器跟牌判定
	 * @param cardInhand
	 * @param out
	 * @param roomConfig
	 * @param nextBaodan
	 * @return
	 */
	public static CardGroup genOutCard(List<CardObj> cardInhand,CardGroup out,ITObject roomConfig,boolean nextBaodan) {
		CardGroup cg = null;
		
		Map<Integer, List<CardObj>> cardMap =CardUtil.getCardListMap(cardInhand);
		int handCardSize = cardInhand.size();
		// 如果有炸弹 并且玩家手上仅剩下炸弹  就不用找了 直接出牌就可以了
		cg = selectZha(cardMap,out,roomConfig);
		if(cg != null && cg.card_list.size() == handCardSize) {
			cg.card_list_mp = CardUtil.toTArray(cg.card_list);
			return cg;
		}
		
		// 如果别的玩家出的是一张单牌，则寻找一个合适的单牌，如果找不到就用炸弹，炸弹没有则过
		if(out.config.type == Config.TYPE_DANPAI) {
			
			CardGroup tempCg = selectDanpai(cardMap,out,roomConfig,nextBaodan);
			if(tempCg != null) {
				cg = tempCg;
			}
		}
		
		// 如果别的玩家出的是不能带牌的牌型（对子，顺子，连队）则寻找合适的牌型，如果找不到就用炸弹，炸弹没有则过
		else if(out.config.type == Config.TYPE_DUIZI 
				|| out.config.type == Config.TYPE_SHUNZI 
				|| out.config.type == Config.TYPE_LIANDUI) {
			
			CardGroup tempCg = selectWithoutCardType(handCardSize,cardMap,out,roomConfig);
			if(tempCg != null) {
				cg = tempCg;
			}
		}
		
		// 如果别的玩家出的是带牌的三带牌型 ,则寻找合适的牌型，如果找不到就用炸弹，炸弹没有则过
		else if(out.config.type == Config.TYPE_3_2) {
			
			boolean bLack = false;
			if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_LACK) == 1) {
				bLack = true;
			}
			
			CardGroup tempCg = selectWithCardType(cardInhand,cardMap,out,roomConfig,bLack);
			if(tempCg != null) {
				cg = tempCg;
			}
		}
		
		// 如果别的玩家出的是带牌的飞机牌型,则寻找合适的牌型，如果找不到用则炸弹，炸弹没有则过
		else if(out.config.type == Config.TYPE_FEIJI) {
			
			boolean bLack = false;
			if(roomConfig.getInt(Config.ROOM_CONFIG_PLANE_LACK) == 1) {
				bLack = true;
			}
	
			CardGroup tempCg = selectWithCardType(cardInhand,cardMap,out,roomConfig,bLack);
			if(tempCg != null) {
				cg = tempCg;
			}
		}
		// 如果是四带二或者四带三  就不处理了，如果有炸弹，则玩家自己去选择是炸还是跟，如果没有炸弹   玩家也大不了，所以后面就不用判断了
		if(cg != null) {
			cg.card_list_mp = CardUtil.toTArray(cg.card_list);
		}

		return cg;
	}
	
	/**
	 * 选择炸弹
	 * @param cardMap
	 * @param out
	 * @param roomConfig
	 * @return
	 */
	private static CardGroup selectZha(Map<Integer, List<CardObj>> cardMap,CardGroup out,ITObject roomConfig) {
		
		CardGroup cg = null;
		
		boolean bThreeA = false;
		if(roomConfig != null && roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
			bThreeA = true;
		}
		
		int minValue = 0;
		if(out.config.type == Config.TYPE_ZHA) {
			minValue = out.min_card;
		}
		
		for(Map.Entry<Integer,List<CardObj>> entry : cardMap.entrySet()) {
			
			if(entry.getValue().size() == 4 || ( entry.getKey() == RoomCard.CARD_A && bThreeA && entry.getValue().size() == 3)) {
				
				if(entry.getKey() > minValue) {
					
					cg = new CardGroup();
					
					cg.config 		= CardConfig.ZHA;
					cg.min_card 	= entry.getKey();
					cg.len 			= 1;
					
					cg.card_list 	= new ArrayList<>();
					for(CardObj cardObj : entry.getValue()) {
						cg.card_list.add(cardObj);
					}
					break;
				}
			}
		}
		
		return cg;
	}
	
	/**
	 * 选择单牌
	 * @param cardMap
	 * @param out
	 * @param roomConfig
	 * @param nextBaodan
	 * @return
	 */
	public static CardGroup selectDanpai(Map<Integer, List<CardObj>> cardMap,CardGroup out,ITObject roomConfig,boolean nextBaodan) {
		CardGroup cg = null;
		
		int minValue = out.min_card + 1;
		
		boolean bDemolition = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_DEMOLITION) == 1) {
			bDemolition = true;
		}
		
		boolean bThreeA = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
			bThreeA = true;
		}
		
		if(!nextBaodan) {
			
			for(int i = minValue; i <= 15; i++) {
				
				List<CardObj> listCard = cardMap.get(i);
				if(listCard != null && listCard.size() >= 1) {
					// 如果是炸弹 并且不能拆分炸弹，则不能用它作为单牌来处理
					if(bDemolition && (listCard.size() == 4 || (i == RoomCard.CARD_A && bThreeA &&  listCard.size() == 3 ))) {
						
					}
					else {
						cg = new CardGroup();
						
						cg.config 		= CardConfig.DAN;
						cg.min_card 	= i;
						cg.len 			= 1;
						
						cg.card_list 	= new ArrayList<>();
						cg.card_list.add(listCard.get(0));
						break;
					}
				}
			}
		}
		else
		{
			for(int i = 15; i >= minValue; i--) {
				
				List<CardObj> listCard = cardMap.get(i);
				if(listCard != null && listCard.size() >= 1) {
					
					// 如果是炸弹 并且不能拆分炸弹，则不能用它作为单牌来处理
					if(bDemolition && (listCard.size() == 4 || (i == RoomCard.CARD_A && bThreeA &&  listCard.size() == 3))) {
						
					}
					else {
						
						cg = new CardGroup();
						
						cg.config 		= CardConfig.DAN;
						cg.min_card 	= i;
						cg.len 			= 1;
						
						cg.card_list 	= new ArrayList<>();
						cg.card_list.add(listCard.get(0));
						break;
					}
				}
			}
		}
		
		return cg;
	}
	
	/**
	 * 选择不需要带牌的牌型
	 * @param handCardSize
	 * @param cardMap
	 * @param out
	 * @param roomConfig
	 * @return
	 */
	private static CardGroup selectWithoutCardType(int handCardSize,Map<Integer, List<CardObj>> cardMap,CardGroup out,ITObject roomConfig) {
		CardGroup cg = null;
		
		boolean bDemolition = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_DEMOLITION) == 1) {
			bDemolition = true;
		}
		
		boolean bThreeA = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
			bThreeA = true;
		}
		
		int len = out.len;
		
		// 如果手牌数满足要求
		if( handCardSize >= len * out.config.repeat_num ) {
			
			List<CardObj> card_list = new ArrayList<CardObj>();
			
			//最小的数字是9   加一，下一位玩家需要出的牌时从10开始
			int min_card = out.min_card + 1;
			
			 //最小的数字加上上家玩家牌的长度。就是下家玩家需要出牌的张数
			int max_card = min_card+len -1;
			
			//长度如果大于一并且最大的牌
			if(!(len>1&&max_card>14)) {
				
				int count =0;
				
				for(int i = min_card; i <= 14;++i) {
					
					List<CardObj> list =cardMap.get(i);
					
					// 如果牌值对应的牌为空  或者他是炸弹，则之前找到的牌取消
					if( list == null || (bDemolition && (list.size() == 4 || (i == RoomCard.CARD_A && bThreeA && list.size() == 3))) ) {
						count=0;
						card_list.clear();
						continue;
					}
					
					// 如果牌值对应的牌的个数满足要求，则将牌放入队列中
					if(list.size() >=out.config.repeat_num) {
						
						for(int k = 0; k < out.config.repeat_num;++k) {
							card_list.add(list.get(k));
						}
						count++; 
						
						// 如果已经找到了足够数量的相同牌型
						if(count == len) {
							
							cg = new CardGroup();
							
							cg.config 		= out.config;
							cg.card_list 	= card_list;
							cg.len 			= len;
							cg.min_card 	= card_list.get(0).cardMod;
					
							return cg;
						}
					}else {
						count=0;
						card_list.clear();
					}
				}
			}
		}
		
		return cg;
	}
	
	private static CardGroup selectWithCardType(List<CardObj> cardInhand,
			Map<Integer, List<CardObj>> cardMap,
			CardGroup out,
			ITObject roomConfig,
			boolean bLack) {
		
		CardGroup cg = null;
		
		int handCardSize = cardInhand.size();
		
		boolean bDemolition = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_DEMOLITION) == 1) {
			bDemolition = true;
		}
		
		boolean bThreeA = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
			bThreeA = true;
		}
		
		int len = out.len;
		
		// 如果手牌数满足要求
		if( handCardSize >= len * out.config.repeat_num ) {
			
			List<CardObj> card_list = new ArrayList<CardObj>();
			
			//最小的数字是9   加一，下一位玩家需要出的牌时从10开始
			int min_card = out.min_card + 1;
			
			 //最小的数字加上上家玩家牌的长度。就是下家玩家需要出牌的张数
			int max_card = min_card+len -1;
			
			//长度如果大于一并且最大的牌
			if(!(len>1&&max_card>14)) {
				
				int count =0;
				
				for(int i = min_card; i <= 14;++i) {
					
					List<CardObj> list =cardMap.get(i);
					
					// 如果牌值对应的牌为空  或者他是炸弹，则之前找到的牌取消
					if( list == null || (bDemolition && (list.size() == 4 || (i == RoomCard.CARD_A && bThreeA && list.size() == 3))) ) {
						count=0;
						card_list.clear();
						continue;
					}
					
					// 如果牌值对应的牌的个数满足要求，则将牌放入队列中
					if(list.size() >= out.config.repeat_num) {
						
						for(int k = 0; k < out.config.repeat_num;++k) {
							card_list.add(list.get(k));
						}
						count++; 
						
						// 如果已经找到了足够数量的相同牌型
						if(count == len) {
							
							int sd = out.config.repeat_num * len + out.config.with_card_num * len;
							
							boolean sandaidan = roomConfig.containsKey(Config.ROOM_CONFIG_SANDAIDAN) && roomConfig.getInt(Config.ROOM_CONFIG_SANDAIDAN) == 1;
							if(sandaidan) {
								
								if(handCardSize < out.card_list.size()) {
									return cg;
								}
							}
							else {
								
								if(bLack == false && handCardSize < sd) {
									
									return cg;
								}
							}

							// 新建一个临时的列表，来保存剩余的牌
							List<CardObj> tem_list = new ArrayList<CardObj>();
							tem_list.addAll(cardInhand);
							CardUtil.removeCard(tem_list, card_list);
							
							// 如果剩余的牌有炸弹，则需要把剩余牌中的炸弹对应的牌从临时列表中剔除，以确定是否有足够的单牌
							// 如果因为剔除的原因，最后牌型不能做成，那就提示他有炸弹出就可以了
							Map<Integer, List<CardObj>> reservedCardMap = CardUtil.getCardListMap(tem_list);
							int duiNum = 0;
							for(Map.Entry<Integer, List<CardObj>> entry : reservedCardMap.entrySet()) {
								
								int num = entry.getValue().size();
								if(num == 4 || (entry.getKey() == RoomCard.CARD_A && bThreeA && num == 3)) {
									
									CardUtil.removeCard(tem_list, entry.getValue());
								}
								
								if(num >= 2) {
									duiNum++;
								}
							}
							
							
							if(sandaidan) {
								
								boolean isDui = sd == out.card_list.size();
								if(isDui) {
									
									if(duiNum < len) {
										return cg;
									}
									
									for(Map.Entry<Integer, List<CardObj>> entry : reservedCardMap.entrySet()) {
										
										int num = entry.getValue().size();
										if(num >= 2 && num < 4) {
											card_list.add(entry.getValue().get(0));
											card_list.add(entry.getValue().get(1));
										}
									}
									
								}else {
									
									for(int m = 0; m < len; m++) {
										card_list.add(tem_list.get(m));
									}
								}
							}
							else {
								
								// 如果手牌数多于牌型的基本要求
								if(handCardSize >= sd) {
									
									if(tem_list.size() < out.config.with_card_num * len) {
										return cg;
									}
									
									for(int m = 0; m < out.config.with_card_num * len; m++) {
										card_list.add(tem_list.get(m));
									}
								}
								else {
									
									card_list.addAll(tem_list);
								}
							}
							
							cg = new CardGroup();
							
							cg.config 		= out.config;
							cg.card_list 	= card_list;
							cg.len 			= len;
							cg.min_card 	= card_list.get(0).cardMod;
						
							return cg;
						}
					}else {
						count=0;
						card_list.clear();
					}
				}
			}
		}
		
		return cg;
	}
	
	/**
	 * 得到所出牌的牌型
	 * @param cardOut
	 * @param roomConfig
	 * @return
	 */
	public static CardGroup getType(List<CardObj> cardOut,ITObject roomConfig) {
		
		CardGroup cg = autoOutLastHand(cardOut,roomConfig,true);
		if(cg == null) {
			
			int len = cardOut.size();
			int sidai = roomConfig.getInt(Config.ROOM_CONFIG_SIDAI);
			// 看看所处的牌是否 4带2 或者4带3
			if((len == 6 && sidai == 2) || (len == 7 && sidai == 3)) {
				
				Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(cardOut);
				for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
					
					if(entry.getValue() == 4) {
						
						cg = new CardGroup();
						cg.card_list = new ArrayList<>();
						if(len == 6) {
							cg.config = CardConfig.SI_2;
						}
						else{
							cg.config = CardConfig.SI_3;
						}
						
						cg.min_card = entry.getKey();
						cg.len = 1;
						
						for(CardObj cardObj : cardOut) {
							cg.card_list.add(cardObj);
						}
						cg.card_list_mp = CardUtil.toTArray(cg.card_list);
					}
				}
			}
		}
		
		return cg;
	}
	
	/**
	 * 
	 * @param cardInhand
	 * @param roomConfig
	 * @return
	 */
	public static CardGroup autoOutLastHand(List<CardObj> cardInhand,ITObject roomConfig,boolean bSpecial) {
		
		CardGroup cg = null;

		Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(cardInhand);
		
		int len = cardInhand.size();
		//Global.logger.info( "auto out len:" + len);
		if(len == 1)
		{
			cg = new CardGroup();
			cg.card_list = new ArrayList<>();
			cg.config = CardConfig.DAN;
			cg.min_card = cardInhand.get(0).cardMod;
			cg.len = 1;
		}
		else if(len == 2) {
			cg = checkTwo(cardMap);
		}
		else if(len == 3) {
			
			cg = checkThree(cardMap,roomConfig);
		}
		else if(len == 4) {
			
			cg = checkFour(cardMap,roomConfig);
		}
		else if(len == 5) {

			if(isConfig4_2_and_4_3(roomConfig) && getMaxCardNum(cardMap) == 4){//四带一
				return null;//不能判为三带二
			}

			cg = checkFive(cardMap,roomConfig,bSpecial);
		}
		else{
			if (bSpecial) {
				if (len == 6) {
					cg = checkSiWithTwo(cardMap,roomConfig);
				}

				if (len == 7) {
					cg = checkSiWithThree(cardMap,roomConfig);
				}
			}

			if (cg == null) {
				cg = checkShunzi(len,cardMap,roomConfig);
				if(cg == null) {
					cg = checkLiandui(len,cardMap,roomConfig);
					if(cg == null) {
						cg = checkFeiji(len,cardMap,roomConfig,bSpecial);
					}
				}
			}
		}
		
		if(cg != null) {
			
			for(CardObj cardObj : cardInhand) {
				cg.card_list.add(cardObj);
			}
			cg.card_list_mp = CardUtil.toTArray(cg.card_list);
		}
		
		return cg;
	}

	private static int getMaxCardNum(Map<Integer, Integer> cardMap) {
		int maxNum = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			if (entry.getValue() > maxNum) {
				maxNum = entry.getValue();
			}
		}

		return maxNum;
	}

	public static boolean isConfig4_2_and_4_3(ITObject roomConfig) {
		if((roomConfig.containsKey(Config.ROOM_CONFIG_SIDAI_2) && roomConfig.getBoolean(Config.ROOM_CONFIG_SIDAI_2))
				||(roomConfig.containsKey(Config.ROOM_CONFIG_SIDAI_3) && roomConfig.getBoolean(Config.ROOM_CONFIG_SIDAI_3))){
			return true;
		} else {
			return false;
		}
	}
	
	private static CardGroup checkTwo(Map<Integer, Integer> cardMap) {
		
		CardGroup cg = null;
		
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			if(entry.getValue() == 2) {
				cg = new CardGroup();
				cg.card_list = new ArrayList<>();
				cg.config = CardConfig.DUIZI;
				cg.min_card = entry.getKey();
				cg.len = 1;
			}
		}
		
		return cg;
	}
	
	private static CardGroup checkThree(Map<Integer, Integer> cardMap,ITObject roomConfig) {
		
		CardGroup cg = null;
		
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			
			if(entry.getValue() == 3) {
				
				boolean bThreeA = false;
				if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
					bThreeA = true;
				}
				
				if(entry.getKey() == RoomCard.CARD_A && bThreeA == true) {
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.ZHA;
					cg.min_card = entry.getKey();
					cg.len = 1;
				}
				else
				{
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.SAN_2;
					cg.min_card = entry.getKey();
					cg.len = 1;
				}
			}
		}
		return cg;
	}
	
	private static CardGroup checkFour(Map<Integer, Integer> cardMap,ITObject roomConfig) {
		
		CardGroup cg = null;
		
		int minCard = 0;
		int maxCard = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			
			if(entry.getValue() == 4) {
				
				cg = new CardGroup();
				cg.card_list = new ArrayList<>();
				cg.config = CardConfig.ZHA;
				cg.min_card = entry.getKey();
				cg.len = 1;
			}
			else if(entry.getValue() == 3) {
				
				boolean bThreeA = false;
				if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
					bThreeA = true;
				}
				
				if(entry.getKey() == RoomCard.CARD_A && bThreeA) {
					return cg;
				}
				
				cg = new CardGroup();
				cg.card_list = new ArrayList<>();
				cg.config = CardConfig.SAN_2;
				cg.min_card = entry.getKey();
				cg.len = 1;
			}
			else if(entry.getValue() == 2) {
				
				if(minCard == 0 || entry.getKey() < minCard) {
					minCard = entry.getKey();
				}
				
				if(maxCard == 0 || entry.getKey() > maxCard) {
					maxCard = entry.getKey();
				}
				
				if(minCard != 0 && maxCard != 0 && minCard + 1 == maxCard) {
					
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.LIANDUI;
					cg.min_card = minCard;
					cg.len = 2;
				}
			}
		}
		return cg;
	}
	
	private static CardGroup checkFive(Map<Integer, Integer> cardMap,ITObject roomConfig,boolean bSpecial) {
		
		CardGroup cg = null;
		
		int minCard = 0;
		int maxCard = 0;
		int count = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			
			if(entry.getValue() == 3 /*|| (entry.getValue() == 4 && bSpecial == true)*/) {
				
				boolean bThreeA = false;
				if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
					bThreeA = true;
				}
				
				if(entry.getKey() == RoomCard.CARD_A && bThreeA) {
					return cg;
				}
				
				if(!roomConfig.containsKey(Config.ROOM_CONFIG_SANDAIDAN) || roomConfig.getInt(Config.ROOM_CONFIG_SANDAIDAN) == 0) {
					
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.SAN_2;
					cg.min_card = entry.getKey();
					cg.len = 1;
				}
				else {
					
					if(entry.getValue() != 4 && cardMap.size() == 2) {
						cg = new CardGroup();
						cg.card_list = new ArrayList<>();
						cg.config = CardConfig.SAN_2;
						cg.min_card = entry.getKey();
						cg.len = 1;
					}
				}
				
				
				break;
			}
			else if(entry.getValue() == 1 && entry.getKey() != RoomCard.CARD_2) {
				
				if(minCard == 0 || entry.getKey() < minCard) {
					minCard = entry.getKey();
				}
				
				if(maxCard == 0 || entry.getKey() > maxCard) {
					maxCard = entry.getKey();
				}
				count++;
				
				if(count == 5 && minCard != 0 && maxCard != 0 && minCard + 4 == maxCard) {
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.SHUNZI;
					cg.min_card = minCard;
					cg.len = 5;
				}
			}
		}
			
		return cg;
	}

	public static CardGroup checkSiWithTwo(Map<Integer, Integer> cardMap,ITObject roomConfig) {

		CardGroup cg = null;

		int minCard = 0;
		int maxCard = 0;
		int count = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {

			if(entry.getValue() == 4) {
				if(roomConfig.containsKey(Config.ROOM_CONFIG_SIDAI_2) && roomConfig.getBoolean(Config.ROOM_CONFIG_SIDAI_2)) {
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.SI_2;
					cg.min_card = entry.getKey();
					cg.len = 1;
				}

				break;
			}
		}

		return cg;
	}

	public static CardGroup checkSiWithThree(Map<Integer, Integer> cardMap,ITObject roomConfig) {

		CardGroup cg = null;

		int minCard = 0;
		int maxCard = 0;
		int count = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {

			if(entry.getValue() == 4) {
				if(roomConfig.containsKey(Config.ROOM_CONFIG_SIDAI_3) && roomConfig.getBoolean(Config.ROOM_CONFIG_SIDAI_3)) {
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.SI_3;
					cg.min_card = entry.getKey();
					cg.len = 1;
				}

				break;
			}
		}

		return cg;
	}
	
	private static CardGroup checkShunzi(int len,Map<Integer, Integer> cardMap,ITObject roomConfig) {
		
		CardGroup cg = null;
		
		int minCard = 0;
		int maxCard = 0;
		int count = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			
			if(entry.getValue() == 1 && entry.getKey() != RoomCard.CARD_2) 
			{
				if(minCard == 0 || entry.getKey() < minCard) {
					minCard = entry.getKey();
				}
				
				if(maxCard == 0 || entry.getKey() > maxCard) {
					maxCard = entry.getKey();
				}
				count++;
				
				if(count == len && minCard != 0 && maxCard != 0 && minCard + len - 1 == maxCard) {
					
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.SHUNZI;
					cg.min_card = minCard;
					cg.len = count;
				}
			}
			else
			{
				break;
			}
		}
		
		return cg;
	}
	
	private static CardGroup checkLiandui(int len,Map<Integer, Integer> cardMap,ITObject roomConfig) {
		
		CardGroup cg = null;
		int minCard = 0;
		int maxCard = 0;
		int count = 0;
		
		if(len % 2 != 0) {
			return cg;
		}
		
		len = len / 2;
		
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			
			if(entry.getValue() == 2) 
			{
				if(minCard == 0 || entry.getKey() < minCard) {
					minCard = entry.getKey();
				}
				
				if(maxCard == 0 || entry.getKey() > maxCard) {
					maxCard = entry.getKey();
				}
				count++;
				
				if(count == len && minCard != 0 && maxCard != 0 && minCard + len - 1 == maxCard) {
					
					cg = new CardGroup();
					cg.card_list = new ArrayList<>();
					cg.config = CardConfig.LIANDUI;
					cg.min_card = minCard;
					cg.len = count;
				}
			}
			else
			{
				break;
			}
		}
		return cg;
	}
	
	private static CardGroup checkFeiji(int len,Map<Integer, Integer> cardMap,ITObject roomConfig,boolean bSpecial) {
		
		CardGroup cg = null;
		
		int[] cardThreeCount = { 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0};
		
		boolean bThreeA = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
			bThreeA = true;
		}
		
		int num2 = 0;
		for(Map.Entry<Integer,Integer> entry : cardMap.entrySet()) {
			
			// 如果有炸弹 则不允许自动出牌
			if(bSpecial == false && (entry.getValue() == 4 || (entry.getKey() == RoomCard.CARD_A && entry.getValue() == 3 && bThreeA == true))) {
				return cg;
			}
			
			if(entry.getValue() >= 3) {
				cardThreeCount[entry.getKey()] = 1;
			}
			else if(entry.getValue() == 2) {
				num2++;
			}
		}
		
		int left = 0;
		int right = 0;
		
		for(int i = 4; i < cardThreeCount.length; i++) {
			
			if(left == 0) {
				
				if(cardThreeCount[i] == 1 && cardThreeCount[i  - 1] == 1) {
					left = i - 1;
					right = i;
				}
			}
			else {
				// 如果有连续的继续寻找
				if(cardThreeCount[i] == 1 && right + 1 == i) {
					
					right = i;
				}
				else
				{
					left = 0;
					right = 0;
				}
			}
			// 判断出来一个顺子，就判定一下是否可以全部出
			if(left != 0 && right != 0) {
				
				int threeCount = right - left + 1;
				int sl = threeCount * 5;
				
				if(!roomConfig.containsKey(Config.ROOM_CONFIG_SANDAIDAN) || roomConfig.getInt(Config.ROOM_CONFIG_SANDAIDAN) == 0) {
					
					if(len <= sl) {
						cg = new CardGroup();
						cg.card_list = new ArrayList<>();
						cg.config = CardConfig.FEIJI;
						cg.min_card = left;
						cg.len = threeCount;
						
						return cg;
					}
				}else {
					
					int withMin = threeCount * 4;
					if(len == withMin || num2 == threeCount || len == threeCount * 3) {
						
						cg = new CardGroup();
						cg.card_list = new ArrayList<>();
						cg.config = CardConfig.FEIJI;
						cg.min_card = left;
						cg.len = threeCount;
						
						return cg;
					}
				}
				
			}
		}
		
		return cg;
	}
	
	/**
	 * 自动出牌
	 * @param cardInhand
	 * @param roomConfig
	 * @return
	 */
	public static CardGroup autoOut(List<CardObj> cardInhand,ITObject roomConfig) {
		
		CardGroup cg = null;
		
		//支持3A炸弹
		boolean bThreeA = false;
		if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
			bThreeA = true;
		}
		
		// 寻找炸弹
		Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(cardInhand);
		for(Map.Entry<Integer, Integer> entry : cardMap.entrySet()) {
			
			if(entry.getValue() == 4 || ( entry.getKey() == RoomCard.CARD_A && bThreeA == true && entry.getValue() == 3)) {
				
				cg = new CardGroup();
				List<CardObj> out_list = new ArrayList<>();
				
				cg.card_list = out_list;
				cg.config = CardConfig.ZHA;
				cg.min_card = entry.getKey();
				cg.len = 1;
				
				for(CardObj cardObj :cardInhand) {
					
					if(cardObj.cardMod == entry.getKey()) {
						out_list.add(cardObj);
					}
				}
			}
		}
		
		return cg;
	}
	
	
	/**
	 * 验证牌型
	 * @param ct
	 * @param left_count
	 * @return
	 */
	public static boolean tryType(CardGroup ct,int left_count,ITObject roomConfig) {
		List<CardObj> cardInhand = ct.card_list;
		int size = cardInhand.size();
		CardConfig config = ct.config;
		if(size <config.min_card_num || size > config.max_card_num) {
			return false;
		}
		int len = ct.len;
		if(len<config.min_len) {
			return false;
		}
		// 牌型所需要的正常牌数
		int tem_size = len*config.repeat_num + len*config.with_card_num;
		

		
		if(!roomConfig.containsKey(Config.ROOM_CONFIG_SANDAIDAN) 
				|| roomConfig.getInt(Config.ROOM_CONFIG_SANDAIDAN) == 0 
				|| (ct.config.type != Config.TYPE_3_2 && ct.config.type != Config.TYPE_FEIJI)) {
			
			//  如果牌型可以带牌 并且手牌的剩余数等于出牌的数目（全出了）
			if(config.with_card_num > 0 && size == left_count) {
				// 牌太少了                                        出牌太多了
				if(size < len*config.repeat_num || size > tem_size) {
					return false;
				}
				// 如果带的牌不够
				if(size < tem_size) {
					// 如果是三张  或者三带
					if(ct.config.type == Config.TYPE_3_2) {
						if(roomConfig.getInt(Config.ROOM_CONFIG_THREE_LACK) == 0){
							return false;
						}
					}
					// 如果是飞机
					else if(ct.config.type == Config.TYPE_FEIJI) {
						if(roomConfig.getInt(Config.ROOM_CONFIG_PLANE_LACK) == 0){
							return false;
						}
					}
				}
			}
			//没有带牌 没有全出
			else {
				if(tem_size!=size) {
					return false;
				}
			}
		}
		
		int min_card = ct.min_card;
		int max_card = min_card+len -1;
		if(len>1&&max_card>14) {
			return false;
		}
		
		Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(cardInhand);
		for(int i=min_card;i<=max_card;++i) {
			if(!cardMap.containsKey(i)) {
				return false;
			}
			if(cardMap.get(i) < config.repeat_num) {
				return false;
			}
		}
		return true;
	}
	


	/**
	 * 比牌大小
	 * @param banker
	 * @param other
	 * @return
	 */
	public final static boolean tryCompete(CardGroup banker, CardGroup other,ITObject roomConfig) {
		int bankerCradType = banker.config.type;
		int otherCradType = other.config.type;
		
		if(bankerCradType !=Config.TYPE_ZHA&& otherCradType == Config.TYPE_ZHA) {
			return true;
		}
		if(bankerCradType != otherCradType) {
			return false;
		}
		
		if(other.min_card > banker.min_card) {
			if(otherCradType == Config.TYPE_ZHA) {
				
				return true;
			}
			else
			{
			
				if(other.len == banker.len) {
					
					if(otherCradType == Config.TYPE_3_2 || otherCradType == Config.TYPE_FEIJI) {
						
						boolean sandaidan = roomConfig.containsKey(Config.ROOM_CONFIG_SANDAIDAN) && roomConfig.getInt(Config.ROOM_CONFIG_SANDAIDAN) == 1;
						if(sandaidan) {
							if(other.card_list.size() != banker.card_list.size()) {
								return false;
							}
						}
					}
					
					return true;
				}
				else
				{
					return false;
				}
			}
		}
	
		return false;
	}
	

	public final static CardGroup tryBig(List<CardObj> cardInhand,CardGroup other) {
		
		List<CardObj> card_list = new ArrayList<CardObj>();
		int size = cardInhand.size();
		CardConfig config = other.config;
		Map<Integer, List<CardObj>> cardMap = null;
		int len = other.len;
		
		if(size >= len*config.repeat_num) {
			
			int min_card = other.min_card + 1;//最小的数字是9   加一，下一位玩家需要出的牌时从10开始
			
			int max_card = min_card+len -1; //最小的数字加上上家玩家牌的长度。就是下家玩家需要出牌的张数
			
			if(!(len>1&&max_card>14)) {//长度如果大于一并且最大的牌
				
				int count =0;
				cardMap = CardUtil.getCardListMap(cardInhand);
				int max = len>1?14:15;
				for(int i=min_card;i<=max;++i) {
					
					List<CardObj> list =cardMap.get(i);
					
					if(cardMap.containsKey(i)&&list.size() >=config.repeat_num) {
						
						//不出炸牌
						if(other.config.type !=Config.TYPE_ZHA && list.size()>=4) {
							count=0;
							card_list.clear();
							continue;
						}
						
						for(int k=0;k<config.repeat_num;++k) {
							card_list.add(list.get(k));
						}
						count++; 
						if(count == len) {
							CardGroup ct = new CardGroup();
							ct.config = other.config;
							ct.card_list = card_list;
							ct.len = len;
							ct.min_card = card_list.get(0).cardMod;
							if(config.with_card_num>0) {
								List<CardObj> tem_list = new ArrayList<CardObj>();
								tem_list.addAll(cardInhand);
								CardUtil.removeCard(tem_list, card_list);
								
								//不把炸牌带出去
								int rcard_size = 0;
								rcard:
								for(int k=0;k<tem_list.size();++k) {
									int card = tem_list.get(k).cardMod;
									List<CardObj> tem_list1 = cardMap.get(card);
									if(tem_list1.size()>=4) {
										CardUtil.removeCard(tem_list, tem_list1);
										rcard_size += 4;
										break rcard;
									}
								}
								int with_card_size = config.with_card_num * len;
								if(rcard_size == 0) {
									with_card_size = tem_list.size()<with_card_size?tem_list.size():with_card_size;
								}
								if(tem_list.size()<with_card_size) {
									break;
								}
								for(int k=0;k<with_card_size;++k) {
									card_list.add(tem_list.get(k));
								}
							}
							return ct;
						}
					}else {
						count=0;
						card_list.clear();
					}
				}
			}
		}

		if(other.config.type !=Config.TYPE_ZHA && cardInhand.size()>=4) {
			if(cardMap==null) {
				cardMap = CardUtil.getCardListMap(cardInhand);
			}
			
			for (Entry<Integer, List<CardObj>> entry : cardMap.entrySet()) {
				int card = entry.getKey();
				List<CardObj> list = entry.getValue();
				if(list.size() >=4) {
					CardGroup ct = new CardGroup();
					ct.config = CardConfig.ZHA;
					ct.card_list = list;
					ct.len = 1;
					ct.min_card = card;
					return ct;
				}
			}
		}
		return null;
	}
	
	public static boolean  checkStartSpring(List<CardObj> cardInhand) {
		
		boolean bRet = false;
		Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(cardInhand);
		
		if(cardMap.getOrDefault(RoomCard.CARD_3, 0) == 4) {
			
			bRet = true;
		}
		else if(cardMap.getOrDefault(RoomCard.CARD_2, 0) == 1 && cardMap.getOrDefault(RoomCard.CARD_A, 0) == 3){
			
			bRet = true;
		}
		
		
		return bRet;
	}
	

	public static void main(String[] args) {

		ITObject test = new TObject();
		ITArray card_list = new TArray();
		card_list.addInt(215);
		card_list.addInt(114);
		card_list.addInt(303);
		card_list.addInt(204);
		card_list.addInt(205);
		//card_list.addInt(307);
		//card_list.addInt(207);
		test.putInt("sidaiyi",0);
		test.putInt("threeA",1);
		test.putInt("threelack",1);
		test.putInt("fourBeltThree",1);
		List<CardObj>  tlist = CardUtil.toList(card_list);
	//	System.out.println(tlist);
		CardGroup ct = CardCheck.getType(tlist, test );
		//Boolean  a = CardCheck.tryType(ct,4,test);
	//	System.out.println(ct);
		//System.out.println(a);
		
	}
}
