* 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 {
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();
validateDeck(deck);
} catch (Exception ex) {

View file

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

View file

@ -1,4 +1,3 @@
package mage.client.dialog;
import mage.cards.decks.importer.DeckImporter;
@ -12,7 +11,6 @@ import javax.swing.*;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class JoinTableDialog extends MageDialog {
@ -24,7 +22,9 @@ public class JoinTableDialog extends MageDialog {
private boolean joined = false;
private boolean isTournament;
/** Creates new form JoinTableDialog */
/**
* Creates new form JoinTableDialog
*/
public JoinTableDialog() {
initComponents();
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.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
@ -73,37 +74,37 @@ public class JoinTableDialog extends MageDialog {
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(btnOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel))
.addComponent(newPlayerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(lblPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(btnOK)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCancel))
.addComponent(newPlayerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(lblPassword)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(newPlayerPanel, 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(lblPassword)
.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)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel)
.addComponent(btnOK))
.addContainerGap())
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(newPlayerPanel, 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(lblPassword)
.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)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnCancel)
.addComponent(btnOK))
.addContainerGap())
);
pack();
@ -119,9 +120,9 @@ public class JoinTableDialog extends MageDialog {
try {
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PASSWORD_JOIN, txtPassword.getText());
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 {
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) {

View file

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

View file

@ -687,11 +687,11 @@ public class NewTournamentDialog extends MageDialog {
table.getTableId(),
this.player1Panel.getPlayerName(),
PlayerType.HUMAN, 1,
DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile()),
DeckImporter.importDeckFromFile(this.player1Panel.getDeckFile(), true),
tOptions.getPassword())) {
for (TournamentPlayerPanel player : players) {
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
SessionHandler.removeTable(roomId, table.getTableId());
table = null;
@ -743,11 +743,7 @@ public class NewTournamentDialog extends MageDialog {
private void spnNumSeatsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumSeatsStateChanged
int numSeats = (Integer) this.spnNumSeats.getValue();
if (numSeats > 2) {
this.spnNumPlayers.setEnabled(false);
} else {
this.spnNumPlayers.setEnabled(true);
}
this.spnNumPlayers.setEnabled(numSeats <= 2);
updateNumSeats();
}//GEN-LAST:event_spnNumSeatsStateChanged
@ -1209,7 +1205,7 @@ public class NewTournamentDialog extends MageDialog {
if (!(cubeFromDeckFilename.isEmpty())) {
Deck cubeFromDeck = new Deck();
try {
cubeFromDeck = Deck.load(DeckImporter.importDeckFromFile(cubeFromDeckFilename), true, true);
cubeFromDeck = Deck.load(DeckImporter.importDeckFromFile(cubeFromDeckFilename, true), true, true);
} catch (GameException e1) {
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.gameId = gameId;
this.playerId = player.getPlayerId();
if (SessionHandler.isTestMode()) {
this.btnCheat.setVisible(true);
} else {
this.btnCheat.setVisible(false);
}
this.btnCheat.setVisible(SessionHandler.isTestMode());
}
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) {
SessionHandler.cheat(gameId, playerId, DeckImporter.importDeckFromFile("cheat.dck"));
SessionHandler.cheat(gameId, playerId, DeckImporter.importDeckFromFile("cheat.dck", false));
}
public boolean isSmallMode() {

View file

@ -1,13 +1,5 @@
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.client.MageFrame;
import mage.client.SessionHandler;
@ -24,7 +16,6 @@ import mage.client.util.gui.countryBox.CountryUtil;
import mage.components.ImagePanel;
import mage.components.ImagePanelStyle;
import mage.constants.CardType;
import static mage.constants.Constants.*;
import mage.constants.ManaType;
import mage.counters.Counter;
import mage.counters.CounterType;
@ -33,6 +24,17 @@ import mage.utils.timer.PriorityTimer;
import mage.view.*;
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.
*
@ -935,7 +937,7 @@ public class PlayerPanelExt extends javax.swing.JPanel {
private void btnCheatActionPerformed(java.awt.event.ActionEvent evt) {
DckDeckImporter deckImporter = new DckDeckImporter();
SessionHandler.cheat(gameId, playerId, deckImporter.importDeck("cheat.dck"));
SessionHandler.cheat(gameId, playerId, deckImporter.importDeck("cheat.dck", false));
}
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 {
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;
}
@ -127,8 +127,7 @@ public class TablePlayerPanel extends javax.swing.JPanel {
if (getPlayerType() != PlayerType.HUMAN) {
this.newPlayerPanel.setVisible(true);
this.newPlayerPanel.setPlayerName(ClientDefaultSettings.computerName + " " + this.lblPlayerNum.getText().charAt(this.lblPlayerNum.getText().length() - 1));
}
else {
} else {
this.newPlayerPanel.setVisible(false);
}
this.revalidate();

View file

@ -95,7 +95,7 @@ public class TablesPanel extends javax.swing.JPanel {
final JToggleButton[] filterButtons;
// time formater
private PrettyTime timeFormater = new PrettyTime(Locale.ENGLISH);
private final PrettyTime timeFormater = new PrettyTime(Locale.ENGLISH);
// time ago renderer
TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() {
@ -127,7 +127,7 @@ public class TablesPanel extends javax.swing.JPanel {
// datetime render
TableCellRenderer datetimeCellRenderer = new DefaultTableCellRenderer() {
DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss");
final DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss");
@Override
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() {
// base panel to render
private JPanel renderPanel = new JPanel();
private ImageIcon skillIcon = new ImageIcon(this.getClass().getResource("/info/yellow_star_16.png"));
private final JPanel renderPanel = new JPanel();
private final ImageIcon skillIcon = new ImageIcon(this.getClass().getResource("/info/yellow_star_16.png"));
@Override
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
TableCellRenderer seatsCellRenderer = new DefaultTableCellRenderer() {
JLabel greenLabel = new JLabel();
final JLabel greenLabel = new JLabel();
@Override
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);
jPanelTop.setLayout(jPanelTopLayout);
jPanelTopLayout.setHorizontalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addContainerGap()
.addComponent(btnNewTable)
.addGap(6, 6, 6)
.addComponent(btnNewTournament)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addComponent(btnQuickStartDuel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnQuickStartMCTS))
.addComponent(btnQuickStartCommander))
.addContainerGap(540, Short.MAX_VALUE))
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addContainerGap()
.addComponent(btnNewTable)
.addGap(6, 6, 6)
.addComponent(btnNewTournament)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.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(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addComponent(btnQuickStartDuel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnQuickStartMCTS))
.addComponent(btnQuickStartCommander))
.addContainerGap(540, Short.MAX_VALUE))
);
jPanelTopLayout.setVerticalGroup(
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup()
.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()
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanelTopLayout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btnQuickStartDuel)
.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())
.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)
.addComponent(btnQuickStartDuel)
.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();
@ -1547,12 +1547,12 @@ public class TablesPanel extends javax.swing.JPanel {
javax.swing.GroupLayout jPanelTablesLayout = new javax.swing.GroupLayout(jPanelTables);
jPanelTables.setLayout(jPanelTablesLayout);
jPanelTablesLayout.setHorizontalGroup(
jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE)
jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE)
);
jPanelTablesLayout.setVerticalGroup(
jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE)
jPanelTablesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSplitPaneTables, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE)
);
jSplitPane1.setLeftComponent(jPanelTables);
@ -1627,7 +1627,7 @@ public class TablesPanel extends javax.swing.JPanel {
+ "5 Mountain" + System.lineSeparator()
+ "5 Plains");
}
DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile);
DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile, false);
PlayerType aiType = useMonteCarloAI ? PlayerType.COMPUTER_MONTE_CARLO : PlayerType.COMPUTER_MAD;
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("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 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)) {
list = loadedDeckCardLists.get(deckName);
} else {
list = DeckImporter.importDeckFromFile(deckName);
list = DeckImporter.importDeckFromFile(deckName, true);
loadedDeckCardLists.put(deckName, list);
}
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 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
private static final boolean CHECK_SOURCE_TOKENS = false;
@ -471,7 +472,7 @@ public class VerifyCardDataTest {
}
@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() {
Collection<String> errorsList = new ArrayList<>();
@ -497,7 +498,7 @@ public class VerifyCardDataTest {
for (Path deckFile : filesList) {
String deckName = deckFile.toString().replace(rootPath, "");
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()) {
errorsList.add("Error: sample deck contains errors " + deckName);

View file

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

View file

@ -7,11 +7,15 @@ import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Original xmage's deck format (uses by deck editor)
*
* @author North
*/
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 final Map<String, String> possibleFixes = new HashMap<>(); // possible fixes for card codes and numbers [code:123] -> [code:456]
@Override
protected void readLine(String line, DeckCardLists deckList) {
protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.isEmpty() || line.startsWith("#")) {
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);
if (m.matches()) {
boolean sideboard = false;
@ -46,12 +60,20 @@ public class DckDeckImporter extends PlainTextDeckImporter {
setCode = setCode == null ? "" : setCode.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
DeckCardInfo deckCardInfo = null;
// search by number
// search by set/number
CardInfo foundedCard = CardRepository.instance.findCard(setCode, cardNum);
boolean wasOutdated = false;
if ((foundedCard != null) && !foundedCard.getName().equals(cardName)) {
@ -63,7 +85,7 @@ public class DckDeckImporter extends PlainTextDeckImporter {
// search by name
if (foundedCard == null) {
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("")) {
@ -74,6 +96,12 @@ public class DckDeckImporter extends PlainTextDeckImporter {
sbMessage.append("Line ").append(lineCount).append(": ")
.append("replaced to [").append(foundedCard.getSetCode()).append(":").append(foundedCard.getCardNumberAsInt()).append("] ")
.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 {
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;
import java.util.Optional;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import java.util.Optional;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class DecDeckImporter extends PlainTextDeckImporter {
@Override
protected void readLine(String line, DeckCardLists deckList) {
protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.isEmpty() || line.startsWith("//")) {
return;
}

View file

@ -1,95 +1,122 @@
package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.apache.log4j.Logger;
import java.io.File;
import java.util.Locale;
import java.util.Optional;
import java.util.Scanner;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
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: "};
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) {
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;
}
FixedInfo(String originalLine) {
this.originalLine = originalLine;
this.fixedLine = originalLine;
}
public String getOriginalLine() {
return originalLine;
}
public Boolean getCanFix() {
return canFix;
}
public void setCanFix(Boolean canFix) {
this.canFix = canFix;
}
public String getFixedLine() {
return fixedLine;
}
public void setFixedLine(String fixedLine) {
this.fixedLine = fixedLine;
}
}
} catch (Exception e) {
// ignore error, deckimporter will process it
}
// not found
return false;
}
protected static final Logger logger = Logger.getLogger(DeckImporter.class);
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 {
@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")) {
return;
@ -27,24 +27,24 @@ public class DekDeckImporter extends PlainTextDeckImporter {
} else {
for (int i = 0; i < cardCount; i++) {
DeckCardInfo deckCardInfo = new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode());
if(isSideboard) {
if (isSideboard) {
deckList.getSideboard().add(deckCardInfo);
} else {
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');
}
}
private String extractAttribute(String line, String name) {
String searchString = name+"=\"";
int startDelim = line.indexOf(searchString)+searchString.length();
String searchString = name + "=\"";
int startDelim = line.indexOf(searchString) + searchString.length();
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 {
private static Pattern SET_PATTERN = Pattern.compile("------ (\\p{Alnum}+) ------$");
private static Pattern PICK_PATTERN = Pattern.compile("--> (.+)$");
private static final Pattern SET_PATTERN = Pattern.compile("------ (\\p{Alnum}+) ------$");
private static final Pattern PICK_PATTERN = Pattern.compile("--> (.+)$");
private String currentSet = null;
@Override
protected void readLine(String line, DeckCardLists deckList) {
protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
Matcher setMatcher = SET_PATTERN.matcher(line);
if (setMatcher.matches()) {
currentSet = setMatcher.group(1);

View file

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

View file

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

View file

@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap;
import mage.cards.decks.CardNameUtil;
import mage.cards.decks.DeckCardInfo;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
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 Pattern MTGA_PATTERN = Pattern.compile(
"(\\p{Digit}+)" +
"\\p{javaWhitespace}+" +
"(" + CARD_NAME_PATTERN.pattern() + ")" +
"\\p{javaWhitespace}+" +
"\\((\\p{Alnum}+)\\)" +
"\\p{javaWhitespace}+" +
"(\\p{Digit}+)");
"\\p{javaWhitespace}+" +
"(" + CARD_NAME_PATTERN.pattern() + ")" +
"\\p{javaWhitespace}+" +
"\\((\\p{Alnum}+)\\)" +
"\\p{javaWhitespace}+" +
"(\\p{Digit}+)");
private final CardLookup lookup = getCardLookup();
private boolean sideboard = false;
@Override
protected void readLine(String line, DeckCardLists deckList) {
protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
if (line.trim().equals("")) {
sideboard = true;
return;

View file

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

View file

@ -1,14 +1,15 @@
package mage.cards.decks.importer;
import java.io.File;
import java.util.Scanner;
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
*/
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 errorMessages you can setup output messages to showup to user (set null for fatal exception on messages.count > 0)
* @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 saveAutoFixedFile save fixed deck file (if any fixes applied)
* @return decks list
*/
public DeckCardLists importDeck(String file, StringBuilder errorMessages) {
public DeckCardLists importDeck(String file, StringBuilder errorMessages, boolean saveAutoFixedFile) {
File f = new File(file);
List<String> originalFile = new ArrayList<>();
List<String> fixedFile = new ArrayList<>();
DeckCardLists deckList = new DeckCardLists();
if (!f.exists()) {
logger.warn("Deckfile " + file + " not found.");
@ -35,17 +40,29 @@ public abstract class PlainTextDeckImporter extends DeckImporter {
sbMessage.setLength(0);
try {
try (Scanner scanner = new Scanner(f)) {
Boolean canFix = true;
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
FixedInfo fixedInfo = new FixedInfo(line);
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(errorMessages != null) {
if (errorMessages != null) {
// normal output for user
errorMessages.append(sbMessage);
}else{
} else {
// fatal error
logger.fatal(sbMessage);
}
@ -59,11 +76,30 @@ public abstract class PlainTextDeckImporter extends DeckImporter {
return deckList;
}
@Override
public DeckCardLists importDeck(String file) {
return importDeck(file, null);
private void saveFixedDeckFile(List<String> fixedfile, File file) {
try (FileOutputStream stream = new FileOutputStream(file)) {
PrintWriter out = new PrintWriter(stream);
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
protected void readLine(String line, DeckCardLists deckList) {
protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) {
line = line.trim();

View file

@ -1,40 +1,39 @@
package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
public class CodDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup(false)
.addCard("Forest")
.addCard("Razorverge Thicket")
.addCard("Avacyn's Pilgrim")
.addCard("War Priest of Thune");
private static final FakeCardLookup LOOKUP = new FakeCardLookup(false)
.addCard("Forest")
.addCard("Razorverge Thicket")
.addCard("Avacyn's Pilgrim")
.addCard("War Priest of Thune");
@Test
public void testImport() {
CodDeckImporter importer = new CodDeckImporter() {
@Override
public CardLookup getCardLookup() {
return LOOKUP;
}
};
StringBuilder errors = new StringBuilder();
DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.cod", errors);
assertEquals("Deck Name", deck.getName());
@Test
public void testImport() {
CodDeckImporter importer = new CodDeckImporter() {
@Override
public CardLookup getCardLookup() {
return LOOKUP;
}
};
StringBuilder errors = new StringBuilder();
DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.cod", errors, false);
assertEquals("Deck Name", deck.getName());
TestDeckChecker.checker()
.addMain("Forest", 12)
.addMain("Razorverge Thicket", 100)
.addMain("Avacyn's Pilgrim", 1)
.addSide("War Priest of Thune", 3)
.verify(deck, 113, 3);
TestDeckChecker.checker()
.addMain("Forest", 12)
.addMain("Razorverge Thicket", 100)
.addMain("Avacyn's Pilgrim", 1)
.addSide("War Priest of Thune", 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;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import mage.cards.decks.DeckCardLists;
public class DecDeckImportTest {
private static final FakeCardLookup LOOKUP = new FakeCardLookup();
private static final FakeCardLookup LOOKUP = new FakeCardLookup();
@Test
public void testImport() {
StringBuilder errors = new StringBuilder();
DecDeckImporter importer = new DecDeckImporter() {
@Override
public CardLookup getCardLookup() {
return LOOKUP;
}
};
DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.dec", errors);
@Test
public void testImport() {
StringBuilder errors = new StringBuilder();
DecDeckImporter importer = new DecDeckImporter() {
@Override
public CardLookup getCardLookup() {
return LOOKUP;
}
};
DeckCardLists deck = importer.importDeck(
"src/test/java/mage/cards/decks/importer/samples/testdeck.dec", errors, false);
TestDeckChecker.checker()
.addMain("Masticore", 4)
.addMain("Metalworker", 4)
.addMain("Phyrexian Colossus", 1)
.addMain("Crumbling Sanctuary", 1)
.addMain("Grim Monolith", 4)
.addMain("Mishra's Helix", 1)
.addMain("Phyrexian Processor", 4)
.addMain("Tangle Wire", 4)
.addMain("Thran Dynamo", 4)
.addMain("Voltaic Key", 4)
.addMain("Tinker", 4)
.addMain("Brainstorm", 4)
.addMain("Crystal Vein", 4)
.addMain("Island", 9)
.addMain("Rishadan Port", 4)
.addMain("Saprazzan Skerry", 4)
.addSide("Annul", 4)
.addSide("Chill", 4)
.addSide("Miscalculation", 4)
.addSide("Mishra's Helix", 1)
.addSide("Rising Waters", 2)
.verify(deck, 60, 15);
TestDeckChecker.checker()
.addMain("Masticore", 4)
.addMain("Metalworker", 4)
.addMain("Phyrexian Colossus", 1)
.addMain("Crumbling Sanctuary", 1)
.addMain("Grim Monolith", 4)
.addMain("Mishra's Helix", 1)
.addMain("Phyrexian Processor", 4)
.addMain("Tangle Wire", 4)
.addMain("Thran Dynamo", 4)
.addMain("Voltaic Key", 4)
.addMain("Tinker", 4)
.addMain("Brainstorm", 4)
.addMain("Crystal Vein", 4)
.addMain("Island", 9)
.addMain("Rishadan Port", 4)
.addMain("Saprazzan Skerry", 4)
.addSide("Annul", 4)
.addSide("Chill", 4)
.addSide("Miscalculation", 4)
.addSide("Mishra's Helix", 1)
.addSide("Rising Waters", 2)
.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 org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
public class DraftLogImporterTest {
@ -19,7 +19,7 @@ public class DraftLogImporterTest {
}
};
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()
.addMain("Raging Ravine", 1)

View file

@ -3,9 +3,7 @@ package mage.cards.decks.importer;
import mage.cards.decks.DeckCardLists;
import org.junit.Test;
import java.io.File;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
public class MtgaImporterTest {
@ -21,7 +19,7 @@ public class MtgaImporterTest {
};
StringBuilder errors = new StringBuilder();
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()
.addMain("Niv-Mizzet Reborn", 1)

View file

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

View file

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