diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java index f08bdbd4366..11347eb59ce 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportClipboardDialog.java @@ -1,5 +1,6 @@ package mage.client.deckeditor; +import mage.cards.decks.importer.MtgaImporter; import mage.client.MageFrame; import mage.client.dialog.MageDialog; import mage.util.DeckUtil; @@ -20,11 +21,18 @@ import java.util.Optional; public class DeckImportClipboardDialog extends MageDialog { private static final String FORMAT_TEXT = - "// Example:\n" + - "//1 Library of Congress\n" + - "//1 Cryptic Gateway\n" + - "//1 Azami, Lady of Scrolls\n" + - "// NB: This is slow as, and will lock your screen :)\n" + + "// MTGO format example:\n" + + "// 1 Library of Congress\n" + + "// 3 Cryptic Gateway\n" + + "//\n" + + "// MTGA, moxfield, archidekt format example:\n" + + "// Deck\n" + + "// 4 Accumulated Knowledge (A25) 40\n" + + "// 2 Adarkar Wastes (EOC) 147\n" + + "// Commander\n" + + "// 1 Grizzly Bears\n" + + "//\n" + + "// Importing deck can take some time to finish\n" + "\n" + "// Your current clipboard:\n" + "\n"; @@ -68,17 +76,19 @@ public class DeckImportClipboardDialog extends MageDialog { } private void onOK() { - String decklist = editData.getText(); - decklist = decklist.replace(FORMAT_TEXT, ""); + String importData = editData.getText(); + importData = importData.replace(FORMAT_TEXT, "").trim(); + // find possible data format String tempDeckPath; - // This dialog also accepts a paste in .mtga format - if (decklist.startsWith("Deck\n")) { // An .mtga list always starts with the first line being "Deck". This kind of paste is processed as .mtga - tempDeckPath = DeckUtil.writeTextToTempFile("cbimportdeck", ".mtga", decklist); + if (MtgaImporter.isMTGA(importData)) { + // MTGA or Moxfield + tempDeckPath = DeckUtil.writeTextToTempFile("cbimportdeck", ".mtga", importData); } else { - // If the paste is not .mtga format, it's processed as plaintext - tempDeckPath = DeckUtil.writeTextToTempFile(decklist); + // text + tempDeckPath = DeckUtil.writeTextToTempFile(importData); } + if (this.callback != null) { callback.onImportDone(tempDeckPath); } diff --git a/Mage/src/main/java/mage/cards/decks/importer/MtgaImporter.java b/Mage/src/main/java/mage/cards/decks/importer/MtgaImporter.java index 8e5047ddda0..dfd973e3b27 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/MtgaImporter.java +++ b/Mage/src/main/java/mage/cards/decks/importer/MtgaImporter.java @@ -8,6 +8,7 @@ import mage.cards.repository.CardInfo; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -18,7 +19,11 @@ import java.util.regex.Pattern; public class MtgaImporter extends PlainTextDeckImporter { private static final Map SET_REMAPPING = ImmutableMap.of("DAR", "DOM"); - private static final Pattern MTGA_PATTERN = Pattern.compile( + + // example: + // 4 Accumulated Knowledge (A25) 40 + // 4 Accumulated Knowledge + public static final Pattern MTGA_PATTERN = Pattern.compile( "(\\p{Digit}+)" + "\\p{javaWhitespace}+" + "(" + CardNameUtil.CARD_NAME_PATTERN.pattern() + ")" + @@ -34,12 +39,15 @@ public class MtgaImporter extends PlainTextDeckImporter { protected void readLine(String line, DeckCardLists deckList, FixedInfo fixedInfo) { line = line.trim(); + String lowerLine = line.toLowerCase(Locale.ENGLISH); - if (line.equals("Deck")) { + // mainboard to support decks from archidekt.com + if (lowerLine.equals("deck") || lowerLine.equals("mainboard")) { + sideboard = false; return; } - if (line.equals("Sideboard") || line.equals("")) { + if (lowerLine.equals("sideboard") || lowerLine.equals("commander") || lowerLine.equals("maybeboard") || lowerLine.equals("")) { sideboard = true; return; } @@ -74,4 +82,34 @@ public class MtgaImporter extends PlainTextDeckImporter { zone.addAll(Collections.nCopies(count, deckCardInfo.copy())); } + public static boolean isMTGA(String data) { + // examples: + // 4 Accumulated Knowledge (A25) 40 + // 4 Accumulated Knowledge + // Deck + // Commander + // Mainboard - extra mark for archidekt.com + // Sideboard - extra mark for archidekt.com + // Maybeboard - extra mark for archidekt.com + + String firstLine = data.split("\\R", 2)[0]; + String firstLineLower = firstLine.toLowerCase(Locale.ENGLISH); + + // by deck marks + if (firstLineLower.startsWith("deck") + || firstLineLower.startsWith("mainboard") + || firstLineLower.startsWith("sideboard") + || firstLineLower.startsWith("commander") + || firstLineLower.startsWith("maybeboard")) { + return true; + } + + // by card marks + Matcher pattern = MtgaImporter.MTGA_PATTERN.matcher(CardNameUtil.normalizeCardName(firstLine)); + return pattern.matches() + && pattern.groupCount() >= 4 + && pattern.group(3) != null + && pattern.group(4) != null; + } + }