mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
Merge pull request #5805 from hitch17/mtga-deck-import
Support for importing mtga decks.
This commit is contained in:
commit
12be28483f
8 changed files with 184 additions and 21 deletions
|
|
@ -1415,14 +1415,15 @@ class ImportFilter extends FileFilter {
|
||||||
|| ext.equalsIgnoreCase("dek")
|
|| ext.equalsIgnoreCase("dek")
|
||||||
|| ext.equalsIgnoreCase("cod")
|
|| ext.equalsIgnoreCase("cod")
|
||||||
|| ext.equalsIgnoreCase("o8d")
|
|| ext.equalsIgnoreCase("o8d")
|
||||||
|| ext.equalsIgnoreCase("draft");
|
|| ext.equalsIgnoreCase("draft")
|
||||||
|
|| ext.equalsIgnoreCase("mtga");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d; *.draft)";
|
return "All formats (*.dec; *.mwDeck; *.txt; *.dek; *.cod; *.o8d; *.draft; *.mtga)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
24
Mage/src/main/java/mage/cards/decks/CardNameUtil.java
Normal file
24
Mage/src/main/java/mage/cards/decks/CardNameUtil.java
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
package mage.cards.decks;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class CardNameUtil {
|
||||||
|
|
||||||
|
public static final Pattern CARD_NAME_PATTERN = Pattern.compile("[ !\"&',\\-./0-9:A-Za-z]+");
|
||||||
|
|
||||||
|
public static String normalizeCardName(String name) {
|
||||||
|
return name
|
||||||
|
.replace("&", "//")
|
||||||
|
.replace("Æ", "Ae")
|
||||||
|
.replace("ö", "o")
|
||||||
|
.replace("û", "u")
|
||||||
|
.replace("í", "i")
|
||||||
|
.replace("â", "a")
|
||||||
|
.replace("á", "a")
|
||||||
|
.replace("à", "a")
|
||||||
|
.replace("é", "e")
|
||||||
|
.replace("ú", "u")
|
||||||
|
.replace("\"", "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,4 +19,37 @@ public class CardLookup {
|
||||||
return CardRepository.instance.findCards(criteria);
|
return CardRepository.instance.findCards(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<CardInfo> lookupCardInfo(String name, String set) {
|
||||||
|
Optional<CardInfo> result = lookupCardInfo(new CardCriteria().name(name).setCodes(set))
|
||||||
|
.stream()
|
||||||
|
.findAny();
|
||||||
|
if (result.isPresent()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookupCardInfo(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<CardInfo> lookupCardInfo(String name, String set, String cardNumber) {
|
||||||
|
Optional<CardInfo> result;
|
||||||
|
try {
|
||||||
|
int intCardNumber = Integer.parseInt(cardNumber);
|
||||||
|
result = lookupCardInfo(
|
||||||
|
new CardCriteria()
|
||||||
|
.name(name)
|
||||||
|
.setCodes(set)
|
||||||
|
.minCardNumber(intCardNumber)
|
||||||
|
.maxCardNumber(intCardNumber))
|
||||||
|
.stream()
|
||||||
|
.findAny();
|
||||||
|
if (result.isPresent()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
/* ignored */
|
||||||
|
}
|
||||||
|
|
||||||
|
return lookupCardInfo(name, set);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ public abstract class DeckImporter {
|
||||||
return new O8dDeckImporter();
|
return new O8dDeckImporter();
|
||||||
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("draft")) {
|
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("draft")) {
|
||||||
return new DraftLogImporter();
|
return new DraftLogImporter();
|
||||||
|
} else if (file.toLowerCase(Locale.ENGLISH).endsWith("mtga")) {
|
||||||
|
return new MtgaImporter();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package mage.cards.decks.importer;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static mage.cards.decks.CardNameUtil.CARD_NAME_PATTERN;
|
||||||
|
|
||||||
|
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}+)");
|
||||||
|
|
||||||
|
private final CardLookup lookup = getCardLookup();
|
||||||
|
private boolean sideboard = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void readLine(String line, DeckCardLists deckList) {
|
||||||
|
if (line.trim().equals("")) {
|
||||||
|
sideboard = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher m = MTGA_PATTERN.matcher(CardNameUtil.normalizeCardName(line));
|
||||||
|
if (m.matches()) {
|
||||||
|
int count = Integer.parseInt(m.group(1));
|
||||||
|
String name = m.group(2);
|
||||||
|
String set = SET_REMAPPING.getOrDefault(m.group(3), m.group(3));
|
||||||
|
String cardNumber = m.group(4);
|
||||||
|
final List<DeckCardInfo> zone = sideboard ? deckList.getSideboard() : deckList.getCards();
|
||||||
|
Optional<CardInfo> found = lookup.lookupCardInfo(name, set, cardNumber);
|
||||||
|
if (!found.isPresent()) {
|
||||||
|
sbMessage.append("Cound not find card for '").append(line).append("'\n");
|
||||||
|
} else {
|
||||||
|
found.ifPresent(card -> zone.addAll(Collections.nCopies(count,
|
||||||
|
new DeckCardInfo(card.getName(), card.getCardNumber(), card.getSetCode()))));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sbMessage.append("Error reading '").append(line).append("'\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package mage.cards.decks.importer;
|
package mage.cards.decks.importer;
|
||||||
|
|
||||||
|
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.CardInfo;
|
import mage.cards.repository.CardInfo;
|
||||||
|
|
@ -109,18 +110,7 @@ public class TxtDeckImporter extends PlainTextDeckImporter {
|
||||||
cardAmount = 1;
|
cardAmount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineName = lineName
|
lineName = CardNameUtil.normalizeCardName(lineName);
|
||||||
.replace("&", "//")
|
|
||||||
.replace("Æ", "Ae")
|
|
||||||
.replace("ö", "o")
|
|
||||||
.replace("û", "u")
|
|
||||||
.replace("í", "i")
|
|
||||||
.replace("â", "a")
|
|
||||||
.replace("á", "a")
|
|
||||||
.replace("à", "a")
|
|
||||||
.replace("é", "e")
|
|
||||||
.replace("ú", "u")
|
|
||||||
.replace("\"", "'");
|
|
||||||
if (lineName.contains("//") && !lineName.contains(" // ")) {
|
if (lineName.contains("//") && !lineName.contains(" // ")) {
|
||||||
lineName = lineName.replace("//", " // ");
|
lineName = lineName.replace("//", " // ");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package mage.cards.decks.importer;
|
||||||
|
|
||||||
|
import mage.cards.decks.DeckCardLists;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class MtgaImporterTest {
|
||||||
|
|
||||||
|
private static final FakeCardLookup LOOKUP = new FakeCardLookup();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImport() {
|
||||||
|
MtgaImporter importer = new MtgaImporter() {
|
||||||
|
@Override
|
||||||
|
public CardLookup getCardLookup() {
|
||||||
|
return LOOKUP;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
StringBuilder errors = new StringBuilder();
|
||||||
|
DeckCardLists deck = importer.importDeck(
|
||||||
|
"src/test/java/mage/cards/decks/importer/samples/testdeck.mtga", errors);
|
||||||
|
|
||||||
|
TestDeckChecker.checker()
|
||||||
|
.addMain("Niv-Mizzet Reborn", 1)
|
||||||
|
.addMain("Teferi, Time Raveler", 1)
|
||||||
|
.addMain("Dovin's Veto", 1)
|
||||||
|
.addMain("Knight of Autumn", 1)
|
||||||
|
.addMain("Expansion // Explosion", 1)
|
||||||
|
.addMain("Forest", 1)
|
||||||
|
.addMain("Teferi, Hero of Dominaria", 1)
|
||||||
|
|
||||||
|
.addSide("Unmoored Ego", 1)
|
||||||
|
.addSide("Beacon Bolt", 1)
|
||||||
|
|
||||||
|
.verify(deck, 7, 2);
|
||||||
|
|
||||||
|
assertEquals("", errors.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
1 Niv-Mizzet Reborn (WAR) 208
|
||||||
|
1 Teferi, Time Raveler (WAR) 221
|
||||||
|
1 Dovin's Veto (WAR) 193
|
||||||
|
1 Knight of Autumn (GRN) 183
|
||||||
|
1 Expansion // Explosion (GRN) 224
|
||||||
|
1 Forest (XLN) 277
|
||||||
|
1 Teferi, Hero of Dominaria (DAR) 207
|
||||||
|
|
||||||
|
1 Unmoored Ego (GRN) 212
|
||||||
|
1 Beacon Bolt (GRN) 154
|
||||||
Loading…
Add table
Add a link
Reference in a new issue