package server; import database.DatabaseConnection; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import tools.FileoutputUtil; import tools.StringUtil; public class RankingWorker { private static final Map<Integer, List<RankingInformation>> rankings = new HashMap(); private static final Map<String, Integer> jobCommands = new HashMap(); private static final List<PokemonInformation> pokemon = new ArrayList(); private static final List<PokedexInformation> pokemon_seen = new ArrayList(); private static final List<PokebattleInformation> pokemon_ratio = new ArrayList(); private static final List<Integer> itemSearch = new ArrayList(); public static Integer getJobCommand(String job) { return jobCommands.get(job); } public static Map<String, Integer> getJobCommands() { return jobCommands; } public static List<RankingInformation> getRankingInfo(int job) { return (List) rankings.get(job); } public static List<PokemonInformation> getPokemonInfo() { return pokemon; } public static List<PokedexInformation> getPokemonCaught() { return pokemon_seen; } public static List<PokebattleInformation> getPokemonRatio() { return pokemon_ratio; } public static List<Integer> getItemSearch() { return itemSearch; } public static void start() { FileoutputUtil.log("系统自动更新玩家排名功能已启动..."); FileoutputUtil.log(new StringBuilder().append("更新间隔时间为: ").append(Start.instance.getRankTime()).append(" 分钟1次。").toString()); Timer.WorldTimer.getInstance().register(new Runnable() { @Override public void run() { RankingWorker.jobCommands.clear(); RankingWorker.rankings.clear(); RankingWorker.pokemon.clear(); RankingWorker.pokemon_seen.clear(); RankingWorker.pokemon_ratio.clear(); RankingWorker.itemSearch.clear(); RankingWorker.updateRank(); } }, 60000 * Start.instance.getRankTime()); } public static void updateRank() { FileoutputUtil.log("开始更新玩家排名..."); long startTime = System.currentTimeMillis(); loadJobCommands(); Connection con = DatabaseConnection.getConnection(); try { con.setAutoCommit(false); updateRanking(con); updatePokemonRatio(con); updateItemSearch(con); con.commit(); con.setAutoCommit(true); } catch (Exception ex) { try { con.rollback(); con.setAutoCommit(true); FileoutputUtil.outputFileError(FileoutputUtil.ScriptEx_Log, ex); System.err.println("更新玩家排名出错"); } catch (SQLException ex2) { FileoutputUtil.outputFileError(FileoutputUtil.ScriptEx_Log, ex2); System.err.println("Could not rollback unfinished ranking transaction"); } } FileoutputUtil.log(new StringBuilder().append("玩家排名更新完成 耗时: ").append((System.currentTimeMillis() - startTime) / 1000L).append(" 秒..").toString()); } public static void printSection(String s) { s = new StringBuilder().append("-[ ").append(s).append(" ]").toString(); while (s.getBytes().length < 79) { s = new StringBuilder().append("=").append(s).toString(); } FileoutputUtil.log(s); } private static void updateRanking(Connection con) throws Exception { StringBuilder sb = new StringBuilder("SELECT c.id, c.job, c.exp, c.level, c.name, c.jobRank, c.rank, c.fame"); sb.append(" FROM characters AS c LEFT JOIN accounts AS a ON c.accountid = a.id WHERE c.gm = 0 AND a.banned = 0 AND c.level >= 160"); sb.append(" ORDER BY c.level DESC , c.exp DESC , c.fame DESC , c.rank ASC"); PreparedStatement ps; try (PreparedStatement charSelect = con.prepareStatement(sb.toString()); ResultSet rs = charSelect.executeQuery()) { ps = con.prepareStatement("UPDATE characters SET jobRank = ?, jobRankMove = ?, rank = ?, rankMove = ? WHERE id = ?"); int rank = 0; Map rankMap = new LinkedHashMap(); for (Iterator i$ = jobCommands.values().iterator(); i$.hasNext();) { int i = ((Integer) i$.next()); rankMap.put(i, 0); rankings.put(i, new ArrayList()); } while (rs.next()) { int job = rs.getInt("job"); if (!rankMap.containsKey(job / 100)) { continue; } int jobRank = ((Integer) rankMap.get(Integer.valueOf(job / 100))) + 1; rankMap.put(job / 100, jobRank); rank++; ((List) rankings.get(-1)).add(new RankingInformation(rs.getString("name"), job, rs.getInt("level"), rs.getLong("exp"), rank, rs.getInt("fame"))); ((List) rankings.get(job / 100)).add(new RankingInformation(rs.getString("name"), job, rs.getInt("level"), rs.getLong("exp"), jobRank, rs.getInt("fame"))); ps.setInt(1, jobRank); ps.setInt(2, rs.getInt("jobRank") - jobRank); ps.setInt(3, rank); ps.setInt(4, rs.getInt("rank") - rank); ps.setInt(5, rs.getInt("id")); ps.addBatch(); } ps.executeBatch(); } ps.close(); } private static void updatePokemonRatio(Connection con) throws Exception { StringBuilder sb = new StringBuilder("SELECT (c.totalWins / c.totalLosses) AS mc, c.name, c.totalWins, c.totalLosses "); sb.append(" FROM characters AS c LEFT JOIN accounts AS a ON c.accountid = a.id"); sb.append(" WHERE c.gm = 0 AND a.banned = 0 AND c.totalWins > 10 AND c.totalLosses > 0"); sb.append(" ORDER BY mc DESC, c.totalWins DESC, c.totalLosses ASC LIMIT 50"); try (PreparedStatement charSelect = con.prepareStatement(sb.toString()); ResultSet rs = charSelect.executeQuery()) { int rank = 0; while (rs.next()) { rank++; pokemon_ratio.add(new PokebattleInformation(rs.getString("name"), rs.getInt("totalWins"), rs.getInt("totalLosses"), rs.getDouble("mc"), rank)); } } } private static void updateItemSearch(Connection con) throws Exception { MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); try (PreparedStatement ps = con.prepareStatement("SELECT itemid, count FROM itemsearch WHERE count > 0 ORDER BY count DESC LIMIT 10"); ResultSet rs = ps.executeQuery()) { itemSearch.clear(); while (rs.next()) { int itemId = rs.getInt("itemid"); if ((itemSearch.contains(itemId)) || (!ii.itemExists(itemId))) { continue; } itemSearch.add(itemId); } } } public static void loadJobCommands() { jobCommands.put("所有", -1); jobCommands.put("新手", 0); jobCommands.put("战士", 1); jobCommands.put("魔法师", 2); jobCommands.put("弓箭手", 3); jobCommands.put("飞侠", 4); jobCommands.put("勇士", 20); } public static class PokebattleInformation { public String toString; public PokebattleInformation(String name, int totalWins, int totalLosses, double caught, int rank) { StringBuilder builder = new StringBuilder("Rank "); builder.append(rank); builder.append(" : #e"); builder.append(name); builder.append("#n - #rRatio: "); builder.append(caught); builder.append("\r\n"); this.toString = builder.toString(); } @Override public String toString() { return this.toString; } } public static class PokedexInformation { public String toString; public PokedexInformation(String name, int caught, int rank) { StringBuilder builder = new StringBuilder("排名 "); builder.append(rank); builder.append(" : #e"); builder.append(name); builder.append("#n - #rCaught: "); builder.append(caught); builder.append("\r\n"); this.toString = builder.toString(); } @Override public String toString() { return this.toString; } } public static class PokemonInformation { public String toString; public PokemonInformation(String name, int totalWins, int totalLosses, int caught, int rank) { StringBuilder builder = new StringBuilder("排名 "); builder.append(rank); builder.append(" : #e"); builder.append(name); builder.append("#n - #r胜利: "); builder.append(totalWins); builder.append("#b 失败: "); builder.append(totalLosses); builder.append("#k Caught:"); builder.append(caught); builder.append("\r\n"); this.toString = builder.toString(); } @Override public String toString() { return this.toString; } } public static class RankingInformation { public String toString; public int rank; public RankingInformation(String name, int job, int level, long exp, int rank, int fame) { this.rank = rank; StringBuilder builder = new StringBuilder("排名 "); builder.append(StringUtil.getRightPaddedStr(String.valueOf(rank), ' ', 3)); builder.append(" : "); builder.append(StringUtil.getRightPaddedStr(name, ' ', 13)); builder.append(" 等级: "); builder.append(StringUtil.getRightPaddedStr(String.valueOf(level), ' ', 3)); builder.append(" 职业: "); builder.append(StringUtil.getRightPaddedStr(MapleCarnivalChallenge.getJobNameById(job), ' ', 10)); builder.append("\r\n"); this.toString = builder.toString(); } @Override public String toString() { return this.toString; } } }