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 5dfc2743e95..cec7d3c43e3 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.form @@ -25,41 +25,49 @@ - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + - - - + + + + + - - - + - - + + @@ -88,6 +96,7 @@ + @@ -98,7 +107,7 @@ - + @@ -107,17 +116,19 @@ - - - - - - - + + + + + + + + + @@ -157,10 +168,12 @@ - + + + - + @@ -174,7 +187,7 @@ - + @@ -198,6 +211,13 @@ + + + + + + + @@ -281,6 +301,8 @@ + + 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 655f289493e..8f557402962 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -27,21 +27,23 @@ */ package mage.client.dialog; - import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import javax.swing.*; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JOptionPane; +import javax.swing.SpinnerNumberModel; import mage.cards.decks.importer.DeckImporterUtil; import mage.client.MageFrame; import mage.client.components.MageComponents; -import mage.client.table.*; +import mage.client.table.TablePlayerPanel; import mage.client.util.Event; import mage.client.util.Listener; +import mage.constants.MatchTimeLimit; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; import mage.game.match.MatchOptions; import mage.remote.Session; import mage.view.GameTypeView; @@ -85,6 +87,8 @@ public class NewTableDialog extends MageDialog { txtName = new javax.swing.JTextField(); lbDeckType = new javax.swing.JLabel(); cbDeckType = new javax.swing.JComboBox(); + lbTimeLimit = new javax.swing.JLabel(); + cbTimeLimit = new javax.swing.JComboBox(); lblGameType = new javax.swing.JLabel(); cbGameType = new javax.swing.JComboBox(); lblFreeMulligans = new javax.swing.JLabel(); @@ -114,6 +118,8 @@ public class NewTableDialog extends MageDialog { lbDeckType.setText("Deck Type:"); + lbTimeLimit.setText("Time Limit:"); + lblGameType.setText("Game Type:"); cbGameType.addActionListener(new java.awt.event.ActionListener() { @@ -177,33 +183,39 @@ public class NewTableDialog extends MageDialog { .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel1)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel2)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() .addGap(16, 16, 16) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lbDeckType) .addComponent(lblGameType) - .addComponent(lblName)) + .addComponent(lblName))) + .addGroup(layout.createSequentialGroup() + .addGap(30, 30, 30) + .addComponent(lbDeckType))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, 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, 50, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(cbDeckType, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, 398, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 546, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(cbDeckType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lbTimeLimit) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.DEFAULT_SIZE, 50, Short.MAX_VALUE)) - .addComponent(txtName)))) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE)))))) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnOK) @@ -233,27 +245,30 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 625, Short.MAX_VALUE) + .addComponent(jSeparator3, javax.swing.GroupLayout.DEFAULT_SIZE, 633, Short.MAX_VALUE) .addContainerGap())) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(lblName) .addComponent(txtName, 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.TRAILING) - .addComponent(lbDeckType) - .addComponent(cbDeckType, 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(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblGameType) + .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)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFreeMulligans))) + .addComponent(lblFreeMulligans)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cbGameType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblGameType))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) @@ -282,7 +297,7 @@ public class NewTableDialog extends MageDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel2) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) + .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 144, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -294,7 +309,7 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createSequentialGroup() .addGap(201, 201, 201) .addComponent(jSeparator3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(240, Short.MAX_VALUE))) + .addContainerGap(244, Short.MAX_VALUE))) ); pack(); @@ -315,6 +330,7 @@ public class NewTableDialog extends MageDialog { } options.setDeckType((String) this.cbDeckType.getSelectedItem()); options.setLimited(false); + options.setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); options.setAttackOption((MultiplayerAttackOption) this.cbAttackOption.getSelectedItem()); options.setRange((RangeOfInfluence) this.cbRange.getSelectedItem()); options.setWinsNeeded((Integer)this.spnNumWins.getValue()); @@ -422,6 +438,7 @@ public class NewTableDialog extends MageDialog { cbGameType.setModel(new DefaultComboBoxModel(session.getGameTypes().toArray())); cbDeckType.setModel(new DefaultComboBoxModel(session.getDeckTypes())); selectLimitedByDefault(); + cbTimeLimit.setModel(new DefaultComboBoxModel(MatchTimeLimit.values())); cbRange.setModel(new DefaultComboBoxModel(RangeOfInfluence.values())); cbAttackOption.setModel(new DefaultComboBoxModel(MultiplayerAttackOption.values())); @@ -464,13 +481,19 @@ public class NewTableDialog extends MageDialog { break; } } + int timeLimit = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, "0")); + for (MatchTimeLimit mtl :MatchTimeLimit.values()) { + if (mtl.getTimeLimit() == timeLimit) { + this.cbTimeLimit.setSelectedItem(mtl); + break; + } + } cbDeckType.setSelectedItem(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_DECK_TYPE, "Limited")); String deckFile = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, null); if (deckFile != null) { this.player1Panel.setDeckFile(deckFile); } this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, "2"))); - this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, "0"))); this.spnNumPlayers.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, "2"))); int range = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, "1")); for (RangeOfInfluence roi :RangeOfInfluence.values()) { @@ -497,9 +520,9 @@ public class NewTableDialog extends MageDialog { private void saveGameSettingsToPrefs(MatchOptions options, String deckFile) { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NAME, options.getName()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_TYPE, options.getDeckType()); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_TIME_LIMIT, Integer.toString(options.getPriorityTime())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_GAME_TYPE, options.getGameType()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_WINS, Integer.toString(options.getWinsNeeded())); - PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS, Integer.toString(options.getFreeMulligans())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_DECK_FILE, deckFile); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_NUMBER_PLAYERS, spnNumPlayers.getValue().toString()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_RANGE, Integer.toString(options.getRange().getRange())); @@ -513,12 +536,14 @@ public class NewTableDialog extends MageDialog { private javax.swing.JComboBox cbDeckType; private javax.swing.JComboBox cbGameType; private javax.swing.JComboBox cbRange; + private javax.swing.JComboBox cbTimeLimit; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JSeparator jSeparator1; private javax.swing.JSeparator jSeparator2; private javax.swing.JSeparator jSeparator3; private javax.swing.JLabel lbDeckType; + private javax.swing.JLabel lbTimeLimit; private javax.swing.JLabel lblAttack; private javax.swing.JLabel lblFreeMulligans; private javax.swing.JLabel lblGameType; @@ -534,4 +559,4 @@ public class NewTableDialog extends MageDialog { private javax.swing.JTextField txtName; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} 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 a11795a9219..d2b4221f2de 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.form @@ -27,36 +27,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -73,6 +43,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -85,39 +91,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - + @@ -140,6 +137,13 @@ + + + + + + + @@ -233,7 +237,7 @@ - + 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 497513246e2..04a623f5fd9 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -41,12 +41,13 @@ import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JOptionPane; import javax.swing.SpinnerNumberModel; -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.client.MageFrame; import mage.client.table.TournamentPlayerPanel; +import mage.constants.MatchTimeLimit; +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; import mage.game.draft.DraftOptions; import mage.game.draft.DraftOptions.TimingOption; import mage.game.tournament.LimitedOptions; @@ -86,6 +87,7 @@ public class NewTournamentDialog extends MageDialog { session = MageFrame.getSession(); this.txtPlayer1Name.setText(session.getUserName()); cbTournamentType.setModel(new DefaultComboBoxModel(session.getTournamentTypes().toArray())); + cbTimeLimit.setModel(new DefaultComboBoxModel(MatchTimeLimit.values())); cbDraftTiming.setModel(new DefaultComboBoxModel(DraftOptions.TimingOption.values())); this.setModal(true); setTournamentOptions(); @@ -104,6 +106,8 @@ public class NewTournamentDialog extends MageDialog { lblName = new javax.swing.JLabel(); txtName = new javax.swing.JTextField(); + lbTimeLimit = new javax.swing.JLabel(); + cbTimeLimit = new javax.swing.JComboBox(); lblConstructionTime = new javax.swing.JLabel(); spnConstructTime = new javax.swing.JSpinner(); jLabel1 = new javax.swing.JLabel(); @@ -131,6 +135,8 @@ public class NewTournamentDialog extends MageDialog { lblName.setText("Name:"); + lbTimeLimit.setText("Time Limit:"); + lblConstructionTime.setText("Construction Time (Minutes):"); jLabel1.setText("Tournament Type:"); @@ -198,7 +204,7 @@ public class NewTournamentDialog extends MageDialog { .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() .addComponent(jLabel4) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtPlayer1Name, javax.swing.GroupLayout.DEFAULT_SIZE, 638, Short.MAX_VALUE))) + .addComponent(txtPlayer1Name))) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -247,29 +253,6 @@ public class NewTournamentDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblName) - .addComponent(jLabel1)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(txtName) - .addComponent(cbTournamentType, 0, 330, Short.MAX_VALUE)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnFreeMulligans) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(lblNumWins)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(19, 19, 19) - .addComponent(lblConstructionTime))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(spnConstructTime, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE) - .addComponent(spnNumWins))) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(btnOk) @@ -283,7 +266,36 @@ public class NewTournamentDialog extends MageDialog { .addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING)) + .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(lblName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, 233, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(lbTimeLimit) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTimeLimit, 0, 115, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(cbTournamentType, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblFreeMulligans) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblNumWins) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(23, 23, 23) + .addComponent(lblConstructionTime) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnConstructTime, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))))) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); @@ -291,32 +303,28 @@ public class NewTournamentDialog extends MageDialog { layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblName)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblConstructionTime) - .addComponent(spnConstructTime, 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(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblNumWins) - .addComponent(spnFreeMulligans, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFreeMulligans)))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblName) + .addComponent(lbTimeLimit) + .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblConstructionTime) + .addComponent(spnConstructTime, 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(jLabel1) + .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)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 65, Short.MAX_VALUE) + .addComponent(pnlPacks, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE) .addGap(11, 11, 11) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE) + .addComponent(spnNumPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE) .addComponent(pnlDraftOptions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jLabel2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -357,6 +365,7 @@ public class NewTournamentDialog extends MageDialog { tOptions.getLimitedOptions().getSetCodes().add(((ExpansionSet) pack.getSelectedItem()).getCode()); } } + tOptions.getMatchOptions().setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); tOptions.getMatchOptions().setDeckType("Limited"); tOptions.getMatchOptions().setWinsNeeded((Integer)this.spnNumWins.getValue()); tOptions.getMatchOptions().setFreeMulligans((Integer)this.spnFreeMulligans.getValue()); @@ -512,6 +521,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JButton btnCancel; private javax.swing.JButton btnOk; private javax.swing.JComboBox cbDraftTiming; + private javax.swing.JComboBox cbTimeLimit; private javax.swing.JComboBox cbTournamentType; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; @@ -520,6 +530,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JPanel jPanel1; + private javax.swing.JLabel lbTimeLimit; private javax.swing.JLabel lblConstructionTime; private javax.swing.JLabel lblFreeMulligans; private javax.swing.JLabel lblName; 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 bef9caf4f93..46f230051d6 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -92,6 +92,7 @@ public class PreferencesDialog extends javax.swing.JDialog { // default setting for new table dialog public static final String KEY_NEW_TABLE_NAME = "newTableName"; public static final String KEY_NEW_TABLE_DECK_TYPE = "newTableDeckType"; + public static final String KEY_NEW_TABLE_TIME_LIMIT = "newTableTimeLimit"; public static final String KEY_NEW_TABLE_GAME_TYPE = "newTableGameType"; public static final String KEY_NEW_TABLE_NUMBER_OF_WINS = "newTableNumberOfWins"; public static final String KEY_NEW_TABLE_NUMBER_OF_FREE_MULLIGANS = "newTableNumberOfFreeMulligans"; diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index d5e08a492e4..fa4137f8435 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -353,7 +353,7 @@ public final class GamePanel extends javax.swing.JPanel { } } PlayerView player = game.getPlayers().get(playerSeat); - PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true); + PlayAreaPanel sessionPlayer = new PlayAreaPanel(player, bigCard, gameId, true, game.getPriorityTime()); players.put(player.getPlayerId(), sessionPlayer); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; @@ -385,7 +385,7 @@ public final class GamePanel extends javax.swing.JPanel { col = numColumns - 1; } player = game.getPlayers().get(playerNum); - PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false); + PlayAreaPanel playerPanel = new PlayAreaPanel(player, bigCard, gameId, false, game.getPriorityTime()); players.put(player.getPlayerId(), playerPanel); c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java index 5f763feb966..48a77a1ec33 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java @@ -64,9 +64,9 @@ public class PlayAreaPanel extends javax.swing.JPanel { addPopupMenu(); } - public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean me) { + public PlayAreaPanel(PlayerView player, BigCard bigCard, UUID gameId, boolean me, int priorityTime) { this(); - init(player, bigCard, gameId); + init(player, bigCard, gameId, priorityTime); update(player); } @@ -99,8 +99,8 @@ public class PlayAreaPanel extends javax.swing.JPanel { }); } - public final void init(PlayerView player, BigCard bigCard, UUID gameId) { - this.playerPanel.init(gameId, player.getPlayerId(), bigCard); + public final void init(PlayerView player, BigCard bigCard, UUID gameId, int priorityTime) { + this.playerPanel.init(gameId, player.getPlayerId(), bigCard, priorityTime); this.battlefieldPanel.init(gameId, bigCard); this.gameId = gameId; if (MageFrame.getSession().isTestMode()) { diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index 3a93ad629aa..8209c856006 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -52,7 +52,6 @@ import mage.client.util.Command; import mage.client.util.ImageHelper; import mage.client.util.gui.BufferedImageBuilder; import mage.components.ImagePanel; -import mage.constants.Constants; import mage.remote.Session; import mage.utils.timer.PriorityTimer; import mage.view.CardView; @@ -112,7 +111,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { initComponents(); } - public void init(UUID gameId, UUID playerId, BigCard bigCard) { + public void init(UUID gameId, UUID playerId, BigCard bigCard, int priorityTime) { this.gameId = gameId; this.playerId = playerId; this.bigCard = bigCard; @@ -120,24 +119,27 @@ public class PlayerPanelExt extends javax.swing.JPanel { cheat.setVisible(session.isTestMode()); cheat.setFocusable(false); - long delay = 1000L; - timer = new PriorityTimer(Constants.PRIORITY_TIME_SEC, delay, new mage.interfaces.Action() { - @Override - public void execute() throws MageException { - // do nothing - } - }); - final PriorityTimer pt = timer; - timer.setTaskOnTick(new mage.interfaces.Action() { - @Override - public void execute() throws MageException { - int priorityTimeValue = pt.getCount(); - String text = getPriorityTimeLeftString(priorityTimeValue); - PlayerPanelExt.this.avatar.setTopText(text); - PlayerPanelExt.this.avatar.repaint(); - } - }); - timer.init(); + if (priorityTime > 0) { + long delay = 1000L; + + timer = new PriorityTimer(priorityTime, delay, new mage.interfaces.Action() { + @Override + public void execute() throws MageException { + // do nothing + } + }); + final PriorityTimer pt = timer; + timer.setTaskOnTick(new mage.interfaces.Action() { + @Override + public void execute() throws MageException { + int priorityTimeValue = pt.getCount(); + String text = getPriorityTimeLeftString(priorityTimeValue); + PlayerPanelExt.this.avatar.setTopText(text); + PlayerPanelExt.this.avatar.repaint(); + } + }); + timer.init(); + } } public void update(PlayerView player) { @@ -206,11 +208,19 @@ public class PlayerPanelExt extends javax.swing.JPanel { } } this.avatar.setText(player.getName()); - if (player.getPriorityTimeLeft() != Integer.MAX_VALUE) { + if (this.timer != null) { + if (player.getPriorityTimeLeft() != Integer.MAX_VALUE) { String priorityTimeValue = getPriorityTimeLeftString(player); this.timer.setCount(player.getPriorityTimeLeft()); this.avatar.setTopText(priorityTimeValue); + } + if (player.hasPriority()) { + this.timer.resume(); + } else { + this.timer.pause(); + } } + this.btnPlayer.setText(player.getName()); if (player.isActive()) { this.avatar.setBorder(greenBorder); @@ -223,11 +233,6 @@ public class PlayerPanelExt extends javax.swing.JPanel { this.btnPlayer.setBorder(emptyBorder); } - if (player.hasPriority()) { - this.timer.resume(); - } else { - this.timer.pause(); - } synchronized (this) { if (player.getTopCard() != null) { diff --git a/Mage.Common/src/mage/view/GameView.java b/Mage.Common/src/mage/view/GameView.java index 3913b9f9548..db5535cf492 100644 --- a/Mage.Common/src/mage/view/GameView.java +++ b/Mage.Common/src/mage/view/GameView.java @@ -59,6 +59,7 @@ import mage.players.Player; public class GameView implements Serializable { private static final long serialVersionUID = 1L; + private int priorityTime; private List players = new ArrayList(); private SimpleCardsView hand; private Map opponentHands; @@ -75,7 +76,9 @@ public class GameView implements Serializable { private int turn; private boolean special = false; + public GameView(GameState state, Game game) { + priorityTime = game.getPriorityTime(); for (Player player: state.getPlayers().values()) { players.add(new PlayerView(player, state, game)); } @@ -255,4 +258,9 @@ public class GameView implements Serializable { public boolean getSpecial() { return special; } + + public int getPriorityTime() { + return priorityTime; + } + } diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index fe29d7fb06a..925539e12aa 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -137,7 +137,7 @@ public class GameController implements GameCallback { throw new IllegalStateException("INIT_TIMER: playerId can't be null"); } long delay = 250L; // run each 250 ms - timer = new PriorityTimer(Constants.PRIORITY_TIME_SEC, delay, new Action() { + timer = new PriorityTimer(game.getPriorityTime(), delay, new Action() { @Override public void execute() throws MageException { game.concede(initPlayerId); @@ -433,10 +433,12 @@ public class GameController implements GameCallback { } private synchronized void updateGame() { - for (Player player: game.getState().getPlayers().values()) { - PriorityTimer timer = timers.get(player.getId()); - if (timer != null) { - player.setPriorityTimeLeft(timer.getCount()); + if (!timers.isEmpty()) { + for (Player player: game.getState().getPlayers().values()) { + PriorityTimer timer = timers.get(player.getId()); + if (timer != null) { + player.setPriorityTimeLeft(timer.getCount()); + } } } for (final GameSession gameSession: gameSessions.values()) { diff --git a/Mage/src/mage/constants/MatchTimeLimit.java b/Mage/src/mage/constants/MatchTimeLimit.java new file mode 100644 index 00000000000..6e48356edb1 --- /dev/null +++ b/Mage/src/mage/constants/MatchTimeLimit.java @@ -0,0 +1,37 @@ +package mage.constants; + +/** + * + * @author LevelX2 + */ +public enum MatchTimeLimit { + NONE(0,"None"), + MIN__20(1200, "20 Minutes"), + MIN__30(1800, "30 Minutes"), + MIN__40(2400, "40 Minutes"), + MIN__50(3000, "50 Minutes"), + MIN__60(3600, "60 Minutes"), + MIN__90(5400, "90 Minutes"), + MIN_120(7200, "120 Minutes"); + + private int matchSeconds; + private String name; + + MatchTimeLimit(int matchSeconds, String name) { + this.matchSeconds = matchSeconds; + this.name = name; + } + + public int getTimeLimit() { + return matchSeconds; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index df3a256a243..5eedb6188c6 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -230,4 +230,6 @@ public interface Game extends MageItem, Serializable { void initTimer(UUID playerId); void resumeTimer(UUID playerId); void pauseTimer(UUID playerId); + int getPriorityTime(); + void setPriorityTime(int priorityTime); } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 1212595fe44..2517430a297 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -155,6 +155,8 @@ public abstract class GameImpl> implements Game, Serializa // used to indicate that currently applied replacement effects have to check for scope relevance (614.12 13/01/18) private boolean scopeRelevant = false; + private int priorityTime; + @Override public abstract T copy(); @@ -198,6 +200,7 @@ public abstract class GameImpl> implements Game, Serializa this.stateCheckRequired = game.stateCheckRequired; this.scorePlayer = game.scorePlayer; this.scopeRelevant = game.scopeRelevant; + this.priorityTime = game.priorityTime; } @Override @@ -589,7 +592,9 @@ public abstract class GameImpl> implements Game, Serializa protected void init(UUID choosingPlayerId, GameOptions gameOptions) { for (Player player: state.getPlayers().values()) { player.beginTurn(this); - initTimer(player.getId()); + if (priorityTime > 0) { + initTimer(player.getId()); + } } if (startMessage == null || startMessage.isEmpty()) { startMessage = "Game has started"; @@ -1949,17 +1954,32 @@ public abstract class GameImpl> implements Game, Serializa @Override public void initTimer(UUID playerId) { - tableEventSource.fireTableEvent(EventType.INIT_TIMER, playerId, null, this); + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.INIT_TIMER, playerId, null, this); + } } @Override public void resumeTimer(UUID playerId) { - tableEventSource.fireTableEvent(EventType.RESUME_TIMER, playerId, null, this); + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.RESUME_TIMER, playerId, null, this); + } } @Override public void pauseTimer(UUID playerId) { - tableEventSource.fireTableEvent(EventType.PAUSE_TIMER, playerId, null, this); + if (priorityTime > 0) { + tableEventSource.fireTableEvent(EventType.PAUSE_TIMER, playerId, null, this); + } } + @Override + public int getPriorityTime() { + return priorityTime; + } + + @Override + public void setPriorityTime(int priorityTime) { + this.priorityTime = priorityTime; + } } diff --git a/Mage/src/mage/game/match/MatchImpl.java b/Mage/src/mage/game/match/MatchImpl.java index 4d11d3e3499..5fcb9b018c2 100644 --- a/Mage/src/mage/game/match/MatchImpl.java +++ b/Mage/src/mage/game/match/MatchImpl.java @@ -162,6 +162,7 @@ public abstract class MatchImpl implements Match { game.loadCards(matchPlayer.getDeck().getSideboard(), matchPlayer.getPlayer().getId()); game.addPlayer(matchPlayer.getPlayer(), matchPlayer.getDeck()); } + game.setPriorityTime(options.getPriorityTime()); } protected void shufflePlayers() { diff --git a/Mage/src/mage/game/match/MatchOptions.java b/Mage/src/mage/game/match/MatchOptions.java index 72aee136ee6..ad6187f2240 100644 --- a/Mage/src/mage/game/match/MatchOptions.java +++ b/Mage/src/mage/game/match/MatchOptions.java @@ -31,6 +31,7 @@ package mage.game.match; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import mage.constants.MatchTimeLimit; import mage.constants.MultiplayerAttackOption; import mage.constants.RangeOfInfluence; @@ -49,6 +50,10 @@ public class MatchOptions implements Serializable { protected String deckType; protected boolean limited; protected List playerTypes = new ArrayList(); + /** + * Time each player has during the game to play using his\her priority. + */ + protected MatchTimeLimit matchTimeLimit; // 0 = no priorityTime handling public MatchOptions(String name, String gameType) { this.name = name; @@ -90,6 +95,7 @@ public class MatchOptions implements Serializable { public void setFreeMulligans(int freeMulligans) { this.freeMulligans = freeMulligans; } + public String getGameType() { return gameType; } @@ -117,4 +123,13 @@ public class MatchOptions implements Serializable { public void setLimited(boolean limited) { this.limited = limited; } + + public int getPriorityTime() { + return matchTimeLimit.getTimeLimit(); + } + + public void setMatchTimeLimit(MatchTimeLimit matchTimeLimit) { + this.matchTimeLimit = matchTimeLimit; + } + }