From 550648ccbe9d531656dcc2c5d0cdc8c2393c505f Mon Sep 17 00:00:00 2001 From: Me Car Date: Wed, 20 Jan 2016 12:47:58 +0900 Subject: [PATCH 1/3] Record game histories. Compute user stats and show them in the user panel. --- .gitignore | 2 + .../mage/client/table/PlayersChatPanel.java | 10 +- Mage.Common/src/mage/view/UsersView.java | 8 +- Mage.Server/pom.xml | 5 + .../main/java/mage/server/MageServerImpl.java | 4 +- .../src/main/java/mage/server/Main.java | 87 +++++++++++ .../java/mage/server/TableController.java | 34 ++--- .../java/mage/server/game/GamesRoomImpl.java | 85 ++++++++++- .../java/mage/server/record/TableRecord.java | 37 +++++ .../server/record/TableRecordRepository.java | 77 ++++++++++ .../mage/server/record/TableRecorderImpl.java | 22 +++ .../java/mage/server/record/UserStats.java | 45 ++++++ .../server/record/UserStatsRepository.java | 111 ++++++++++++++ .../tournament/TournamentController.java | 38 ++--- Mage/pom.xml | 137 +++++++++++++++++- Mage/src/main/java/mage/game/Table.java | 38 ++++- Mage/src/main/java/mage/game/match/Match.java | 3 + .../main/java/mage/game/match/MatchImpl.java | 23 +++ .../java/mage/game/tournament/Tournament.java | 3 + .../mage/game/tournament/TournamentImpl.java | 52 +++++++ .../game/tournament/TournamentPlayer.java | 26 +++- Mage/src/main/proto/result.proto | 79 ++++++++++ 22 files changed, 866 insertions(+), 60 deletions(-) create mode 100644 Mage.Server/src/main/java/mage/server/record/TableRecord.java create mode 100644 Mage.Server/src/main/java/mage/server/record/TableRecordRepository.java create mode 100644 Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java create mode 100644 Mage.Server/src/main/java/mage/server/record/UserStats.java create mode 100644 Mage.Server/src/main/java/mage/server/record/UserStatsRepository.java create mode 100644 Mage/src/main/proto/result.proto diff --git a/.gitignore b/.gitignore index 2262d283532..c8e97c13349 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,5 @@ Mage.Client/serverlist.txt /target/ client_secrets.json + +dependency-reduced-pom.xml diff --git a/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java b/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java index eff39e49483..8f1d8546fa6 100644 --- a/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java @@ -61,7 +61,7 @@ public class PlayersChatPanel extends javax.swing.JPanel { private final List players = new ArrayList<>(); private final UserTableModel userTableModel; - private static final int[] defaultColumnsWidth = {20, 100, 100, 80, 80}; + private static final int[] defaultColumnsWidth = {20, 100, 100, 100, 80, 80}; /* @@ -118,7 +118,7 @@ public class PlayersChatPanel extends javax.swing.JPanel { class UserTableModel extends AbstractTableModel { - private final String[] columnNames = new String[]{"Loc", "Players", "Info", "Games", "Connection"}; + private final String[] columnNames = new String[]{"Loc", "Players", "History", "Info", "Games", "Connection"}; private UsersView[] players = new UsersView[0]; public void loadData(Collection roomUserInfoList) throws MageRemoteException { @@ -154,10 +154,12 @@ public class PlayersChatPanel extends javax.swing.JPanel { case 1: return players[arg0].getUserName(); case 2: - return players[arg0].getInfoState(); + return players[arg0].getHistory(); case 3: - return players[arg0].getInfoGames(); + return players[arg0].getInfoState(); case 4: + return players[arg0].getInfoGames(); + case 5: return players[arg0].getInfoPing(); } return ""; diff --git a/Mage.Common/src/mage/view/UsersView.java b/Mage.Common/src/mage/view/UsersView.java index c5e8522bec4..6e9d649461b 100644 --- a/Mage.Common/src/mage/view/UsersView.java +++ b/Mage.Common/src/mage/view/UsersView.java @@ -39,12 +39,14 @@ public class UsersView implements Serializable { private final String flagName; private final String userName; + private final String history; private final String infoState; private final String infoGames; private final String infoPing; - public UsersView(String flagName, String userName, String infoState, String infoGames, String infoPing) { + public UsersView(String flagName, String userName, String history, String infoState, String infoGames, String infoPing) { this.flagName = flagName; + this.history = history; this.userName = userName; this.infoState = infoState; this.infoGames = infoGames; @@ -59,6 +61,10 @@ public class UsersView implements Serializable { return userName; } + public String getHistory() { + return history; + } + public String getInfoState() { return infoState; } diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 436fee41923..e3151182514 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -199,6 +199,11 @@ jersey-multipart 1.19 + + org.xerial + sqlite-jdbc + 3.7.2 + diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 3c0672bfdd4..b2a7553eb91 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -438,7 +438,7 @@ public class MageServerImpl implements MageServer { // } @Override public boolean startMatch(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { - if (!TableManager.getInstance().getController(tableId).changeTableState(TableState.STARTING)) { + if (!TableManager.getInstance().getController(tableId).changeTableStateToStarting()) { return false; } execute("startMatch", sessionId, new Action() { @@ -463,7 +463,7 @@ public class MageServerImpl implements MageServer { // } @Override public boolean startTournament(final String sessionId, final UUID roomId, final UUID tableId) throws MageException { - if (!TableManager.getInstance().getController(tableId).changeTableState(TableState.STARTING)) { + if (!TableManager.getInstance().getController(tableId).changeTableStateToStarting()) { return false; } execute("startTournament", sessionId, new Action() { diff --git a/Mage.Server/src/main/java/mage/server/Main.java b/Mage.Server/src/main/java/mage/server/Main.java index 666678032bd..3c6216cff53 100644 --- a/Mage.Server/src/main/java/mage/server/Main.java +++ b/Mage.Server/src/main/java/mage/server/Main.java @@ -32,10 +32,20 @@ import java.io.FilenameFilter; import java.net.InetAddress; import java.net.MalformedURLException; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import javax.management.MBeanServer; import mage.cards.repository.CardScanner; import mage.game.match.MatchType; +import mage.game.result.ResultProtos.MatchPlayerProto; +import mage.game.result.ResultProtos.MatchProto; +import mage.game.result.ResultProtos.TableProto; +import mage.game.result.ResultProtos.TourneyPlayerProto; +import mage.game.result.ResultProtos.TourneyProto; +import mage.game.result.ResultProtos.UserStatsProto; import mage.game.tournament.TournamentType; import mage.interfaces.MageServer; import mage.remote.Connection; @@ -43,6 +53,10 @@ import mage.server.draft.CubeFactory; import mage.server.game.DeckValidatorFactory; import mage.server.game.GameFactory; import mage.server.game.PlayerFactory; +import mage.server.record.TableRecord; +import mage.server.record.TableRecordRepository; +import mage.server.record.UserStats; +import mage.server.record.UserStatsRepository; import mage.server.tournament.TournamentFactory; import mage.server.util.ConfigSettings; import mage.server.util.PluginClassLoader; @@ -88,6 +102,8 @@ public class Main { protected static boolean testMode; protected static boolean fastDbMode; + private static final ScheduledExecutorService updateUserStatsTaskExecutor = Executors.newSingleThreadScheduledExecutor(); + /** * @param args the command line arguments */ @@ -174,6 +190,13 @@ public class Main { } catch (Exception ex) { logger.fatal("Failed to start server - " + connection.toString(), ex); } + + updateUserStatsTaskExecutor.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + updateUserStats(); + } + }, 60, 60, TimeUnit.SECONDS); } static void initStatistics() { @@ -368,4 +391,68 @@ public class Main { public static boolean isTestMode() { return testMode; } + + private static void updateUserStats() { + long latestEndTimeMs = UserStatsRepository.instance.getLatestEndTimeMs(); + List records = TableRecordRepository.instance.getAfter(latestEndTimeMs); + for (TableRecord record : records) { + TableProto table = record.getProto(); + if (table.getControllerName().equals("System")) { + // This is a sub table within a tournament, so it's already handled by the main + // tournament table. + continue; + } + if (table.hasMatch()) { + MatchProto match = table.getMatch(); + for (MatchPlayerProto player : match.getPlayersList()) { + UserStats userStats = UserStatsRepository.instance.getUser(player.getName()); + UserStatsProto proto = userStats != null ? userStats.getProto() : + UserStatsProto.newBuilder().setName(player.getName()).build(); + UserStatsProto.Builder builder = UserStatsProto.newBuilder(proto) + .setMatches(proto.getMatches() + 1); + switch (player.getQuit()) { + case IDLE_TIMEOUT: + builder.setMatchesIdleTimeout(proto.getMatchesIdleTimeout() + 1); + break; + case TIMER_TIMEOUT: + builder.setMatchesTimerTimeout(proto.getMatchesTimerTimeout() + 1); + break; + case QUIT: + builder.setMatchesQuit(proto.getMatchesQuit() + 1); + break; + } + if (userStats == null) { + UserStatsRepository.instance.add(new UserStats(builder.build(), table.getEndTimeMs())); + } else { + UserStatsRepository.instance.update(new UserStats(builder.build(), table.getEndTimeMs())); + } + } + } else if (table.hasTourney()) { + TourneyProto tourney = table.getTourney(); + for (TourneyPlayerProto player : tourney.getPlayersList()) { + UserStats userStats = UserStatsRepository.instance.getUser(player.getName()); + UserStatsProto proto = userStats != null ? userStats.getProto() : + UserStatsProto.newBuilder().setName(player.getName()).build(); + UserStatsProto.Builder builder = UserStatsProto.newBuilder(proto) + .setTourneys(proto.getTourneys() + 1); + switch (player.getQuit()) { + case DURING_ROUND: + builder.setTourneysQuitDuringRound(proto.getTourneysQuitDuringRound() + 1); + break; + case DURING_DRAFTING: + builder.setTourneysQuitDuringDrafting(proto.getTourneysQuitDuringDrafting() + 1); + break; + case DURING_CONSTRUCTION: + builder.setTourneysQuitDuringConstruction(proto.getTourneysQuitDuringConstruction() + 1); + break; + } + if (userStats == null) { + UserStatsRepository.instance.add(new UserStats(builder.build(), table.getEndTimeMs())); + } else { + UserStatsRepository.instance.update(new UserStats(builder.build(), table.getEndTimeMs())); + } + } + } + } + } } diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index ecc05278221..64edc644b12 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -62,6 +62,7 @@ import mage.server.game.DeckValidatorFactory; import mage.server.game.GameFactory; import mage.server.game.GameManager; import mage.server.game.PlayerFactory; +import mage.server.record.TableRecorderImpl; import mage.server.services.LogKeys; import mage.server.services.impl.LogServiceImpl; import mage.server.tournament.TournamentController; @@ -105,7 +106,7 @@ public class TableController { } else { controllerName = "System"; } - table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getDeckType()), options.getPlayerTypes(), match); + table = new Table(roomId, options.getGameType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getDeckType()), options.getPlayerTypes(), TableRecorderImpl.getInstance(), match); chatId = ChatManager.getInstance().createChatSession("Match Table " + table.getId()); init(); } @@ -124,7 +125,7 @@ public class TableController { } else { controllerName = "System"; } - table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getMatchOptions().getDeckType()), options.getPlayerTypes(), tournament); + table = new Table(roomId, options.getTournamentType(), options.getName(), controllerName, DeckValidatorFactory.getInstance().createDeckValidator(options.getMatchOptions().getDeckType()), options.getPlayerTypes(), TableRecorderImpl.getInstance(), tournament); chatId = ChatManager.getInstance().createChatSession("Tourn. table " + table.getId()); } @@ -237,6 +238,7 @@ public class TableController { TournamentPlayer newTournamentPlayer = tournament.getPlayer(newPlayer.getId()); newTournamentPlayer.setState(oldTournamentPlayer.getState()); + newTournamentPlayer.setReplacedTournamentPlayer(oldTournamentPlayer); DraftManager.getInstance().getController(table.getId()).replacePlayer(oldPlayer, newPlayer); return true; @@ -957,26 +959,16 @@ public class TableController { return getTable().getState(); } - public synchronized boolean changeTableState(TableState newTableState) { - switch (newTableState) { - case WAITING: - if (getTable().getState().equals(TableState.STARTING)) { - // tournament already started - return false; - } - break; - case STARTING: - if (!getTable().getState().equals(TableState.READY_TO_START)) { - // tournament is not ready, can't start - return false; - } - if (!table.allSeatsAreOccupied()) { - logger.debug("Not alle Seats are occupied: stop start tableId:" + table.getId()); - return false; - } - break; + public synchronized boolean changeTableStateToStarting() { + if (!getTable().getState().equals(TableState.READY_TO_START)) { + // tournament is not ready, can't start + return false; } - getTable().setState(newTableState); + if (!table.allSeatsAreOccupied()) { + logger.debug("Not alle Seats are occupied: stop start tableId:" + table.getId()); + return false; + } + getTable().setState(TableState.STARTING); return true; } } diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java index 9afcea78466..1f540b6d915 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -43,11 +43,14 @@ import mage.constants.TableState; import mage.game.GameException; import mage.game.Table; import mage.game.match.MatchOptions; +import mage.game.result.ResultProtos.UserStatsProto; import mage.game.tournament.TournamentOptions; import mage.server.RoomImpl; import mage.server.TableManager; import mage.server.User; import mage.server.UserManager; +import mage.server.record.UserStats; +import mage.server.record.UserStatsRepository; import mage.server.tournament.TournamentManager; import mage.server.util.ConfigSettings; import mage.server.util.ThreadExecutor; @@ -91,6 +94,74 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { return tableView; } + private static void joinStrings(StringBuilder joined, List strings, String separator) { + for (int i = 0; i < strings.size(); ++i) { + if (i > 0) { + joined.append(separator); + } + joined.append(strings.get(i)); + } + } + + private static String joinBuilders(List builders) { + if (builders.isEmpty()) { + return null; + } + StringBuilder builder = builders.get(0); + for (int i = 1; i < builders.size(); ++i) { + builder.append(" "); + builder.append(builders.get(i)); + } + return builder.toString(); + } + + private static String userStatsToString(UserStatsProto proto) { + List builders = new ArrayList(); + if (proto.getMatches() > 0) { + StringBuilder builder = new StringBuilder(); + builder.append("Matches:"); + builder.append(proto.getMatches()); + List quit = new ArrayList(); + if (proto.getMatchesIdleTimeout() > 0) { + quit.add("I:" + Integer.toString(proto.getMatchesIdleTimeout())); + } + if (proto.getMatchesTimerTimeout() > 0) { + quit.add("T:" + Integer.toString(proto.getMatchesTimerTimeout())); + } + if (proto.getMatchesQuit() > 0) { + quit.add("Q:" + Integer.toString(proto.getMatchesQuit())); + } + if (quit.size() > 0) { + builder.append(" ("); + joinStrings(builder, quit, " "); + builder.append(")"); + } + builders.add(builder); + } + if (proto.getTourneys() > 0) { + StringBuilder builder = new StringBuilder(); + builder.append("Tourneys:"); + builder.append(proto.getTourneys()); + List quit = new ArrayList(); + if (proto.getTourneysQuitDuringDrafting() > 0) { + quit.add("D:" + Integer.toString(proto.getTourneysQuitDuringDrafting())); + } + if (proto.getTourneysQuitDuringConstruction() > 0) { + quit.add("C:" + Integer.toString(proto.getTourneysQuitDuringConstruction())); + } + if (proto.getTourneysQuitDuringRound() > 0) { + quit.add("R:" + Integer.toString(proto.getTourneysQuitDuringRound())); + } + if (quit.size() > 0) { + builder.append(" ("); + joinStrings(builder, quit, " "); + builder.append(")"); + } + builders.add(builder); + } + return joinBuilders(builders); + } + private void update() { ArrayList tableList = new ArrayList<>(); ArrayList matchList = new ArrayList<>(); @@ -100,11 +171,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { if (table.getState() != TableState.FINISHED) { tableList.add(new TableView(table)); } else if (matchList.size() < 50) { - if (table.isTournament()) { - matchList.add(new MatchView(table)); - } else { - matchList.add(new MatchView(table)); - } + matchList.add(new MatchView(table)); } else { // more since 50 matches finished since this match so remove it if (table.isTournament()) { @@ -117,13 +184,19 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { matchView = matchList; List users = new ArrayList<>(); for (User user : UserManager.getInstance().getUsers()) { + String history = null; + UserStats stats = UserStatsRepository.instance.getUser(user.getName()); + if (stats != null) { + history = userStatsToString(stats.getProto()); + } try { - users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), user.getInfo(), user.getGameInfo(), user.getPingInfo())); + users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), history, user.getInfo(), user.getGameInfo(), user.getPingInfo())); } catch (Exception ex) { logger.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex); users.add(new UsersView( (user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world", user.getName() != null ? user.getName() : "", + history != null ? history : "", user.getInfo() != null ? user.getInfo() : "", "[exception]", user.getPingInfo() != null ? user.getPingInfo() : "")); diff --git a/Mage.Server/src/main/java/mage/server/record/TableRecord.java b/Mage.Server/src/main/java/mage/server/record/TableRecord.java new file mode 100644 index 00000000000..456e54c8031 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/record/TableRecord.java @@ -0,0 +1,37 @@ +package mage.server.record; + +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; +import mage.game.result.ResultProtos.TableProto; +import org.mage.mage.shaded.protobuf.InvalidProtocolBufferException; +import org.apache.log4j.Logger; + +@DatabaseTable(tableName = "table_history") +public class TableRecord { + + private static final Logger logger = Logger.getLogger(TableRecord.class); + + @DatabaseField(dataType = DataType.BYTE_ARRAY, indexName = "proto_index", unique = true) + protected byte[] proto; + + @DatabaseField(indexName = "end_time_ms") + protected long endTimeMs; + + public TableRecord() { + } + + public TableRecord(TableProto proto, long endTimeMs) { + this.proto = proto.toByteArray(); + this.endTimeMs = endTimeMs; + } + + public TableProto getProto() { + try { + return TableProto.parseFrom(this.proto); + } catch (InvalidProtocolBufferException ex) { + logger.error("Failed to parse serialized proto", ex); + } + return null; + } +} diff --git a/Mage.Server/src/main/java/mage/server/record/TableRecordRepository.java b/Mage.Server/src/main/java/mage/server/record/TableRecordRepository.java new file mode 100644 index 00000000000..927a474c397 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/record/TableRecordRepository.java @@ -0,0 +1,77 @@ +package mage.server.record; + +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.jdbc.JdbcConnectionSource; +import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.support.DatabaseConnection; +import com.j256.ormlite.table.TableUtils; +import java.io.File; +import java.sql.SQLException; +import java.util.List; +import mage.cards.repository.RepositoryUtil; +import org.apache.log4j.Logger; + +public enum TableRecordRepository { + + instance; + + private static final String JDBC_URL = "jdbc:sqlite:./db/table_record.db"; + private static final String VERSION_ENTITY_NAME = "table_record"; + // raise this if db structure was changed + private static final long DB_VERSION = 0; + + private Dao dao; + + private TableRecordRepository() { + File file = new File("db"); + if (!file.exists()) { + file.mkdirs(); + } + try { + ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); + boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION); + + if (obsolete) { + TableUtils.dropTable(connectionSource, TableRecord.class, true); + } + + TableUtils.createTableIfNotExists(connectionSource, TableRecord.class); + dao = DaoManager.createDao(connectionSource, TableRecord.class); + } catch (SQLException ex) { + Logger.getLogger(TableRecordRepository.class).error("Error creating table_record repository - ", ex); + } + } + + public void add(TableRecord tableHistory) { + try { + dao.create(tableHistory); + } catch (SQLException ex) { + Logger.getLogger(TableRecordRepository.class).error("Error adding a table_record to DB - ", ex); + } + } + + public List getAfter(long endTimeMs) { + try { + QueryBuilder qb = dao.queryBuilder(); + qb.where().gt("endTimeMs", endTimeMs); + qb.orderBy("endTimeMs", true); + return dao.query(qb.prepare()); + } catch (SQLException ex) { + Logger.getLogger(TableRecordRepository.class).error("Error getting table_records from DB - ", ex); + } + return null; + } + + public void closeDB() { + try { + if (dao != null && dao.getConnectionSource() != null) { + DatabaseConnection conn = dao.getConnectionSource().getReadWriteConnection(); + conn.executeStatement("shutdown compact", 0); + } + } catch (SQLException ex) { + Logger.getLogger(TableRecordRepository.class).error("Error closing table_record repository - ", ex); + } + } +} diff --git a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java new file mode 100644 index 00000000000..0b5017b8f60 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java @@ -0,0 +1,22 @@ +package mage.server.record; + +import mage.game.Table; +import mage.game.Table.TableRecorder; +import mage.game.result.ResultProtos.TableProto; +import org.apache.log4j.Logger; + +public class TableRecorderImpl implements TableRecorder { + + private static TableRecorderImpl INSTANCE = new TableRecorderImpl(); + private static final Logger logger = Logger.getLogger(TableRecorderImpl.class); + + public static TableRecorderImpl getInstance() { + return INSTANCE; + } + + public void record(Table table) { + TableProto proto = table.toProto(); + logger.info("Adding record:\n" + proto.toString()); + TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs())); + } +} diff --git a/Mage.Server/src/main/java/mage/server/record/UserStats.java b/Mage.Server/src/main/java/mage/server/record/UserStats.java new file mode 100644 index 00000000000..94adcecc554 --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/record/UserStats.java @@ -0,0 +1,45 @@ +package mage.server.record; + +import com.j256.ormlite.field.DataType; +import com.j256.ormlite.field.DatabaseField; +import com.j256.ormlite.table.DatabaseTable; +import mage.game.result.ResultProtos.UserStatsProto; +import org.mage.mage.shaded.protobuf.InvalidProtocolBufferException; +import org.apache.log4j.Logger; + +@DatabaseTable(tableName = "user_stats") +public class UserStats { + + private static final Logger logger = Logger.getLogger(TableRecord.class); + + @DatabaseField(indexName = "user_name_index", unique = true, id = true) + protected String userName; + + @DatabaseField(dataType = DataType.BYTE_ARRAY) + protected byte[] proto; + + @DatabaseField(indexName = "end_time_ms_index") + protected long endTimeMs; + + public UserStats() { + } + + public UserStats(UserStatsProto proto, long endTimeMs) { + this.userName = proto.getName(); + this.proto = proto.toByteArray(); + this.endTimeMs = endTimeMs; + } + + public UserStatsProto getProto() { + try { + return UserStatsProto.parseFrom(this.proto); + } catch (InvalidProtocolBufferException ex) { + logger.error("Failed to parse serialized proto", ex); + } + return null; + } + + public long getEndTimeMs() { + return this.endTimeMs; + } +} diff --git a/Mage.Server/src/main/java/mage/server/record/UserStatsRepository.java b/Mage.Server/src/main/java/mage/server/record/UserStatsRepository.java new file mode 100644 index 00000000000..de43a7c76bc --- /dev/null +++ b/Mage.Server/src/main/java/mage/server/record/UserStatsRepository.java @@ -0,0 +1,111 @@ +package mage.server.record; + +import com.j256.ormlite.dao.Dao; +import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.jdbc.JdbcConnectionSource; +import com.j256.ormlite.stmt.QueryBuilder; +import com.j256.ormlite.support.ConnectionSource; +import com.j256.ormlite.support.DatabaseConnection; +import com.j256.ormlite.table.TableUtils; +import java.io.File; +import java.sql.SQLException; +import java.util.List; +import mage.cards.repository.RepositoryUtil; +import org.apache.log4j.Logger; + +public enum UserStatsRepository { + + instance; + + private static final String JDBC_URL = "jdbc:sqlite:./db/user_stats.db"; + private static final String VERSION_ENTITY_NAME = "user_stats"; + // raise this if db structure was changed + private static final long DB_VERSION = 0; + + private Dao dao; + + private UserStatsRepository() { + File file = new File("db"); + if (!file.exists()) { + file.mkdirs(); + } + try { + ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL); + boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION); + + if (obsolete) { + TableUtils.dropTable(connectionSource, UserStats.class, true); + } + + TableUtils.createTableIfNotExists(connectionSource, UserStats.class); + dao = DaoManager.createDao(connectionSource, UserStats.class); + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error creating user_stats repository - ", ex); + } + } + + public void add(UserStats userStats) { + try { + dao.create(userStats); + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error adding a user_stats to DB - ", ex); + } + } + + public void update(UserStats userStats) { + try { + dao.update(userStats); + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error updating a user_stats in DB - ", ex); + } + } + + public UserStats getUser(String userName) { + try { + QueryBuilder qb = dao.queryBuilder(); + qb.where().eq("userName", userName); + List users = dao.query(qb.prepare()); + if (users.size() == 1) { + return users.get(0); + } + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error getting a user from DB - ", ex); + } + return null; + } + + public List getAllUsers() { + try { + QueryBuilder qb = dao.queryBuilder(); + return dao.query(qb.prepare()); + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error getting all users from DB - ", ex); + } + return null; + } + + public long getLatestEndTimeMs() { + try { + QueryBuilder qb = dao.queryBuilder(); + qb.orderBy("endTimeMs", false).limit(1); + List users = dao.query(qb.prepare()); + if (users.size() == 1) { + return users.get(0).getEndTimeMs(); + } + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error getting the latest end time from DB - ", ex); + } + return 0; + } + + public void closeDB() { + try { + if (dao != null && dao.getConnectionSource() != null) { + DatabaseConnection conn = dao.getConnectionSource().getReadWriteConnection(); + conn.executeStatement("shutdown compact", 0); + } + } catch (SQLException ex) { + Logger.getLogger(UserStatsRepository.class).error("Error closing user_stats repository - ", ex); + } + } +} diff --git a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java index fa26d966f17..a212ad60b3d 100644 --- a/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java +++ b/Mage.Server/src/main/java/mage/server/tournament/TournamentController.java @@ -43,6 +43,7 @@ import mage.game.events.TableEvent; import static mage.game.events.TableEvent.EventType.CONSTRUCT; import mage.game.match.Match; import mage.game.match.MatchOptions; +import mage.game.result.ResultProtos.TourneyQuitStatus; import mage.game.tournament.Tournament; import mage.game.tournament.TournamentPairing; import mage.game.tournament.TournamentPlayer; @@ -351,31 +352,34 @@ public class TournamentController { tournamentSession.setKilled(); if (tournamentPlayer.isInTournament()) { String info; + TourneyQuitStatus status; if (tournament.isDoneConstructing()) { info = new StringBuilder("during round ").append(tournament.getRounds().size()).toString(); // quit active matches of that tournament TableManager.getInstance().userQuitTournamentSubTables(tournament.getId(), userId); - } else { - if (tournamentPlayer.getState().equals(TournamentPlayerState.DRAFTING)) { - info = "during Draft phase"; - if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) { - this.abortDraftTournament(); - } else { - DraftController draftController = DraftManager.getInstance().getController(tableId); - if (draftController != null) { - DraftSession draftSession = draftController.getDraftSession(playerId); - if (draftSession != null) { - DraftManager.getInstance().kill(draftSession.getDraftId(), userId); - } + status = TourneyQuitStatus.DURING_ROUND; + } else if (tournamentPlayer.getState().equals(TournamentPlayerState.DRAFTING)) { + info = "during Draft phase"; + if (!checkToReplaceDraftPlayerByAi(userId, tournamentPlayer)) { + this.abortDraftTournament(); + } else { + DraftController draftController = DraftManager.getInstance().getController(tableId); + if (draftController != null) { + DraftSession draftSession = draftController.getDraftSession(playerId); + if (draftSession != null) { + DraftManager.getInstance().kill(draftSession.getDraftId(), userId); } } - } else if (tournamentPlayer.getState().equals(TournamentPlayerState.CONSTRUCTING)) { - info = "during Construction phase"; - } else { - info = ""; } + status = TourneyQuitStatus.DURING_DRAFTING; + } else if (tournamentPlayer.getState().equals(TournamentPlayerState.CONSTRUCTING)) { + info = "during Construction phase"; + status = TourneyQuitStatus.DURING_CONSTRUCTION; + } else { + info = ""; + status = TourneyQuitStatus.NO_TOURNEY_QUIT; } - tournamentPlayer.setQuit(info); + tournamentPlayer.setQuit(info, status); tournament.quit(playerId); tournamentSession.quit(); ChatManager.getInstance().broadcast(chatId, "", tournamentPlayer.getPlayer().getLogName() + " has quit the tournament", MessageColor.BLACK, true, MessageType.STATUS, SoundToPlay.PlayerQuitTournament); diff --git a/Mage/pom.xml b/Mage/pom.xml index d4caa17a281..4b163a6e8fe 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -36,6 +36,11 @@ junit 4.12 + + com.google.protobuf + protobuf-java + ${protobuf.version} + @@ -51,11 +56,141 @@ + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + + copy-protoc + generate-sources + + copy + + + + + com.google.protobuf + protoc + ${protobuf.version} + ${os.detected.classifier} + exe + true + ${project.build.directory} + + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + exec-protoc + generate-sources + + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + ${build-helper-maven-plugin.version} + + + add-classes + generate-sources + + add-source + + + + ${protobuf.output.directory} + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + com.google.protobuf + ${project.groupId}.${project.artifactId}.shaded.protobuf + + + + + + mage + + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + - + + + + ${project.basedir}/src/main/proto + ${project.build.directory}/generated-sources + + + 1.9.1 + 1.8 + 2.10 + 2.4.2 + 1.4.1.Final + 3.0.0-beta-1 + diff --git a/Mage/src/main/java/mage/game/Table.java b/Mage/src/main/java/mage/game/Table.java index f5c714f95fe..b6669a428e7 100644 --- a/Mage/src/main/java/mage/game/Table.java +++ b/Mage/src/main/java/mage/game/Table.java @@ -38,6 +38,7 @@ import mage.game.events.Listener; import mage.game.events.TableEvent; import mage.game.events.TableEventSource; import mage.game.match.Match; +import mage.game.result.ResultProtos.TableProto; import mage.game.tournament.Tournament; import mage.players.Player; @@ -61,24 +62,29 @@ public class Table implements Serializable { private TableState state; private Match match; private Tournament tournament; + private TableRecorder recorder; + + public interface TableRecorder { + void record(Table table); + }; protected TableEventSource tableEventSource = new TableEventSource(); - public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List playerTypes, Tournament tournament) { - this(roomId, gameType, name, controllerName, validator, playerTypes); + public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List playerTypes, TableRecorder recorder, Tournament tournament) { + this(roomId, gameType, name, controllerName, validator, playerTypes, recorder); this.tournament = tournament; this.isTournament = true; setState(TableState.WAITING); } - public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List playerTypes, Match match) { - this(roomId, gameType, name, controllerName, validator, playerTypes); + public Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List playerTypes, TableRecorder recorder, Match match) { + this(roomId, gameType, name, controllerName, validator, playerTypes, recorder); this.match = match; this.isTournament = false; setState(TableState.WAITING); } - protected Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List playerTypes) { + protected Table(UUID roomId, String gameType, String name, String controllerName, DeckValidator validator, List playerTypes, TableRecorder recorder) { tableId = UUID.randomUUID(); this.roomId = roomId; this.numSeats = playerTypes.size(); @@ -88,6 +94,7 @@ public class Table implements Serializable { this.createTime = new Date(); createSeats(playerTypes); this.validator = validator; + this.recorder = recorder; } private void createSeats(List playerTypes) { @@ -235,6 +242,9 @@ public class Table implements Serializable { if (isTournament()) { getTournament().setTournamentState(state.toString()); } + if (state == TableState.FINISHED) { + this.recorder.record(this); + } } public TableState getState() { @@ -296,5 +306,21 @@ public class Table implements Serializable { return match.getEndTime(); } } - + + public TableProto toProto() { + TableProto.Builder builder = TableProto.newBuilder(); + if (this.isTournament()) { + builder.getTourneyBuilder().mergeFrom(this.getTournament().toProto()); + } else { + builder.getMatchBuilder().mergeFrom(this.getMatch().toProto()); + } + return builder.setGameType(this.getGameType()) + .setName(this.getName()) + .setGameType(this.getGameType()) + .setDeckType(this.getDeckType()) + .setControllerName(this.getControllerName()) + .setStartTimeMs(this.getStartTime().getTime()) + .setEndTimeMs(this.getEndTime().getTime()) + .build(); + } } diff --git a/Mage/src/main/java/mage/game/match/Match.java b/Mage/src/main/java/mage/game/match/Match.java index f695949c87e..6fc81ef884f 100644 --- a/Mage/src/main/java/mage/game/match/Match.java +++ b/Mage/src/main/java/mage/game/match/Match.java @@ -39,6 +39,7 @@ import java.util.Date; import java.util.List; import java.util.UUID; import mage.game.GameInfo; +import mage.game.result.ResultProtos.MatchProto; /** * @@ -111,4 +112,6 @@ public interface Match { void setTableId(UUID tableId); void setTournamentRound(int round); + + MatchProto toProto(); } diff --git a/Mage/src/main/java/mage/game/match/MatchImpl.java b/Mage/src/main/java/mage/game/match/MatchImpl.java index 9bc0db8ca2f..30f7cd53ee0 100644 --- a/Mage/src/main/java/mage/game/match/MatchImpl.java +++ b/Mage/src/main/java/mage/game/match/MatchImpl.java @@ -41,6 +41,8 @@ import mage.game.events.Listener; import mage.game.events.TableEvent; import mage.game.events.TableEvent.EventType; import mage.game.events.TableEventSource; +import mage.game.result.ResultProtos.MatchProto; +import mage.game.result.ResultProtos.MatchQuitStatus; import mage.players.Player; import mage.util.DateFormat; import org.apache.log4j.Logger; @@ -488,4 +490,25 @@ public abstract class MatchImpl implements Match { this.getGames().clear(); } + @Override + public MatchProto toProto() { + MatchProto.Builder builder = MatchProto.newBuilder() + .setName(this.getName()) + .setGameType(this.getOptions().getGameType()) + .setDeckType(this.getOptions().getDeckType()) + .setGames(this.getNumGames()) + .setDraws(this.getDraws()); + for (MatchPlayer matchPlayer : this.getPlayers()) { + MatchQuitStatus status = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT : + matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT : + matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT : + MatchQuitStatus.QUIT; + builder.addPlayersBuilder() + .setName(matchPlayer.getName()) + .setQuit(status) + .setWins(matchPlayer.getWins()); + } + return builder.build(); + } + } diff --git a/Mage/src/main/java/mage/game/tournament/Tournament.java b/Mage/src/main/java/mage/game/tournament/Tournament.java index 7aba2501053..97c3d7f1d43 100644 --- a/Mage/src/main/java/mage/game/tournament/Tournament.java +++ b/Mage/src/main/java/mage/game/tournament/Tournament.java @@ -38,6 +38,7 @@ import mage.game.draft.Draft; import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; import mage.game.events.TableEvent; +import mage.game.result.ResultProtos.TourneyProto; import mage.players.Player; /** @@ -98,4 +99,6 @@ public interface Tournament { void clearDraft(); Draft getDraft(); + + TourneyProto toProto(); } diff --git a/Mage/src/main/java/mage/game/tournament/TournamentImpl.java b/Mage/src/main/java/mage/game/tournament/TournamentImpl.java index a578a681107..177c299e9e6 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentImpl.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentImpl.java @@ -51,6 +51,11 @@ import mage.game.events.TableEvent.EventType; import mage.game.events.TableEventSource; import mage.game.match.Match; import mage.game.match.MatchPlayer; +import mage.game.result.ResultProtos.MatchPlayerProto; +import mage.game.result.ResultProtos.MatchProto; +import mage.game.result.ResultProtos.MatchQuitStatus; +import mage.game.result.ResultProtos.TourneyProto; +import mage.game.result.ResultProtos.TourneyRoundProto; import mage.players.Player; import org.apache.log4j.Logger; @@ -555,4 +560,51 @@ public abstract class TournamentImpl implements Tournament { return draft; } + @Override + public TourneyProto toProto() { + TourneyProto.Builder tourneyBuilder = TourneyProto.newBuilder() + .setBoosterInfo(this.getBoosterInfo()); + for (TournamentPlayer player : players.values()) { + TournamentPlayer replacedPlayer = player.getReplacedTournamentPlayer(); + if (replacedPlayer != null) { + player = replacedPlayer; + } + tourneyBuilder.addPlayersBuilder().mergeFrom(player.toProto()); + } + for (Round round : rounds) { + TourneyRoundProto.Builder roundBuilder = tourneyBuilder.addRoundsBuilder() + .setRound(round.getRoundNumber()); + for (TournamentPairing pair : round.getPairs()) { + Match match = pair.getMatch(); + if (match != null && match.hasEnded()) { + MatchProto.Builder matchBuilder = roundBuilder.addMatchesBuilder() + .setName(match.getName()) + .setGameType(match.getOptions().getGameType()) + .setDeckType(match.getOptions().getDeckType()) + .setGames(match.getNumGames()) + .setDraws(match.getDraws()) + .addPlayers(matchToProto(match, pair.getPlayer1())) + .addPlayers(matchToProto(match, pair.getPlayer2())); + } + } + for (TournamentPlayer tp : round.getPlayerByes()) { + roundBuilder.addByes(tp.getPlayer().getName()); + } + } + return tourneyBuilder.build(); + } + + private MatchPlayerProto matchToProto(Match match, TournamentPlayer player) { + MatchPlayer matchPlayer = match.getPlayer(player.getPlayer().getId()); + MatchQuitStatus quit = !matchPlayer.hasQuit() ? MatchQuitStatus.NO_MATCH_QUIT : + matchPlayer.getPlayer().hasIdleTimeout() ? MatchQuitStatus.IDLE_TIMEOUT : + matchPlayer.getPlayer().hasTimerTimeout() ? MatchQuitStatus.TIMER_TIMEOUT : + MatchQuitStatus.QUIT; + return MatchPlayerProto.newBuilder() + .setName(player.getPlayer().getName()) + .setWins(matchPlayer.getWins()) + .setQuit(quit) + .build(); + } + } diff --git a/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java b/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java index 3d85eef6bf0..e8a7a24debc 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java @@ -31,6 +31,8 @@ package mage.game.tournament; import java.util.Set; import mage.cards.decks.Deck; import mage.constants.TournamentPlayerState; +import mage.game.result.ResultProtos.TourneyPlayerProto; +import mage.game.result.ResultProtos.TourneyQuitStatus; import mage.players.Player; import mage.util.TournamentUtil; @@ -52,6 +54,8 @@ public class TournamentPlayer { protected boolean quit = false; protected boolean doneConstructing; protected boolean joined = false; + protected TourneyQuitStatus quitStatus = TourneyQuitStatus.NO_TOURNEY_QUIT; + protected TournamentPlayer replacedTournamentPlayer; public TournamentPlayer(Player player, String playerType) { this.player = player; @@ -60,7 +64,6 @@ public class TournamentPlayer { this.stateInfo = ""; this.disconnectInfo = ""; this.results = ""; - } public Player getPlayer() { @@ -185,12 +188,13 @@ public class TournamentPlayer { return quit; } - public void setQuit(String info) { + public void setQuit(String info, TourneyQuitStatus status) { setEliminated(); this.setState(TournamentPlayerState.CANCELED); this.setStateInfo(info); this.quit = true; this.doneConstructing = true; + this.quitStatus = status; } /** @@ -216,5 +220,23 @@ public class TournamentPlayer { && !this.getState().equals(TournamentPlayerState.ELIMINATED) && !this.getState().equals(TournamentPlayerState.FINISHED); } + + public TournamentPlayer getReplacedTournamentPlayer() { + return this.replacedTournamentPlayer; + } + + public void setReplacedTournamentPlayer(TournamentPlayer player) { + this.replacedTournamentPlayer = player; + } + + public TourneyPlayerProto toProto() { + return TourneyPlayerProto.newBuilder() + .setName(this.player.getName()) + .setPlayerType(this.playerType) + .setStateInfo(this.stateInfo) + .setDisconnectInfo(this.disconnectInfo) + .setQuit(this.quitStatus) + .build(); + } } diff --git a/Mage/src/main/proto/result.proto b/Mage/src/main/proto/result.proto new file mode 100644 index 00000000000..def7b8c52d0 --- /dev/null +++ b/Mage/src/main/proto/result.proto @@ -0,0 +1,79 @@ +package mage.game.result; + +option java_outer_classname = "ResultProtos"; + +message TableProto { + optional MatchProto match = 1; + optional TourneyProto tourney = 2; + optional string game_type = 3; + optional string deck_type = 4; + optional string name = 5; + optional string controller_name = 6; + optional int64 start_time_ms = 7; + optional int64 end_time_ms = 8; +} + +message MatchProto { + optional string name = 1; + optional string game_type = 2; + optional string deck_type = 3; + optional int32 games = 4; + optional int32 draws = 5; + repeated MatchPlayerProto players = 6; +} + +message MatchPlayerProto { + optional string name = 1; + optional int32 wins = 2; + optional MatchQuitStatus quit = 3; + optional bool bye = 4; +} + +enum MatchQuitStatus { + NO_MATCH_QUIT = 0; + IDLE_TIMEOUT = 1; // I + TIMER_TIMEOUT = 2; // T + QUIT = 3; // Q +} + +message TourneyProto { + optional string booster_info = 1; + repeated TourneyPlayerProto players = 2; + repeated TourneyRoundProto rounds = 3; +} + +message TourneyPlayerProto { + optional string name = 1; + optional string player_type = 2; + optional string replaced_player_name = 3; + optional string state_info = 4; + optional string disconnect_info = 5; + optional TourneyQuitStatus quit = 6; +} + +enum TourneyQuitStatus { + NO_TOURNEY_QUIT = 0; + DURING_ROUND = 1; + DURING_DRAFTING = 2; + DURING_CONSTRUCTION = 3; +} + +message TourneyRoundProto { + optional int32 round = 1; + repeated MatchProto matches = 2; + repeated string byes = 3; +} + +message UserStatsProto { + optional string name = 1; + + optional int32 tourneys = 2; + optional int32 tourneys_quit_during_round = 3; + optional int32 tourneys_quit_during_drafting = 4; + optional int32 tourneys_quit_during_construction = 5; + + optional int32 matches = 6; + optional int32 matches_idle_timeout = 7; + optional int32 matches_timer_timeout = 8; + optional int32 matches_quit = 9; +} From 379e61f98ac0cd3a9f000ec06ab30bf03cfbe091 Mon Sep 17 00:00:00 2001 From: Me Car Date: Wed, 20 Jan 2016 13:04:04 +0900 Subject: [PATCH 2/3] Adjust the index correctly. --- .../src/main/java/mage/client/table/PlayersChatPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java b/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java index 8f1d8546fa6..0aa6e20af9c 100644 --- a/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/PlayersChatPanel.java @@ -128,7 +128,7 @@ public class PlayersChatPanel extends javax.swing.JPanel { TableColumnModel tcm = th.getColumnModel(); tcm.getColumn(jTablePlayers.convertColumnIndexToView(1)).setHeaderValue("Players (" + this.players.length + ")"); - tcm.getColumn(jTablePlayers.convertColumnIndexToView(3)).setHeaderValue( + tcm.getColumn(jTablePlayers.convertColumnIndexToView(4)).setHeaderValue( "Games " + roomUserInfo.getNumberActiveGames() + (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (") + " limit: " + roomUserInfo.getNumberMaxGames() + ")"); From 46e560bd94bf3e86a524bd1a7d511ebc2549ce5f Mon Sep 17 00:00:00 2001 From: Me Car Date: Wed, 20 Jan 2016 14:39:11 +0900 Subject: [PATCH 3/3] Removed unuseful proto fields. Added a better pom.xml documentation. Removed an unuseful logging. --- .../src/main/java/mage/server/record/TableRecorderImpl.java | 1 - Mage/pom.xml | 6 +++--- .../main/java/mage/game/tournament/TournamentPlayer.java | 2 -- Mage/src/main/proto/result.proto | 4 +--- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java index 0b5017b8f60..b4d16688edf 100644 --- a/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java +++ b/Mage.Server/src/main/java/mage/server/record/TableRecorderImpl.java @@ -16,7 +16,6 @@ public class TableRecorderImpl implements TableRecorder { public void record(Table table) { TableProto proto = table.toProto(); - logger.info("Adding record:\n" + proto.toString()); TableRecordRepository.instance.add(new TableRecord(proto, proto.getEndTimeMs())); } } diff --git a/Mage/pom.xml b/Mage/pom.xml index 4b163a6e8fe..d81c9655d9b 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -56,7 +56,7 @@ - + org.apache.maven.plugins @@ -167,7 +167,7 @@ mage - + @@ -178,7 +178,7 @@ - + ${project.basedir}/src/main/proto diff --git a/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java b/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java index e8a7a24debc..5b4042155a5 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentPlayer.java @@ -233,8 +233,6 @@ public class TournamentPlayer { return TourneyPlayerProto.newBuilder() .setName(this.player.getName()) .setPlayerType(this.playerType) - .setStateInfo(this.stateInfo) - .setDisconnectInfo(this.disconnectInfo) .setQuit(this.quitStatus) .build(); } diff --git a/Mage/src/main/proto/result.proto b/Mage/src/main/proto/result.proto index def7b8c52d0..b24d4714f5f 100644 --- a/Mage/src/main/proto/result.proto +++ b/Mage/src/main/proto/result.proto @@ -46,9 +46,7 @@ message TourneyPlayerProto { optional string name = 1; optional string player_type = 2; optional string replaced_player_name = 3; - optional string state_info = 4; - optional string disconnect_info = 5; - optional TourneyQuitStatus quit = 6; + optional TourneyQuitStatus quit = 4; } enum TourneyQuitStatus {