Record game histories. Compute user stats and show them in the user panel.

This commit is contained in:
Me Car 2016-01-20 12:47:58 +09:00
parent 9f3e2aa4c4
commit 550648ccbe
22 changed files with 866 additions and 60 deletions

View file

@ -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() {

View file

@ -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<TableRecord> 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()));
}
}
}
}
}
}

View file

@ -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;
}
}

View file

@ -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<String> 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<StringBuilder> 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<StringBuilder> builders = new ArrayList();
if (proto.getMatches() > 0) {
StringBuilder builder = new StringBuilder();
builder.append("Matches:");
builder.append(proto.getMatches());
List<String> 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<String> 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<TableView> tableList = new ArrayList<>();
ArrayList<MatchView> 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<UsersView> 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() : "<no name>",
history != null ? history : "<no history>",
user.getInfo() != null ? user.getInfo() : "<no info>",
"[exception]",
user.getPingInfo() != null ? user.getPingInfo() : "<no ping>"));

View file

@ -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;
}
}

View file

@ -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<TableRecord, Object> 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<TableRecord> getAfter(long endTimeMs) {
try {
QueryBuilder<TableRecord, Object> 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);
}
}
}

View file

@ -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()));
}
}

View file

@ -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;
}
}

View file

@ -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<UserStats, Object> 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<UserStats, Object> qb = dao.queryBuilder();
qb.where().eq("userName", userName);
List<UserStats> 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<UserStats> getAllUsers() {
try {
QueryBuilder<UserStats, Object> 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<UserStats, Object> qb = dao.queryBuilder();
qb.orderBy("endTimeMs", false).limit(1);
List<UserStats> 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);
}
}
}

View file

@ -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);