diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form index 01912da458..8a9d385eae 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form @@ -32,31 +32,33 @@ - + - + - - - - - - - - - + - - - - + + + + + + + + + + + + + + @@ -107,7 +109,7 @@ - + @@ -122,13 +124,15 @@ + + - - + + @@ -378,5 +382,12 @@ + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java index 71135fc798..2a7c9fc7f8 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -81,6 +81,7 @@ public class NewTableDialog extends MageDialog { player1Panel.showLevel(false); this.spnNumWins.setModel(new SpinnerNumberModel(1, 1, 5, 1)); this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1)); + this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); MageFrame.getUI().addButton(MageComponents.NEW_TABLE_OK_BUTTON, btnOK); } @@ -125,6 +126,8 @@ public class NewTableDialog extends MageDialog { jSeparator1 = new javax.swing.JSeparator(); btnOK = new javax.swing.JButton(); btnCancel = new javax.swing.JButton(); + lblQuitRatio = new javax.swing.JLabel(); + spnQuitRatio = new javax.swing.JSpinner(); setTitle("New Table"); @@ -209,6 +212,10 @@ public class NewTableDialog extends MageDialog { } }); + lblQuitRatio.setText("Allowed quit %"); + + spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table"); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -227,22 +234,26 @@ public class NewTableDialog extends MageDialog { .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 270, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(chkRollbackTurnsAllowed) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE) + .addGap(13, 13, 13) .addComponent(lblFreeMulligans) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(txtName) - .addComponent(cbDeckType, 0, 332, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lbTimeLimit, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblPassword, javax.swing.GroupLayout.Alignment.TRAILING)) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE))))) + .addComponent(lbTimeLimit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblPassword) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, 332, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblQuitRatio) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() @@ -280,7 +291,7 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 586, Short.MAX_VALUE) + .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 660, Short.MAX_VALUE) .addContainerGap())) ); layout.setVerticalGroup( @@ -291,13 +302,15 @@ public class NewTableDialog extends MageDialog { .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblName) .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblPassword)) + .addComponent(lblPassword) + .addComponent(lbTimeLimit) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbDeckType) - .addComponent(lbTimeLimit)) + .addComponent(lblQuitRatio) + .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -376,6 +389,7 @@ public class NewTableDialog extends MageDialog { options.setRollbackTurnsAllowed(chkRollbackTurnsAllowed.isSelected()); options.setFreeMulligans((Integer) this.spnFreeMulligans.getValue()); options.setPassword(this.txtPassword.getText()); + options.setQuitRatio((Integer) this.spnQuitRatio.getValue()); if (!checkMatchOptions(options)) { return; } @@ -613,6 +627,7 @@ public class NewTableDialog extends MageDialog { } this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, "2"))); this.chkRollbackTurnsAllowed.setSelected(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_ROLLBACK_TURNS_ALLOWED, "Yes").equals("Yes")); + this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, "0"))); int range = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, "1")); for (RangeOfInfluence roi : RangeOfInfluence.values()) { @@ -635,6 +650,8 @@ public class NewTableDialog extends MageDialog { break; } } + + this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO, "100"))); } /** @@ -658,6 +675,7 @@ public class NewTableDialog extends MageDialog { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, Integer.toString(options.getRange().getRange())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_ATTACK_OPTION, options.getAttackOption().toString()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_SKILL_LEVEL, options.getSkillLevel().toString()); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO, Integer.toString(options.getQuitRatio())); StringBuilder playerTypesString = new StringBuilder(); ListIterator iterator = players.listIterator(); while (iterator.hasNext()) { @@ -694,6 +712,7 @@ public class NewTableDialog extends MageDialog { private javax.swing.JLabel lblNumPlayers; private javax.swing.JLabel lblNumWins; private javax.swing.JLabel lblPassword; + private javax.swing.JLabel lblQuitRatio; private javax.swing.JLabel lblRange; private javax.swing.JLabel lblSkillLevel; private mage.client.table.NewPlayerPanel player1Panel; @@ -701,6 +720,7 @@ public class NewTableDialog extends MageDialog { private javax.swing.JSpinner spnFreeMulligans; private javax.swing.JSpinner spnNumPlayers; private javax.swing.JSpinner spnNumWins; + private javax.swing.JSpinner spnQuitRatio; private javax.swing.JTextField txtName; private javax.swing.JTextField txtPassword; // End of variables declaration//GEN-END:variables diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form index 92ca80af08..bcce7a2ac5 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form @@ -72,7 +72,7 @@ - + @@ -85,16 +85,16 @@ - - - - - - + + + + + + @@ -114,6 +114,11 @@ + + + + + @@ -140,14 +145,19 @@ - - + + + + + + + @@ -191,7 +201,7 @@ - + @@ -525,5 +535,15 @@ + + + + + + + + + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index 101b3f708d..3667ce7c02 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -99,6 +99,7 @@ public class NewTournamentDialog extends MageDialog { this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1)); this.spnConstructTime.setModel(new SpinnerNumberModel(10, CONSTRUCTION_TIME_MIN, CONSTRUCTION_TIME_MAX, 2)); this.spnNumRounds.setModel(new SpinnerNumberModel(2, 2, 10, 1)); + this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); } public void showDialog(UUID roomId) { @@ -179,6 +180,8 @@ public class NewTournamentDialog extends MageDialog { btnOk = new javax.swing.JButton(); btnCancel = new javax.swing.JButton(); pnlRandomPacks = new javax.swing.JPanel(); + lblQuitRatio = new javax.swing.JLabel(); + spnQuitRatio = new javax.swing.JSpinner(); setTitle("New Tournament"); @@ -345,6 +348,10 @@ public class NewTournamentDialog extends MageDialog { pnlRandomPacks.setToolTipText(""); pnlRandomPacks.setLayout(new javax.swing.BoxLayout(pnlRandomPacks, javax.swing.BoxLayout.Y_AXIS)); + lblQuitRatio.setText("Allowed quit %:"); + + spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table"); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -401,15 +408,15 @@ public class NewTournamentDialog extends MageDialog { .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(layout.createSequentialGroup() - .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGap(28, 28, 28) .addComponent(lblNumWins) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lblQuitRatio) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGroup(layout.createSequentialGroup() .addComponent(lblName) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -425,7 +432,11 @@ public class NewTournamentDialog extends MageDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(lblPassword) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE))))) + .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))))) .addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlRandomPacks, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) @@ -445,12 +456,16 @@ public class NewTournamentDialog extends MageDialog { .addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblTournamentType) - .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblFreeMulligans) .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblNumWins) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblQuitRatio) + .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblTournamentType)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbDraftCube, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -487,7 +502,7 @@ public class NewTournamentDialog extends MageDialog { .addComponent(lblConstructionTime) .addComponent(chkRollbackTurnsAllowed))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(player1Panel, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE) + .addComponent(player1Panel, javax.swing.GroupLayout.PREFERRED_SIZE, 62, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(pnlPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -513,6 +528,7 @@ public class NewTournamentDialog extends MageDialog { tOptions.setPassword(txtPassword.getText()); tOptions.getPlayerTypes().add("Human"); tOptions.setWatchingAllowed(cbAllowSpectators.isSelected()); + tOptions.setQuitRatio((Integer)spnQuitRatio.getValue()); for (TournamentPlayerPanel player: players) { tOptions.getPlayerTypes().add((String) player.getPlayerType().getSelectedItem()); } @@ -689,7 +705,7 @@ public class NewTournamentDialog extends MageDialog { this.lblConstructionTime.setVisible(tournamentType.isLimited()); this.spnConstructTime.setVisible(tournamentType.isLimited()); - + this.lbDeckType.setVisible(!tournamentType.isLimited()); this.cbDeckType.setVisible(!tournamentType.isLimited()); this.lblGameType.setVisible(!tournamentType.isLimited()); @@ -914,7 +930,7 @@ public class NewTournamentDialog extends MageDialog { } this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS, "0"))); this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS, "2"))); - + this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO, "100"))); TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem(); activatePanelElements(tournamentType); @@ -985,6 +1001,7 @@ public class NewTournamentDialog extends MageDialog { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_TYPE, tOptions.getTournamentType()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS, Integer.toString(tOptions.getMatchOptions().getFreeMulligans())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS, Integer.toString(tOptions.getMatchOptions().getWinsNeeded())); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO, Integer.toString(tOptions.getQuitRatio())); if (tOptions.getTournamentType().startsWith("Sealed")) { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_SEALED, tOptions.getLimitedOptions().getSetCodes().toString()); @@ -1050,6 +1067,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JLabel lblPacks; private javax.swing.JLabel lblPassword; private javax.swing.JLabel lblPlayer1; + private javax.swing.JLabel lblQuitRatio; private javax.swing.JLabel lblTournamentType; private mage.client.table.NewPlayerPanel player1Panel; private javax.swing.JPanel pnlDraftOptions; @@ -1062,6 +1080,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JSpinner spnNumPlayers; private javax.swing.JSpinner spnNumRounds; private javax.swing.JSpinner spnNumWins; + private javax.swing.JSpinner spnQuitRatio; private javax.swing.JTextField txtName; private javax.swing.JTextField txtPassword; private org.jdesktop.beansbinding.BindingGroup bindingGroup; diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 88e68ca865..bac599ff4a 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -194,6 +194,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_NEW_TABLE_SKILL_LEVEL = "newTableSkillLevel"; public static final String KEY_NEW_TABLE_NUMBER_PLAYERS = "newTableNumberPlayers"; public static final String KEY_NEW_TABLE_PLAYER_TYPES = "newTablePlayerTypes"; + public static final String KEY_NEW_TABLE_QUIT_RATIO = "newTableQuitRatio"; // pref setting for new tournament dialog public static final String KEY_NEW_TOURNAMENT_NAME = "newTournamentName"; @@ -212,6 +213,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_NEW_TOURNAMENT_ALLOW_SPECTATORS = "newTournamentAllowSpectators"; public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks"; public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile"; + public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio"; // pref setting for deck generator public static final String KEY_NEW_DECK_GENERATOR_DECK_SIZE = "newDeckGeneratorDeckSize"; 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 497376ade0..543ceb53ab 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[] DEFAULT_COLUMNS_WIDTH = {20, 100, 100, 100, 80, 80}; + private static final int[] DEFAULT_COLUMNS_WIDTH = {20, 100, 40, 100, 40, 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", "Matches", "Tourneys", "Games", "Connection"}; + private final String[] columnNames = new String[]{"Loc", "Players", "Matches", "MQ%", "Tourneys", "TQ%", "Games", "Connection"}; private UsersView[] players = new UsersView[0]; public void loadData(Collection roomUserInfoList) throws MageRemoteException { @@ -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(4)).setHeaderValue( + tcm.getColumn(jTablePlayers.convertColumnIndexToView(6)).setHeaderValue( "Games " + roomUserInfo.getNumberActiveGames() + (roomUserInfo.getNumberActiveGames() != roomUserInfo.getNumberGameThreads() ? " (T:" + roomUserInfo.getNumberGameThreads() : " (") + " limit: " + roomUserInfo.getNumberMaxGames() + ")"); @@ -156,10 +156,14 @@ public class PlayersChatPanel extends javax.swing.JPanel { case 2: return players[arg0].getMatchHistory(); case 3: - return players[arg0].getTourneyHistory(); + return players[arg0].getMatchQuitRatio(); case 4: - return players[arg0].getInfoGames(); + return players[arg0].getTourneyHistory(); case 5: + return players[arg0].getTourneyQuitRatio(); + case 6: + return players[arg0].getInfoGames(); + case 7: return players[arg0].getInfoPing(); } return ""; diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index 1fa0b11e79..63e2b2c2ce 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -119,7 +119,7 @@ public class TablesPanel extends javax.swing.JPanel { JToggleButton[] filterButtons; - private static final int[] defaultColumnsWidth = {35, 150, 120, 180, 80, 120, 80, 60, 60}; + private static final int[] defaultColumnsWidth = {35, 150, 120, 180, 80, 120, 80, 60, 40, 60}; /** * Creates new form TablesPanel @@ -1239,9 +1239,10 @@ class TableTableModel extends AbstractTableModel { public static final int COLUMN_INFO = 4; public static final int COLUMN_STATUS = 5; public static final int COLUMN_SKILL = 7; - public static final int ACTION_COLUMN = 8; // column the action is located (starting with 0) + public static final int COLUMN_QUIT_RATIO = 8; + public static final int ACTION_COLUMN = 9; // column the action is located (starting with 0) - private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Created / Started", "Skill Level", "Action"}; + private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Created / Started", "Skill Level", "Quit %", "Action"}; private TableView[] tables = new TableView[0]; private static final DateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss"); @@ -1288,6 +1289,8 @@ class TableTableModel extends AbstractTableModel { case 7: return tables[arg0].getSkillLevel(); case 8: + return tables[arg0].getQuitRatio(); + case 9: switch (tables[arg0].getTableState()) { case WAITING: @@ -1314,14 +1317,14 @@ class TableTableModel extends AbstractTableModel { default: return ""; } - case 9: - return tables[arg0].isTournament(); case 10: + return tables[arg0].isTournament(); + case 11: if (!tables[arg0].getGames().isEmpty()) { return tables[arg0].getGames().get(0); } return null; - case 11: + case 12: return tables[arg0].getTableId(); } return ""; diff --git a/Mage.Common/src/mage/view/TableView.java b/Mage.Common/src/mage/view/TableView.java index 8005e9d9e9..3cda470098 100644 --- a/Mage.Common/src/mage/view/TableView.java +++ b/Mage.Common/src/mage/view/TableView.java @@ -62,6 +62,7 @@ public class TableView implements Serializable { private boolean isTournament; private List seats = new ArrayList<>(); private List games = new ArrayList<>(); + private final String quitRatio; public TableView(Table table) { this.tableId = table.getId(); @@ -130,6 +131,7 @@ public class TableView implements Serializable { } this.additionalInfo = addInfo.toString(); this.skillLevel = table.getMatch().getOptions().getSkillLevel(); + this.quitRatio = Integer.toString(table.getMatch().getOptions().getQuitRatio()); } else { // TOURNAMENT if (table.getTournament().getOptions().getNumberRounds() > 0) { @@ -176,6 +178,7 @@ public class TableView implements Serializable { this.tableStateText = stateText.toString(); this.deckType = table.getDeckType() + " " + table.getTournament().getBoosterInfo() + (tableNameInfo != null ? tableNameInfo : ""); this.skillLevel = table.getTournament().getOptions().getMatchOptions().getSkillLevel(); + this.quitRatio = Integer.toString(table.getTournament().getOptions().getQuitRatio()); } } @@ -230,4 +233,7 @@ public class TableView implements Serializable { return skillLevel; } + public String getQuitRatio() { + return quitRatio; + } } diff --git a/Mage.Common/src/mage/view/UsersView.java b/Mage.Common/src/mage/view/UsersView.java index 24aece6f1f..cf2544767c 100644 --- a/Mage.Common/src/mage/view/UsersView.java +++ b/Mage.Common/src/mage/view/UsersView.java @@ -40,14 +40,19 @@ public class UsersView implements Serializable { private final String flagName; private final String userName; private final String matchHistory; + private final String matchQuitRatio; private final String tourneyHistory; + private final String tourneyQuitRatio; private final String infoGames; private final String infoPing; - public UsersView(String flagName, String userName, String matchHistory, String tourneyHistory, String infoGames, String infoPing) { + public UsersView(String flagName, String userName, String matchHistory, int matchQuitRatio, + String tourneyHistory, int tourneyQuitRatio, String infoGames, String infoPing) { this.flagName = flagName; this.matchHistory = matchHistory; + this.matchQuitRatio = Integer.toString(matchQuitRatio); this.tourneyHistory = tourneyHistory; + this.tourneyQuitRatio = Integer.toString(tourneyQuitRatio); this.userName = userName; this.infoGames = infoGames; this.infoPing = infoPing; @@ -65,10 +70,18 @@ public class UsersView implements Serializable { return matchHistory; } + public String getMatchQuitRatio() { + return matchQuitRatio; + } + public String getTourneyHistory() { return tourneyHistory; } + public String getTourneyQuitRatio() { + return tourneyQuitRatio; + } + public String getInfoGames() { return infoGames; } diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index d0a62c9940..07d58fcea6 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -238,9 +238,21 @@ public class MageServerImpl implements MageServer { @Override public TableView execute() throws MageException { UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId(); + User user = UserManager.getInstance().getUser(userId); + + // check if the user satisfies the quitRatio requirement. + if (user != null) { + int quitRatio = options.getQuitRatio(); + if (quitRatio < user.getMatchQuitRatio()) { + String message = new StringBuilder("Your quit ratio ").append(user.getMatchQuitRatio()) + .append("% is higher than the table requirement ").append(quitRatio).append("%").toString(); + user.showUserMessage("Create table", message); + throw new MageException("No message"); + } + } + TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(userId, options); if (logger.isDebugEnabled()) { - User user = UserManager.getInstance().getUser(userId); if (user != null) { logger.debug("TABLE created - tableId: " + table.getTableId() + " " + table.getTableName()); logger.debug("- " + user.getName() + " userId: " + user.getId()); @@ -260,6 +272,7 @@ public class MageServerImpl implements MageServer { public TableView execute() throws MageException { try { UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId(); + User user = UserManager.getInstance().getUser(userId); // check AI players max String maxAiOpponents = ConfigSettings.getInstance().getMaxAiOpponents(); if (maxAiOpponents != null) { @@ -271,13 +284,22 @@ public class MageServerImpl implements MageServer { } } if (aiPlayers > max) { - User user = UserManager.getInstance().getUser(userId); if (user != null) { user.showUserMessage("Create tournament", "It's only allowed to use a maximum of " + max + " AI players."); } throw new MageException("No message"); } } + // check if the user satisfies the quitRatio requirement. + if (user != null) { + int quitRatio = options.getQuitRatio(); + if (quitRatio < user.getTourneyQuitRatio()) { + String message = new StringBuilder("Your quit ratio ").append(user.getTourneyQuitRatio()) + .append("% is higher than the table requirement ").append(quitRatio).append("%").toString(); + user.showUserMessage("Create tournament", message); + throw new MageException("No message"); + } + } TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTournamentTable(userId, options); logger.debug("Tournament table " + table.getTableId() + " created"); LogServiceImpl.instance.log(LogKeys.KEY_TOURNAMENT_TABLE_CREATED, sessionId, userId.toString(), table.getTableId().toString()); diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 0af0a5c829..2348e4b3d4 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -170,7 +170,7 @@ public class TableController { } } if (userPlayerMap.containsKey(userId) && playerType.equals("Human")) { - user.showUserMessage("Join Table", new StringBuilder("You can join a table only one time.").toString()); + user.showUserMessage("Join Table", "You can join a table only one time."); return false; } Deck deck = null; @@ -195,6 +195,14 @@ public class TableController { return false; } } + // Check quit ratio. + int quitRatio = table.getTournament().getOptions().getQuitRatio(); + if (quitRatio < user.getTourneyQuitRatio()) { + String message = new StringBuilder("Your quit ratio ").append(user.getTourneyQuitRatio()) + .append("% is higher than the table requirement ").append(quitRatio).append("%").toString(); + user.showUserMessage("Join Table", message); + return false; + } Player player = createPlayer(name, seat.getPlayerType(), skill); if (player != null) { @@ -284,6 +292,15 @@ public class TableController { } return false; } + // Check quit ratio. + int quitRatio = table.getMatch().getOptions().getQuitRatio(); + if (quitRatio < user.getMatchQuitRatio()) { + String message = new StringBuilder("Your quit ratio ").append(user.getMatchQuitRatio()) + .append("% is higher than the table requirement ").append(quitRatio).append("%").toString(); + user.showUserMessage("Join Table", message); + return false; + } + Player player = createPlayer(name, seat.getPlayerType(), skill); if (player == null) { String message = new StringBuilder("Could not create player ").append(name).append(" of type ").append(seat.getPlayerType()).toString(); diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 8a48715539..866d1da00f 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -530,10 +530,14 @@ public class User { userStats = UserStatsRepository.instance.getUser(this.userName); if (userStats != null) { userData.setMatchHistory(userStatsToMatchHistory(userStats.getProto())); + userData.setMatchQuitRatio(userStatsToMatchQuitRatio(userStats.getProto())); userData.setTourneyHistory(userStatsToTourneyHistory(userStats.getProto())); + userData.setTourneyQuitRatio(userStatsToTourneyQuitRatio(userStats.getProto())); } else { userData.setMatchHistory("0"); + userData.setMatchQuitRatio(0); userData.setTourneyHistory("0"); + userData.setTourneyQuitRatio(0); } } @@ -544,6 +548,13 @@ public class User { return ""; } + public int getMatchQuitRatio() { + if (userData != null) { + return userData.getMatchQuitRatio(); + } + return 0; + } + public String getTourneyHistory() { if (userData != null) { return userData.getTourneyHistory(); @@ -556,6 +567,13 @@ public class User { " Tourneys: " + userStatsToTourneyHistory(proto); } + public int getTourneyQuitRatio() { + if (userData != null) { + return userData.getTourneyQuitRatio(); + } + return 0; + } + public static String userStatsToMatchHistory(ResultProtos.UserStatsProto proto) { StringBuilder builder = new StringBuilder(); builder.append(proto.getMatches()); @@ -577,6 +595,17 @@ public class User { return builder.toString(); } + public static int userStatsToMatchQuitRatio(ResultProtos.UserStatsProto proto) { + int matches = proto.getMatches(); + if (matches == 0) { + return 0; + } + int quits = proto.getMatchesIdleTimeout() + + proto.getMatchesTimerTimeout() + + proto.getMatchesQuit(); + return 100 * quits / matches; + } + public static String userStatsToTourneyHistory(ResultProtos.UserStatsProto proto) { StringBuilder builder = new StringBuilder(); builder.append(proto.getTourneys()); @@ -598,6 +627,17 @@ public class User { return builder.toString(); } + public static int userStatsToTourneyQuitRatio(ResultProtos.UserStatsProto proto) { + int tourneys = proto.getTourneys(); + if (tourneys == 0) { + return 0; + } + int quits = proto.getTourneysQuitDuringDrafting() + + proto.getTourneysQuitDuringConstruction() + + proto.getTourneysQuitDuringRound(); + return 100 * quits / tourneys; + } + private static void joinStrings(StringBuilder joined, List strings, String separator) { for (int i = 0; i < strings.size(); ++i) { if (i > 0) { 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 8c9d25b96d..5d4d66f27f 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -114,14 +114,18 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { List users = new ArrayList<>(); for (User user : UserManager.getInstance().getUsers()) { try { - users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), user.getMatchHistory(), user.getTourneyHistory(), user.getGameInfo(), user.getPingInfo())); + users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), + user.getMatchHistory(), user.getMatchQuitRatio(), user.getTourneyHistory(), + user.getTourneyQuitRatio(), 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() : "", user.getMatchHistory() != null ? user.getMatchHistory() : "", + user.getMatchQuitRatio(), user.getTourneyHistory() != null ? user.getTourneyHistory() : "", + user.getTourneyQuitRatio(), "[exception]", user.getPingInfo() != null ? user.getPingInfo() : "")); } diff --git a/Mage/src/main/java/mage/game/match/MatchOptions.java b/Mage/src/main/java/mage/game/match/MatchOptions.java index 7fce862547..28479dda0a 100644 --- a/Mage/src/main/java/mage/game/match/MatchOptions.java +++ b/Mage/src/main/java/mage/game/match/MatchOptions.java @@ -54,6 +54,7 @@ public class MatchOptions implements Serializable { protected String password; protected SkillLevel skillLevel; protected boolean rollbackTurnsAllowed; + protected int quitRatio; /** * Time each player has during the game to play using his\her priority. @@ -167,5 +168,13 @@ public class MatchOptions implements Serializable { public void setRollbackTurnsAllowed(boolean rollbackTurnsAllowed) { this.rollbackTurnsAllowed = rollbackTurnsAllowed; - } + } + + public int getQuitRatio() { + return quitRatio; + } + + public void setQuitRatio(int quitRatio) { + this.quitRatio = quitRatio; + } } diff --git a/Mage/src/main/java/mage/game/tournament/TournamentOptions.java b/Mage/src/main/java/mage/game/tournament/TournamentOptions.java index 3f107e4369..4a111ebcd7 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentOptions.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentOptions.java @@ -46,6 +46,7 @@ public class TournamentOptions implements Serializable { protected boolean watchingAllowed = true; protected int numberRounds; protected String password; + protected int quitRatio; public TournamentOptions(String name) { this.name = name; @@ -103,4 +104,11 @@ public class TournamentOptions implements Serializable { this.password = password; } + public int getQuitRatio() { + return quitRatio; + } + + public void setQuitRatio(int quitRatio) { + this.quitRatio = quitRatio; + } } diff --git a/Mage/src/main/java/mage/players/net/UserData.java b/Mage/src/main/java/mage/players/net/UserData.java index f875260d2c..572688c19e 100644 --- a/Mage/src/main/java/mage/players/net/UserData.java +++ b/Mage/src/main/java/mage/players/net/UserData.java @@ -24,7 +24,9 @@ public class UserData implements Serializable { protected boolean autoOrderTrigger; protected String matchHistory; + protected int matchQuitRatio; protected String tourneyHistory; + protected int tourneyQuitRatio; public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, @@ -44,7 +46,9 @@ public class UserData implements Serializable { this.passPriorityActivation = passPriorityActivation; this.autoOrderTrigger = autoOrderTrigger; this.matchHistory = ""; + this.matchQuitRatio = 0; this.tourneyHistory = ""; + this.tourneyQuitRatio = 0; } public void update(UserData userData) { @@ -183,6 +187,14 @@ public class UserData implements Serializable { return matchHistory; } + public void setMatchQuitRatio(int ratio) { + this.matchQuitRatio = ratio; + } + + public int getMatchQuitRatio() { + return matchQuitRatio; + } + public void setTourneyHistory(String history) { this.tourneyHistory = history; } @@ -191,6 +203,14 @@ public class UserData implements Serializable { return tourneyHistory; } + public void setTourneyQuitRatio(int ratio) { + this.tourneyQuitRatio = ratio; + } + + public int getTourneyQuitRatio() { + return tourneyQuitRatio; + } + public static String getDefaultFlagName() { return "world.png"; }