* GUI: added auto-fix for deck files on usage (if deck contains wrong card numbers then it will be fixed and saved automaticity);

This commit is contained in:
Oleg Agafonov 2020-08-08 21:27:20 +04:00
parent 9652d83aec
commit c5d7a3e9f9
31 changed files with 644 additions and 567 deletions

View file

@ -187,7 +187,7 @@ public class LegalityLabel extends JLabel {
} }
try { try {
StringBuilder errorMessages = new StringBuilder(); StringBuilder errorMessages = new StringBuilder();
Deck deck = Deck.load(DeckImporter.importDeckFromFile(deckFile.getAbsolutePath(), errorMessages), true, true); Deck deck = Deck.load(DeckImporter.importDeckFromFile(deckFile.getAbsolutePath(), errorMessages, false), true, true);
errorMessage = errorMessages.toString(); errorMessage = errorMessages.toString();
validateDeck(deck); validateDeck(deck);
} catch (Exception ex) { } catch (Exception ex) {

View file

@ -187,11 +187,9 @@ public class DeckEditorPanel extends javax.swing.JPanel {
case SIDEBOARDING: case SIDEBOARDING:
this.btnSubmit.setVisible(true); this.btnSubmit.setVisible(true);
this.btnSubmitTimer.setVisible(true); this.btnSubmitTimer.setVisible(true);
if (mode == DeckEditorMode.SIDEBOARDING) { /*(if (mode == LIMITED_BUILDING)*/
this.deckArea.setOrientation(/*limitedBuildingOrientation = */false); /*limitedBuildingOrientation = */
} else /*(if (mode == LIMITED_BUILDING)*/ { this.deckArea.setOrientation(/*limitedBuildingOrientation = */mode != DeckEditorMode.SIDEBOARDING);
this.deckArea.setOrientation(/*limitedBuildingOrientation = */true);
}
this.cardSelector.setVisible(false); this.cardSelector.setVisible(false);
this.btnExit.setVisible(false); this.btnExit.setVisible(false);
this.btnImport.setVisible(false); this.btnImport.setVisible(false);
@ -479,14 +477,14 @@ public class DeckEditorPanel extends javax.swing.JPanel {
@Override @Override
protected boolean handleFilesDrop(boolean move, List<File> files) { protected boolean handleFilesDrop(boolean move, List<File> files) {
loadDeck(files.get(0).getAbsolutePath()); loadDeck(files.get(0).getAbsolutePath(), true);
return true; return true;
} }
@Override @Override
protected boolean handlePlainTextDrop(boolean move, String text) { protected boolean handlePlainTextDrop(boolean move, String text) {
String tmpFile = DeckUtil.writeTextToTempFile(text); String tmpFile = DeckUtil.writeTextToTempFile(text);
loadDeck(tmpFile); loadDeck(tmpFile, false);
return true; return true;
} }
})); }));
@ -679,7 +677,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
StringBuilder errorMessages = new StringBuilder(); StringBuilder errorMessages = new StringBuilder();
Deck newDeck = null; Deck newDeck = null;
newDeck = Deck.load(importer.importDeck(file.getPath(), errorMessages)); newDeck = Deck.load(importer.importDeck(file.getPath(), errorMessages, true)); // file will be auto-fixed and saved on simple errors
processAndShowImportErrors(errorMessages); processAndShowImportErrors(errorMessages);
if (newDeck != null) { if (newDeck != null) {
@ -711,7 +709,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
dialog.showDialog(); dialog.showDialog();
if (!dialog.getTmpPath().isEmpty()) { if (!dialog.getTmpPath().isEmpty()) {
loadDeck(dialog.getTmpPath()); loadDeck(dialog.getTmpPath(), false);
} }
} }
@ -725,7 +723,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try { try {
deckToAppend = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages), true, true); deckToAppend = Deck.load(DeckImporter.importDeckFromFile(dialog.getTmpPath(), errorMessages, false), true, true);
processAndShowImportErrors(errorMessages); processAndShowImportErrors(errorMessages);
if (deckToAppend != null) { if (deckToAppend != null) {
@ -819,11 +817,11 @@ public class DeckEditorPanel extends javax.swing.JPanel {
} }
} }
private boolean loadDeck(String file) { private boolean loadDeck(String file, boolean saveAutoFixedFile) {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try { try {
StringBuilder errorMessages = new StringBuilder(); StringBuilder errorMessages = new StringBuilder();
Deck newDeck = Deck.load(DeckImporter.importDeckFromFile(file, errorMessages), true, true); Deck newDeck = Deck.load(DeckImporter.importDeckFromFile(file, errorMessages, saveAutoFixedFile), true, true);
processAndShowImportErrors(errorMessages); processAndShowImportErrors(errorMessages);
if (newDeck != null) { if (newDeck != null) {
@ -1343,7 +1341,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
Deck newDeck = null; Deck newDeck = null;
StringBuilder errorMessages = new StringBuilder(); StringBuilder errorMessages = new StringBuilder();
newDeck = Deck.load(DeckImporter.importDeckFromFile(file.getPath(), errorMessages), true, true); newDeck = Deck.load(DeckImporter.importDeckFromFile(file.getPath(), errorMessages, true), true, true);
processAndShowImportErrors(errorMessages); processAndShowImportErrors(errorMessages);
if (newDeck != null) { if (newDeck != null) {
@ -1394,7 +1392,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
try { try {
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR)); MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
String path = DeckGenerator.generateDeck(); String path = DeckGenerator.generateDeck();
deck = Deck.load(DeckImporter.importDeckFromFile(path), true, true); deck = Deck.load(DeckImporter.importDeckFromFile(path, false), true, true);
} catch (GameException ex) { } catch (GameException ex) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading generated deck", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), ex.getMessage(), "Error loading generated deck", JOptionPane.ERROR_MESSAGE);
} catch (DeckGeneratorException ex) { } catch (DeckGeneratorException ex) {

View file

@ -1,4 +1,3 @@
package mage.client.dialog; package mage.client.dialog;
import mage.cards.decks.importer.DeckImporter; import mage.cards.decks.importer.DeckImporter;
@ -12,7 +11,6 @@ import javax.swing.*;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class JoinTableDialog extends MageDialog { public class JoinTableDialog extends MageDialog {
@ -24,7 +22,9 @@ public class JoinTableDialog extends MageDialog {
private boolean joined = false; private boolean joined = false;
private boolean isTournament; private boolean isTournament;
/** Creates new form JoinTableDialog */ /**
* Creates new form JoinTableDialog
*/
public JoinTableDialog() { public JoinTableDialog() {
initComponents(); initComponents();
newPlayerPanel.showLevel(false); newPlayerPanel.showLevel(false);
@ -43,7 +43,8 @@ public class JoinTableDialog extends MageDialog {
} }
/** This method is called from within the constructor to /**
* This method is called from within the constructor to
* initialize the form. * initialize the form.
* WARNING: Do NOT modify this code. The content of this method is * WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor. * always regenerated by the Form Editor.
@ -73,37 +74,37 @@ public class JoinTableDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout); getContentPane().setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
.addComponent(btnOK) .addComponent(btnOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel)) .addComponent(btnCancel))
.addComponent(newPlayerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE) .addComponent(newPlayerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(lblPassword) .addComponent(lblPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap()) .addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(newPlayerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(newPlayerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblPassword) .addComponent(lblPassword)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel) .addComponent(btnCancel)
.addComponent(btnOK)) .addComponent(btnOK))
.addContainerGap()) .addContainerGap())
); );
pack(); pack();
@ -119,11 +120,11 @@ public class JoinTableDialog extends MageDialog {
try { try {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD_JOIN, txtPassword.getText()); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD_JOIN, txtPassword.getText());
if (isTournament) { if (isTournament) {
joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText()); joined = session.joinTournamentTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile(), true), this.txtPassword.getText());
} else { } else {
joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), this.txtPassword.getText()); joined = session.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), PlayerType.HUMAN, 1, DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile(), true), this.txtPassword.getText());
} }
} catch (Exception ex) { } catch (Exception ex) {
handleError(ex); handleError(ex);
} }

View file

@ -525,7 +525,7 @@ public class NewTableDialog extends MageDialog {
table.getTableId(), table.getTableId(),
this.player1Panel.getPlayerName(), this.player1Panel.getPlayerName(),
PlayerType.HUMAN, 1, PlayerType.HUMAN, 1,
DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()), DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile(), true),
this.txtPassword.getText())) { this.txtPassword.getText())) {
for (TablePlayerPanel player : players) { for (TablePlayerPanel player : players) {
if (player.getPlayerType() != PlayerType.HUMAN) { if (player.getPlayerType() != PlayerType.HUMAN) {

View file

@ -687,11 +687,11 @@ public class NewTournamentDialog extends MageDialog {
table.getTableId(), table.getTableId(),
this.player1Panel.getPlayerName(), this.player1Panel.getPlayerName(),
PlayerType.HUMAN, 1, PlayerType.HUMAN, 1,
DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()), DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile(), true),
tOptions.getPassword())) { tOptions.getPassword())) {
for (TournamentPlayerPanel player : players) { for (TournamentPlayerPanel player : players) {
if (player.getPlayerType().getSelectedItem() != PlayerType.HUMAN) { if (player.getPlayerType().getSelectedItem() != PlayerType.HUMAN) {
if (!player.joinTournamentTable(roomId, table.getTableId(), DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()))) { if (!player.joinTournamentTable(roomId, table.getTableId(), DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile(), true))) {
// error message must be send by sever // error message must be send by sever
SessionHandler.removeTable(roomId, table.getTableId()); SessionHandler.removeTable(roomId, table.getTableId());
table = null; table = null;
@ -743,11 +743,7 @@ public class NewTournamentDialog extends MageDialog {
private void spnNumSeatsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumSeatsStateChanged private void spnNumSeatsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumSeatsStateChanged
int numSeats = (Integer) this.spnNumSeats.getValue(); int numSeats = (Integer) this.spnNumSeats.getValue();
if (numSeats > 2) { this.spnNumPlayers.setEnabled(numSeats <= 2);
this.spnNumPlayers.setEnabled(false);
} else {
this.spnNumPlayers.setEnabled(true);
}
updateNumSeats(); updateNumSeats();
}//GEN-LAST:event_spnNumSeatsStateChanged }//GEN-LAST:event_spnNumSeatsStateChanged
@ -1209,7 +1205,7 @@ public class NewTournamentDialog extends MageDialog {
if (!(cubeFromDeckFilename.isEmpty())) { if (!(cubeFromDeckFilename.isEmpty())) {
Deck cubeFromDeck = new Deck(); Deck cubeFromDeck = new Deck();
try { try {
cubeFromDeck = Deck.load(DeckImporter.importDeckFromFile(cubeFromDeckFilename), true, true); cubeFromDeck = Deck.load(DeckImporter.importDeckFromFile(cubeFromDeckFilename, true), true, true);
} catch (GameException e1) { } catch (GameException e1) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE);
} }

View file

@ -498,11 +498,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
this.battlefieldPanel.init(gameId, bigCard); this.battlefieldPanel.init(gameId, bigCard);
this.gameId = gameId; this.gameId = gameId;
this.playerId = player.getPlayerId(); this.playerId = player.getPlayerId();
if (SessionHandler.isTestMode()) { this.btnCheat.setVisible(SessionHandler.isTestMode());
this.btnCheat.setVisible(true);
} else {
this.btnCheat.setVisible(false);
}
} }
public final void update(GameView game, PlayerView player, Set<UUID> possibleTargets) { public final void update(GameView game, PlayerView player, Set<UUID> possibleTargets) {
@ -561,7 +557,7 @@ public class PlayAreaPanel extends javax.swing.JPanel {
} }
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) { private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {
SessionHandler.cheat(gameId, playerId, DeckImporter.importDeckFromFile("cheat.dck")); SessionHandler.cheat(gameId, playerId, DeckImporter.importDeckFromFile("cheat.dck", false));
} }
public boolean isSmallMode() { public boolean isSmallMode() {

View file

@ -1,13 +1,5 @@
package mage.client.game; package mage.client.game;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import mage.cards.decks.importer.DckDeckImporter; import mage.cards.decks.importer.DckDeckImporter;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.SessionHandler; import mage.client.SessionHandler;
@ -24,7 +16,6 @@ import mage.client.util.gui.countryBox.CountryUtil;
import mage.components.ImagePanel; import mage.components.ImagePanel;
import mage.components.ImagePanelStyle; import mage.components.ImagePanelStyle;
import mage.constants.CardType; import mage.constants.CardType;
import static mage.constants.Constants.*;
import mage.constants.ManaType; import mage.constants.ManaType;
import mage.counters.Counter; import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
@ -33,6 +24,17 @@ import mage.utils.timer.PriorityTimer;
import mage.view.*; import mage.view.*;
import org.mage.card.arcane.ManaSymbols; import org.mage.card.arcane.ManaSymbols;
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import static mage.constants.Constants.*;
/** /**
* Enhanced player pane. * Enhanced player pane.
* *
@ -935,7 +937,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) { private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {
DckDeckImporter deckImporter = new DckDeckImporter(); DckDeckImporter deckImporter = new DckDeckImporter();
SessionHandler.cheat(gameId, playerId, deckImporter.importDeck("cheat.dck")); SessionHandler.cheat(gameId, playerId, deckImporter.importDeck("cheat.dck", false));
} }
public PlayerView getPlayer() { public PlayerView getPlayer() {

View file

@ -53,7 +53,7 @@ public class TablePlayerPanel extends javax.swing.JPanel {
public boolean joinTable(UUID roomId, UUID tableId) throws IOException, ClassNotFoundException { public boolean joinTable(UUID roomId, UUID tableId) throws IOException, ClassNotFoundException {
if (this.cbPlayerType.getSelectedItem() != PlayerType.HUMAN) { if (this.cbPlayerType.getSelectedItem() != PlayerType.HUMAN) {
return SessionHandler.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), (PlayerType) this.cbPlayerType.getSelectedItem(), this.newPlayerPanel.getLevel(), DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile()), ""); return SessionHandler.joinTable(roomId, tableId, this.newPlayerPanel.getPlayerName(), (PlayerType) this.cbPlayerType.getSelectedItem(), this.newPlayerPanel.getLevel(), DeckImporter.importDeckFromFile(this.newPlayerPanel.getDeckFile(), true), "");
} }
return true; return true;
} }
@ -127,8 +127,7 @@ public class TablePlayerPanel extends javax.swing.JPanel {
if (getPlayerType() != PlayerType.HUMAN) { if (getPlayerType() != PlayerType.HUMAN) {
this.newPlayerPanel.setVisible(true); this.newPlayerPanel.setVisible(true);
this.newPlayerPanel.setPlayerName(ClientDefaultSettings.computerName + " " + this.lblPlayerNum.getText().charAt(this.lblPlayerNum.getText().length() - 1)); this.newPlayerPanel.setPlayerName(ClientDefaultSettings.computerName + " " + this.lblPlayerNum.getText().charAt(this.lblPlayerNum.getText().length() - 1));
} } else {
else {
this.newPlayerPanel.setVisible(false); this.newPlayerPanel.setVisible(false);
} }
this.revalidate(); this.revalidate();

View file

@ -95,7 +95,7 @@ public class TablesPanel extends javax.swing.JPanel {
final JToggleButton[] filterButtons; final JToggleButton[] filterButtons;
// time formater // time formater
private PrettyTime timeFormater = new PrettyTime(Locale.ENGLISH); private final PrettyTime timeFormater = new PrettyTime(Locale.ENGLISH);
// time ago renderer // time ago renderer
TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() { TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() {
@ -127,7 +127,7 @@ public class TablesPanel extends javax.swing.JPanel {
// datetime render // datetime render
TableCellRenderer datetimeCellRenderer = new DefaultTableCellRenderer() { TableCellRenderer datetimeCellRenderer = new DefaultTableCellRenderer() {
DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss"); final DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss");
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@ -147,8 +147,8 @@ public class TablesPanel extends javax.swing.JPanel {
TableCellRenderer skillCellRenderer = new DefaultTableCellRenderer() { TableCellRenderer skillCellRenderer = new DefaultTableCellRenderer() {
// base panel to render // base panel to render
private JPanel renderPanel = new JPanel(); private final JPanel renderPanel = new JPanel();
private ImageIcon skillIcon = new ImageIcon(this.getClass().getResource("/info/yellow_star_16.png")); private final ImageIcon skillIcon = new ImageIcon(this.getClass().getResource("/info/yellow_star_16.png"));
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@ -181,7 +181,7 @@ public class TablesPanel extends javax.swing.JPanel {
// seats render // seats render
TableCellRenderer seatsCellRenderer = new DefaultTableCellRenderer() { TableCellRenderer seatsCellRenderer = new DefaultTableCellRenderer() {
JLabel greenLabel = new JLabel(); final JLabel greenLabel = new JLabel();
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
@ -1469,48 +1469,48 @@ public class TablesPanel extends javax.swing.JPanel {
javax.swing.GroupLayout jPanelTopLayout = new javax.swing.GroupLayout(jPanelTop); javax.swing.GroupLayout jPanelTopLayout = new javax.swing.GroupLayout(jPanelTop);
jPanelTop.setLayout(jPanelTopLayout); jPanelTop.setLayout(jPanelTopLayout);
jPanelTopLayout.setHorizontalGroup( jPanelTopLayout.setHorizontalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup() .addGroup(jPanelTopLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(btnNewTable) .addComponent(btnNewTable)
.addGap(6, 6, 6) .addGap(6, 6, 6)
.addComponent(btnNewTournament) .addComponent(btnNewTournament)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup() .addGroup(jPanelTopLayout.createSequentialGroup()
.addComponent(btnQuickStartDuel) .addComponent(btnQuickStartDuel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnQuickStartMCTS)) .addComponent(btnQuickStartMCTS))
.addComponent(btnQuickStartCommander)) .addComponent(btnQuickStartCommander))
.addContainerGap(540, Short.MAX_VALUE)) .addContainerGap(540, Short.MAX_VALUE))
); );
jPanelTopLayout.setVerticalGroup( jPanelTopLayout.setVerticalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup() .addGroup(jPanelTopLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnNewTable)
.addComponent(btnNewTournament))
.addGroup(jPanelTopLayout.createSequentialGroup()
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnQuickStartDuel) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnQuickStartMCTS)) .addComponent(btnNewTable)
.addGap(0, 0, Short.MAX_VALUE))) .addComponent(btnNewTournament))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanelTopLayout.createSequentialGroup()
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelTopLayout.createSequentialGroup() .addGroup(jPanelTopLayout.createSequentialGroup()
.addComponent(btnQuickStartCommander) .addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE))))) .addComponent(btnQuickStartDuel)
.addContainerGap()) .addComponent(btnQuickStartMCTS))
.addGap(0, 0, Short.MAX_VALUE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addComponent(btnQuickStartCommander)
.addGap(0, 0, Short.MAX_VALUE)))))
.addContainerGap())
); );
gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints = new java.awt.GridBagConstraints();
@ -1547,12 +1547,12 @@ public class TablesPanel extends javax.swing.JPanel {
javax.swing.GroupLayout jPanelTablesLayout = new javax.swing.GroupLayout(jPanelTables); javax.swing.GroupLayout jPanelTablesLayout = new javax.swing.GroupLayout(jPanelTables);
jPanelTables.setLayout(jPanelTablesLayout); jPanelTables.setLayout(jPanelTablesLayout);
jPanelTablesLayout.setHorizontalGroup( jPanelTablesLayout.setHorizontalGroup(
jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE) .addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE)
); );
jPanelTablesLayout.setVerticalGroup( jPanelTablesLayout.setVerticalGroup(
jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE) .addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE)
); );
jSplitPane1.setLeftComponent(jPanelTables); jSplitPane1.setLeftComponent(jPanelTables);
@ -1627,7 +1627,7 @@ public class TablesPanel extends javax.swing.JPanel {
+ "5 Mountain" + System.lineSeparator() + "5 Mountain" + System.lineSeparator()
+ "5 Plains"); + "5 Plains");
} }
DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile); DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile, false);
PlayerType aiType = useMonteCarloAI ? PlayerType.COMPUTER_MONTE_CARLO : PlayerType.COMPUTER_MAD; PlayerType aiType = useMonteCarloAI ? PlayerType.COMPUTER_MONTE_CARLO : PlayerType.COMPUTER_MAD;
MatchOptions options = new MatchOptions(gameName, gameType, false, 2); MatchOptions options = new MatchOptions(gameName, gameType, false, 2);

View file

@ -35,7 +35,7 @@ public class TxtDeckImporterTest {
Assert.assertEquals("Deck does not contain 3 cards, found " + deck.getCards().size(), 3, deck.getCards().size()); Assert.assertEquals("Deck does not contain 3 cards, found " + deck.getCards().size(), 3, deck.getCards().size());
Assert.assertEquals("Sideboard does not contain 2 cards, found " + deck.getSideboard().size(), 2, deck.getSideboard().size()); Assert.assertEquals("Sideboard does not contain 2 cards, found " + deck.getSideboard().size(), 2, deck.getSideboard().size());
DeckCardLists imported = importer.importDeck("JustLands.txt"); DeckCardLists imported = importer.importDeck("JustLands.txt", false);
Assert.assertEquals("Imported deck does not contain 3 cards, found " + imported.getCards().size(), 3, imported.getCards().size()); Assert.assertEquals("Imported deck does not contain 3 cards, found " + imported.getCards().size(), 3, imported.getCards().size());
Assert.assertEquals("Imported sideboard does not contain 2 cards, found " + imported.getSideboard().size(), 2, imported.getSideboard().size()); Assert.assertEquals("Imported sideboard does not contain 2 cards, found " + imported.getSideboard().size(), 2, imported.getSideboard().size());

View file

@ -248,7 +248,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
if (loadedDeckCardLists.containsKey(deckName)) { if (loadedDeckCardLists.containsKey(deckName)) {
list = loadedDeckCardLists.get(deckName); list = loadedDeckCardLists.get(deckName);
} else { } else {
list = DeckImporter.importDeckFromFile(deckName); list = DeckImporter.importDeckFromFile(deckName, true);
loadedDeckCardLists.put(deckName, list); loadedDeckCardLists.put(deckName, list);
} }
Deck deck = Deck.load(list, false, false); Deck deck = Deck.load(list, false, false);

View file

@ -53,6 +53,7 @@ public class VerifyCardDataTest {
private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class); private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class);
private static final String FULL_ABILITIES_CHECK_SET_CODE = "THB"; // check all abilities and output cards with wrong abilities texts; private static final String FULL_ABILITIES_CHECK_SET_CODE = "THB"; // check all abilities and output cards with wrong abilities texts;
private static final boolean AUTO_FIX_SAMPLE_DECKS = false; // debug only: fix sample decks if it contains errors like wrong card numbers
// right now this is very noisy, and not useful enough to make any assertions on // right now this is very noisy, and not useful enough to make any assertions on
private static final boolean CHECK_SOURCE_TOKENS = false; private static final boolean CHECK_SOURCE_TOKENS = false;
@ -471,7 +472,7 @@ public class VerifyCardDataTest {
} }
@Test @Test
@Ignore // TODO: enable and fix broken decks after promo sets merge https://github.com/magefree/mage/pull/6190 //@Ignore // TODO: enable and fix broken decks after promo sets merge https://github.com/magefree/mage/pull/6190
public void test_checkSampleDecks() { public void test_checkSampleDecks() {
Collection<String> errorsList = new ArrayList<>(); Collection<String> errorsList = new ArrayList<>();
@ -497,7 +498,7 @@ public class VerifyCardDataTest {
for (Path deckFile : filesList) { for (Path deckFile : filesList) {
String deckName = deckFile.toString().replace(rootPath, ""); String deckName = deckFile.toString().replace(rootPath, "");
StringBuilder deckErrors = new StringBuilder(); StringBuilder deckErrors = new StringBuilder();
DeckCardLists deckCards = DeckImporter.importDeckFromFile(deckFile.toString(), deckErrors); DeckCardLists deckCards = DeckImporter.importDeckFromFile(deckFile.toString(), deckErrors, AUTO_FIX_SAMPLE_DECKS);
if (!deckErrors.toString().isEmpty()) { if (!deckErrors.toString().isEmpty()) {
errorsList.add("Error: sample deck contains errors " + deckName); errorsList.add("Error: sample deck contains errors " + deckName);

View file

@ -1,5 +1,11 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -7,68 +13,67 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
public class CodDeckImporter extends XmlDeckImporter { public class CodDeckImporter extends XmlDeckImporter {
@Override /**
public DeckCardLists importDeck(String filename, StringBuilder errorMessages) { * @param filename
try { * @param errorMessages
Document doc = getXmlDocument(filename); * @param saveAutoFixedFile do not supported for current format
DeckCardLists decklist = new DeckCardLists(); * @return
*/
@Override
public DeckCardLists importDeck(String filename, StringBuilder errorMessages, boolean saveAutoFixedFile) {
try {
Document doc = getXmlDocument(filename);
DeckCardLists decklist = new DeckCardLists();
List<Node> mainCards = getNodes(doc, "/cockatrice_deck/zone[@name='main']/card"); List<Node> mainCards = getNodes(doc, "/cockatrice_deck/zone[@name='main']/card");
decklist.setCards(mainCards.stream() decklist.setCards(mainCards.stream()
.flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) .flatMap(toDeckCardInfo(getCardLookup(), errorMessages))
.collect(Collectors.toList())); .collect(Collectors.toList()));
List<Node> sideboardCards = getNodes(doc, "/cockatrice_deck/zone[@name='side']/card"); List<Node> sideboardCards = getNodes(doc, "/cockatrice_deck/zone[@name='side']/card");
decklist.setSideboard(sideboardCards.stream() decklist.setSideboard(sideboardCards.stream()
.flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) .flatMap(toDeckCardInfo(getCardLookup(), errorMessages))
.collect(Collectors.toList())); .collect(Collectors.toList()));
getNodes(doc, "/cockatrice_deck/deckname") getNodes(doc, "/cockatrice_deck/deckname")
.forEach(n -> decklist.setName(n.getTextContent().trim())); .forEach(n -> decklist.setName(n.getTextContent().trim()));
return decklist; return decklist;
} catch (Exception e) { } catch (Exception e) {
logger.error("Error loading deck", e); logger.error("Error loading deck", e);
errorMessages.append("There was an error loading the deck."); errorMessages.append("There was an error loading the deck.");
return new DeckCardLists(); return new DeckCardLists();
}
} }
}
private static int getQuantityFromNode(Node node) { private static int getQuantityFromNode(Node node) {
Node numberNode = node.getAttributes().getNamedItem("number"); Node numberNode = node.getAttributes().getNamedItem("number");
if (numberNode == null) { if (numberNode == null) {
return 1; return 1;
}
try {
return Math.min(100, Math.max(1, Integer.parseInt(numberNode.getNodeValue())));
} catch (NumberFormatException e) {
return 1;
}
} }
try {
return Math.min(100, Math.max(1, Integer.parseInt(numberNode.getNodeValue())));
} catch (NumberFormatException e) {
return 1;
}
}
private static Function<Node, Stream<DeckCardInfo>> toDeckCardInfo(CardLookup lookup, StringBuilder errors) { private static Function<Node, Stream<DeckCardInfo>> toDeckCardInfo(CardLookup lookup, StringBuilder errors) {
return node -> { return node -> {
String name = node.getAttributes().getNamedItem("name").getNodeValue().trim(); String name = node.getAttributes().getNamedItem("name").getNodeValue().trim();
Optional<CardInfo> cardInfo = lookup.lookupCardInfo(name); Optional<CardInfo> cardInfo = lookup.lookupCardInfo(name);
if (cardInfo.isPresent()) { if (cardInfo.isPresent()) {
CardInfo info = cardInfo.get(); CardInfo info = cardInfo.get();
return Collections.nCopies( return Collections.nCopies(
getQuantityFromNode(node), getQuantityFromNode(node),
new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream(); new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream();
} else { } else {
errors.append("Could not find card: '").append(name).append("'\n"); errors.append("Could not find card: '").append(name).append("'\n");
return Stream.empty(); return Stream.empty();
} }
}; };
} }
} }

View file

@ -7,11 +7,15 @@ import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository; import mage.cards.repository.CardRepository;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
* Original xmage's deck format (uses by deck editor)
*
* @author North * @author North
*/ */
public class DckDeckImporter extends PlainTextDeckImporter { public class DckDeckImporter extends PlainTextDeckImporter {
@ -24,13 +28,23 @@ public class DckDeckImporter extends PlainTextDeckImporter {
private static final Pattern layoutStackEntryPattern = Pattern.compile("\\[(\\w+[^:]*\\w*):(\\w+\\w*)]"); // test cases: [JR:64ab],[JR:64],[MPSAK1321:43],[MPSAKH:9],[MPS123-AKH:32],[MPS-13AKH:30],[MPS-AKH:49],[MPS-AKH:11], [PUMA:U16] private static final Pattern layoutStackEntryPattern = Pattern.compile("\\[(\\w+[^:]*\\w*):(\\w+\\w*)]"); // test cases: [JR:64ab],[JR:64],[MPSAK1321:43],[MPSAKH:9],[MPS123-AKH:32],[MPS-13AKH:30],[MPS-AKH:49],[MPS-AKH:11], [PUMA:U16]
private final Map<String, String> possibleFixes = new HashMap<>(); // possible fixes for card codes and numbers [code:123] -> [code:456]
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.isEmpty() || line.startsWith("#")) { if (line.isEmpty() || line.startsWith("#")) {
return; return;
} }
// AUTO-FIX apply (if card number was fixed before then it can be replaced in layout or other lines too)
for (Map.Entry<String, String> fix : this.possibleFixes.entrySet()) {
if (line.contains(fix.getKey())) {
line = line.replace(fix.getKey(), fix.getValue());
}
}
fixedInfo.setFixedLine(line);
Matcher m = pattern.matcher(line); Matcher m = pattern.matcher(line);
if (m.matches()) { if (m.matches()) {
boolean sideboard = false; boolean sideboard = false;
@ -46,12 +60,20 @@ public class DckDeckImporter extends PlainTextDeckImporter {
setCode = setCode == null ? "" : setCode.trim(); setCode = setCode == null ? "" : setCode.trim();
cardName = cardName == null ? "" : cardName.trim(); cardName = cardName == null ? "" : cardName.trim();
// search priority: set/code -> name // text for auto-fix
String originalText = "";
if (!setCode.isEmpty() && !cardNum.isEmpty()) {
// [ISD:144]
originalText = "[" + setCode + ":" + cardNum + "]";
}
String fixedText = originalText;
// search priority: set/number -> name
// with bulletproof on card number or name changes // with bulletproof on card number or name changes
DeckCardInfo deckCardInfo = null; DeckCardInfo deckCardInfo = null;
// search by number // search by set/number
CardInfo foundedCard = CardRepository.instance.findCard(setCode, cardNum); CardInfo foundedCard = CardRepository.instance.findCard(setCode, cardNum);
boolean wasOutdated = false; boolean wasOutdated = false;
if ((foundedCard != null) && !foundedCard.getName().equals(cardName)) { if ((foundedCard != null) && !foundedCard.getName().equals(cardName)) {
@ -63,7 +85,7 @@ public class DckDeckImporter extends PlainTextDeckImporter {
// search by name // search by name
if (foundedCard == null) { if (foundedCard == null) {
if (!wasOutdated) { if (!wasOutdated) {
sbMessage.append("Line ").append(lineCount).append(": ").append("can't find card by number, will try ro replace: ").append(line).append('\n'); sbMessage.append("Line ").append(lineCount).append(": ").append("can't find card by number, will try to replace: ").append(line).append('\n');
} }
if (!cardName.equals("")) { if (!cardName.equals("")) {
@ -74,6 +96,12 @@ public class DckDeckImporter extends PlainTextDeckImporter {
sbMessage.append("Line ").append(lineCount).append(": ") sbMessage.append("Line ").append(lineCount).append(": ")
.append("replaced to [").append(foundedCard.getSetCode()).append(":").append(foundedCard.getCardNumberAsInt()).append("] ") .append("replaced to [").append(foundedCard.getSetCode()).append(":").append(foundedCard.getCardNumberAsInt()).append("] ")
.append(foundedCard.getName()).append('\n'); .append(foundedCard.getName()).append('\n');
// AUTO-FIX POSSIBLE (apply and save it for another lines like layout)
// [ISD:144]
fixedText = "[" + foundedCard.getSetCode() + ":" + foundedCard.getCardNumber() + "]";
fixedInfo.setFixedLine(fixedInfo.getOriginalLine().replace(originalText, fixedText));
this.possibleFixes.put(originalText, fixedText);
} else { } else {
sbMessage.append("Line ").append(lineCount).append(": ").append("ERROR, can't find card [").append(cardName).append("]").append('\n'); sbMessage.append("Line ").append(lineCount).append(": ").append("ERROR, can't find card [").append(cardName).append("]").append('\n');
} }

View file

@ -1,21 +1,19 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import java.util.Optional;
import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import java.util.Optional;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class DecDeckImporter extends PlainTextDeckImporter { public class DecDeckImporter extends PlainTextDeckImporter {
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.isEmpty() || line.startsWith("//")) { if (line.isEmpty() || line.startsWith("//")) {
return; return;
} }

View file

@ -1,95 +1,122 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.File; import java.io.File;
import java.util.Locale; import java.util.Locale;
import java.util.Optional;
import java.util.Scanner; import java.util.Scanner;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
public abstract class DeckImporter { public abstract class DeckImporter {
protected static final Logger logger = Logger.getLogger(DeckImporter.class); public class FixedInfo {
private final String originalLine;
private String fixedLine;
private Boolean canFix = true; // set false if deck have critical error and can't be auto-fixed
private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "}; FixedInfo(String originalLine) {
this.originalLine = originalLine;
public static DeckImporter getDeckImporter(String file) { this.fixedLine = originalLine;
if (file == null) { }
return null;
} if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) { public String getOriginalLine() {
return new DecDeckImporter(); return originalLine;
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) { }
return new MWSDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) { public Boolean getCanFix() {
return new TxtDeckImporter(haveSideboardSection(file)); return canFix;
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("dck")) { }
return new DckDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("dek")) { public void setCanFix(Boolean canFix) {
return new DekDeckImporter(); this.canFix = canFix;
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("cod")) { }
return new CodDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("o8d")) { public String getFixedLine() {
return new O8dDeckImporter(); return fixedLine;
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("json")) { }
return new MtgjsonDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("draft")) { public void setFixedLine(String fixedLine) {
return new DraftLogImporter(); this.fixedLine = fixedLine;
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("mtga")) {
return new MtgaImporter();
} else {
return null;
}
}
public static DeckCardLists importDeckFromFile(String file) {
return importDeckFromFile(file, new StringBuilder());
}
public static DeckCardLists importDeckFromFile(String file, StringBuilder errorMessages) {
DeckImporter deckImporter = getDeckImporter(file);
if (deckImporter != null) {
return deckImporter.importDeck(file, errorMessages);
} else {
return new DeckCardLists();
}
}
public abstract DeckCardLists importDeck(String file, StringBuilder errorMessages);
public DeckCardLists importDeck(String file) {
return importDeck(file, new StringBuilder());
}
public CardLookup getCardLookup() {
return CardLookup.instance;
}
private static boolean haveSideboardSection(String file) {
// search for sideboard section:
// or //sideboard
// or SB: 1 card name -- special deckstats.net
File f = new File(file);
try (Scanner scanner = new Scanner(f)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim().toLowerCase(Locale.ENGLISH);
for (String mark : SIDEBOARD_MARKS) {
if (line.startsWith(mark)) {
return true;
}
} }
}
} catch (Exception e) {
// ignore error, deckimporter will process it
} }
// not found protected static final Logger logger = Logger.getLogger(DeckImporter.class);
return false;
}
private static final String[] SIDEBOARD_MARKS = new String[]{"//sideboard", "sb: "};
public static DeckImporter getDeckImporter(String file) {
if (file == null) {
return null;
}
if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) {
return new DecDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) {
return new MWSDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("txt")) {
return new TxtDeckImporter(haveSideboardSection(file));
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("dck")) {
return new DckDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("dek")) {
return new DekDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("cod")) {
return new CodDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("o8d")) {
return new O8dDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("json")) {
return new MtgjsonDeckImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("draft")) {
return new DraftLogImporter();
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("mtga")) {
return new MtgaImporter();
} else {
return null;
}
}
public static DeckCardLists importDeckFromFile(String file, boolean saveAutoFixedFile) {
return importDeckFromFile(file, new StringBuilder(), saveAutoFixedFile);
}
public static DeckCardLists importDeckFromFile(String file, StringBuilder errorMessages, boolean saveAutoFixedFile) {
DeckImporter deckImporter = getDeckImporter(file);
if (deckImporter != null) {
return deckImporter.importDeck(file, errorMessages, saveAutoFixedFile);
} else {
return new DeckCardLists();
}
}
public abstract DeckCardLists importDeck(String file, StringBuilder errorMessages, boolean saveAutoFixedFile);
public DeckCardLists importDeck(String file, boolean saveAutoFixedFile) {
return importDeck(file, new StringBuilder(), saveAutoFixedFile);
}
public CardLookup getCardLookup() {
return CardLookup.instance;
}
private static boolean haveSideboardSection(String file) {
// search for sideboard section:
// or //sideboard
// or SB: 1 card name -- special deckstats.net
File f = new File(file);
try (Scanner scanner = new Scanner(f)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim().toLowerCase(Locale.ENGLISH);
for (String mark : SIDEBOARD_MARKS) {
if (line.startsWith(mark)) {
return true;
}
}
}
} catch (Exception e) {
// ignore error, deckimporter will process it
}
// not found
return false;
}
} }

View file

@ -11,7 +11,7 @@ import mage.cards.repository.CardRepository;
public class DekDeckImporter extends PlainTextDeckImporter { public class DekDeckImporter extends PlainTextDeckImporter {
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.isEmpty() || line.startsWith("#") || !line.contains("<Cards CatID")) { if (line.isEmpty() || line.startsWith("#") || !line.contains("<Cards CatID")) {
return; return;
@ -27,24 +27,24 @@ public class DekDeckImporter extends PlainTextDeckImporter {
} else { } else {
for (int i = 0; i < cardCount; i++) { for (int i = 0; i < cardCount; i++) {
DeckCardInfo deckCardInfo = new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode()); DeckCardInfo deckCardInfo = new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode());
if(isSideboard) { if (isSideboard) {
deckList.getSideboard().add(deckCardInfo); deckList.getSideboard().add(deckCardInfo);
} else { } else {
deckList.getCards().add(deckCardInfo); deckList.getCards().add(deckCardInfo);
} }
} }
} }
}catch (NumberFormatException nfe) { } catch (NumberFormatException nfe) {
sbMessage.append("Invalid number: ").append(extractAttribute(line, "Quantity")).append(" at line ").append(lineCount).append('\n'); sbMessage.append("Invalid number: ").append(extractAttribute(line, "Quantity")).append(" at line ").append(lineCount).append('\n');
} }
} }
private String extractAttribute(String line, String name) { private String extractAttribute(String line, String name) {
String searchString = name+"=\""; String searchString = name + "=\"";
int startDelim = line.indexOf(searchString)+searchString.length(); int startDelim = line.indexOf(searchString) + searchString.length();
int endDelim = line.substring(startDelim).indexOf('\"'); int endDelim = line.substring(startDelim).indexOf('\"');
return line.substring(startDelim, startDelim+endDelim); return line.substring(startDelim, startDelim + endDelim);
} }
} }

View file

@ -11,13 +11,14 @@ import java.util.regex.Pattern;
public class DraftLogImporter extends PlainTextDeckImporter { public class DraftLogImporter extends PlainTextDeckImporter {
private static Pattern SET_PATTERN = Pattern.compile("------ (\\p{Alnum}+) ------$"); private static final Pattern SET_PATTERN = Pattern.compile("------ (\\p{Alnum}+) ------$");
private static Pattern PICK_PATTERN = Pattern.compile("--> (.+)$"); private static final Pattern PICK_PATTERN = Pattern.compile("--> (.+)$");
private String currentSet = null; private String currentSet = null;
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
Matcher setMatcher = SET_PATTERN.matcher(line); Matcher setMatcher = SET_PATTERN.matcher(line);
if (setMatcher.matches()) { if (setMatcher.matches()) {
currentSet = setMatcher.group(1); currentSet = setMatcher.group(1);

View file

@ -1,14 +1,12 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import java.io.File; import mage.cards.decks.DeckCardLists;
import java.io.FileReader;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser; import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
import mage.cards.decks.DeckCardLists; import java.io.File;
import java.io.FileReader;
/** /**
* @author github: timhae * @author github: timhae
@ -18,12 +16,12 @@ public abstract class JsonDeckImporter extends DeckImporter {
protected StringBuilder sbMessage = new StringBuilder(); protected StringBuilder sbMessage = new StringBuilder();
/** /**
* * @param file file to import
* @param file file to import * @param errorMessages you can setup output messages to showup to user
* @param errorMessages you can setup output messages to showup to user * @param saveAutoFixedFile do not supported for that format
* @return decks list * @return decks list
*/ */
public DeckCardLists importDeck(String file, StringBuilder errorMessages) { public DeckCardLists importDeck(String file, StringBuilder errorMessages, boolean saveAutoFixedFile) {
File f = new File(file); File f = new File(file);
DeckCardLists deckList = new DeckCardLists(); DeckCardLists deckList = new DeckCardLists();
if (!f.exists()) { if (!f.exists()) {
@ -62,8 +60,8 @@ public abstract class JsonDeckImporter extends DeckImporter {
} }
@Override @Override
public DeckCardLists importDeck(String file) { public DeckCardLists importDeck(String file, boolean saveAutoFixedFile) {
return importDeck(file, null); return importDeck(file, null, saveAutoFixedFile);
} }
protected abstract void readJson(JSONObject line, DeckCardLists decklist); protected abstract void readJson(JSONObject line, DeckCardLists decklist);

View file

@ -1,23 +1,21 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import java.util.List;
import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardCriteria; import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.util.RandomUtil; import mage.util.RandomUtil;
import java.util.List;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class MWSDeckImporter extends PlainTextDeckImporter { public class MWSDeckImporter extends PlainTextDeckImporter {
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.isEmpty() || line.startsWith("//")) { if (line.isEmpty() || line.startsWith("//")) {
return; return;
} }
@ -47,7 +45,7 @@ public class MWSDeckImporter extends PlainTextDeckImporter {
if (!cards.isEmpty()) { if (!cards.isEmpty()) {
cardInfo = cards.get(RandomUtil.nextInt(cards.size())); cardInfo = cards.get(RandomUtil.nextInt(cards.size()));
} }
} }
if (cardInfo == null) { if (cardInfo == null) {
cardInfo = getCardLookup().lookupCardInfo(lineName).orElse(null); cardInfo = getCardLookup().lookupCardInfo(lineName).orElse(null);
} }

View file

@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap;
import mage.cards.decks.CardNameUtil; import mage.cards.decks.CardNameUtil;
import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import java.util.Collections; import java.util.Collections;
@ -21,18 +20,19 @@ public class MtgaImporter extends PlainTextDeckImporter {
private static final Map<String, String> SET_REMAPPING = ImmutableMap.of("DAR", "DOM"); private static final Map<String, String> SET_REMAPPING = ImmutableMap.of("DAR", "DOM");
private static final Pattern MTGA_PATTERN = Pattern.compile( private static final Pattern MTGA_PATTERN = Pattern.compile(
"(\\p{Digit}+)" + "(\\p{Digit}+)" +
"\\p{javaWhitespace}+" + "\\p{javaWhitespace}+" +
"(" + CARD_NAME_PATTERN.pattern() + ")" + "(" + CARD_NAME_PATTERN.pattern() + ")" +
"\\p{javaWhitespace}+" + "\\p{javaWhitespace}+" +
"\\((\\p{Alnum}+)\\)" + "\\((\\p{Alnum}+)\\)" +
"\\p{javaWhitespace}+" + "\\p{javaWhitespace}+" +
"(\\p{Digit}+)"); "(\\p{Digit}+)");
private final CardLookup lookup = getCardLookup(); private final CardLookup lookup = getCardLookup();
private boolean sideboard = false; private boolean sideboard = false;
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.trim().equals("")) { if (line.trim().equals("")) {
sideboard = true; sideboard = true;
return; return;

View file

@ -1,5 +1,11 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -7,65 +13,64 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
public class O8dDeckImporter extends XmlDeckImporter { public class O8dDeckImporter extends XmlDeckImporter {
@Override /**
public DeckCardLists importDeck(String filename, StringBuilder errorMessages) { * @param filename
try { * @param errorMessages
Document doc = getXmlDocument(filename); * @param saveAutoFixedFile do not supported for current format
DeckCardLists decklist = new DeckCardLists(); * @return
*/
@Override
public DeckCardLists importDeck(String filename, StringBuilder errorMessages, boolean saveAutoFixedFile) {
try {
Document doc = getXmlDocument(filename);
DeckCardLists decklist = new DeckCardLists();
List<Node> mainCards = getNodes(doc, "/deck/section[@name='Main']/card"); List<Node> mainCards = getNodes(doc, "/deck/section[@name='Main']/card");
decklist.setCards(mainCards.stream() decklist.setCards(mainCards.stream()
.flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) .flatMap(toDeckCardInfo(getCardLookup(), errorMessages))
.collect(Collectors.toList())); .collect(Collectors.toList()));
List<Node> sideboardCards = getNodes(doc, "/deck/section[@name='Sideboard']/card"); List<Node> sideboardCards = getNodes(doc, "/deck/section[@name='Sideboard']/card");
decklist.setSideboard(sideboardCards.stream() decklist.setSideboard(sideboardCards.stream()
.flatMap(toDeckCardInfo(getCardLookup(), errorMessages)) .flatMap(toDeckCardInfo(getCardLookup(), errorMessages))
.collect(Collectors.toList())); .collect(Collectors.toList()));
return decklist; return decklist;
} catch (Exception e) { } catch (Exception e) {
logger.error("Error loading deck", e); logger.error("Error loading deck", e);
errorMessages.append("There was an error loading the deck."); errorMessages.append("There was an error loading the deck.");
return new DeckCardLists(); return new DeckCardLists();
}
} }
}
private static int getQuantityFromNode(Node node) { private static int getQuantityFromNode(Node node) {
Node numberNode = node.getAttributes().getNamedItem("qty"); Node numberNode = node.getAttributes().getNamedItem("qty");
if (numberNode == null) { if (numberNode == null) {
return 1; return 1;
}
try {
return Math.min(100, Math.max(1, Integer.parseInt(numberNode.getNodeValue())));
} catch (NumberFormatException e) {
return 1;
}
} }
try {
return Math.min(100, Math.max(1, Integer.parseInt(numberNode.getNodeValue())));
} catch (NumberFormatException e) {
return 1;
}
}
private static Function<Node, Stream<DeckCardInfo>> toDeckCardInfo(CardLookup lookup, StringBuilder errors) { private static Function<Node, Stream<DeckCardInfo>> toDeckCardInfo(CardLookup lookup, StringBuilder errors) {
return node -> { return node -> {
String name = node.getTextContent(); String name = node.getTextContent();
Optional<CardInfo> cardInfo = lookup.lookupCardInfo(name); Optional<CardInfo> cardInfo = lookup.lookupCardInfo(name);
if (cardInfo.isPresent()) { if (cardInfo.isPresent()) {
CardInfo info = cardInfo.get(); CardInfo info = cardInfo.get();
return Collections.nCopies( return Collections.nCopies(
getQuantityFromNode(node), getQuantityFromNode(node),
new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream(); new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream();
} else { } else {
errors.append("Could not find card: '").append(name).append("'\n"); errors.append("Could not find card: '").append(name).append("'\n");
return Stream.empty(); return Stream.empty();
} }
}; };
} }
} }

View file

@ -1,14 +1,15 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import java.io.File;
import java.util.Scanner;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/** /**
*
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public abstract class PlainTextDeckImporter extends DeckImporter { public abstract class PlainTextDeckImporter extends DeckImporter {
@ -18,13 +19,17 @@ public abstract class PlainTextDeckImporter extends DeckImporter {
/** /**
* Import deck from text file
* *
* @param file file to import * @param file file to import
* @param errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0) * @param errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0)
* @param saveAutoFixedFile save fixed deck file (if any fixes applied)
* @return decks list * @return decks list
*/ */
public DeckCardLists importDeck(String file, StringBuilder errorMessages) { public DeckCardLists importDeck(String file, StringBuilder errorMessages, boolean saveAutoFixedFile) {
File f = new File(file); File f = new File(file);
List<String> originalFile = new ArrayList<>();
List<String> fixedFile = new ArrayList<>();
DeckCardLists deckList = new DeckCardLists(); DeckCardLists deckList = new DeckCardLists();
if (!f.exists()) { if (!f.exists()) {
logger.warn("Deckfile " + file + " not found."); logger.warn("Deckfile " + file + " not found.");
@ -35,17 +40,29 @@ public abstract class PlainTextDeckImporter extends DeckImporter {
sbMessage.setLength(0); sbMessage.setLength(0);
try { try {
try (Scanner scanner = new Scanner(f)) { try (Scanner scanner = new Scanner(f)) {
Boolean canFix = true;
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim(); String line = scanner.nextLine().trim();
FixedInfo fixedInfo = new FixedInfo(line);
lineCount++; lineCount++;
readLine(line, deckList); readLine(line, deckList, fixedInfo);
originalFile.add(line);
fixedFile.add(fixedInfo.getFixedLine());
canFix = canFix && fixedInfo.getCanFix();
}
// auto-fix
if (saveAutoFixedFile && canFix && !originalFile.equals(fixedFile)) {
logger.warn("WARNING, deck file contains errors, try to apply auto-fix and save: " + f.getAbsolutePath());
saveFixedDeckFile(fixedFile, f);
} }
if (sbMessage.length() > 0) { if (sbMessage.length() > 0) {
if(errorMessages != null) { if (errorMessages != null) {
// normal output for user // normal output for user
errorMessages.append(sbMessage); errorMessages.append(sbMessage);
}else{ } else {
// fatal error // fatal error
logger.fatal(sbMessage); logger.fatal(sbMessage);
} }
@ -59,11 +76,30 @@ public abstract class PlainTextDeckImporter extends DeckImporter {
return deckList; return deckList;
} }
private void saveFixedDeckFile(List<String> fixedfile, File file) {
@Override try (FileOutputStream stream = new FileOutputStream(file)) {
public DeckCardLists importDeck(String file) { PrintWriter out = new PrintWriter(stream);
return importDeck(file, null); for (String line : fixedfile) {
out.println(line);
}
out.close();
} catch (Exception e) {
logger.error("Can't save fixed deck file: " + file.getAbsolutePath() + ", reason: " + e.getMessage());
}
} }
protected abstract void readLine(String line, DeckCardLists deckList);
@Override
public DeckCardLists importDeck(String file, boolean saveAutoFixedFile) {
return importDeck(file, null, saveAutoFixedFile);
}
/**
* Read one text line from file and convert it to card
*
* @param line original text line
* @param deckList deck list for new card
* @param fixedInfo fixed info that contains fixed line (if converter can auto-fix deck file, e.g. replace one card to another)
*/
protected abstract void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo);
} }

View file

@ -31,7 +31,7 @@ public class TxtDeckImporter extends PlainTextDeckImporter {
} }
@Override @Override
protected void readLine(String line, DeckCardLists deckList) { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
line = line.trim(); line = line.trim();

View file

@ -1,40 +1,39 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
public class CodDeckImportTest { public class CodDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup(false) private static final FakeCardLookup LOOKUP = new FakeCardLookup(false)
.addCard("Forest") .addCard("Forest")
.addCard("Razorverge Thicket") .addCard("Razorverge Thicket")
.addCard("Avacyn's Pilgrim") .addCard("Avacyn's Pilgrim")
.addCard("War Priest of Thune"); .addCard("War Priest of Thune");
@Test @Test
public void testImport() { public void testImport() {
CodDeckImporter importer = new CodDeckImporter() { CodDeckImporter importer = new CodDeckImporter() {
@Override @Override
public CardLookup getCardLookup() { public CardLookup getCardLookup() {
return LOOKUP; return LOOKUP;
} }
}; };
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.cod", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.cod", errors, false);
assertEquals("Deck Name", deck.getName()); assertEquals("Deck Name", deck.getName());
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Forest", 12) .addMain("Forest", 12)
.addMain("Razorverge Thicket", 100) .addMain("Razorverge Thicket", 100)
.addMain("Avacyn's Pilgrim", 1) .addMain("Avacyn's Pilgrim", 1)
.addSide("War Priest of Thune", 3) .addSide("War Priest of Thune", 3)
.verify(deck, 113, 3); .verify(deck, 113, 3);
assertEquals("Could not find card: '@#$NOT A REAL CARD NAME@#$'\n", errors.toString()); assertEquals("Could not find card: '@#$NOT A REAL CARD NAME@#$'\n", errors.toString());
} }
} }

View file

@ -1,52 +1,51 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
public class DecDeckImportTest { public class DecDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup(); private static final FakeCardLookup LOOKUP = new FakeCardLookup();
@Test @Test
public void testImport() { public void testImport() {
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
DecDeckImporter importer = new DecDeckImporter() { DecDeckImporter importer = new DecDeckImporter() {
@Override @Override
public CardLookup getCardLookup() { public CardLookup getCardLookup() {
return LOOKUP; return LOOKUP;
} }
}; };
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.dec", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.dec", errors, false);
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Masticore", 4) .addMain("Masticore", 4)
.addMain("Metalworker", 4) .addMain("Metalworker", 4)
.addMain("Phyrexian Colossus", 1) .addMain("Phyrexian Colossus", 1)
.addMain("Crumbling Sanctuary", 1) .addMain("Crumbling Sanctuary", 1)
.addMain("Grim Monolith", 4) .addMain("Grim Monolith", 4)
.addMain("Mishra's Helix", 1) .addMain("Mishra's Helix", 1)
.addMain("Phyrexian Processor", 4) .addMain("Phyrexian Processor", 4)
.addMain("Tangle Wire", 4) .addMain("Tangle Wire", 4)
.addMain("Thran Dynamo", 4) .addMain("Thran Dynamo", 4)
.addMain("Voltaic Key", 4) .addMain("Voltaic Key", 4)
.addMain("Tinker", 4) .addMain("Tinker", 4)
.addMain("Brainstorm", 4) .addMain("Brainstorm", 4)
.addMain("Crystal Vein", 4) .addMain("Crystal Vein", 4)
.addMain("Island", 9) .addMain("Island", 9)
.addMain("Rishadan Port", 4) .addMain("Rishadan Port", 4)
.addMain("Saprazzan Skerry", 4) .addMain("Saprazzan Skerry", 4)
.addSide("Annul", 4) .addSide("Annul", 4)
.addSide("Chill", 4) .addSide("Chill", 4)
.addSide("Miscalculation", 4) .addSide("Miscalculation", 4)
.addSide("Mishra's Helix", 1) .addSide("Mishra's Helix", 1)
.addSide("Rising Waters", 2) .addSide("Rising Waters", 2)
.verify(deck, 60, 15); .verify(deck, 60, 15);
assertEquals("", errors.toString()); assertEquals("", errors.toString());
} }
} }

View file

@ -3,7 +3,7 @@ package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
public class DraftLogImporterTest { public class DraftLogImporterTest {
@ -19,7 +19,7 @@ public class DraftLogImporterTest {
} }
}; };
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.draft", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.draft", errors, false);
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Raging Ravine", 1) .addMain("Raging Ravine", 1)

View file

@ -3,9 +3,7 @@ package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import org.junit.Test; import org.junit.Test;
import java.io.File; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
public class MtgaImporterTest { public class MtgaImporterTest {
@ -21,7 +19,7 @@ public class MtgaImporterTest {
}; };
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.mtga", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.mtga", errors, false);
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Niv-Mizzet Reborn", 1) .addMain("Niv-Mizzet Reborn", 1)

View file

@ -1,57 +1,56 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
public class MtgjsonDeckImportTest { public class MtgjsonDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup(); private static final FakeCardLookup LOOKUP = new FakeCardLookup();
@Test @Test
public void testImport() { public void testImport() {
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
MtgjsonDeckImporter importer = new MtgjsonDeckImporter() { MtgjsonDeckImporter importer = new MtgjsonDeckImporter() {
@Override @Override
public CardLookup getCardLookup() { public CardLookup getCardLookup() {
return LOOKUP; return LOOKUP;
} }
}; };
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.json", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.json", errors, false);
assertEquals("Arcane Tempo", deck.getName()); assertEquals("Arcane Tempo", deck.getName());
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Goblin Electromancer", 4) .addMain("Goblin Electromancer", 4)
.addMain("Crackling Drake", 4) .addMain("Crackling Drake", 4)
.addMain("Murmuring Mystic", 2) .addMain("Murmuring Mystic", 2)
.addMain("Arclight Phoenix", 1) .addMain("Arclight Phoenix", 1)
.addMain("Niv-Mizzet, Parun", 2) .addMain("Niv-Mizzet, Parun", 2)
.addMain("Chart a Course", 4) .addMain("Chart a Course", 4)
.addMain("Lava Coil", 4) .addMain("Lava Coil", 4)
.addMain("Beacon Bolt", 1) .addMain("Beacon Bolt", 1)
.addMain("Opt", 4) .addMain("Opt", 4)
.addMain("Radical Idea", 4) .addMain("Radical Idea", 4)
.addMain("Shock", 4) .addMain("Shock", 4)
.addMain("Dive Down", 2) .addMain("Dive Down", 2)
.addMain("Blink of an Eye", 1) .addMain("Blink of an Eye", 1)
.addMain("The Mirari Conjecture", 1) .addMain("The Mirari Conjecture", 1)
.addMain("Sulfur Falls", 3) .addMain("Sulfur Falls", 3)
.addMain("Izzet Guildgate", 4) .addMain("Izzet Guildgate", 4)
.addMain("Island", 8) .addMain("Island", 8)
.addMain("Mountain", 7) .addMain("Mountain", 7)
.addSide("The Mirari Conjecture", 1) .addSide("The Mirari Conjecture", 1)
.addSide("Beacon Bolt", 1) .addSide("Beacon Bolt", 1)
.addSide("Negate", 3) .addSide("Negate", 3)
.addSide("Entrancing Melody", 3) .addSide("Entrancing Melody", 3)
.addSide("Fiery Cannonade", 3) .addSide("Fiery Cannonade", 3)
.addSide("Shivan Fire", 2) .addSide("Shivan Fire", 2)
.addSide("Disdainful Stroke", 2) .addSide("Disdainful Stroke", 2)
.verify(deck, 60, 15); .verify(deck, 60, 15);
assertEquals("", errors.toString()); assertEquals("", errors.toString());
} }
} }

View file

@ -1,57 +1,51 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
public class MwsDeckImportTest { public class MwsDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup(); private static final FakeCardLookup LOOKUP = new FakeCardLookup();
@Test @Test
public void testImport() { public void testImport() {
MWSDeckImporter importer = new MWSDeckImporter() { MWSDeckImporter importer = new MWSDeckImporter() {
@Override @Override
public CardLookup getCardLookup() { public CardLookup getCardLookup() {
return LOOKUP; return LOOKUP;
} }
}; };
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.mwDeck", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.mwDeck", errors, false);
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Mutavault", 4) .addMain("Mutavault", 4)
.addMain("Plains", 18) .addMain("Plains", 18)
.addMain("Daring Skyjek", 2) .addMain("Daring Skyjek", 2)
.addMain("Azorius Arrester", 4) .addMain("Azorius Arrester", 4)
.addMain("Banisher Priest", 4) .addMain("Banisher Priest", 4)
.addMain("Boros Elite", 4) .addMain("Boros Elite", 4)
.addMain("Dryad Militant", 4) .addMain("Dryad Militant", 4)
.addMain("Imposing Sovereign", 4) .addMain("Imposing Sovereign", 4)
.addMain("Precinct Captain", 4) .addMain("Precinct Captain", 4)
.addMain("Soldier of the Pantheon", 4) .addMain("Soldier of the Pantheon", 4)
.addMain("Spear of Heliod", 3) .addMain("Spear of Heliod", 3)
.addMain("Rootborn Defenses", 1) .addMain("Rootborn Defenses", 1)
.addMain("Brave the Elements", 4) .addMain("Brave the Elements", 4)
.addSide("Wear/Tear", 1) .addSide("Wear/Tear", 1)
.addSide("Glare of Heresy", 2) .addSide("Glare of Heresy", 2)
.addSide("Fiendslayer Paladin", 3) .addSide("Fiendslayer Paladin", 3)
.addSide("Riot Control", 3) .addSide("Riot Control", 3)
.addSide("Ajani, Caller of the Pride", 3) .addSide("Ajani, Caller of the Pride", 3)
.addSide("Rootborn Defenses", 3) .addSide("Rootborn Defenses", 3)
.verify(deck, 60, 15); .verify(deck, 60, 15);
assertEquals("", errors.toString()); assertEquals("", errors.toString());
} }
} }

View file

@ -1,33 +1,32 @@
package mage.cards.decks.importer; package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
public class O8dDeckImportTest { public class O8dDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup(); private static final FakeCardLookup LOOKUP = new FakeCardLookup();
@Test @Test
public void testImport() { public void testImport() {
O8dDeckImporter importer = new O8dDeckImporter() { O8dDeckImporter importer = new O8dDeckImporter() {
@Override @Override
public CardLookup getCardLookup() { public CardLookup getCardLookup() {
return LOOKUP; return LOOKUP;
} }
}; };
StringBuilder errors = new StringBuilder(); StringBuilder errors = new StringBuilder();
DeckCardLists deck = importer.importDeck( DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.o8d", errors); "src/test/java/mage/cards/decks/importer/samples/testdeck.o8d", errors, false);
TestDeckChecker.checker() TestDeckChecker.checker()
.addMain("Forest", 1) .addMain("Forest", 1)
.addSide("Island", 2) .addSide("Island", 2)
.verify(deck, 1, 2); .verify(deck, 1, 2);
assertEquals("", errors.toString()); assertEquals("", errors.toString());
} }
} }