mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Added full support to all Deckstats deck exports + bug fix&extra tests
Now DeckRecognizer supports all the exports of decks from Deckstats.net. This now also includes card lists grouped by Rarity, CMC, and Mana Colours. A new set of tests have been also added to test for the new non-card token types parsing, as well as a condition with multiple constraints imposed on the deck recogniser at a time. In particular, now all the combinations of constraints (also together) have been tested, and therefore the types of token returned has been adjusted. Signed-off-by: leriomaggio <valeriomaggio@gmail.com>
This commit is contained in:
@@ -27,10 +27,7 @@ import forge.item.IPaperCard;
|
|||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -39,9 +36,6 @@ import java.util.regex.Pattern;
|
|||||||
* DeckRecognizer class.
|
* DeckRecognizer class.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Forge
|
|
||||||
* @version $Id: DeckRecognizer.java 10499 2011-09-17 15:08:47Z Max mtg $
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class DeckRecognizer {
|
public class DeckRecognizer {
|
||||||
/**
|
/**
|
||||||
@@ -52,11 +46,14 @@ public class DeckRecognizer {
|
|||||||
ILLEGAL_CARD_REQUEST,
|
ILLEGAL_CARD_REQUEST,
|
||||||
INVALID_CARD_REQUEST,
|
INVALID_CARD_REQUEST,
|
||||||
UNKNOWN_CARD_REQUEST,
|
UNKNOWN_CARD_REQUEST,
|
||||||
DECK_NAME,
|
|
||||||
DECK_SECTION_NAME,
|
|
||||||
COMMENT,
|
|
||||||
UNKNOWN_TEXT,
|
UNKNOWN_TEXT,
|
||||||
CARD_TYPE
|
DECK_NAME,
|
||||||
|
COMMENT,
|
||||||
|
DECK_SECTION_NAME,
|
||||||
|
CARD_TYPE,
|
||||||
|
CARD_RARITY,
|
||||||
|
CARD_CMC,
|
||||||
|
MANA_COLOUR
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,23 +71,29 @@ public class DeckRecognizer {
|
|||||||
|
|
||||||
public static Token IllegalCard(final String cardName, final String setCode, final int count) {
|
public static Token IllegalCard(final String cardName, final String setCode, final int count) {
|
||||||
String ttext = setCode == null || setCode.equals("") ? cardName :
|
String ttext = setCode == null || setCode.equals("") ? cardName :
|
||||||
String.format("%s [%s]", cardName, setCode);
|
String.format("%s (%s)", cardName, setCode);
|
||||||
return new Token(null, TokenType.ILLEGAL_CARD_REQUEST, count, ttext);
|
return new Token(null, TokenType.ILLEGAL_CARD_REQUEST, count, ttext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Token InvalidCard(final String cardName, final String setCode, final int count) {
|
public static Token InvalidCard(final String cardName, final String setCode, final int count) {
|
||||||
String ttext = setCode == null || setCode.equals("") ? cardName :
|
String ttext = setCode == null || setCode.equals("") ? cardName :
|
||||||
String.format("%s [%s]", cardName, setCode);
|
String.format("%s (%s)", cardName, setCode);
|
||||||
return new Token(null, TokenType.INVALID_CARD_REQUEST, count, ttext);
|
return new Token(null, TokenType.INVALID_CARD_REQUEST, count, ttext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Token UnknownCard(final String cardName, final String setCode, final int count) {
|
public static Token UnknownCard(final String cardName, final String setCode, final int count) {
|
||||||
String ttext = setCode == null || setCode.equals("") ? cardName :
|
String ttext = setCode == null || setCode.equals("") ? cardName :
|
||||||
String.format("%s [%s]", cardName, setCode);
|
String.format("%s (%s)", cardName, setCode);
|
||||||
return new Token(null, TokenType.UNKNOWN_CARD_REQUEST, count, ttext);
|
return new Token(null, TokenType.UNKNOWN_CARD_REQUEST, count, ttext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Token DeckSection(final String sectionName){
|
public static Token DeckSection(final String sectionName0){
|
||||||
|
String sectionName = sectionName0.toLowerCase();
|
||||||
|
if (sectionName.equals("side") || sectionName.contains("sideboard"))
|
||||||
|
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Sideboard.name());
|
||||||
|
if (sectionName.equals("main") || sectionName.contains("card")
|
||||||
|
|| sectionName.equals("mainboard") || sectionName.equals("deck"))
|
||||||
|
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Main.name());
|
||||||
if (sectionName.equals("avatar"))
|
if (sectionName.equals("avatar"))
|
||||||
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Avatar.name());
|
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Avatar.name());
|
||||||
if (sectionName.equals("commander"))
|
if (sectionName.equals("commander"))
|
||||||
@@ -99,11 +102,6 @@ public class DeckRecognizer {
|
|||||||
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Schemes.name());
|
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Schemes.name());
|
||||||
if (sectionName.equals("conspiracy"))
|
if (sectionName.equals("conspiracy"))
|
||||||
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Conspiracy.name());
|
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Conspiracy.name());
|
||||||
if (sectionName.equals("side") || sectionName.contains("sideboard"))
|
|
||||||
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Sideboard.name());
|
|
||||||
if (sectionName.equals("main") || sectionName.contains("card")
|
|
||||||
|| sectionName.equals("mainboard") || sectionName.equals("deck"))
|
|
||||||
return new Token(TokenType.DECK_SECTION_NAME, DeckSection.Main.name());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +146,6 @@ public class DeckRecognizer {
|
|||||||
private static final String LINE_COMMENT_DELIMITER_OR_MD_HEADER = "#";
|
private static final String LINE_COMMENT_DELIMITER_OR_MD_HEADER = "#";
|
||||||
private static final String ASTERISK = "* "; // Note the blank space after asterisk!
|
private static final String ASTERISK = "* "; // Note the blank space after asterisk!
|
||||||
|
|
||||||
// private static final Pattern EDITION_AFTER_CARD_NAME = Pattern.compile("([\\d]{1,2})?\\s*([a-zA-Z',\\/\\-\\s]+)\\s*((\\(|\\[)([a-zA-Z0-9]{3})(\\)|\\])\\s*)?([\\d]{1,3})?");
|
|
||||||
|
|
||||||
// Core Matching Patterns (initialised in Constructor)
|
// Core Matching Patterns (initialised in Constructor)
|
||||||
public static final String REGRP_DECKNAME = "deckName";
|
public static final String REGRP_DECKNAME = "deckName";
|
||||||
public static final String REX_DECK_NAME =
|
public static final String REX_DECK_NAME =
|
||||||
@@ -157,9 +153,15 @@ public class DeckRecognizer {
|
|||||||
REGRP_DECKNAME);
|
REGRP_DECKNAME);
|
||||||
public static final Pattern DECK_NAME_PATTERN = Pattern.compile(REX_DECK_NAME, Pattern.CASE_INSENSITIVE);
|
public static final Pattern DECK_NAME_PATTERN = Pattern.compile(REX_DECK_NAME, Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
public static final String REGRP_NOCARD = "token";
|
public static final String REGRP_TOKEN = "token";
|
||||||
public static final String REX_NOCARD = String.format("^(?<pre>[^a-zA-Z]*)\\s*(?<title>(\\w+[:]\\s*))?(?<%s>[a-zA-Z]+)(?<post>[^a-zA-Z]*)?$", REGRP_NOCARD);
|
public static final String REX_NOCARD = String.format("^(?<pre>[^a-zA-Z]*)\\s*(?<title>(\\w+[:]\\s*))?(?<%s>[a-zA-Z]+)(?<post>[^a-zA-Z]*)?$", REGRP_TOKEN);
|
||||||
|
public static final String REX_CMC = String.format("^(?<pre>[^a-zA-Z]*)\\s*(?<%s>(C(M)?C(\\s)?\\d{1,2}))(?<post>[^\\d]*)?$", REGRP_TOKEN);
|
||||||
|
public static final String REX_RARITY = String.format("^(?<pre>[^a-zA-Z]*)\\s*(?<%s>((un)?common|(mythic)?\\s*(rare)?|land))(?<post>[^a-zA-Z]*)?$", REGRP_TOKEN);
|
||||||
|
public static final String REX_COLOUR = String.format("^(?<pre>[^a-zA-Z]*)\\s*(?<%s>(white|blue|black|red|green|colorless))(?<post>[^a-zA-Z]*)?$", REGRP_TOKEN);
|
||||||
public static final Pattern NONCARD_PATTERN = Pattern.compile(REX_NOCARD, Pattern.CASE_INSENSITIVE);
|
public static final Pattern NONCARD_PATTERN = Pattern.compile(REX_NOCARD, Pattern.CASE_INSENSITIVE);
|
||||||
|
public static final Pattern CMC_PATTERN = Pattern.compile(REX_CMC, Pattern.CASE_INSENSITIVE);
|
||||||
|
public static final Pattern CARD_RARITY_PATTERN = Pattern.compile(REX_RARITY, Pattern.CASE_INSENSITIVE);
|
||||||
|
public static final Pattern MANA_PATTERN = Pattern.compile(REX_COLOUR, Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
public static final String REGRP_SET = "setcode";
|
public static final String REGRP_SET = "setcode";
|
||||||
public static final String REGRP_COLLNR = "collnr";
|
public static final String REGRP_COLLNR = "collnr";
|
||||||
@@ -170,61 +172,69 @@ public class DeckRecognizer {
|
|||||||
public static final String REX_SET_CODE = String.format("(?<%s>[a-zA-Z0-9_]{2,7})", REGRP_SET);
|
public static final String REX_SET_CODE = String.format("(?<%s>[a-zA-Z0-9_]{2,7})", REGRP_SET);
|
||||||
public static final String REX_COLL_NUMBER = String.format("(?<%s>\\*?[0-9A-Z]+\\S?[A-Z]*)", REGRP_COLLNR);
|
public static final String REX_COLL_NUMBER = String.format("(?<%s>\\*?[0-9A-Z]+\\S?[A-Z]*)", REGRP_COLLNR);
|
||||||
public static final String REX_CARD_COUNT = String.format("(?<%s>[\\d]{1,2})(?<mult>x)?", REGRP_CARDNO);
|
public static final String REX_CARD_COUNT = String.format("(?<%s>[\\d]{1,2})(?<mult>x)?", REGRP_CARDNO);
|
||||||
|
|
||||||
// EXTRA
|
// EXTRA
|
||||||
public static final String REGRP_FOIL_GFISH = "foil";
|
public static final String REGRP_FOIL_GFISH = "foil";
|
||||||
private static final String REX_FOIL_MTGGOLDFISH = String.format(
|
private static final String REX_FOIL_MTGGOLDFISH = String.format(
|
||||||
"(?<%s>\\(F\\))?", REGRP_FOIL_GFISH);
|
"(?<%s>\\(F\\))?", REGRP_FOIL_GFISH);
|
||||||
|
|
||||||
// 1. Card-Set Request (Amount?, CardName, Set)
|
// 1. Card-Set Request (Amount?, CardName, Set)
|
||||||
public static final String REX_CARD_SET_REQUEST = String.format(
|
public static final String REX_CARD_SET_REQUEST = String.format(
|
||||||
"(%s\\s)?\\s*%s\\s*(\\s|\\||\\(|\\[|\\{)%s(\\s|\\)|\\]|\\})?\\s*%s",
|
"(%s\\s)?\\s*%s\\s*(\\s|\\||\\(|\\[|\\{)%s(\\s|\\)|\\]|\\})?\\s*%s",
|
||||||
REX_CARD_COUNT, REX_CARD_NAME, REX_SET_CODE, REX_FOIL_MTGGOLDFISH);
|
REX_CARD_COUNT, REX_CARD_NAME, REX_SET_CODE, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern CARD_SET_PATTERN = Pattern.compile(REX_CARD_SET_REQUEST);
|
public static final Pattern CARD_SET_PATTERN = Pattern.compile(REX_CARD_SET_REQUEST);
|
||||||
|
|
||||||
// 2. Set-Card Request (Amount?, Set, CardName)
|
// 2. Set-Card Request (Amount?, Set, CardName)
|
||||||
public static final String REX_SET_CARD_REQUEST = String.format(
|
public static final String REX_SET_CARD_REQUEST = String.format(
|
||||||
"(%s\\s)?\\s*(\\(|\\[|\\{)?%s(\\s+|\\)|\\]|\\}|\\|)\\s*%s\\s*%s\\s*",
|
"(%s\\s)?\\s*(\\(|\\[|\\{)?%s(\\s+|\\)|\\]|\\}|\\|)\\s*%s\\s*%s\\s*",
|
||||||
REX_CARD_COUNT, REX_SET_CODE, REX_CARD_NAME, REX_FOIL_MTGGOLDFISH);
|
REX_CARD_COUNT, REX_SET_CODE, REX_CARD_NAME, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern SET_CARD_PATTERN = Pattern.compile(REX_SET_CARD_REQUEST);
|
public static final Pattern SET_CARD_PATTERN = Pattern.compile(REX_SET_CARD_REQUEST);
|
||||||
|
|
||||||
// 3. Full-Request (Amount?, CardName, Set, Collector Number|Art Index) - MTGArena Format
|
// 3. Full-Request (Amount?, CardName, Set, Collector Number|Art Index) - MTGArena Format
|
||||||
public static final String REX_FULL_REQUEST_CARD_SET = String.format(
|
public static final String REX_FULL_REQUEST_CARD_SET = String.format(
|
||||||
"(%s\\s)?\\s*%s\\s*(\\||\\(|\\[|\\{|\\s)%s(\\s|\\)|\\]|\\})?\\s+%s\\s*%s\\s*",
|
"(%s\\s)?\\s*%s\\s*(\\||\\(|\\[|\\{|\\s)%s(\\s|\\)|\\]|\\})?\\s+%s\\s*%s\\s*",
|
||||||
REX_CARD_COUNT, REX_CARD_NAME, REX_SET_CODE, REX_COLL_NUMBER, REX_FOIL_MTGGOLDFISH);
|
REX_CARD_COUNT, REX_CARD_NAME, REX_SET_CODE, REX_COLL_NUMBER, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern CARD_SET_COLLNO_PATTERN = Pattern.compile(REX_FULL_REQUEST_CARD_SET);
|
public static final Pattern CARD_SET_COLLNO_PATTERN = Pattern.compile(REX_FULL_REQUEST_CARD_SET);
|
||||||
|
|
||||||
// 4. Full-Request (Amount?, Set, CardName, Collector Number|Art Index) - Alternative for flexibility
|
// 4. Full-Request (Amount?, Set, CardName, Collector Number|Art Index) - Alternative for flexibility
|
||||||
public static final String REX_FULL_REQUEST_SET_CARD = String.format(
|
public static final String REX_FULL_REQUEST_SET_CARD = String.format(
|
||||||
"^(%s\\s)?\\s*(\\(|\\[|\\{)?%s(\\s+|\\)|\\]|\\}|\\|)\\s*%s\\s+%s\\s*%s$",
|
"^(%s\\s)?\\s*(\\(|\\[|\\{)?%s(\\s+|\\)|\\]|\\}|\\|)\\s*%s\\s+%s\\s*%s$",
|
||||||
REX_CARD_COUNT, REX_SET_CODE, REX_CARD_NAME, REX_COLL_NUMBER, REX_FOIL_MTGGOLDFISH);
|
REX_CARD_COUNT, REX_SET_CODE, REX_CARD_NAME, REX_COLL_NUMBER, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern SET_CARD_COLLNO_PATTERN = Pattern.compile(REX_FULL_REQUEST_SET_CARD);
|
public static final Pattern SET_CARD_COLLNO_PATTERN = Pattern.compile(REX_FULL_REQUEST_SET_CARD);
|
||||||
|
|
||||||
// 5. (MTGGoldfish mostly) (Amount?, Card Name, <Collector Number>, Set)
|
// 5. (MTGGoldfish mostly) (Amount?, Card Name, <Collector Number>, Set)
|
||||||
public static final String REX_FULL_REQUEST_CARD_COLLNO_SET = String.format(
|
public static final String REX_FULL_REQUEST_CARD_COLLNO_SET = String.format(
|
||||||
"^(%s\\s)?\\s*%s\\s+(\\<%s\\>)\\s*(\\(|\\[|\\{)?%s(\\s+|\\)|\\]|\\}|\\|)\\s*%s$",
|
"^(%s\\s)?\\s*%s\\s+(\\<%s\\>)\\s*(\\(|\\[|\\{)?%s(\\s+|\\)|\\]|\\}|\\|)\\s*%s$",
|
||||||
REX_CARD_COUNT, REX_CARD_NAME, REX_COLL_NUMBER, REX_SET_CODE, REX_FOIL_MTGGOLDFISH);
|
REX_CARD_COUNT, REX_CARD_NAME, REX_COLL_NUMBER, REX_SET_CODE, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern CARD_COLLNO_SET_PATTERN = Pattern.compile(REX_FULL_REQUEST_CARD_COLLNO_SET);
|
public static final Pattern CARD_COLLNO_SET_PATTERN = Pattern.compile(REX_FULL_REQUEST_CARD_COLLNO_SET);
|
||||||
|
|
||||||
// 6. XMage format (Amount?, [Set:Collector Number] Card Name)
|
// 6. XMage format (Amount?, [Set:Collector Number] Card Name)
|
||||||
public static final String REX_FULL_REQUEST_XMAGE = String.format(
|
public static final String REX_FULL_REQUEST_XMAGE = String.format(
|
||||||
"^(%s\\s)?\\s*(\\[)?%s:%s(\\])\\s+%s\\s*%s$",
|
"^(%s\\s)?\\s*(\\[)?%s:%s(\\])\\s+%s\\s*%s$",
|
||||||
REX_CARD_COUNT, REX_SET_CODE, REX_COLL_NUMBER, REX_CARD_NAME, REX_FOIL_MTGGOLDFISH);
|
REX_CARD_COUNT, REX_SET_CODE, REX_COLL_NUMBER, REX_CARD_NAME, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern SET_COLLNO_CARD_XMAGE_PATTERN = Pattern.compile(REX_FULL_REQUEST_XMAGE);
|
public static final Pattern SET_COLLNO_CARD_XMAGE_PATTERN = Pattern.compile(REX_FULL_REQUEST_XMAGE);
|
||||||
|
|
||||||
// 7. Card-Only Request (Amount?)
|
// 7. Card-Only Request (Amount?)
|
||||||
public static final String REX_CARDONLY = String.format(
|
public static final String REX_CARDONLY = String.format(
|
||||||
"(%s\\s)?\\s*%s\\s*%s", REX_CARD_COUNT, REX_CARD_NAME, REX_FOIL_MTGGOLDFISH);
|
"(%s\\s)?\\s*%s\\s*%s", REX_CARD_COUNT, REX_CARD_NAME, REX_FOIL_MTGGOLDFISH);
|
||||||
public static final Pattern CARD_ONLY_PATTERN = Pattern.compile(REX_CARDONLY);
|
public static final Pattern CARD_ONLY_PATTERN = Pattern.compile(REX_CARDONLY);
|
||||||
|
|
||||||
|
|
||||||
// CoreTypes (to recognise Tokens of type CardType
|
// CoreTypes (to recognise Tokens of type CardType
|
||||||
private static CharSequence[] CARD_TYPES = allCardTypes();
|
private static final CharSequence[] CARD_TYPES = allCardTypes();
|
||||||
|
|
||||||
private static final CharSequence[] DECK_SECTION_NAMES = {"avatar", "commander",
|
private static final CharSequence[] DECK_SECTION_NAMES = {"avatar", "commander",
|
||||||
"schemes", "conspiracy", "planes", "deck",
|
"schemes", "conspiracy", "planes", "deck",
|
||||||
"main", "card", "mainboard", "side", "sideboard"};
|
"main", "card", "mainboard", "side", "sideboard"};
|
||||||
|
|
||||||
|
private static CharSequence[] allCardTypes(){
|
||||||
|
List<String> cardTypesList = new ArrayList<>();
|
||||||
|
// CoreTypesNames
|
||||||
|
List<CardType.CoreType> coreTypes = Lists.newArrayList(CardType.CoreType.values());
|
||||||
|
for (CardType.CoreType coreType : coreTypes)
|
||||||
|
cardTypesList.add(coreType.name().toLowerCase());
|
||||||
|
// Manual Additions:
|
||||||
|
// NOTE: "sorceries" is also included as it can be found in exported deck, even if it's incorrect.
|
||||||
|
// Example: https://deckstats.net/decks/70852/556925-artifacts/en - see Issue 1010
|
||||||
|
cardTypesList.add("sorceries"); // Sorcery is the only name with different plural form
|
||||||
|
cardTypesList.add("aura"); // in case.
|
||||||
|
cardTypesList.add("mana"); // "Mana" (see Issue 1010)
|
||||||
|
cardTypesList.add("spell");
|
||||||
|
cardTypesList.add("other spell");
|
||||||
|
cardTypesList.add("planeswalker");
|
||||||
|
return cardTypesList.toArray(new CharSequence[cardTypesList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
private final CardDb db;
|
private final CardDb db;
|
||||||
private final CardDb altDb;
|
private final CardDb altDb;
|
||||||
private Date releaseDateConstraint = null;
|
private Date releaseDateConstraint = null;
|
||||||
@@ -244,32 +254,33 @@ public class DeckRecognizer {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
final char smartQuote = (char) 8217;
|
final char smartQuote = (char) 8217;
|
||||||
String line = rawLine.trim().replace(smartQuote, '\'');
|
String refLine = rawLine.trim().replace(smartQuote, '\'');
|
||||||
// Remove any link (e.g. Markdown Export format from TappedOut)
|
// Remove any link (e.g. Markdown Export format from TappedOut)
|
||||||
line = purgeAllLinks(line);
|
refLine = purgeAllLinks(refLine);
|
||||||
|
|
||||||
if (StringUtils.startsWith(line, LINE_COMMENT_DELIMITER_OR_MD_HEADER))
|
String line;
|
||||||
line = line.replaceAll(LINE_COMMENT_DELIMITER_OR_MD_HEADER, "");
|
if (StringUtils.startsWith(refLine, LINE_COMMENT_DELIMITER_OR_MD_HEADER))
|
||||||
|
line = refLine.replaceAll(LINE_COMMENT_DELIMITER_OR_MD_HEADER, "");
|
||||||
|
else
|
||||||
|
line = refLine.trim(); // Remove any trailing formatting
|
||||||
|
|
||||||
// Some websites export split card names with a single slash. Replace with double slash.
|
// Some websites export split card names with a single slash. Replace with double slash.
|
||||||
line = SEARCH_SINGLE_SLASH.matcher(line).replaceFirst(" // ");
|
line = SEARCH_SINGLE_SLASH.matcher(line).replaceFirst(" // ");
|
||||||
line = line.trim(); // Remove any trailing formattings
|
if (StringUtils.startsWith(line, ASTERISK)) // markdown lists (tappedout md export)
|
||||||
if (StringUtils.startsWith(line, DOUBLE_SLASH))
|
|
||||||
line = line.substring(2); // In this case, we are sure to support split cards
|
|
||||||
|
|
||||||
if (StringUtils.startsWith(line, ASTERISK))
|
|
||||||
line = line.substring(2);
|
line = line.substring(2);
|
||||||
|
|
||||||
// In some format, cards in the Sideboard have an SB: prefix.
|
// In some format, cards in the Sideboard have an SB: prefix.
|
||||||
// We won't support that as it is, due to how the recognition process works, so a section must be
|
// We won't support that as it is, due to how the recognition process works, so a section must be
|
||||||
// specified (e.g. Sideboard or Side) to allow that those cards will be imported in sideboard.
|
// specified (e.g. Sideboard or Side) to allow that those cards will be imported in sideboard.
|
||||||
if (StringUtils.startsWith(line.trim(), "SB:"))
|
if (StringUtils.startsWith(line.trim(), "SB:"))
|
||||||
line = StringUtils.replace(line, "SB:", "").trim();
|
//refLine = StringUtils.replace(refLine, "SB:", "").trim();
|
||||||
|
return new Token(TokenType.COMMENT, 0, line);
|
||||||
|
|
||||||
Token result = recogniseCardToken(line);
|
Token result = recogniseCardToken(line);
|
||||||
if (result == null)
|
if (result == null)
|
||||||
result = recogniseNonCardToken(line);
|
result = recogniseNonCardToken(line);
|
||||||
return result != null ? result : new Token(TokenType.UNKNOWN_TEXT, 0, line);
|
return result != null ? result : StringUtils.startsWith(refLine, DOUBLE_SLASH) || StringUtils.startsWith(refLine, LINE_COMMENT_DELIMITER_OR_MD_HEADER) ?
|
||||||
|
new Token(TokenType.COMMENT, 0, refLine) : new Token(TokenType.UNKNOWN_TEXT, 0, refLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String purgeAllLinks(String line){
|
public static String purgeAllLinks(String line){
|
||||||
@@ -288,9 +299,6 @@ public class DeckRecognizer {
|
|||||||
public Token recogniseCardToken(final String text) {
|
public Token recogniseCardToken(final String text) {
|
||||||
String line = text.trim();
|
String line = text.trim();
|
||||||
Token uknonwnCardToken = null;
|
Token uknonwnCardToken = null;
|
||||||
|
|
||||||
// TODO: recognize format: http://topdeck.ru/forum/index.php?showtopic=12711
|
|
||||||
// @leriomaggio: DONE!
|
|
||||||
List<Matcher> cardMatchers = getRegExMatchers(line);
|
List<Matcher> cardMatchers = getRegExMatchers(line);
|
||||||
for (Matcher matcher : cardMatchers) {
|
for (Matcher matcher : cardMatchers) {
|
||||||
String cardName = getRexGroup(matcher, REGRP_CARD);
|
String cardName = getRexGroup(matcher, REGRP_CARD);
|
||||||
@@ -313,7 +321,7 @@ public class DeckRecognizer {
|
|||||||
int artIndex;
|
int artIndex;
|
||||||
try {
|
try {
|
||||||
artIndex = Integer.parseInt(collectorNumber);
|
artIndex = Integer.parseInt(collectorNumber);
|
||||||
} catch (NumberFormatException ex){
|
} catch (NumberFormatException ex) {
|
||||||
artIndex = IPaperCard.NO_ART_INDEX;
|
artIndex = IPaperCard.NO_ART_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,19 +352,31 @@ public class DeckRecognizer {
|
|||||||
}
|
}
|
||||||
// ok so we can simply ignore everything but card name - as set code does not exist
|
// ok so we can simply ignore everything but card name - as set code does not exist
|
||||||
// At this stage, we know the card name exists in the DB so a Card MUST be found
|
// At this stage, we know the card name exists in the DB so a Card MUST be found
|
||||||
// unless it is illegal for current format.
|
// unless it is illegal for current format or invalid with selected date.
|
||||||
// In that case, an illegalCard token will be returned!
|
PaperCard pc = null;
|
||||||
PaperCard pc = this.getCardFromSupportedEditions(cr.cardName, cr.isFoil);
|
if (hasGameFormatConstraints()) {
|
||||||
if (pc != null){
|
Predicate<PaperCard> filter = (Predicate<PaperCard>) this.db.isLegal(this.allowedSetCodes);
|
||||||
if (isIllegalCardInDeckFormat(pc))
|
pc = this.getCardFromSupportedEditions(cr.cardName, cr.isFoil, filter);
|
||||||
|
}
|
||||||
|
if (pc == null)
|
||||||
|
pc = this.getCardFromSupportedEditions(cr.cardName, cr.isFoil, null);
|
||||||
|
|
||||||
|
if (pc != null) {
|
||||||
|
if (isIllegalSetInGameFormat(pc.getEdition()) || isIllegalCardInDeckFormat(pc))
|
||||||
return Token.IllegalCard(pc.getName(), pc.getEdition(), cardCount);
|
return Token.IllegalCard(pc.getName(), pc.getEdition(), cardCount);
|
||||||
|
CardEdition edition = StaticData.instance().getCardEdition(pc.getEdition());
|
||||||
|
if (isNotCompliantWithReleaseDateRestrictions(edition))
|
||||||
|
return Token.InvalidCard(pc.getName(), pc.getEdition(), cardCount);
|
||||||
return Token.KnownCard(pc, cardCount);
|
return Token.KnownCard(pc, cardCount);
|
||||||
}
|
}
|
||||||
return Token.IllegalCard(cardName, "", cardCount);
|
|
||||||
}
|
}
|
||||||
return uknonwnCardToken; // either null or unknown card
|
return uknonwnCardToken; // either null or unknown card
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasGameFormatConstraints() {
|
||||||
|
return this.allowedSetCodes != null && this.allowedSetCodes.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private String getRexGroup(Matcher matcher, String groupName){
|
private String getRexGroup(Matcher matcher, String groupName){
|
||||||
String rexGroup;
|
String rexGroup;
|
||||||
try{
|
try{
|
||||||
@@ -368,7 +388,7 @@ public class DeckRecognizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIllegalCardInDeckFormat(PaperCard pc) {
|
private boolean isIllegalCardInDeckFormat(PaperCard pc) {
|
||||||
return this.deckFormat != null && !deckFormat.isLegalCard(pc);
|
return this.deckFormat != null && !this.deckFormat.isLegalCard(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIllegalSetInGameFormat(String setCode) {
|
private boolean isIllegalSetInGameFormat(String setCode) {
|
||||||
@@ -438,79 +458,119 @@ public class DeckRecognizer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PaperCard getCardFromSupportedEditions(final String cardName, boolean isFoil){
|
private PaperCard getCardFromSupportedEditions(final String cardName, boolean isFoil,
|
||||||
Predicate<PaperCard> filter = null;
|
Predicate<PaperCard> filter){
|
||||||
if (this.allowedSetCodes != null && this.allowedSetCodes.size() > 0)
|
|
||||||
filter = (Predicate<PaperCard>) this.db.isLegal(this.allowedSetCodes);
|
|
||||||
String reqInfo = CardDb.CardRequest.compose(cardName, isFoil);
|
String reqInfo = CardDb.CardRequest.compose(cardName, isFoil);
|
||||||
|
CardDb targetDb = this.db.contains(cardName) ? this.db : this.altDb;
|
||||||
PaperCard result;
|
PaperCard result;
|
||||||
if (this.releaseDateConstraint != null){
|
if (this.releaseDateConstraint != null) {
|
||||||
result = this.db.getCardFromEditionsReleasedBefore(reqInfo,
|
result = targetDb.getCardFromEditionsReleasedBefore(reqInfo,
|
||||||
this.releaseDateConstraint, filter);
|
this.releaseDateConstraint, filter);
|
||||||
if (result == null)
|
if (result == null)
|
||||||
result = this.altDb.getCardFromEditionsReleasedBefore(reqInfo,
|
result = targetDb.getCardFromEditions(reqInfo, filter);
|
||||||
this.releaseDateConstraint, filter);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result = this.db.getCardFromEditions(reqInfo, filter);
|
|
||||||
if (result == null)
|
|
||||||
result = this.altDb.getCardFromEditions(reqInfo, filter);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
result = targetDb.getCardFromEditions(reqInfo, filter);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Token recogniseNonCardToken(final String text) {
|
public Token recogniseNonCardToken(final String text) {
|
||||||
if (isDeckSectionName(text)) {
|
if (isDeckSectionName(text)) {
|
||||||
String tokenText = getNonCardTokenText(text.toLowerCase().trim());
|
String tokenText = nonCardTokenMatch(text);
|
||||||
return Token.DeckSection(tokenText);
|
return Token.DeckSection(tokenText);
|
||||||
}
|
}
|
||||||
if (isCardType(text)) {
|
if (isCardRarity(text)){
|
||||||
String tokenText = getNonCardTokenText(text);
|
String tokenText = cardRarityTokenMatch(text);
|
||||||
|
return new Token(TokenType.CARD_RARITY, tokenText);
|
||||||
|
}
|
||||||
|
if (isCardCMC(text)){
|
||||||
|
String tokenText = cardCMCTokenMatch(text);
|
||||||
|
return new Token(TokenType.CARD_CMC, tokenText);
|
||||||
|
}
|
||||||
|
if (isCardType(text)){
|
||||||
|
String tokenText = nonCardTokenMatch(text);
|
||||||
return new Token(TokenType.CARD_TYPE, tokenText);
|
return new Token(TokenType.CARD_TYPE, tokenText);
|
||||||
}
|
}
|
||||||
|
if(isManaToken(text)){
|
||||||
|
String tokenText = manaTokenMatch(text);
|
||||||
|
return new Token(TokenType.MANA_COLOUR, tokenText);
|
||||||
|
}
|
||||||
if (isDeckName(text)) {
|
if (isDeckName(text)) {
|
||||||
String deckName = getDeckName(text);
|
String deckName = deckNameMatch(text);
|
||||||
return new Token(TokenType.DECK_NAME, deckName);
|
return new Token(TokenType.DECK_NAME, deckName);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getNonCardTokenText(final String line){
|
/* -----------------------------------------------------------------------------
|
||||||
Matcher noncardMatcher = NONCARD_PATTERN.matcher(line);
|
Note: Card types, CMC, and Rarity Tokens are **only** used for style formatting
|
||||||
if (!noncardMatcher.matches())
|
in the Import Editor. This won't affect the import process in any way.
|
||||||
return "";
|
The use of this token has been borrowed by Deckstats.net format export.
|
||||||
return noncardMatcher.group(REGRP_NOCARD);
|
----------------------------------------------------------------------------- */
|
||||||
}
|
|
||||||
|
|
||||||
private static CharSequence[] allCardTypes(){
|
|
||||||
List<String> cardTypesList = new ArrayList<>();
|
|
||||||
// CoreTypesNames
|
|
||||||
List<CardType.CoreType> coreTypes = Lists.newArrayList(CardType.CoreType.values());
|
|
||||||
for (CardType.CoreType coreType : coreTypes)
|
|
||||||
cardTypesList.add(coreType.name().toLowerCase());
|
|
||||||
// Manual Additions:
|
|
||||||
// NOTE: "sorceries" is also included as it can be found in exported deck, even if it's incorrect.
|
|
||||||
// Example: https://deckstats.net/decks/70852/556925-artifacts/en - see Issue 1010
|
|
||||||
cardTypesList.add("sorceries"); // Sorcery is the only name with different plural form
|
|
||||||
cardTypesList.add("aura"); // in case.
|
|
||||||
cardTypesList.add("mana"); // "Mana" (see Issue 1010)
|
|
||||||
cardTypesList.add("spell");
|
|
||||||
cardTypesList.add("other spell");
|
|
||||||
cardTypesList.add("planeswalker");
|
|
||||||
return cardTypesList.toArray(new CharSequence[cardTypesList.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Card types recognition is ONLY used for style formatting in the Import Editor
|
|
||||||
// This won't affect the import process of cards in any way !-)
|
|
||||||
public static boolean isCardType(final String lineAsIs) {
|
public static boolean isCardType(final String lineAsIs) {
|
||||||
if (lineAsIs == null)
|
String nonCardToken = nonCardTokenMatch(lineAsIs);
|
||||||
|
if (nonCardToken == null)
|
||||||
return false;
|
return false;
|
||||||
String line = lineAsIs.toLowerCase().trim();
|
return StringUtils.containsAny(nonCardToken.toLowerCase(), CARD_TYPES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCardRarity(final String lineAsIs){
|
||||||
|
return cardRarityTokenMatch(lineAsIs) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCardCMC(final String lineAsIs) {
|
||||||
|
return cardCMCTokenMatch(lineAsIs) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isManaToken(final String lineAsIs) {
|
||||||
|
return manaTokenMatch(lineAsIs) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDeckSectionName(final String lineAsIs) {
|
||||||
|
String nonCardToken = nonCardTokenMatch(lineAsIs);
|
||||||
|
if (nonCardToken == null)
|
||||||
|
return false;
|
||||||
|
return StringUtils.equalsAnyIgnoreCase(nonCardToken, DECK_SECTION_NAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nonCardTokenMatch(final String lineAsIs){
|
||||||
|
if (lineAsIs == null)
|
||||||
|
return null;
|
||||||
|
String line = lineAsIs.trim();
|
||||||
Matcher noncardMatcher = NONCARD_PATTERN.matcher(line);
|
Matcher noncardMatcher = NONCARD_PATTERN.matcher(line);
|
||||||
if (!noncardMatcher.matches())
|
if (!noncardMatcher.matches())
|
||||||
return false;
|
return null;
|
||||||
String nonCardToken = noncardMatcher.group(REGRP_NOCARD);
|
return noncardMatcher.group(REGRP_TOKEN);
|
||||||
return StringUtils.containsAny(nonCardToken, CARD_TYPES);
|
}
|
||||||
|
|
||||||
|
private static String cardRarityTokenMatch(final String lineAsIs){
|
||||||
|
if (lineAsIs == null)
|
||||||
|
return null;
|
||||||
|
String line = lineAsIs.trim();
|
||||||
|
Matcher cardRarityMatcher = CARD_RARITY_PATTERN.matcher(line);
|
||||||
|
if (!cardRarityMatcher.matches())
|
||||||
|
return null;
|
||||||
|
return cardRarityMatcher.group(REGRP_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String cardCMCTokenMatch(final String lineAsIs){
|
||||||
|
if (lineAsIs == null)
|
||||||
|
return null;
|
||||||
|
String line = lineAsIs.trim();
|
||||||
|
Matcher cardCMCmatcher = CMC_PATTERN.matcher(line);
|
||||||
|
if (!cardCMCmatcher.matches())
|
||||||
|
return null;
|
||||||
|
return cardCMCmatcher.group(REGRP_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String manaTokenMatch(final String lineAsIs){
|
||||||
|
if (lineAsIs == null)
|
||||||
|
return null;
|
||||||
|
String line = lineAsIs.trim();
|
||||||
|
Matcher manaMatcher = MANA_PATTERN.matcher(line);
|
||||||
|
if (!manaMatcher.matches())
|
||||||
|
return null;
|
||||||
|
return manaMatcher.group(REGRP_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDeckName(final String lineAsIs) {
|
public static boolean isDeckName(final String lineAsIs) {
|
||||||
@@ -518,11 +578,10 @@ public class DeckRecognizer {
|
|||||||
return false;
|
return false;
|
||||||
final String line = lineAsIs.trim();
|
final String line = lineAsIs.trim();
|
||||||
final Matcher deckNameMatcher = DECK_NAME_PATTERN.matcher(line);
|
final Matcher deckNameMatcher = DECK_NAME_PATTERN.matcher(line);
|
||||||
boolean matches = deckNameMatcher.matches();
|
return deckNameMatcher.matches();
|
||||||
return matches;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDeckName(final String text) {
|
public static String deckNameMatch(final String text) {
|
||||||
if (text == null)
|
if (text == null)
|
||||||
return "";
|
return "";
|
||||||
String line = text.trim();
|
String line = text.trim();
|
||||||
@@ -532,17 +591,6 @@ public class DeckRecognizer {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDeckSectionName(final String text) {
|
|
||||||
if (text == null)
|
|
||||||
return false;
|
|
||||||
String line = text.toLowerCase().trim();
|
|
||||||
Matcher noncardMatcher = NONCARD_PATTERN.matcher(line);
|
|
||||||
if (!noncardMatcher.matches())
|
|
||||||
return false;
|
|
||||||
String nonCardToken = noncardMatcher.group(REGRP_NOCARD);
|
|
||||||
return StringUtils.equalsAnyIgnoreCase(nonCardToken, DECK_SECTION_NAMES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDateConstraint(int year, int month) {
|
public void setDateConstraint(int year, int month) {
|
||||||
Calendar ca = Calendar.getInstance();
|
Calendar ca = Calendar.getInstance();
|
||||||
ca.set(year, month, 1);
|
ca.set(year, month, 1);
|
||||||
|
|||||||
@@ -130,35 +130,35 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Red Green Aggro");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Red Green Aggro");
|
||||||
|
|
||||||
matchingDeckName = "Name: Red Green Aggro";
|
matchingDeckName = "Name: Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Red Green Aggro");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Red Green Aggro");
|
||||||
|
|
||||||
matchingDeckName = "Name:Red Green Aggro";
|
matchingDeckName = "Name:Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Red Green Aggro");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Red Green Aggro");
|
||||||
|
|
||||||
matchingDeckName = "Name: Red Green Aggro";
|
matchingDeckName = "Name: Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Red Green Aggro");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Red Green Aggro");
|
||||||
|
|
||||||
matchingDeckName = "Deck:Red Green Aggro";
|
matchingDeckName = "Deck:Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Red Green Aggro");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Red Green Aggro");
|
||||||
|
|
||||||
// Case Insensitive
|
// Case Insensitive
|
||||||
matchingDeckName = "deck: Red Green Aggro";
|
matchingDeckName = "deck: Red Green Aggro";
|
||||||
@@ -166,7 +166,7 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Red Green Aggro");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Red Green Aggro");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Red Green Aggro");
|
||||||
|
|
||||||
// Forge deck format
|
// Forge deck format
|
||||||
matchingDeckName = "Name=Sliver Overlord (Commander)";
|
matchingDeckName = "Name=Sliver Overlord (Commander)";
|
||||||
@@ -174,38 +174,38 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertTrue(deckNameMatcher.matches());
|
assertTrue(deckNameMatcher.matches());
|
||||||
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
assertTrue(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Sliver Overlord (Commander)");
|
assertEquals(deckNameMatcher.group(DeckRecognizer.REGRP_DECKNAME), "Sliver Overlord (Commander)");
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "Sliver Overlord (Commander)");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "Sliver Overlord (Commander)");
|
||||||
|
|
||||||
// Failing Cases
|
// Failing Cases
|
||||||
matchingDeckName = ":Red Green Aggro";
|
matchingDeckName = ":Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertFalse(deckNameMatcher.matches());
|
assertFalse(deckNameMatcher.matches());
|
||||||
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "");
|
||||||
|
|
||||||
matchingDeckName = "Red Green Aggro";
|
matchingDeckName = "Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertFalse(deckNameMatcher.matches());
|
assertFalse(deckNameMatcher.matches());
|
||||||
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "");
|
||||||
|
|
||||||
matchingDeckName = "Name-Red Green Aggro";
|
matchingDeckName = "Name-Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertFalse(deckNameMatcher.matches());
|
assertFalse(deckNameMatcher.matches());
|
||||||
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "");
|
||||||
|
|
||||||
matchingDeckName = "Deck.Red Green Aggro";
|
matchingDeckName = "Deck.Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertFalse(deckNameMatcher.matches());
|
assertFalse(deckNameMatcher.matches());
|
||||||
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "");
|
||||||
|
|
||||||
matchingDeckName = ":Red Green Aggro";
|
matchingDeckName = ":Red Green Aggro";
|
||||||
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
deckNameMatcher = deckNamePattern.matcher(matchingDeckName);
|
||||||
assertFalse(deckNameMatcher.matches());
|
assertFalse(deckNameMatcher.matches());
|
||||||
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
assertFalse(DeckRecognizer.isDeckName(matchingDeckName));
|
||||||
assertEquals(DeckRecognizer.getDeckName(matchingDeckName), "");
|
assertEquals(DeckRecognizer.deckNameMatch(matchingDeckName), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test void testMatchDeckSectionNames(){
|
@Test void testMatchDeckSectionNames(){
|
||||||
@@ -249,6 +249,43 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertTrue(DeckRecognizer.isCardType(entry), "Fail on " + entry);
|
assertTrue(DeckRecognizer.isCardType(entry), "Fail on " + entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test void testOnlyContainingCardTypeWontMatchCardTypeToken(){
|
||||||
|
String[] nonCardTypes = new String[] {"Spell collection", "instants list",
|
||||||
|
"creatures elves", "land list"};
|
||||||
|
for (String nonCardTypeTokens : nonCardTypes)
|
||||||
|
assertFalse(DeckRecognizer.isCardType(nonCardTypeTokens), "Fail on "+nonCardTypeTokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testRarityTypeTokenMatch(){
|
||||||
|
String[] rarityTokens = new String[] {"Common", "uncommon", "rare", "mythic", "mythic rare", "land"};
|
||||||
|
for (String line : rarityTokens)
|
||||||
|
assertTrue(DeckRecognizer.isCardRarity(line), "Fail on "+line);
|
||||||
|
|
||||||
|
String[] nonRarityTokens = new String[] {"Common cards", "uncommon cards", "mythics", "rares", "lands"};
|
||||||
|
for (String line : nonRarityTokens)
|
||||||
|
assertFalse(DeckRecognizer.isCardRarity(line), "Fail on "+line);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testCMCTokenMatch(){
|
||||||
|
String[] cmcTokens = new String[] {"CC0", "CMC2", "CMC11", "cc3"};
|
||||||
|
for (String line : cmcTokens)
|
||||||
|
assertTrue(DeckRecognizer.isCardCMC(line), "Fail on "+line);
|
||||||
|
|
||||||
|
String[] nonCMCtokens = new String[] {"cc", "CMC", "cc322", "cmc111"};
|
||||||
|
for (String line : nonCMCtokens)
|
||||||
|
assertFalse(DeckRecognizer.isCardCMC(line), "Fail on "+line);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testManaTokenMatch(){
|
||||||
|
String[] cmcTokens = new String[] {"Blue", "red", "White", "// Black", " //Colorless----", "(green)"};
|
||||||
|
for (String line : cmcTokens)
|
||||||
|
assertTrue(DeckRecognizer.isManaToken(line), "Fail on " + line);
|
||||||
|
|
||||||
|
String[] nonCMCtokens = new String[] {"blues", "red more words", "mainboard"};
|
||||||
|
for (String line : nonCMCtokens)
|
||||||
|
assertFalse(DeckRecognizer.isManaToken(line), "Fail on "+line);
|
||||||
|
}
|
||||||
|
|
||||||
/*=============================
|
/*=============================
|
||||||
* TEST RECOGNISE NON-CARD LINES
|
* TEST RECOGNISE NON-CARD LINES
|
||||||
* =============================
|
* =============================
|
||||||
@@ -266,6 +303,13 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertEquals(t.getText(), "Lands");
|
assertEquals(t.getText(), "Lands");
|
||||||
assertEquals(t.getNumber(), 0);
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
// Test Token Types
|
||||||
|
t = recognizer.recogniseNonCardToken("//Land");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.CARD_RARITY);
|
||||||
|
assertEquals(t.getText(), "Land");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
t = recognizer.recogniseNonCardToken("[Main]");
|
t = recognizer.recogniseNonCardToken("[Main]");
|
||||||
assertNotNull(t);
|
assertNotNull(t);
|
||||||
assertEquals(t.getType(), TokenType.DECK_SECTION_NAME);
|
assertEquals(t.getType(), TokenType.DECK_SECTION_NAME);
|
||||||
@@ -301,6 +345,42 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertEquals(t.getType(), TokenType.DECK_NAME);
|
assertEquals(t.getType(), TokenType.DECK_NAME);
|
||||||
assertEquals(t.getText(), "OLDSCHOOL 93-94 Red Green Aggro by Zombies with JetPack");
|
assertEquals(t.getText(), "OLDSCHOOL 93-94 Red Green Aggro by Zombies with JetPack");
|
||||||
assertEquals(t.getNumber(), 0);
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
t = recognizer.recogniseNonCardToken("CMC0");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.CARD_CMC);
|
||||||
|
assertEquals(t.getText(), "CMC0");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
t = recognizer.recogniseNonCardToken("CC1");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.CARD_CMC);
|
||||||
|
assertEquals(t.getText(), "CC1");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
t = recognizer.recogniseNonCardToken("//Common");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.CARD_RARITY);
|
||||||
|
assertEquals(t.getText(), "Common");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
t = recognizer.recogniseNonCardToken("(mythic rare)");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.CARD_RARITY);
|
||||||
|
assertEquals(t.getText(), "mythic rare");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
t = recognizer.recogniseNonCardToken("//Blue");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.MANA_COLOUR);
|
||||||
|
assertEquals(t.getText(), "Blue");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
|
|
||||||
|
t = recognizer.recogniseNonCardToken("(Colorless)");
|
||||||
|
assertNotNull(t);
|
||||||
|
assertEquals(t.getType(), TokenType.MANA_COLOUR);
|
||||||
|
assertEquals(t.getText(), "Colorless");
|
||||||
|
assertEquals(t.getNumber(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*=============================
|
/*=============================
|
||||||
@@ -696,7 +776,6 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test void testInvalidMatchFullSetCardRequest(){
|
@Test void testInvalidMatchFullSetCardRequest(){
|
||||||
System.out.println(DeckRecognizer.REX_FULL_REQUEST_SET_CARD);
|
|
||||||
// NOTE: this will be matcher by another pattern
|
// NOTE: this will be matcher by another pattern
|
||||||
String invalidRequest = "1 Power Sink TMP"; // missing collector number
|
String invalidRequest = "1 Power Sink TMP"; // missing collector number
|
||||||
Matcher matcher = DeckRecognizer.SET_CARD_COLLNO_PATTERN.matcher(invalidRequest);
|
Matcher matcher = DeckRecognizer.SET_CARD_COLLNO_PATTERN.matcher(invalidRequest);
|
||||||
@@ -1242,6 +1321,274 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertNull(cardToken.getCard());
|
assertNull(cardToken.getCard());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test void testCardMatchWithDateANDGameFormatConstraints(){
|
||||||
|
StaticData magicDb = FModel.getMagicDb();
|
||||||
|
CardDb db = magicDb.getCommonCards();
|
||||||
|
CardDb altDb = magicDb.getVariantCards();
|
||||||
|
DeckRecognizer recognizer = new DeckRecognizer(db, altDb);
|
||||||
|
|
||||||
|
// Baseline - no constraints
|
||||||
|
assertEquals(db.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
|
||||||
|
String lineRequest = "2x Lightning Dragon";
|
||||||
|
Token cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
PaperCard tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Lightning Dragon");
|
||||||
|
assertEquals(tc.getEdition(), "VMA");
|
||||||
|
|
||||||
|
recognizer.setDateConstraint(2000, 0); // Jan 2000
|
||||||
|
// Setting Fantasy Constructed Game Format: Urza's Block Format (no promo)
|
||||||
|
List<String> allowedSets = Arrays.asList("USG", "ULG", "UDS");
|
||||||
|
recognizer.setGameFormatConstraint(allowedSets);
|
||||||
|
|
||||||
|
lineRequest = "2x Lightning Dragon|USG";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Lightning Dragon");
|
||||||
|
assertEquals(tc.getEdition(), "USG");
|
||||||
|
|
||||||
|
// Relaxing Constraint on Set
|
||||||
|
lineRequest = "2x Lightning Dragon";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Lightning Dragon");
|
||||||
|
assertEquals(tc.getEdition(), "USG"); // the latest available within set requested
|
||||||
|
|
||||||
|
// Now setting a tighter date constraint
|
||||||
|
recognizer.setDateConstraint(1998, 0); // Jan 1998
|
||||||
|
lineRequest = "2x Lightning Dragon|USG";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.INVALID_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
|
||||||
|
lineRequest = "2x Lightning Dragon";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.INVALID_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Lightning Dragon (USG)");
|
||||||
|
|
||||||
|
// Now relaxing date constraint but removing USG from allowed sets
|
||||||
|
// VMA release date: 2014-06-16
|
||||||
|
recognizer.setDateConstraint(2015, 0); // This will match VMA
|
||||||
|
recognizer.setGameFormatConstraint(Arrays.asList("ULG", "UDS"));
|
||||||
|
|
||||||
|
lineRequest = "2x Lightning Dragon|USG";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
|
||||||
|
lineRequest = "2x Lightning Dragon";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
|
||||||
|
// Now relaxing date constraint but removing USG from allowed sets
|
||||||
|
// VMA release date: 2014-06-16
|
||||||
|
recognizer.setDateConstraint(2015, 0); // This will match VMA
|
||||||
|
recognizer.setGameFormatConstraint(Arrays.asList("VMA", "ULG", "UDS"));
|
||||||
|
lineRequest = "2x Lightning Dragon";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Lightning Dragon");
|
||||||
|
assertEquals(tc.getEdition(), "VMA");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testCardMatchWithDateANDdeckFormatConstraints(){
|
||||||
|
StaticData magicDb = FModel.getMagicDb();
|
||||||
|
CardDb db = magicDb.getCommonCards();
|
||||||
|
CardDb altDb = magicDb.getVariantCards();
|
||||||
|
DeckRecognizer recognizer = new DeckRecognizer(db, altDb);
|
||||||
|
|
||||||
|
// Baseline - no constraints
|
||||||
|
assertEquals(db.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
|
||||||
|
|
||||||
|
String lineRequest = "Flash";
|
||||||
|
Token cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getNumber(), 1);
|
||||||
|
PaperCard tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Flash");
|
||||||
|
assertEquals(tc.getEdition(), "A25");
|
||||||
|
|
||||||
|
recognizer.setDateConstraint(2012, 0); // Jan 2012
|
||||||
|
recognizer.setDeckFormatConstraint(DeckFormat.TinyLeaders);
|
||||||
|
|
||||||
|
lineRequest = "Flash";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Flash (6ED)");
|
||||||
|
|
||||||
|
lineRequest = "2x Cancel";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Cancel");
|
||||||
|
assertEquals(tc.getEdition(), "M12"); // the latest within date constraint
|
||||||
|
|
||||||
|
lineRequest = "2x Cancel|M21";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.INVALID_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Cancel (M21)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testCardMatchWithGameANDdeckFormatConstraints(){
|
||||||
|
StaticData magicDb = FModel.getMagicDb();
|
||||||
|
CardDb db = magicDb.getCommonCards();
|
||||||
|
CardDb altDb = magicDb.getVariantCards();
|
||||||
|
DeckRecognizer recognizer = new DeckRecognizer(db, altDb);
|
||||||
|
|
||||||
|
// Baseline - no constraints
|
||||||
|
assertEquals(db.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
|
||||||
|
|
||||||
|
String lineRequest = "Flash";
|
||||||
|
Token cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getNumber(), 1);
|
||||||
|
PaperCard tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Flash");
|
||||||
|
assertEquals(tc.getEdition(), "A25");
|
||||||
|
|
||||||
|
recognizer.setGameFormatConstraint(Arrays.asList("MIR", "VIS", "WTH"));
|
||||||
|
recognizer.setDeckFormatConstraint(DeckFormat.TinyLeaders);
|
||||||
|
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Flash (MIR)");
|
||||||
|
|
||||||
|
lineRequest = "2x Femeref Knight";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Femeref Knight");
|
||||||
|
assertEquals(tc.getEdition(), "MIR");
|
||||||
|
|
||||||
|
lineRequest = "2x Incinerate";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertEquals(cardToken.getNumber(), 2);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Incinerate");
|
||||||
|
assertEquals(tc.getEdition(), "MIR");
|
||||||
|
|
||||||
|
lineRequest = "Noble Elephant";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST); // violating Deck format
|
||||||
|
assertEquals(cardToken.getNumber(), 1);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Noble Elephant (MIR)");
|
||||||
|
|
||||||
|
lineRequest = "Incinerate|ICE";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST); // violating Game format
|
||||||
|
assertEquals(cardToken.getNumber(), 1);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Incinerate (ICE)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testCardMatchWitDateANDgameANDdeckFormatConstraints(){
|
||||||
|
StaticData magicDb = FModel.getMagicDb();
|
||||||
|
CardDb db = magicDb.getCommonCards();
|
||||||
|
CardDb altDb = magicDb.getVariantCards();
|
||||||
|
DeckRecognizer recognizer = new DeckRecognizer(db, altDb);
|
||||||
|
|
||||||
|
// Baseline - no constraints
|
||||||
|
assertEquals(db.getCardArtPreference(), CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS);
|
||||||
|
|
||||||
|
String lineRequest = "Flash";
|
||||||
|
Token cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getNumber(), 1);
|
||||||
|
PaperCard tc = cardToken.getCard();
|
||||||
|
assertEquals(tc.getName(), "Flash");
|
||||||
|
assertEquals(tc.getEdition(), "A25");
|
||||||
|
|
||||||
|
recognizer.setGameFormatConstraint(Arrays.asList("MIR", "VIS", "WTH"));
|
||||||
|
recognizer.setDeckFormatConstraint(DeckFormat.TinyLeaders);
|
||||||
|
recognizer.setDateConstraint(1999, 2); // March '99
|
||||||
|
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Flash (MIR)");
|
||||||
|
|
||||||
|
lineRequest = "Ardent Militia";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.ILLEGAL_CARD_REQUEST); // illegal in deck format
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Ardent Militia (WTH)"); // within set constraints
|
||||||
|
|
||||||
|
lineRequest = "Buried Alive|UMA";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.INVALID_CARD_REQUEST); // illegal in game format
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Buried Alive (UMA)"); // within set constraints
|
||||||
|
|
||||||
|
lineRequest = "Buried Alive";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.LEGAL_CARD_REQUEST); // illegal in deck format
|
||||||
|
assertNotNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getCard().getName(), "Buried Alive");
|
||||||
|
assertEquals(cardToken.getCard().getEdition(), "WTH"); // within set constraints
|
||||||
|
|
||||||
|
recognizer.setDateConstraint(1997, 2); // March '97 - before WTH
|
||||||
|
lineRequest = "Buried Alive";
|
||||||
|
cardToken = recognizer.recogniseCardToken(lineRequest);
|
||||||
|
assertNotNull(cardToken);
|
||||||
|
assertEquals(cardToken.getType(), TokenType.INVALID_CARD_REQUEST);
|
||||||
|
assertNull(cardToken.getCard());
|
||||||
|
assertEquals(cardToken.getText(), "Buried Alive (WTH)");
|
||||||
|
}
|
||||||
|
|
||||||
/*==================================
|
/*==================================
|
||||||
* TEST RECOGNISE CARD EXTRA FORMATS
|
* TEST RECOGNISE CARD EXTRA FORMATS
|
||||||
* =================================
|
* =================================
|
||||||
@@ -1413,4 +1760,90 @@ public class DeckRecognizerTest extends ForgeCardMockTestCase {
|
|||||||
assertEquals(acCard.getEdition(), "LRW");
|
assertEquals(acCard.getEdition(), "LRW");
|
||||||
assertEquals(acCard.getCollectorNumber(), "51");
|
assertEquals(acCard.getCollectorNumber(), "51");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*====================================
|
||||||
|
* TEST RECOGNISE LINES (MIXED inputs)
|
||||||
|
* ===================================
|
||||||
|
*/
|
||||||
|
@Test void testRecognizeLines(){
|
||||||
|
StaticData magicDb = FModel.getMagicDb();
|
||||||
|
CardDb db = magicDb.getCommonCards();
|
||||||
|
CardDb altDb = magicDb.getVariantCards();
|
||||||
|
DeckRecognizer recognizer = new DeckRecognizer(db, altDb);
|
||||||
|
|
||||||
|
String lineRequest = "// MainBoard";
|
||||||
|
Token token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.DECK_SECTION_NAME);
|
||||||
|
assertEquals(token.getText(), "Main");
|
||||||
|
|
||||||
|
lineRequest = "## Sideboard (15)";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.DECK_SECTION_NAME);
|
||||||
|
assertEquals(token.getText(), "Sideboard");
|
||||||
|
|
||||||
|
lineRequest = "Normal Text";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.UNKNOWN_TEXT);
|
||||||
|
assertEquals(token.getText(), "Normal Text");
|
||||||
|
|
||||||
|
lineRequest = "//Creatures";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.CARD_TYPE);
|
||||||
|
assertEquals(token.getText(), "Creatures");
|
||||||
|
|
||||||
|
lineRequest = "//Lands";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.CARD_TYPE);
|
||||||
|
assertEquals(token.getText(), "Lands");
|
||||||
|
|
||||||
|
lineRequest = "//Land";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.CARD_RARITY);
|
||||||
|
assertEquals(token.getText(), "Land");
|
||||||
|
|
||||||
|
lineRequest = "//Creatures with text";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.COMMENT);
|
||||||
|
assertEquals(token.getText(), "//Creatures with text");
|
||||||
|
|
||||||
|
lineRequest = "SB:Ancestral Recall";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.COMMENT);
|
||||||
|
assertEquals(token.getText(), "SB:Ancestral Recall");
|
||||||
|
|
||||||
|
lineRequest = "Ancestral Recall";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNull(token.getText());
|
||||||
|
assertNotNull(token.getCard());
|
||||||
|
|
||||||
|
lineRequest = "* 4 [Counterspell](http://tappedout.nethttp://tappedout.net/mtg-card/counterspell/)";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.LEGAL_CARD_REQUEST);
|
||||||
|
assertNull(token.getText());
|
||||||
|
assertNotNull(token.getCard());
|
||||||
|
assertEquals(token.getNumber(), 4);
|
||||||
|
|
||||||
|
lineRequest = "### Instant (14)";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.CARD_TYPE);
|
||||||
|
assertEquals(token.getText(), "Instant");
|
||||||
|
|
||||||
|
lineRequest = "### General line as comment";
|
||||||
|
token = recognizer.recognizeLine(lineRequest);
|
||||||
|
assertNotNull(token);
|
||||||
|
assertEquals(token.getType(), TokenType.COMMENT);
|
||||||
|
assertEquals(token.getText(), "### General line as comment");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user