lashuju

172 阅读11分钟
package com.cokutau.game.pjc3.statjob.dish.purchaser;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

import org.w3c.dom.Element;

import com.cokutau.common.dbconnector.Db;
import com.cokutau.common.dbconnector.DbGroup;
import com.cokutau.common.dbconnector.DbManager;
import com.cokutau.common.dbconnector.DbNames;
import com.cokutau.common.dbconnector.ResultSetConvertor;
import com.cokutau.common.dbconnector.RowVisitor;
import com.cokutau.common.kumisc.config.CommonConfig;
import com.cokutau.common.kumisc.config.CommonConfigManager;
import com.cokutau.common.kumisc.config.CommonDefine;
import com.cokutau.common.kumisc.statdish.MergeType;
import com.cokutau.common.kumisc.statdish.StatData;
import com.cokutau.common.kumisc.statdish.StatDataCommon;
import com.cokutau.common.kumisc.statdish.StatDishContext;
import com.cokutau.common.kumisc.statdish.ValueType;
import com.cokutau.common.kumisc.statdish.purchaser.AbstractStatPurchaser;
import com.cokutau.common.utils.KuCollectionUtil;
import com.cokutau.common.utils.KuStringUtil;
import com.cokutau.common.utils.KuXmlUtil;
import com.cokutau.common.utils.substitute.SubstituteContext;
import com.cokutau.job.common.JobLogger;

public class StatPurchaser_TopMajestyHeroTeamCultivateInfo extends AbstractStatPurchaser {
	
	private static final Comparator<TopMajesty> COMPARATOR_TOP_MAJESTY = Comparator.comparingLong(TopMajesty::getBattleAbility).reversed();
	private static final Comparator<HeroInfo> COMPARATOR_HERO_INFO = Comparator.comparingLong(HeroInfo::getBattleAbility).reversed();
	private static final int POSITION_NUM = 5;
	private static final int EQUIP_NUM = 4;
	private static final int TREASURE_NUM = 2;
	private static final int LAST_DIMENSION_INDEX = 1;// !!!!

	private final int topNum;

	public StatPurchaser_TopMajestyHeroTeamCultivateInfo(Element element, SubstituteContext substituteContext) {
		super(element, substituteContext);
		this.topNum = KuXmlUtil.getAttributeAsInt(element, "topNum", 100);
	}

	@Override
	public StatData purchase(StatDishContext context) throws Throwable {
		// 维度
		String[] dimensionNames = { "UserId", "#Value" };
//		String[] dimensionNames = { "ZoneId", "Rank", "#Value" };
		List<ValueType> valueTypeList = new ArrayList<>();
		valueTypeList.add(new ValueType("#Value", "玩家编号", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "玩家名", MergeType.ANYONE, ""));
		valueTypeList.add(new ValueType("#Value", "所在服", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "开服时间", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "名次", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "战力", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "VIP等级", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "等级", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "登录天数", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "注册时间", MergeType.ANYONE, null));
		valueTypeList.add(new ValueType("#Value", "最近登录时间", MergeType.ANYONE, null));
		valueTypeList.add(new ValueType("#Value", "最近登出时间", MergeType.ANYONE, null));
		valueTypeList.add(new ValueType("#Value", "在线总分钟", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "账号编号", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "渠道编号", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "主公品质", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "当前战斗力", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "最高战斗力", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "全队穿戴将星数", MergeType.SUM, 0));
		valueTypeList.add(new ValueType("#Value", "全队紫色将星数", MergeType.SUM, 0));
		valueTypeList.add(new ValueType("#Value", "全队橙色将星数", MergeType.SUM, 0));
		valueTypeList.add(new ValueType("#Value", "全队红色将星数", MergeType.SUM, 0));
		valueTypeList.add(new ValueType("#Value", "军团编号", MergeType.ANYONE, 0));
		valueTypeList.add(new ValueType("#Value", "军团名字", MergeType.ANYONE, ""));
		for (int heroNumber = 1; heroNumber <= POSITION_NUM; heroNumber++) {
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将名称", heroNumber) , MergeType.ANYONE, "无"));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将品质", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将战力", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将进阶等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将天命等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将觉醒等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均装备品级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均装备等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均装备精炼等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均装备觉醒等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均配饰品级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均配饰等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将平均配饰精炼等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将宝物等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将宝物进阶等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将战马名称", heroNumber) , MergeType.ANYONE, "无"));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将战马资质", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将战马等级", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将战马星数", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将穿戴将星数", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将紫色将星数", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将橙色将星数", heroNumber) , MergeType.ANYONE, 0));
			valueTypeList.add(new ValueType("#Value", String.format("战力第%s武将红色将星数", heroNumber) , MergeType.ANYONE, 0));
		}
		System.out.println(KuStringUtil.join(valueTypeList.stream().map(v -> v.item).iterator(), ","));
		StatDataCommon statData = new StatDataCommon(dimensionNames, valueTypeList);
		for (ValueType valueType : valueTypeList) {
			for (int dimensionIndex = 0; dimensionIndex < dimensionNames.length; dimensionIndex++) {
				if (dimensionNames[dimensionIndex].equals(valueType.dimensionName)) {
					statData.addItem(dimensionIndex, valueType.item, false);
					break;
				}
			}
		}
		Object[] itemsTemplate = new Object[dimensionNames.length];
		//
		Map<Db, Map<Long, TopMajesty>> userDb2TopMajestyMap = queryUserDb2TopMajestyMap();
		//
		CommonConfig zoneConfig = CommonConfigManager.instance.getCommonConfigByStr("Zone");
		CommonConfig heroConfig = CommonConfigManager.instance.getCommonConfigByStr("Hero");
		CommonConfig equipConfig = CommonConfigManager.instance.getCommonConfigByStr("Equip");
		CommonConfig treasureConfig = CommonConfigManager.instance.getCommonConfigByStr("Treasure");
		CommonConfig horseConfig = CommonConfigManager.instance.getCommonConfigByStr("Horse");
		CommonConfig jinNangConfig = CommonConfigManager.instance.getCommonConfigByStr("JinNang");
		for (Entry<Db, Map<Long, TopMajesty>> e : userDb2TopMajestyMap.entrySet()) {
			Db userDb = e.getKey();
			JobLogger.getDefaultLogger().info("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> handle userDb. userDbName={}", userDb.getName());
			Map<Long, TopMajesty> topMajestyMap = e.getValue();
			String strUserIds = KuStringUtil.join(topMajestyMap.keySet().iterator(), ",");
			if (strUserIds.isEmpty()) {
				continue;
			}
			queryMajestyTable(userDb, strUserIds, statData, itemsTemplate, zoneConfig, topMajestyMap);
			queryUserDataTable(userDb, strUserIds, statData, itemsTemplate, topMajestyMap);
			queryUserOnlineRecordTable(userDb, strUserIds, statData, itemsTemplate, topMajestyMap);
			queryHeroTable(userDb, strUserIds, topMajestyMap);
			queryEquipTable(userDb, strUserIds, topMajestyMap);
			queryTreasureTable(userDb, strUserIds, topMajestyMap);
			queryBaoWuTable(userDb, strUserIds, topMajestyMap);
			queryHorseTable(userDb, strUserIds, topMajestyMap);
			queryJinNangTable(userDb, strUserIds, topMajestyMap);
			//
			addStatData(statData, itemsTemplate, heroConfig, equipConfig, treasureConfig, horseConfig, jinNangConfig, topMajestyMap);
			// let gc go
			topMajestyMap.clear();
		}
		return statData;
	}

	private void addStatData(StatDataCommon statData, Object[] itemsTemplate, CommonConfig heroConfig, CommonConfig equipConfig, CommonConfig treasureConfig, CommonConfig horseConfig, CommonConfig jinNangConfig, Map<Long, TopMajesty> topMajestyMap) {
		for (TopMajesty topMajesty : topMajestyMap.values()) {
			itemsTemplate[0] = topMajesty.getUserId();
//			itemsTemplate[0] = topMajesty.getZoneId();
//			itemsTemplate[1] = topMajesty.getRank();
			List<HeroInfo> heroInfoList = topMajesty.getHeroInfoList();
			if (heroInfoList.isEmpty()) {
				continue;
			}
			topMajesty.clearHeroInfoMap();
			Collections.sort(heroInfoList, COMPARATOR_HERO_INFO);
			for (int heroNumber = 1; heroNumber <= heroInfoList.size(); heroNumber++) {
				HeroInfo heroInfo = heroInfoList.get(heroNumber - 1);
				String strHeroDefineId = String.valueOf(heroInfo.getHeroDefineId());
				int quality = heroInfo.getQuality();
				String heroDefineName = strHeroDefineId;
				CommonDefine heroDefine = heroConfig.getItem(strHeroDefineId);
				if (heroDefine != null) {
					quality = Math.max(Integer.parseInt(String.valueOf(heroDefine.get("quality"))), quality);
					heroDefineName = String.valueOf(heroDefine.get("name"));
				}
				addStatData(statData, itemsTemplate, String.format("战力第%s武将名称", heroNumber), heroDefineName);
				addStatData(statData, itemsTemplate, String.format("战力第%s武将品质", heroNumber), quality);
				addStatData(statData, itemsTemplate, String.format("战力第%s武将战力", heroNumber), heroInfo.getBattleAbility());
				addStatData(statData, itemsTemplate, String.format("战力第%s武将等级", heroNumber), heroInfo.getLevel());
				addStatData(statData, itemsTemplate, String.format("战力第%s武将进阶等级", heroNumber), heroInfo.getStep());
				addStatData(statData, itemsTemplate, String.format("战力第%s武将天命等级", heroNumber), heroInfo.getFateLevel());
				addStatData(statData, itemsTemplate, String.format("战力第%s武将觉醒等级", heroNumber), heroInfo.getWakeLevel());
				//
				double equipAvgGrade = heroInfo.getEquipInfoList().stream().mapToDouble(e -> {
					CommonDefine item = equipConfig.getItem(String.valueOf(e.defineId));
					return item == null? 0 : Integer.parseInt(String.valueOf(item.get("grade")));
				}).sum() / EQUIP_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均装备品级", heroNumber), equipAvgGrade);
				double equipAvgStrengthenLevel = heroInfo.getEquipInfoList().stream().mapToDouble(e -> e.strengthenLevel).sum() / EQUIP_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均装备等级", heroNumber), equipAvgStrengthenLevel);
				double equipAvgRefineLevel = heroInfo.getEquipInfoList().stream().mapToDouble(e -> e.refineLevel).sum() / EQUIP_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均装备精炼等级", heroNumber), equipAvgRefineLevel);
				double equipAvgWakeLevel = heroInfo.getEquipInfoList().stream().mapToDouble(e -> e.wakeLevel).sum() / EQUIP_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均装备觉醒等级", heroNumber), equipAvgWakeLevel);
				//
				double treasureAvgGrade = heroInfo.getTreasureInfoList().stream().mapToDouble(e -> {
					CommonDefine item = treasureConfig.getItem(String.valueOf(e.defineId));
					return item == null? 0 : Integer.parseInt(String.valueOf(item.get("grade")));
				}).sum() / TREASURE_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均配饰品级", heroNumber), treasureAvgGrade);
				double treasureAvgStrengthenLevel = heroInfo.getTreasureInfoList().stream().mapToDouble(e -> e.strengthenLevel).sum() / TREASURE_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均配饰等级", heroNumber), treasureAvgStrengthenLevel);
				double treasureAvgRefineLevel = heroInfo.getTreasureInfoList().stream().mapToDouble(e -> e.refineLevel).sum() / TREASURE_NUM;
				addStatData(statData, itemsTemplate, String.format("战力第%s武将平均配饰精炼等级", heroNumber), treasureAvgRefineLevel);
				//
				BaoWuInfo baoWuInfo = heroInfo.getBaoWuInfo();
				if (baoWuInfo != null) {
					addStatData(statData, itemsTemplate, String.format("战力第%s武将宝物等级", heroNumber), baoWuInfo.strengthenLevel);
					addStatData(statData, itemsTemplate, String.format("战力第%s武将宝物进阶等级", heroNumber), baoWuInfo.advanceLevel);
				}
				//
				HorseInfo horseInfo = heroInfo.getHorseInfo();
				if (horseInfo != null) {
					String strHorseDefineId = String.valueOf(horseInfo.defineId);
					String horseDefineName = strHorseDefineId;
					int grade = 0;
					CommonDefine horseDefine = horseConfig.getItem(strHorseDefineId);
					if (horseDefine != null) {
						horseDefineName = String.valueOf(horseDefine.get("name"));
						grade = Integer.parseInt(String.valueOf(horseDefine.get("grade")));
					}
					addStatData(statData, itemsTemplate, String.format("战力第%s武将战马名称", heroNumber), horseDefineName);
					addStatData(statData, itemsTemplate, String.format("战力第%s武将战马资质", heroNumber), grade);
					addStatData(statData, itemsTemplate, String.format("战力第%s武将战马等级", heroNumber), horseInfo.level);
					addStatData(statData, itemsTemplate, String.format("战力第%s武将战马星数", heroNumber), horseInfo.star);
				}
				//
				List<Integer> jinNangDefineIdList = heroInfo.getJinNangDefineIdList();
				if (KuCollectionUtil.isNotEmpty(jinNangDefineIdList)) {
					int purpleNum = 0, orangeNum = 0, redNum = 0;
					for (Integer jinNangDefineId : jinNangDefineIdList) {
						String strJinNangDefineId = String.valueOf(jinNangDefineId);
						CommonDefine jinNangDefine = jinNangConfig.getItem(strJinNangDefineId);
						if (jinNangDefine != null) {
							String strQuality = String.valueOf(jinNangDefine.get("quality"));
							if ("4".equals(strQuality)) {
								purpleNum++;
							} else if ("5".equals(strQuality)) {
								orangeNum++;
							} else if ("6".equals(strQuality)) {
								redNum++;
							}
						}
					}
					if (jinNangDefineIdList.size() > 0) {
						addStatData(statData, itemsTemplate, String.format("战力第%s武将穿戴将星数", heroNumber), jinNangDefineIdList.size());
						addStatData(statData, itemsTemplate, "全队穿戴将星数", jinNangDefineIdList.size());
					}
					if (purpleNum > 0) {
						addStatData(statData, itemsTemplate, String.format("战力第%s武将紫色将星数", heroNumber), purpleNum);
						addStatData(statData, itemsTemplate, "全队紫色将星数", purpleNum);
					}
					if (orangeNum > 0) {
						addStatData(statData, itemsTemplate, String.format("战力第%s武将橙色将星数", heroNumber), orangeNum);
						addStatData(statData, itemsTemplate, "全队橙色将星数", orangeNum);
					}
					if (redNum > 0) {
						addStatData(statData, itemsTemplate, String.format("战力第%s武将红色将星数", heroNumber), redNum);
						addStatData(statData, itemsTemplate, "全队红色将星数", redNum);
					}
				}
			}
		}
	}
	
	private void queryJinNangTable(Db userDb, String strUserIds, Map<Long, TopMajesty> topMajestyMap) {
		String sqlTemplate = "SELECT a.PositionId,a.UserId,b.DefineId FROM" + 
				"(SELECT * FROM `H_HeroTeamBattlePosition` WHERE TeamType=1 AND JinNangUIds<>'') a RIGHT JOIN" + 
				"(SELECT * FROM `M_JinNang` WHERE Place<>0) b ON a.UserId=b.UserId" + 
				" WHERE FIND_IN_SET(b.UId,REPLACE(a.JinNangUIds,'#',',')) AND a.PositionId IS NOT NULL AND a.UserId IN (#USER_IDS#)";
		String sql = sqlTemplate.replace("#USER_IDS#", strUserIds);
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryJinNangTable! userId={}", userId);
					return;
				}
				int positionId = rs.getInt("PositionId");
				HeroInfo heroInfo = topMajesty.getHeroInfoNotNull(positionId);
				int defineId = rs.getInt("DefineId");
				heroInfo.addJinNangDefineId(defineId);
			}
		});
	}
	
	private void queryHorseTable(Db userDb, String strUserIds, Map<Long, TopMajesty> topMajestyMap) {
		String sqlTemplate = "SELECT a.PositionId,a.UserId,b.DefineId,b.Level,b.Star FROM `H_HeroTeamBattlePosition` a INNER JOIN `M_Horse` b ON a.UserId=b.UserId AND a.#UID#=b.UId AND a.#UID#<>0 AND a.TeamType=1 AND a.UserId IN (#USER_IDS#)";
		sqlTemplate = sqlTemplate.replace("#USER_IDS#", strUserIds);
		String sql = sqlTemplate.replace("#UID#", "HorseUId");
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryBaoWuTable! userId={}", userId);
					return;
				}
				int positionId = rs.getInt("PositionId");
				HeroInfo heroInfo = topMajesty.getHeroInfoNotNull(positionId);
				int defineId = rs.getInt("DefineId");
				int level = rs.getInt("Level");
				int star = rs.getInt("Star");
				HorseInfo horseInfo = new HorseInfo(defineId, level, star);
				heroInfo.setHorseInfo(horseInfo);
			}
		});
	}
	
	private void queryBaoWuTable(Db userDb, String strUserIds, Map<Long, TopMajesty> topMajestyMap) {
		String sqlTemplate = "SELECT a.PositionId,a.UserId,b.DefineId,b.StrengthenLevel,b.AdvanceLevel FROM `H_HeroTeamBattlePosition` a INNER JOIN `M_BaoWu` b ON a.UserId=b.UserId AND a.#UID#=b.UId AND a.#UID#<>0 AND a.TeamType=1 AND a.UserId IN (#USER_IDS#)";
		sqlTemplate = sqlTemplate.replace("#USER_IDS#", strUserIds);
		String sql = sqlTemplate.replace("#UID#", "BaoWuUId");
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryBaoWuTable! userId={}", userId);
					return;
				}
				int positionId = rs.getInt("PositionId");
				HeroInfo heroInfo = topMajesty.getHeroInfoNotNull(positionId);
				int defineId = rs.getInt("DefineId");
				int strengthenLevel = rs.getInt("StrengthenLevel");
				int advanceLevel = rs.getInt("AdvanceLevel");
				BaoWuInfo baoWuInfo = new BaoWuInfo(defineId, strengthenLevel, advanceLevel);
				heroInfo.setBaoWuInfo(baoWuInfo);
			}
		});
	}
	
	private void queryTreasureTable(Db userDb, String strUserIds, Map<Long, TopMajesty> topMajestyMap) {
		String sqlTemplate = "SELECT a.PositionId,a.UserId,b.DefineId,b.StrengthenLevel,b.RefineLevel FROM `H_HeroTeamBattlePosition` a INNER JOIN `M_Treasure` b ON a.UserId=b.UserId AND a.#UID#=b.UId AND a.#UID#<>0 AND a.TeamType=1 AND a.UserId IN (#USER_IDS#)";
		sqlTemplate = sqlTemplate.replace("#USER_IDS#", strUserIds);
		for (int equipNumber = 1; equipNumber <= TREASURE_NUM; equipNumber++) {
			String sql = sqlTemplate.replace("#UID#", String.format("TreasureUId%d", equipNumber));
			userDb.executeQuery(sql, new RowVisitor() {
				@Override
				public void visitRow(ResultSet rs) throws SQLException {
					Long userId = rs.getLong("UserId");
					TopMajesty topMajesty = topMajestyMap.get(userId);
					if (topMajesty == null) {
						JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryTreasureTable! userId={}", userId);
						return;
					}
					int positionId = rs.getInt("PositionId");
					HeroInfo heroInfo = topMajesty.getHeroInfoNotNull(positionId);
					int defineId = rs.getInt("DefineId");
					int strengthenLevel = rs.getInt("StrengthenLevel");
					int refineLevel = rs.getInt("RefineLevel");
					TreasureInfo treasureInfo = new TreasureInfo(defineId, strengthenLevel, refineLevel);
					heroInfo.addTreasureInfo(treasureInfo);
				}
			});
		}
	}
	
	private void queryEquipTable(Db userDb, String strUserIds, Map<Long, TopMajesty> topMajestyMap) {
		String sqlTemplate = "SELECT a.PositionId,a.UserId,b.DefineId,b.StrengthenLevel,b.RefineLevel,b.WakeLevel FROM `H_HeroTeamBattlePosition` a INNER JOIN `M_Equip` b ON a.UserId=b.UserId AND a.#UID#=b.UId AND a.#UID#<>0 AND a.TeamType=1 AND a.UserId IN (#USER_IDS#)";
		sqlTemplate = sqlTemplate.replace("#USER_IDS#", strUserIds);
		for (int equipNumber = 1; equipNumber <= EQUIP_NUM; equipNumber++) {
			String sql = sqlTemplate.replace("#UID#", String.format("EquipUId%d", equipNumber));
			userDb.executeQuery(sql, new RowVisitor() {
				@Override
				public void visitRow(ResultSet rs) throws SQLException {
					Long userId = rs.getLong("UserId");
					TopMajesty topMajesty = topMajestyMap.get(userId);
					if (topMajesty == null) {
						JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryEquipTable! userId={}", userId);
						return;
					}
					int positionId = rs.getInt("PositionId");
					HeroInfo heroInfo = topMajesty.getHeroInfoNotNull(positionId);
					int defineId = rs.getInt("DefineId");
					int strengthenLevel = rs.getInt("StrengthenLevel");
					int refineLevel = rs.getInt("RefineLevel");
					int wakeLevel = rs.getInt("WakeLevel");
					EquipInfo equipInfo = new EquipInfo(defineId, strengthenLevel, refineLevel, wakeLevel);
					heroInfo.addEquipInfo(equipInfo);
				}
			});
		}
	}
	
	private void queryHeroTable(Db userDb, String strUserIds, Map<Long, TopMajesty> topMajestyMap) {
		String sql = String.format("SELECT a.PositionId,b.UserId,b.HeroId,b.DefineId,b.Level,b.Step,b.Quality,b.WakeStar,b.WakeLevel,b.FateLevel,b.BattleAbility FROM `H_HeroTeamBattlePosition` a INNER JOIN `H_Hero` b ON a.UserId=b.UserId AND a.HeroId=b.HeroId AND a.TeamType=1 AND a.UserId IN (%s)", strUserIds);
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryHeroTable! userId={}", userId);
					return;
				}
				int positionId = rs.getInt("PositionId");
				HeroInfo heroInfo = topMajesty.getHeroInfoNotNull(positionId);
				heroInfo.setHeroUId(rs.getInt("HeroId"));
				heroInfo.setHeroDefineId(rs.getInt("DefineId"));
				heroInfo.setQuality(rs.getInt("Quality"));
				heroInfo.setBattleAbility(rs.getInt("BattleAbility"));
				heroInfo.setLevel(rs.getInt("Level"));
				heroInfo.setStep(rs.getInt("Step"));
				heroInfo.setFateLevel(rs.getInt("FateLevel"));
				heroInfo.setWakeLevel(10 * rs.getInt("WakeStar") + rs.getInt("WakeLevel"));
			}
		});
	}

	private void queryUserOnlineRecordTable(Db userDb, String strUserIds, StatDataCommon statData, Object[] itemsTemplate, Map<Long, TopMajesty> topMajestyMap) {
		String sql = String.format("SELECT UserId,SUM(OnlineSeconds) TotalOnlineSeconds FROM `UserOnlineRecord` WHERE UserId IN (%s) GROUP BY UserId", strUserIds);
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryUserOnlineRecordTable! userId={}", userId);
					return;
				}
				itemsTemplate[0] = userId;
//				itemsTemplate[0] = topMajesty.getZoneId();
//				itemsTemplate[1] = topMajesty.getRank();
				addStatData(statData, itemsTemplate, "在线总分钟", Math.ceil((double)rs.getLong("TotalOnlineSeconds") / 60));
			}
		});
	}
	
	private void queryUserDataTable(Db userDb, String strUserIds, StatDataCommon statData, Object[] itemsTemplate, Map<Long, TopMajesty> topMajestyMap) {
		String sql = String.format("SELECT UserId,LatestLoginTime,LatestLogoutTime FROM `UserData` WHERE UserId IN (%s)", strUserIds);
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryUserDataTable! userId={}", userId);
					return;
				}
				itemsTemplate[0] = userId;
//				itemsTemplate[0] = topMajesty.getZoneId();
//				itemsTemplate[1] = topMajesty.getRank();
				addStatData(statData, itemsTemplate, "最近登出时间", rs.getTimestamp("LatestLogoutTime"));
			}
		});
	}

	private void queryMajestyTable(Db userDb, String strUserIds, StatDataCommon statData, Object[] itemsTemplate, CommonConfig zoneConfig, Map<Long, TopMajesty> topMajestyMap) {
		String sql = String.format("SELECT UserId,Nickname,AccountId,PlatformId,VIPLevel,MajestyLevel,MajestyQuality,BattleAbility,BestBattleAbility,ArmyId,ArmyName,RegisterTime,LatestLoginTime,CumulatedLoginDays FROM `Majesty` WHERE UserId IN (%s)", strUserIds);
		userDb.executeQuery(sql, new RowVisitor() {
			@Override
			public void visitRow(ResultSet rs) throws SQLException {
				Long userId = rs.getLong("UserId");
				TopMajesty topMajesty = topMajestyMap.get(userId);
				if (topMajesty == null) {
					JobLogger.getDefaultLogger().warn("<StatPurchaser_TopMajestyHeroTeamCultivateInfo> topMajesty not exist while queryMajestyTable! userId={}", userId);
					return;
				}
				itemsTemplate[0] = userId;
//				itemsTemplate[0] = topMajesty.getZoneId();
//				itemsTemplate[1] = topMajesty.getRank();
				addStatData(statData, itemsTemplate, "玩家编号", userId);
				addStatData(statData, itemsTemplate, "玩家名", rs.getString("Nickname"));
				addStatData(statData, itemsTemplate, "所在服", topMajesty.getZoneId());
				CommonDefine zoneDefine = zoneConfig.getItem(String.valueOf(topMajesty.getZoneId()));
				Date zoneOpenDateTime = zoneDefine == null ? null : (Date) zoneDefine.get("OpenDateTime");
				addStatData(statData, itemsTemplate, "开服时间", zoneOpenDateTime);
				addStatData(statData, itemsTemplate, "名次", topMajesty.getRank());
				addStatData(statData, itemsTemplate, "战力", topMajesty.getBattleAbility());
				addStatData(statData, itemsTemplate, "VIP等级", rs.getInt("VIPLevel"));
				addStatData(statData, itemsTemplate, "等级", rs.getInt("MajestyLevel"));
				//
				addStatData(statData, itemsTemplate, "登录天数", rs.getInt("CumulatedLoginDays"));
				addStatData(statData, itemsTemplate, "注册时间", rs.getTimestamp("RegisterTime"));
				addStatData(statData, itemsTemplate, "最近登录时间", rs.getTimestamp("LatestLoginTime"));
				//
				addStatData(statData, itemsTemplate, "账号编号", rs.getLong("AccountId"));
				addStatData(statData, itemsTemplate, "渠道编号", rs.getInt("PlatformId"));
				addStatData(statData, itemsTemplate, "主公品质", rs.getInt("MajestyQuality"));
				addStatData(statData, itemsTemplate, "当前战斗力", rs.getLong("BattleAbility"));
				addStatData(statData, itemsTemplate, "最高战斗力", rs.getLong("BestBattleAbility"));
				addStatData(statData, itemsTemplate, "军团编号", rs.getInt("ArmyId"));
				String armyName = rs.getString("ArmyName");
				addStatData(statData, itemsTemplate, "军团名字", armyName == null ? "" : armyName);
			}
		});
	}

	private static void addStatData(StatDataCommon statData, Object[] itemsTemplate, String item, Object value) {
		itemsTemplate[LAST_DIMENSION_INDEX] = item;
		statData.addValue(itemsTemplate, value);
	}

	private Map<Db, Map<Long, TopMajesty>> queryUserDb2TopMajestyMap() {
		DbGroup userDbGroup = DbManager.getInstance().getDbGroup(DbNames.USER);
		Function<? super Integer, ? extends List<TopMajesty>> valueCreator1 = k -> new ArrayList<>(this.topNum);
		Map<Integer, List<TopMajesty>> zoneId2TopMajestyList = new HashMap<>();
		for (Db userDb : userDbGroup.getDbs()) {
			List<Integer> zoneIdList = userDb.executeQueryObjectList("SELECT DISTINCT ZoneId FROM `Majesty`", ResultSetConvertor.INTEGER);
			for (Integer zoneId : zoneIdList) {
				String sql = String.format("SELECT UserId,ZoneId,BattleAbility FROM `Majesty` WHERE ZoneId=? ORDER BY BattleAbility DESC,MajestyLevel DESC LIMIT %s", this.topNum);
				List<TopMajesty> tmpTopMajestyList = userDb.executeQueryObjectList(sql, new Object[] { zoneId }, TopMajesty.convertor);
				List<TopMajesty> topMajestyList = zoneId2TopMajestyList.computeIfAbsent(zoneId, valueCreator1);
				topMajestyList.addAll(tmpTopMajestyList);
			}
		}
		Function<? super Db, ? extends Map<Long, TopMajesty>> valueCreator2 = k -> new HashMap<>(this.topNum);
		Map<Db, Map<Long, TopMajesty>> userDb2TopMajestyMap = new HashMap<>();
		for (List<TopMajesty> topMajestyList : zoneId2TopMajestyList.values()) {
			topMajestyList.sort(COMPARATOR_TOP_MAJESTY);
			int rank = 0;
			for (TopMajesty majesty : topMajestyList) {
				if (rank >= this.topNum) {
					break;
				}
				rank++;
				Db userDb = userDbGroup.getDb(majesty.getUserId());
				Map<Long, TopMajesty> topMajestyMap = userDb2TopMajestyMap.computeIfAbsent(userDb, valueCreator2);
				majesty.setRank(rank);
				topMajestyMap.put(majesty.getUserId(), majesty);
			}
		}
		return userDb2TopMajestyMap;
	}

	private static class TopMajesty {
		private final long userId;
		private final int zoneId;
		private final long battleAbility;
		private int rank = 0;
		private Map<Integer, HeroInfo> heroInfoMap;

		public static final ResultSetConvertor<TopMajesty> convertor = new ResultSetConvertor<TopMajesty>() {
			@Override
			public TopMajesty convert(ResultSet rs) throws SQLException {
				long userId = rs.getLong("UserId");
				int zoneId = rs.getInt("ZoneId");
				long battleAbility = rs.getLong("BattleAbility");
				return new TopMajesty(userId, zoneId, battleAbility);
			}
		};

		public TopMajesty(long userId, int zoneId, long battleAbility) {
			super();
			this.userId = userId;
			this.zoneId = zoneId;
			this.battleAbility = battleAbility;
		}

		public long getUserId() {
			return userId;
		}

		public int getZoneId() {
			return zoneId;
		}

		public int getRank() {
			return rank;
		}

		public void setRank(int rank) {
			this.rank = rank;
		}

		public long getBattleAbility() {
			return battleAbility;
		}
		
		public HeroInfo getHeroInfoNotNull(Integer positionId) {
			if (this.heroInfoMap == null) {
				this.heroInfoMap = new HashMap<>(5);
			}
			HeroInfo heroInfo = this.heroInfoMap.get(positionId);
			if (heroInfo == null) {
				heroInfo = new HeroInfo();
				this.heroInfoMap.put(positionId, heroInfo);
			}
			return heroInfo;
		}
		
		public List<HeroInfo> getHeroInfoList() {
			if (this.heroInfoMap == null) {
				return Collections.emptyList();
			}
			return new ArrayList<>(this.heroInfoMap.values());
		}
		
		public void clearHeroInfoMap() {
			this.heroInfoMap = null;// let gc go
		}
		
	}
	
	private static class HeroInfo {
		
		private int heroUId;
		private int heroDefineId;
		private int quality;
		private long battleAbility;
		private int level;
		private int step;
		private int fateLevel;
		private int wakeLevel;
		private final List<EquipInfo> equipInfoList = new ArrayList<>(EQUIP_NUM);
		private final List<TreasureInfo> treasureInfoList = new ArrayList<>(TREASURE_NUM);
		private BaoWuInfo baoWuInfo = null;
		private HorseInfo horseInfo = null;
		private final List<Integer> jinNangDefineIdList = new ArrayList<>();
		
		public HeroInfo() {
			super();
		}

		@SuppressWarnings("unused")
		public int getHeroUId() {
			return heroUId;
		}

		public void setHeroUId(int heroUId) {
			this.heroUId = heroUId;
		}

		public int getHeroDefineId() {
			return heroDefineId;
		}

		public void setHeroDefineId(int heroDefineId) {
			this.heroDefineId = heroDefineId;
		}

		public int getQuality() {
			return quality;
		}

		public void setQuality(int quality) {
			this.quality = quality;
		}

		public long getBattleAbility() {
			return battleAbility;
		}

		public void setBattleAbility(long battleAbility) {
			this.battleAbility = battleAbility;
		}

		public int getLevel() {
			return level;
		}

		public void setLevel(int level) {
			this.level = level;
		}

		public int getStep() {
			return step;
		}

		public void setStep(int step) {
			this.step = step;
		}

		public int getFateLevel() {
			return fateLevel;
		}

		public void setFateLevel(int fateLevel) {
			this.fateLevel = fateLevel;
		}

		public int getWakeLevel() {
			return wakeLevel;
		}

		public void setWakeLevel(int wakeLevel) {
			this.wakeLevel = wakeLevel;
		}
		
		public List<EquipInfo> getEquipInfoList() {
			return equipInfoList;
		}
		
		public void addEquipInfo(EquipInfo equipInfo) {
			this.equipInfoList.add(equipInfo);
		}
		
		public List<TreasureInfo> getTreasureInfoList() {
			return treasureInfoList;
		}
		
		public void addTreasureInfo(TreasureInfo treasureInfo) {
			this.treasureInfoList.add(treasureInfo);
		}
		
		public BaoWuInfo getBaoWuInfo() {
			return baoWuInfo;
		}
		
		public void setBaoWuInfo(BaoWuInfo baoWuInfo) {
			this.baoWuInfo = baoWuInfo;
		}
		
		public HorseInfo getHorseInfo() {
			return horseInfo;
		}
		
		public void setHorseInfo(HorseInfo horseInfo) {
			this.horseInfo = horseInfo;
		}
		
		public void addJinNangDefineId(Integer jinNangDefineId) {
			this.jinNangDefineIdList.add(jinNangDefineId);
		}
		
		public List<Integer> getJinNangDefineIdList() {
			return jinNangDefineIdList;
		}
	}
	
	private static class EquipInfo {
		public final int defineId;
		public final int strengthenLevel;
		public final int refineLevel;
		public final int wakeLevel;
		public EquipInfo(int defineId, int strengthenLevel, int refineLevel, int wakeLevel) {
			super();
			this.defineId = defineId;
			this.strengthenLevel = strengthenLevel;
			this.refineLevel = refineLevel;
			this.wakeLevel = wakeLevel;
		}
	}
	
	private static class TreasureInfo {
		public final int defineId;
		public final int strengthenLevel;
		public final int refineLevel;
		public TreasureInfo(int defineId, int strengthenLevel, int refineLevel) {
			super();
			this.defineId = defineId;
			this.strengthenLevel = strengthenLevel;
			this.refineLevel = refineLevel;
		}
	}
	
	private static class BaoWuInfo {
		@SuppressWarnings("unused")
		public final int defineId;
		public final int strengthenLevel;
		public final int advanceLevel;
		public BaoWuInfo(int defineId, int strengthenLevel, int advanceLevel) {
			super();
			this.defineId = defineId;
			this.strengthenLevel = strengthenLevel;
			this.advanceLevel = advanceLevel;
		}
	}
	
	private static class HorseInfo {
		public final int defineId;
		public final int level;
		public final int star;
		public HorseInfo(int defineId, int level, int star) {
			super();
			this.defineId = defineId;
			this.level = level;
			this.star = star;
		}
	}
}