mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
Parser for cardname.txt is ready, CardDb is initialized when PreloadFactory starts.
Warning: this commit may break the build. I'll fix it right now if so the co does.
This commit is contained in:
@@ -8,7 +8,9 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@@ -25,6 +27,8 @@ import net.slightlymagic.braids.util.progress_monitor.StderrProgressMonitor;
|
|||||||
import com.google.code.jyield.Generator;
|
import com.google.code.jyield.Generator;
|
||||||
import com.google.code.jyield.YieldUtils;
|
import com.google.code.jyield.YieldUtils;
|
||||||
|
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.card.CardRulesReader;
|
||||||
import forge.card.trigger.TriggerHandler;
|
import forge.card.trigger.TriggerHandler;
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
import forge.properties.NewConstants;
|
import forge.properties.NewConstants;
|
||||||
@@ -59,10 +63,12 @@ public class CardReader
|
|||||||
protected static final int UNKNOWN_NUMBER_OF_FILES_REMAINING = -1; // NOPMD by Braids on 8/18/11 10:54 PM
|
protected static final int UNKNOWN_NUMBER_OF_FILES_REMAINING = -1; // NOPMD by Braids on 8/18/11 10:54 PM
|
||||||
|
|
||||||
private transient Map<String, Card> mapToFill;
|
private transient Map<String, Card> mapToFill;
|
||||||
|
private transient List<CardRules> listRulesToFill;
|
||||||
private transient File cardsfolder;
|
private transient File cardsfolder;
|
||||||
|
|
||||||
private transient ZipFile zip;
|
private transient ZipFile zip;
|
||||||
private transient Charset charset;
|
private transient Charset charset;
|
||||||
|
private transient CardRulesReader rulesReader;
|
||||||
|
|
||||||
private transient Enumeration<? extends ZipEntry> zipEnum;
|
private transient Enumeration<? extends ZipEntry> zipEnum;
|
||||||
|
|
||||||
@@ -73,6 +79,10 @@ public class CardReader
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill ) {
|
||||||
|
this(theCardsFolder, theMapToFill, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a convenience for CardReader(cardsfolder, mapToFill, true); .
|
* This is a convenience for CardReader(cardsfolder, mapToFill, true); .
|
||||||
*
|
*
|
||||||
@@ -82,8 +92,9 @@ public class CardReader
|
|||||||
* place the cards once read
|
* place the cards once read
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill) {
|
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill,
|
||||||
this(theCardsFolder, theMapToFill, true);
|
final List<CardRules> listRules2Fill) {
|
||||||
|
this(theCardsFolder, theMapToFill, listRules2Fill, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,11 +107,16 @@ public class CardReader
|
|||||||
*
|
*
|
||||||
* @param useZip if true, attempts to load cards from a zip file, if one exists.
|
* @param useZip if true, attempts to load cards from a zip file, if one exists.
|
||||||
*/
|
*/
|
||||||
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill, final boolean useZip) {
|
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill,
|
||||||
|
final List<CardRules> listRules2Fill, final boolean useZip)
|
||||||
|
{
|
||||||
if (theMapToFill == null) {
|
if (theMapToFill == null) {
|
||||||
throw new NullPointerException("theMapToFill must not be null."); // NOPMD by Braids on 8/18/11 10:53 PM
|
throw new NullPointerException("theMapToFill must not be null."); // NOPMD by Braids on 8/18/11 10:53 PM
|
||||||
}
|
}
|
||||||
this.mapToFill = theMapToFill;
|
this.mapToFill = theMapToFill;
|
||||||
|
// These read data for lightweight classes.
|
||||||
|
this.listRulesToFill = listRules2Fill == null ? new ArrayList<CardRules>() : listRules2Fill;
|
||||||
|
this.rulesReader = new CardRulesReader();
|
||||||
|
|
||||||
if (!theCardsFolder.exists()) {
|
if (!theCardsFolder.exists()) {
|
||||||
throw new RuntimeException(// NOPMD by Braids on 8/18/11 10:53 PM
|
throw new RuntimeException(// NOPMD by Braids on 8/18/11 10:53 PM
|
||||||
@@ -294,6 +310,7 @@ public class CardReader
|
|||||||
*/
|
*/
|
||||||
protected final Card loadCard(final InputStream inputStream) {
|
protected final Card loadCard(final InputStream inputStream) {
|
||||||
final Card card = new Card();
|
final Card card = new Card();
|
||||||
|
rulesReader.reset();
|
||||||
|
|
||||||
InputStreamReader inputStreamReader = null;
|
InputStreamReader inputStreamReader = null;
|
||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
@@ -303,6 +320,7 @@ public class CardReader
|
|||||||
|
|
||||||
String line = readLine(reader);
|
String line = readLine(reader);
|
||||||
while (!"End".equals(line)) {
|
while (!"End".equals(line)) {
|
||||||
|
rulesReader.parseLine(line);
|
||||||
if (line.charAt(0) == '#') { // NOPMD by Braids on 8/18/11 10:59 PM
|
if (line.charAt(0) == '#') { // NOPMD by Braids on 8/18/11 10:59 PM
|
||||||
//no need to do anything, this indicates a comment line
|
//no need to do anything, this indicates a comment line
|
||||||
} else if (line.startsWith("Name:")) {
|
} else if (line.startsWith("Name:")) {
|
||||||
@@ -386,6 +404,7 @@ public class CardReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listRulesToFill.add(rulesReader.getCard());
|
||||||
mapToFill.put(card.getName(), card);
|
mapToFill.put(card.getName(), card);
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,20 @@ public final class CardDb {
|
|||||||
private static volatile CardDb onlyInstance = null; // 'volatile' keyword makes this working
|
private static volatile CardDb onlyInstance = null; // 'volatile' keyword makes this working
|
||||||
public static CardDb instance() {
|
public static CardDb instance() {
|
||||||
if (onlyInstance == null) {
|
if (onlyInstance == null) {
|
||||||
synchronized (CardDb.class) {
|
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
|
||||||
if (onlyInstance == null) { // It's broken under 1.4 and below, on 1.5+ works again!
|
|
||||||
onlyInstance = new CardDb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return onlyInstance;
|
return onlyInstance;
|
||||||
}
|
}
|
||||||
|
public static void setup(final Iterator<CardRules> list) {
|
||||||
|
if (onlyInstance != null) {
|
||||||
|
throw new RuntimeException("CardDb has already been initialized, don't do it twice please");
|
||||||
|
}
|
||||||
|
synchronized (CardDb.class) {
|
||||||
|
if (onlyInstance == null) { // It's broken under 1.4 and below, on 1.5+ works again!
|
||||||
|
onlyInstance = new CardDb(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Here oracle cards
|
// Here oracle cards
|
||||||
private final Map<String, CardRules> cards = new Hashtable<String, CardRules>();
|
private final Map<String, CardRules> cards = new Hashtable<String, CardRules>();
|
||||||
@@ -96,7 +102,7 @@ public final class CardDb {
|
|||||||
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
|
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
|
||||||
}
|
}
|
||||||
// Advanced fetch by name+set
|
// Advanced fetch by name+set
|
||||||
public CardPrinted getCard(final String name, final String set) { return getCard(name, set, 1); }
|
public CardPrinted getCard(final String name, final String set) { return getCard(name, set, 0); }
|
||||||
public CardPrinted getCard(final String name, final String set, final int artIndex) {
|
public CardPrinted getCard(final String name, final String set, final int artIndex) {
|
||||||
// 1. get set
|
// 1. get set
|
||||||
Map<String, CardPrinted[]> cardsFromset = allCardsBySet.get(set);
|
Map<String, CardPrinted[]> cardsFromset = allCardsBySet.get(set);
|
||||||
@@ -111,7 +117,7 @@ public final class CardDb {
|
|||||||
throw new NoSuchElementException(err);
|
throw new NoSuchElementException(err);
|
||||||
}
|
}
|
||||||
// 3. Get the proper copy
|
// 3. Get the proper copy
|
||||||
if (artIndex > 0 && artIndex <= cards.length) { return cards[artIndex]; }
|
if (artIndex >= 0 && artIndex <= cards.length) { return cards[artIndex]; }
|
||||||
String err = String.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
|
String err = String.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
|
||||||
throw new NoSuchElementException(err);
|
throw new NoSuchElementException(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public final class CardManaCost implements Comparable<CardManaCost> {
|
|||||||
|
|
||||||
private Float compareWeight = null;
|
private Float compareWeight = null;
|
||||||
|
|
||||||
|
public static final CardManaCost empty = new CardManaCost();
|
||||||
|
|
||||||
// pass mana cost parser here
|
// pass mana cost parser here
|
||||||
private CardManaCost() {
|
private CardManaCost() {
|
||||||
@@ -29,12 +30,7 @@ public final class CardManaCost implements Comparable<CardManaCost> {
|
|||||||
stringValue = "";
|
stringValue = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final CardManaCost empty = new CardManaCost();
|
// public ctor, should give it a mana parser
|
||||||
|
|
||||||
public CardManaCost(final String cost) {
|
|
||||||
this(new ParserMtgData(cost));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CardManaCost(final ManaParser parser) {
|
public CardManaCost(final ManaParser parser) {
|
||||||
if (!parser.hasNext()) {
|
if (!parser.hasNext()) {
|
||||||
throw new RuntimeException("Empty manacost passed to parser (this should have been handled before)");
|
throw new RuntimeException("Empty manacost passed to parser (this should have been handled before)");
|
||||||
@@ -49,7 +45,7 @@ public final class CardManaCost implements Comparable<CardManaCost> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getSimpleString() {
|
private String getSimpleString() {
|
||||||
if (shards.isEmpty()) return Integer.toString(genericCost);
|
if (shards.isEmpty()) { return Integer.toString(genericCost); }
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
boolean isFirst = false;
|
boolean isFirst = false;
|
||||||
@@ -98,61 +94,6 @@ public final class CardManaCost implements Comparable<CardManaCost> {
|
|||||||
int getTotalColorlessCost();
|
int getTotalColorlessCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ParserMtgData implements ManaParser {
|
|
||||||
private final String cost;
|
|
||||||
|
|
||||||
private int nextBracket;
|
|
||||||
private int colorlessCost;
|
|
||||||
|
|
||||||
|
|
||||||
public ParserMtgData(final String cost) {
|
|
||||||
this.cost = cost;
|
|
||||||
// System.out.println(cost);
|
|
||||||
nextBracket = cost.indexOf('{');
|
|
||||||
colorlessCost = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalColorlessCost() {
|
|
||||||
if ( hasNext() ) {
|
|
||||||
throw new RuntimeException("Colorless cost should be obtained after iteration is complete");
|
|
||||||
}
|
|
||||||
return colorlessCost;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() { return nextBracket != -1; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CardManaCostShard next() {
|
|
||||||
int closeBracket = cost.indexOf('}', nextBracket);
|
|
||||||
String unparsed = cost.substring(nextBracket + 1, closeBracket);
|
|
||||||
nextBracket = cost.indexOf('{', closeBracket + 1);
|
|
||||||
|
|
||||||
// System.out.println(unparsed);
|
|
||||||
if (StringUtils.isNumeric(unparsed)) {
|
|
||||||
colorlessCost += Integer.parseInt(unparsed);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int atoms = 0;
|
|
||||||
for (int iChar = 0; iChar < unparsed.length(); iChar++) {
|
|
||||||
switch (unparsed.charAt(iChar)) {
|
|
||||||
case 'W': atoms |= CardManaCostShard.Atom.WHITE; break;
|
|
||||||
case 'U': atoms |= CardManaCostShard.Atom.BLUE; break;
|
|
||||||
case 'B': atoms |= CardManaCostShard.Atom.BLACK; break;
|
|
||||||
case 'R': atoms |= CardManaCostShard.Atom.RED; break;
|
|
||||||
case 'G': atoms |= CardManaCostShard.Atom.GREEN; break;
|
|
||||||
case '2': atoms |= CardManaCostShard.Atom.OR_2_COLORLESS; break;
|
|
||||||
case 'P': atoms |= CardManaCostShard.Atom.OR_2_LIFE; break;
|
|
||||||
case 'X': atoms |= CardManaCostShard.Atom.IS_X; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CardManaCostShard.valueOf(atoms);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() { } // unsuported
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ public final class CardRules {
|
|||||||
|
|
||||||
private Map<String, CardInSet> setsPrinted = null;
|
private Map<String, CardInSet> setsPrinted = null;
|
||||||
|
|
||||||
private boolean removedFromAIDecks = false;
|
private boolean isRemovedFromAIDecks = false;
|
||||||
private boolean removedFromRandomDecks = false;
|
private boolean isRemovedFromRandomDecks = false;
|
||||||
|
|
||||||
// Ctor and builders are needed here
|
// Ctor and builders are needed here
|
||||||
public String getName() { return name; }
|
public String getName() { return name; }
|
||||||
@@ -46,27 +46,13 @@ public final class CardRules {
|
|||||||
public String[] getRules() { return rules; }
|
public String[] getRules() { return rules; }
|
||||||
public Set<Entry<String, CardInSet>> getSetsPrinted() { return setsPrinted.entrySet(); }
|
public Set<Entry<String, CardInSet>> getSetsPrinted() { return setsPrinted.entrySet(); }
|
||||||
|
|
||||||
public String getPower() { return power; }
|
public final String getPower() { return power; }
|
||||||
public int getIntPower() { return iPower; }
|
public final int getIntPower() { return iPower; }
|
||||||
public String getToughness() { return toughness; }
|
public final String getToughness() { return toughness; }
|
||||||
public int getIntToughness() { return iToughness; }
|
public final int getIntToughness() { return iToughness; }
|
||||||
public String getLoyalty() { return loyalty; }
|
public final String getLoyalty() { return loyalty; }
|
||||||
|
public final boolean getemovedFromAIDecks() { return isRemovedFromAIDecks; }
|
||||||
/**
|
public final boolean getRemovedFromRandomDecks() { return isRemovedFromRandomDecks; }
|
||||||
* Getter for removedFromAIDecks.
|
|
||||||
* @return the removedFromAIDecks value
|
|
||||||
*/
|
|
||||||
public final boolean isRemovedFromAIDecks() {
|
|
||||||
return removedFromAIDecks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getter for removedFromRandomDecks.
|
|
||||||
* @return the removedFromRandomDecks value
|
|
||||||
*/
|
|
||||||
public final boolean isRemovedFromRandomDecks() {
|
|
||||||
return removedFromRandomDecks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPTorLoyalty() {
|
public String getPTorLoyalty() {
|
||||||
if (getType().isCreature()) { return power + "/" + toughness; }
|
if (getType().isCreature()) { return power + "/" + toughness; }
|
||||||
@@ -74,17 +60,19 @@ public final class CardRules {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public CardRules(final String cardName, final CardType cardType, final String manacost,
|
public CardRules(final String cardName, final CardType cardType, final CardManaCost manacost,
|
||||||
final String ptLine, final String[] cardRules, final Map<String, CardInSet> setsData,
|
final String ptLine, final String[] cardRules, final Map<String, CardInSet> setsData,
|
||||||
final boolean removedFromRandomDecks0, final boolean removedFromAIDecks0)
|
final boolean removedFromRandomDecks, final boolean removedFromAIDecks)
|
||||||
{
|
{
|
||||||
this.name = cardName;
|
this.name = cardName;
|
||||||
this.type = cardType;
|
this.type = cardType;
|
||||||
this.cost = manacost == null ? CardManaCost.empty : new CardManaCost(manacost);
|
this.cost = manacost;
|
||||||
this.rules = cardRules;
|
this.rules = cardRules;
|
||||||
this.color = new CardColor(cost);
|
this.color = new CardColor(cost);
|
||||||
this.removedFromAIDecks = removedFromAIDecks0;
|
this.isRemovedFromAIDecks = removedFromAIDecks;
|
||||||
this.removedFromRandomDecks = removedFromRandomDecks0;
|
this.isRemovedFromRandomDecks = removedFromRandomDecks;
|
||||||
|
|
||||||
|
//System.out.println(cardName);
|
||||||
|
|
||||||
if (cardType.isCreature()) {
|
if (cardType.isCreature()) {
|
||||||
int slashPos = ptLine.indexOf('/');
|
int slashPos = ptLine.indexOf('/');
|
||||||
@@ -124,6 +112,10 @@ public final class CardRules {
|
|||||||
return cis.getRarity();
|
return cis.getRarity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAiStatus() {
|
||||||
|
return isRemovedFromAIDecks ? (isRemovedFromRandomDecks ? "AI ?" : "AI") : (isRemovedFromRandomDecks ? "?" :"");
|
||||||
|
}
|
||||||
|
|
||||||
public abstract static class Predicates {
|
public abstract static class Predicates {
|
||||||
|
|
||||||
// Static builder methods - they choose concrete implementation by themselves
|
// Static builder methods - they choose concrete implementation by themselves
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@@ -11,9 +12,12 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
//import java.util.zip.ZipEntry;
|
//import java.util.zip.ZipEntry;
|
||||||
//import java.util.zip.ZipFile;
|
//import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
import forge.card.CardManaCost.ManaParser;
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
import forge.properties.NewConstants;
|
import forge.properties.NewConstants;
|
||||||
|
|
||||||
@@ -25,358 +29,64 @@ import forge.properties.NewConstants;
|
|||||||
*
|
*
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class CardRulesReader
|
public class CardRulesReader {
|
||||||
//implements Runnable, // NOPMD by Braids on 8/18/11 10:55 PM
|
|
||||||
implements NewConstants
|
|
||||||
{
|
|
||||||
private static final String CARD_FILE_DOT_EXTENSION = ".txt"; // NOPMD by Braids on 8/18/11 11:04 PM
|
|
||||||
|
|
||||||
/** Default charset when loading from files. */
|
private String cardName = null;
|
||||||
public static final String DEFAULT_CHARSET_NAME = "US-ASCII"; // NOPMD by Braids on 8/18/11 10:54 PM
|
private CardType cardType = null;
|
||||||
|
private CardManaCost manaCost = CardManaCost.empty;
|
||||||
|
private String ptLine = null;
|
||||||
|
private String[] cardRules = null;
|
||||||
|
private Map<String, CardInSet> setsData = new TreeMap<String, CardInSet>();
|
||||||
|
private boolean removedFromAIDecks = false;
|
||||||
|
private boolean removedFromRandomDecks = false;
|
||||||
|
|
||||||
/** Regex that matches a single hyphen (-) or space. */
|
// Reset all fields to parse next card (to avoid allocating new CardRulesReader N times)
|
||||||
public static final Pattern HYPHEN_OR_SPACE = Pattern.compile("[ -]");
|
public final void reset() {
|
||||||
|
cardName = null;
|
||||||
/** Regex for punctuation that we omit from card file names. */
|
cardType = null;
|
||||||
public static final Pattern PUNCTUATION_TO_ZAP = Pattern.compile("[,'\"]"); // NOPMD by Braids on 8/18/11 10:54 PM
|
manaCost = CardManaCost.empty;
|
||||||
|
ptLine = null;
|
||||||
/** Regex that matches two or more underscores (_). */
|
cardRules = null;
|
||||||
public static final Pattern MULTIPLE_UNDERSCORES = Pattern.compile("__+"); // NOPMD by Braids on 8/18/11 10:54 PM
|
setsData = new TreeMap<String, CardInSet>();
|
||||||
|
removedFromAIDecks = false;
|
||||||
/** Special value for estimatedFilesRemaining. */
|
removedFromRandomDecks = false;
|
||||||
protected static final int UNKNOWN_NUMBER_OF_FILES_REMAINING = -1; // NOPMD by Braids on 8/18/11 10:54 PM
|
|
||||||
|
|
||||||
//private transient Map<String, CardRules> mapToFill;
|
|
||||||
//private transient File cardsfolder;
|
|
||||||
|
|
||||||
//private transient ZipFile zip;
|
|
||||||
private transient Charset charset;
|
|
||||||
|
|
||||||
//private transient Enumeration<? extends ZipEntry> zipEnum;
|
|
||||||
|
|
||||||
/*
|
|
||||||
private transient long estimatedFilesRemaining = // NOPMD by Braids on 8/18/11 10:56 PM
|
|
||||||
UNKNOWN_NUMBER_OF_FILES_REMAINING;
|
|
||||||
*/
|
|
||||||
|
|
||||||
private transient Iterable<File> findNonDirsIterable; // NOPMD by Braids on 8/18/11 10:56 PM
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a convenience for CardReader(cardsfolder, mapToFill, true); .
|
|
||||||
*
|
|
||||||
* @param theCardsFolder indicates location of the cardsFolder
|
|
||||||
*
|
|
||||||
* @param theMapToFill maps card names to Card instances; this is where we
|
|
||||||
* place the cards once read
|
|
||||||
*
|
|
||||||
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill) {
|
|
||||||
this(theCardsFolder, theMapToFill, true);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Constructor for CardReader.</p>
|
|
||||||
*
|
|
||||||
* @param theCardsFolder indicates location of the cardsFolder
|
|
||||||
*
|
|
||||||
* @param theMapToFill maps card names to Card instances; this is where we
|
|
||||||
* place the cards once read
|
|
||||||
*
|
|
||||||
* @param useZip if true, attempts to load cards from a zip file, if one exists.
|
|
||||||
public CardReader(final File theCardsFolder, final Map<String, Card> theMapToFill, final boolean useZip) {
|
|
||||||
if (theMapToFill == null) {
|
|
||||||
throw new NullPointerException("theMapToFill must not be null."); // NOPMD by Braids on 8/18/11 10:53 PM
|
|
||||||
}
|
|
||||||
this.mapToFill = theMapToFill;
|
|
||||||
|
|
||||||
if (!theCardsFolder.exists()) {
|
|
||||||
throw new RuntimeException(// NOPMD by Braids on 8/18/11 10:53 PM
|
|
||||||
"CardReader : constructor error -- file not found -- filename is "
|
|
||||||
+ theCardsFolder.getAbsolutePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!theCardsFolder.isDirectory()) {
|
public final CardRules getCard() {
|
||||||
throw new RuntimeException(// NOPMD by Braids on 8/18/11 10:53 PM
|
return new CardRules(cardName, cardType, manaCost, ptLine, cardRules, setsData, removedFromRandomDecks, removedFromAIDecks);
|
||||||
"CardReader : constructor error -- not a directory -- "
|
|
||||||
+ theCardsFolder.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cardsfolder = theCardsFolder;
|
|
||||||
|
|
||||||
|
|
||||||
final File zipFile = new File(theCardsFolder, "cardsfolder.zip");
|
|
||||||
|
|
||||||
// Prepare resources to read cards lazily.
|
|
||||||
if (useZip && zipFile.exists()) {
|
|
||||||
try {
|
|
||||||
this.zip = new ZipFile(zipFile);
|
|
||||||
} catch (Exception exn) {
|
|
||||||
System.err.println("Error reading zip file \"" // NOPMD by Braids on 8/18/11 10:53 PM
|
|
||||||
+ zipFile.getAbsolutePath() + "\": " + exn + ". "
|
|
||||||
+ "Defaulting to txt files in \""
|
|
||||||
+ theCardsFolder.getAbsolutePath()
|
|
||||||
+ "\"."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useZip && zip != null) {
|
|
||||||
zipEnum = zip.entries();
|
|
||||||
estimatedFilesRemaining = zip.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
setEncoding(DEFAULT_CHARSET_NAME);
|
|
||||||
|
|
||||||
} //CardReader()
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This finalizer helps assure there is no memory or thread leak with
|
|
||||||
* findNonDirsIterable, which was created with YieldUtils.toIterable.
|
|
||||||
*
|
|
||||||
* @throws Throwable indirectly
|
|
||||||
*/
|
|
||||||
protected final void finalize() throws Throwable {
|
|
||||||
try {
|
|
||||||
if (findNonDirsIterable != null) {
|
|
||||||
for (@SuppressWarnings("unused") File ignored
|
|
||||||
: findNonDirsIterable)
|
|
||||||
{
|
|
||||||
// Do nothing; just exercising the Iterable.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
super.finalize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public final void parseLine(final String line) {
|
||||||
* Reads the rest of ALL the cards into memory. This is not lazy.
|
if (line.startsWith("Name:")) {
|
||||||
public final void run() {
|
|
||||||
loadCardsUntilYouFind(null);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts reading cards into memory until the given card is found.
|
|
||||||
*
|
|
||||||
* After that, we save our place in the list of cards (on disk) in case we
|
|
||||||
* need to load more.
|
|
||||||
*
|
|
||||||
* @param cardName the name to find; if null, load all cards.
|
|
||||||
*
|
|
||||||
* @return the Card or null if it was not found.
|
|
||||||
protected final Card loadCardsUntilYouFind(final String cardName) {
|
|
||||||
Card result = null;
|
|
||||||
|
|
||||||
// Try to retrieve card loading progress monitor model.
|
|
||||||
// If no progress monitor present, output results to console.
|
|
||||||
BaseProgressMonitor monitor = null;
|
|
||||||
final FView view = Singletons.getView();
|
|
||||||
if (view != null) {
|
|
||||||
monitor = view.getCardLoadingProgressMonitor();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitor == null) {
|
|
||||||
monitor = new StderrProgressMonitor(1, 0L);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through txt files or zip archive.
|
|
||||||
// Report relevant numbers to progress monitor model.
|
|
||||||
if (zip == null) {
|
|
||||||
if (estimatedFilesRemaining == UNKNOWN_NUMBER_OF_FILES_REMAINING) {
|
|
||||||
final Generator<File> findNonDirsGen = new FindNonDirectoriesSkipDotDirectoriesGenerator(cardsfolder);
|
|
||||||
estimatedFilesRemaining = GeneratorFunctions.estimateSize(findNonDirsGen);
|
|
||||||
findNonDirsIterable = YieldUtils.toIterable(findNonDirsGen);
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor.setTotalUnitsThisPhase(estimatedFilesRemaining);
|
|
||||||
|
|
||||||
for (File cardTxtFile : findNonDirsIterable) {
|
|
||||||
if (!cardTxtFile.getName().endsWith(CARD_FILE_DOT_EXTENSION)) {
|
|
||||||
monitor.incrementUnitsCompletedThisPhase(1L);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = loadCard(cardTxtFile);
|
|
||||||
monitor.incrementUnitsCompletedThisPhase(1L);
|
|
||||||
|
|
||||||
if (cardName != null && cardName.equals(result.getName())) {
|
|
||||||
break; // no thread leak here if entire card DB is loaded, or if this object is finalized.
|
|
||||||
}
|
|
||||||
|
|
||||||
} //endfor
|
|
||||||
|
|
||||||
} else {
|
|
||||||
monitor.setTotalUnitsThisPhase(estimatedFilesRemaining);
|
|
||||||
ZipEntry entry;
|
|
||||||
|
|
||||||
// zipEnum was initialized in the constructor.
|
|
||||||
while (zipEnum.hasMoreElements()) {
|
|
||||||
entry = (ZipEntry) zipEnum.nextElement();
|
|
||||||
|
|
||||||
if (entry.isDirectory() || !entry.getName().endsWith(CARD_FILE_DOT_EXTENSION)) {
|
|
||||||
monitor.incrementUnitsCompletedThisPhase(1L);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = loadCard(entry);
|
|
||||||
monitor.incrementUnitsCompletedThisPhase(1L);
|
|
||||||
|
|
||||||
if (cardName != null && cardName.equals(result.getName())) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} //endif
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} //loadCardsUntilYouFind(String)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Reads a line from the given reader and handles exceptions.</p>
|
|
||||||
*
|
|
||||||
* @return a {@link java.lang.String} object.
|
|
||||||
* @param reader a {@link java.io.BufferedReader} object.
|
|
||||||
*/
|
|
||||||
public static String readLine(final BufferedReader reader) {
|
|
||||||
//makes the checked exception, into an unchecked runtime exception
|
|
||||||
try {
|
|
||||||
String line = reader.readLine();
|
|
||||||
if (line != null) {
|
|
||||||
line = line.trim();
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ErrorViewer.showError(ex);
|
|
||||||
throw new RuntimeException("CardReader : readLine(Card) error", ex); // NOPMD by Braids on 8/18/11 10:53 PM
|
|
||||||
}
|
|
||||||
} //readLine(BufferedReader)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Load a card from an InputStream.</p>
|
|
||||||
*
|
|
||||||
* @param txtFileLocator describes the location of the txt file we are
|
|
||||||
* parsing
|
|
||||||
*
|
|
||||||
* @param inputStream the stream from which to load the card's information
|
|
||||||
*
|
|
||||||
* @return the card loaded from the stream
|
|
||||||
*
|
|
||||||
* @throws CardParsingException if there is something wrong with the
|
|
||||||
* stream's contents
|
|
||||||
*/
|
|
||||||
protected final CardRules loadCard(final String txtFileLocator, final InputStream inputStream)
|
|
||||||
throws CardParsingException
|
|
||||||
{
|
|
||||||
int lineNum = 0;
|
|
||||||
|
|
||||||
String cardName = null;
|
|
||||||
CardType cardType = null;
|
|
||||||
String manacost = null;
|
|
||||||
String ptLine = null;
|
|
||||||
String[] cardRules = null;
|
|
||||||
Map<String, CardInSet> setsData = new TreeMap<String, CardInSet>();
|
|
||||||
boolean removedFromAIDecks = false;
|
|
||||||
boolean removedFromRandomDecks = false;
|
|
||||||
|
|
||||||
InputStreamReader inputStreamReader = null;
|
|
||||||
BufferedReader reader = null;
|
|
||||||
try {
|
|
||||||
inputStreamReader = new InputStreamReader(inputStream, charset);
|
|
||||||
reader = new BufferedReader(inputStreamReader);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
String line = readLine(reader);
|
|
||||||
lineNum++;
|
|
||||||
|
|
||||||
if (line.charAt(0) == '#') {
|
|
||||||
//no need to do anything, this indicates a comment line
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} else if (line.startsWith("Name:")) {
|
|
||||||
cardName = getValueAfterKey(line, "Name:");
|
cardName = getValueAfterKey(line, "Name:");
|
||||||
|
|
||||||
if (cardName == null || cardName.isEmpty()) {
|
if (cardName == null || cardName.isEmpty()) {
|
||||||
throw new CardParsingException(txtFileLocator, lineNum, "Card name is empty");
|
throw new RuntimeException("Card name is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (line.startsWith("ManaCost:")) {
|
} else if (line.startsWith("ManaCost:")) {
|
||||||
final String value = getValueAfterKey(line, "ManaCost:");
|
String sCost = getValueAfterKey(line, "ManaCost:");
|
||||||
|
manaCost = "no cost".equals(sCost) ? CardManaCost.empty : new CardManaCost(new ParserCardnameTxtManaCost(sCost));
|
||||||
if (!"no cost".equals(value)) {
|
|
||||||
manacost = value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert manacost == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (line.startsWith("Types:")) {
|
} else if (line.startsWith("Types:")) {
|
||||||
final String value = getValueAfterKey(line, "Types:");
|
cardType = CardType.parse(getValueAfterKey(line, "Types:"));
|
||||||
|
|
||||||
try {
|
|
||||||
cardType = CardType.parse(value);
|
|
||||||
}
|
|
||||||
catch (Throwable exn) {
|
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
|
||||||
"In Types: " + exn.getMessage(), exn);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (line.startsWith("Oracle:")) {
|
} else if (line.startsWith("Oracle:")) {
|
||||||
final String value = getValueAfterKey(line, "Oracle:");
|
cardRules = getValueAfterKey(line, "Oracle:").split("\\n");
|
||||||
cardRules = value.split("\\n");
|
|
||||||
|
|
||||||
} else if (line.startsWith("PT:")) {
|
} else if (line.startsWith("PT:")) {
|
||||||
throwCPEIfPTIsNotNull(ptLine, txtFileLocator, lineNum);
|
|
||||||
ptLine = getValueAfterKey(line, "PT:");
|
ptLine = getValueAfterKey(line, "PT:");
|
||||||
|
|
||||||
} else if (line.startsWith("Loyalty:")) {
|
} else if (line.startsWith("Loyalty:")) {
|
||||||
throwCPEIfPTIsNotNull(ptLine, txtFileLocator, lineNum);
|
|
||||||
ptLine = getValueAfterKey(line, "Loyalty:");
|
ptLine = getValueAfterKey(line, "Loyalty:");
|
||||||
|
|
||||||
} else if (line.startsWith("SVar:RemAIDeck:")) {
|
} else if (line.startsWith("SVar:RemAIDeck:")) {
|
||||||
final String value = getValueAfterKey(line, "SVar:RemAIDeck:");
|
removedFromAIDecks = "True".equalsIgnoreCase(getValueAfterKey(line, "SVar:RemAIDeck:"));
|
||||||
removedFromAIDecks = ("True".equalsIgnoreCase(value));
|
|
||||||
|
|
||||||
} else if (line.startsWith("SVar:RemRandomDeck:")) {
|
} else if (line.startsWith("SVar:RemRandomDeck:")) {
|
||||||
final String value = getValueAfterKey(line, "SVar:RemRandomDeck:");
|
removedFromRandomDecks = "True".equalsIgnoreCase(getValueAfterKey(line, "SVar:RemRandomDeck:"));
|
||||||
removedFromRandomDecks = ("True".equalsIgnoreCase(value));
|
|
||||||
|
|
||||||
} else if (line.startsWith("SetInfo:")) {
|
} else if (line.startsWith("SetInfo:")) {
|
||||||
parseSetInfoLine(txtFileLocator, lineNum, line, setsData);
|
parseSetInfoLine(line, setsData);
|
||||||
|
|
||||||
} else if ("End".equals(line)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // while true
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException ignored) { // NOPMD by Braids on 8/18/11 11:08 PM
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
inputStreamReader.close();
|
|
||||||
} catch (IOException ignored) { // NOPMD by Braids on 8/18/11 11:08 PM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return new CardRules(cardName, cardType, manacost, ptLine, cardRules, setsData, removedFromRandomDecks,
|
|
||||||
removedFromAIDecks);
|
|
||||||
}
|
|
||||||
catch (Throwable exn) {
|
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
|
||||||
"Error constructing CardRules instance: " + exn.toString(),
|
|
||||||
exn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,9 +100,7 @@ public class CardRulesReader
|
|||||||
*
|
*
|
||||||
* @throws CardParsingException if there is a problem parsing the line
|
* @throws CardParsingException if there is a problem parsing the line
|
||||||
*/
|
*/
|
||||||
public static void parseSetInfoLine(final String txtFileLocator, final int lineNum, final String line,
|
public static void parseSetInfoLine(final String line, final Map<String, CardInSet> setsData)
|
||||||
final Map<String, CardInSet> setsData)
|
|
||||||
throws CardParsingException
|
|
||||||
{
|
{
|
||||||
final int setCodeIx = 0;
|
final int setCodeIx = 0;
|
||||||
final int rarityIx = 1;
|
final int rarityIx = 1;
|
||||||
@@ -405,7 +113,7 @@ public class CardRulesReader
|
|||||||
final String[] pieces = value.split("\\|");
|
final String[] pieces = value.split("\\|");
|
||||||
|
|
||||||
if (pieces.length <= rarityIx) {
|
if (pieces.length <= rarityIx) {
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
throw new RuntimeException(
|
||||||
"SetInfo line <<" + value + ">> has insufficient pieces");
|
"SetInfo line <<" + value + ">> has insufficient pieces");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +123,7 @@ public class CardRulesReader
|
|||||||
int numIllustrations = 1;
|
int numIllustrations = 1;
|
||||||
|
|
||||||
if (setsData.containsKey(setCode)) {
|
if (setsData.containsKey(setCode)) {
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
throw new RuntimeException(
|
||||||
"Found multiple SetInfo lines for set code <<" + setCode + ">>");
|
"Found multiple SetInfo lines for set code <<" + setCode + ">>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,13 +132,13 @@ public class CardRulesReader
|
|||||||
numIllustrations = Integer.parseInt(pieces[numPicIx]);
|
numIllustrations = Integer.parseInt(pieces[numPicIx]);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException nfe) {
|
catch (NumberFormatException nfe) {
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
throw new RuntimeException(
|
||||||
"Fourth item of SetInfo is not an integer in <<"
|
"Fourth item of SetInfo is not an integer in <<"
|
||||||
+ value + ">>");
|
+ value + ">>");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numIllustrations < 1) {
|
if (numIllustrations < 1) {
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
throw new RuntimeException(
|
||||||
"Fourth item of SetInfo is not a positive integer, but"
|
"Fourth item of SetInfo is not a positive integer, but"
|
||||||
+ numIllustrations);
|
+ numIllustrations);
|
||||||
}
|
}
|
||||||
@@ -456,8 +164,7 @@ public class CardRulesReader
|
|||||||
rarity = CardRarity.Special;
|
rarity = CardRarity.Special;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
throw new RuntimeException("Unrecognized rarity string <<" + txtRarity + ">>");
|
||||||
"Unrecognized rarity string <<" + txtRarity + ">>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CardInSet cardInSet = new CardInSet(rarity, numIllustrations);
|
CardInSet cardInSet = new CardInSet(rarity, numIllustrations);
|
||||||
@@ -465,37 +172,6 @@ public class CardRulesReader
|
|||||||
setsData.put(setCode, cardInSet);
|
setsData.put(setCode, cardInSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if ptLine is null; if it is not, throw a CardParsingException.
|
|
||||||
*
|
|
||||||
* @param ptLine the previously seen power/toughness or loyalty value, if any
|
|
||||||
* @param txtFileLocator describes location of the card's txt file
|
|
||||||
* @param lineNum the line number just read
|
|
||||||
*
|
|
||||||
* @throws CardParsingException iff ptLine is not null
|
|
||||||
*/
|
|
||||||
public static void throwCPEIfPTIsNotNull(final String ptLine, final String txtFileLocator, final int lineNum)
|
|
||||||
throws CardParsingException
|
|
||||||
{
|
|
||||||
if (ptLine != null) {
|
|
||||||
throw new CardParsingException(txtFileLocator, lineNum,
|
|
||||||
"more than one PT or Loyalty is present");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse the value from a card.txt line.
|
|
||||||
*
|
|
||||||
* Throws {@link IndexOutOfBoundsException} if fieldNameWithColon is not in line.
|
|
||||||
*
|
|
||||||
* @param line the raw line; may have newline at end
|
|
||||||
*
|
|
||||||
* @param fieldNameWithColon the field name with its colon, used to
|
|
||||||
* identify the key
|
|
||||||
*
|
|
||||||
* @return the value after the colon, with its leading and trailing
|
|
||||||
* whitespace removed
|
|
||||||
*/
|
|
||||||
public static String getValueAfterKey(final String line, final String fieldNameWithColon) {
|
public static String getValueAfterKey(final String line, final String fieldNameWithColon) {
|
||||||
final int startIx = fieldNameWithColon.length();
|
final int startIx = fieldNameWithColon.length();
|
||||||
final String lineAfterColon = line.substring(startIx);
|
final String lineAfterColon = line.substring(startIx);
|
||||||
@@ -503,137 +179,62 @@ public class CardRulesReader
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the character encoding to use when loading cards.
|
public static class ParserCardnameTxtManaCost implements ManaParser {
|
||||||
*
|
private final String[] cost;
|
||||||
* @param charsetName the name of the charset, for example, "UTF-8"
|
private int nextToken;
|
||||||
*/
|
private int colorlessCost;
|
||||||
public final void setEncoding(final String charsetName) {
|
|
||||||
this.charset = Charset.forName(charsetName);
|
|
||||||
|
public ParserCardnameTxtManaCost(final String cost) {
|
||||||
|
this.cost = cost.split(" ");
|
||||||
|
// System.out.println(cost);
|
||||||
|
nextToken = 0;
|
||||||
|
colorlessCost = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalColorlessCost() {
|
||||||
|
if ( hasNext() ) {
|
||||||
|
throw new RuntimeException("Colorless cost should be obtained after iteration is complete");
|
||||||
|
}
|
||||||
|
return colorlessCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() { return nextToken < cost.length; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CardManaCostShard next() {
|
||||||
|
|
||||||
|
String unparsed = cost[nextToken++];;
|
||||||
|
|
||||||
|
// System.out.println(unparsed);
|
||||||
|
if (StringUtils.isNumeric(unparsed)) {
|
||||||
|
colorlessCost += Integer.parseInt(unparsed);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int atoms = 0;
|
||||||
|
for (int iChar = 0; iChar < unparsed.length(); iChar++) {
|
||||||
|
switch (unparsed.charAt(iChar)) {
|
||||||
|
case 'W': atoms |= CardManaCostShard.Atom.WHITE; break;
|
||||||
|
case 'U': atoms |= CardManaCostShard.Atom.BLUE; break;
|
||||||
|
case 'B': atoms |= CardManaCostShard.Atom.BLACK; break;
|
||||||
|
case 'R': atoms |= CardManaCostShard.Atom.RED; break;
|
||||||
|
case 'G': atoms |= CardManaCostShard.Atom.GREEN; break;
|
||||||
|
case '2': atoms |= CardManaCostShard.Atom.OR_2_COLORLESS; break;
|
||||||
|
case 'P': atoms |= CardManaCostShard.Atom.OR_2_LIFE; break;
|
||||||
|
case 'X': atoms |= CardManaCostShard.Atom.IS_X; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CardManaCostShard.valueOf(atoms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() { } // unsuported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a card from a txt file.
|
|
||||||
*
|
|
||||||
* @param pathToTxtFile the full or relative path to the file to load
|
|
||||||
*
|
|
||||||
* @return a new Card instance
|
|
||||||
protected final Card loadCard(final File pathToTxtFile) {
|
|
||||||
FileInputStream fileInputStream = null;
|
|
||||||
try {
|
|
||||||
fileInputStream = new FileInputStream(pathToTxtFile);
|
|
||||||
return loadCard(fileInputStream);
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ErrorViewer.showError(ex, "File \"%s\" exception", pathToTxtFile.getAbsolutePath());
|
|
||||||
throw new RuntimeException(// NOPMD by Braids on 8/18/11 10:53 PM
|
|
||||||
"CardReader : run error -- file exception -- filename is "
|
|
||||||
+ pathToTxtFile.getPath(), ex);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
fileInputStream.close();
|
|
||||||
} catch (IOException ignored) { // NOPMD by Braids on 8/18/11 11:08 PM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a card from an entry in a zip file.
|
|
||||||
*
|
|
||||||
* @param entry to load from
|
|
||||||
*
|
|
||||||
* @return a new Card instance
|
|
||||||
protected final Card loadCard(final ZipEntry entry) {
|
|
||||||
InputStream zipInputStream = null;
|
|
||||||
try {
|
|
||||||
zipInputStream = zip.getInputStream(entry);
|
|
||||||
return loadCard(zipInputStream);
|
|
||||||
|
|
||||||
} catch (IOException exn) {
|
|
||||||
throw new RuntimeException(exn); // NOPMD by Braids on 8/18/11 10:53 PM
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (zipInputStream != null) {
|
|
||||||
zipInputStream.close();
|
|
||||||
}
|
|
||||||
} catch (IOException ignored) { // NOPMD by Braids on 8/18/11 11:08 PM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to guess what the path to a given card's txt file would be.
|
|
||||||
*
|
|
||||||
* @param asciiCardName the card name in canonicalized ASCII form
|
|
||||||
*
|
|
||||||
* @return the likeliest path of the card's txt file, excluding
|
|
||||||
* cardsFolder but including the subdirectory of that and the ".txt"
|
|
||||||
* suffix. For example, "e/elvish_warrior.txt"
|
|
||||||
*
|
|
||||||
* @see CardUtil#canonicalizeCardName
|
|
||||||
*/
|
|
||||||
public final String toMostLikelyPath(final String asciiCardName) {
|
|
||||||
String baseFileName = asciiCardName;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* friarsol wrote: "hyphens and spaces are converted to underscores,
|
|
||||||
* commas and apostrophes are removed (I'm not sure if there are any
|
|
||||||
* other punctuation used)."
|
|
||||||
*
|
|
||||||
* @see http://www.slightlymagic.net/forum/viewtopic.php?f=52&t=4887#p63189
|
|
||||||
*/
|
|
||||||
|
|
||||||
baseFileName = HYPHEN_OR_SPACE.matcher(baseFileName).replaceAll("_");
|
|
||||||
baseFileName = MULTIPLE_UNDERSCORES.matcher(baseFileName).replaceAll("_");
|
|
||||||
baseFileName = PUNCTUATION_TO_ZAP.matcher(baseFileName).replaceAll("");
|
|
||||||
|
|
||||||
// Place the file within a single-letter subdirectory.
|
|
||||||
final StringBuffer buf = new StringBuffer(1 + 1 + baseFileName.length() + CARD_FILE_DOT_EXTENSION.length());
|
|
||||||
buf.append(Character.toLowerCase(baseFileName.charAt(0)));
|
|
||||||
|
|
||||||
// Zip file is always created with unix-style path names.
|
|
||||||
buf.append('/');
|
|
||||||
|
|
||||||
buf.append(baseFileName.toLowerCase(Locale.ENGLISH));
|
|
||||||
buf.append(CARD_FILE_DOT_EXTENSION);
|
|
||||||
|
|
||||||
return buf.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempt to load a card by its canonical ASCII name.
|
|
||||||
*
|
|
||||||
* @param canonicalASCIIName the canonical ASCII name of the card
|
|
||||||
*
|
|
||||||
* @return a new Card instance having that name, or null if not found
|
|
||||||
public final Card findCard(final String canonicalASCIIName) { // NOPMD by Braids on 8/18/11 11:08 PM
|
|
||||||
UtilFunctions.checkNotNull("canonicalASCIIName", canonicalASCIIName);
|
|
||||||
|
|
||||||
final String cardFilePath = toMostLikelyPath(canonicalASCIIName);
|
|
||||||
|
|
||||||
Card result = null;
|
|
||||||
|
|
||||||
if (zip != null) {
|
|
||||||
final ZipEntry entry = zip.getEntry(cardFilePath);
|
|
||||||
|
|
||||||
if (entry != null) {
|
|
||||||
result = loadCard(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
result = loadCard(new File(cardsfolder, cardFilePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == null || !(result.getName().equals(canonicalASCIIName))) {
|
|
||||||
//System.err.println(":Could not find \"" + cardFilePath + "\".");
|
|
||||||
result = loadCardsUntilYouFind(canonicalASCIIName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
|
import net.slightlymagic.braids.util.lambda.Lambda1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>CardSet class.</p>
|
* <p>CardSet class.</p>
|
||||||
*
|
*
|
||||||
@@ -24,6 +26,12 @@ public final class CardSet implements Comparable<CardSet> { // immutable
|
|||||||
public String getCode2() { return code2; }
|
public String getCode2() { return code2; }
|
||||||
public int getIndex() { return index; }
|
public int getIndex() { return index; }
|
||||||
|
|
||||||
|
|
||||||
|
public static final Lambda1<String, CardSet> fnGetName = new Lambda1<String, CardSet>() {
|
||||||
|
@Override public String apply(final CardSet arg1) { return arg1.name; } };
|
||||||
|
public static final Lambda1<CardSet, CardSet> fn1 = new Lambda1<CardSet, CardSet>() {
|
||||||
|
@Override public CardSet apply(final CardSet arg1) { return arg1; } };
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(final CardSet o) {
|
public int compareTo(final CardSet o) {
|
||||||
if (o == null) { return 1; }
|
if (o == null) { return 1; }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.FileUtil;
|
import forge.FileUtil;
|
||||||
|
import forge.card.CardManaCost.ManaParser;
|
||||||
import forge.properties.ForgeProps;
|
import forge.properties.ForgeProps;
|
||||||
import forge.properties.NewConstants;
|
import forge.properties.NewConstants;
|
||||||
|
|
||||||
@@ -84,9 +85,12 @@ public final class MtgDataParser implements Iterator<CardRules> {
|
|||||||
String name = it.next();
|
String name = it.next();
|
||||||
|
|
||||||
if (!it.hasNext()) { weHaveNext = false; return null; }
|
if (!it.hasNext()) { weHaveNext = false; return null; }
|
||||||
|
|
||||||
String manaCost = it.next();
|
String manaCost = it.next();
|
||||||
|
CardManaCost cost = CardManaCost.empty;
|
||||||
CardType type = null;
|
CardType type = null;
|
||||||
if (manaCost.startsWith("{")) {
|
if (manaCost.startsWith("{")) {
|
||||||
|
cost = new CardManaCost(new ManaParserMtgData(manaCost));
|
||||||
if (!it.hasNext()) { weHaveNext = false; return null; }
|
if (!it.hasNext()) { weHaveNext = false; return null; }
|
||||||
type = CardType.parse(it.next());
|
type = CardType.parse(it.next());
|
||||||
} else { // Land?
|
} else { // Land?
|
||||||
@@ -114,7 +118,7 @@ public final class MtgDataParser implements Iterator<CardRules> {
|
|||||||
|
|
||||||
if (sets.isEmpty()) { return null; } // that was a bad card - it won't be added by invoker
|
if (sets.isEmpty()) { return null; } // that was a bad card - it won't be added by invoker
|
||||||
|
|
||||||
return new CardRules(name, type, manaCost, ptOrLoyalty, strs.toArray(emptyArray), sets,
|
return new CardRules(name, type, cost, ptOrLoyalty, strs.toArray(emptyArray), sets,
|
||||||
// TODO: fix last two parameters
|
// TODO: fix last two parameters
|
||||||
false, false);
|
false, false);
|
||||||
}
|
}
|
||||||
@@ -159,4 +163,63 @@ public final class MtgDataParser implements Iterator<CardRules> {
|
|||||||
@Override public void remove() { }
|
@Override public void remove() { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class ManaParserMtgData implements ManaParser {
|
||||||
|
private final String cost;
|
||||||
|
|
||||||
|
private int nextBracket;
|
||||||
|
private int colorlessCost;
|
||||||
|
|
||||||
|
|
||||||
|
public ManaParserMtgData(final String cost) {
|
||||||
|
this.cost = cost;
|
||||||
|
// System.out.println(cost);
|
||||||
|
nextBracket = cost.indexOf('{');
|
||||||
|
colorlessCost = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalColorlessCost() {
|
||||||
|
if ( hasNext() ) {
|
||||||
|
throw new RuntimeException("Colorless cost should be obtained after iteration is complete");
|
||||||
|
}
|
||||||
|
return colorlessCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() { return nextBracket != -1; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CardManaCostShard next() {
|
||||||
|
int closeBracket = cost.indexOf('}', nextBracket);
|
||||||
|
String unparsed = cost.substring(nextBracket + 1, closeBracket);
|
||||||
|
nextBracket = cost.indexOf('{', closeBracket + 1);
|
||||||
|
|
||||||
|
// System.out.println(unparsed);
|
||||||
|
if (StringUtils.isNumeric(unparsed)) {
|
||||||
|
colorlessCost += Integer.parseInt(unparsed);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int atoms = 0;
|
||||||
|
for (int iChar = 0; iChar < unparsed.length(); iChar++) {
|
||||||
|
switch (unparsed.charAt(iChar)) {
|
||||||
|
case 'W': atoms |= CardManaCostShard.Atom.WHITE; break;
|
||||||
|
case 'U': atoms |= CardManaCostShard.Atom.BLUE; break;
|
||||||
|
case 'B': atoms |= CardManaCostShard.Atom.BLACK; break;
|
||||||
|
case 'R': atoms |= CardManaCostShard.Atom.RED; break;
|
||||||
|
case 'G': atoms |= CardManaCostShard.Atom.GREEN; break;
|
||||||
|
case '2': atoms |= CardManaCostShard.Atom.OR_2_COLORLESS; break;
|
||||||
|
case 'P': atoms |= CardManaCostShard.Atom.OR_2_LIFE; break;
|
||||||
|
case 'X': atoms |= CardManaCostShard.Atom.IS_X; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CardManaCostShard.valueOf(atoms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() { } // unsuported
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ package forge.card.cardFactory;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import forge.AllZone;
|
import forge.AllZone;
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CardReader;
|
import forge.CardReader;
|
||||||
|
import forge.card.CardDb;
|
||||||
|
import forge.card.CardRules;
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
import forge.properties.ForgeProps;
|
import forge.properties.ForgeProps;
|
||||||
|
|
||||||
@@ -69,10 +73,13 @@ public class PreloadingCardFactory extends AbstractCardFactory {
|
|||||||
protected void readCards(File file) {
|
protected void readCards(File file) {
|
||||||
getMap().clear();
|
getMap().clear();
|
||||||
|
|
||||||
CardReader read = new CardReader(ForgeProps.getFile(CARDSFOLDER), getMap());
|
List<CardRules> listCardRules = new ArrayList<CardRules>();
|
||||||
|
CardReader read = new CardReader(ForgeProps.getFile(CARDSFOLDER), getMap(), listCardRules);
|
||||||
|
|
||||||
|
|
||||||
// this fills in our map of card names to Card instances.
|
// this fills in our map of card names to Card instances.
|
||||||
read.run();
|
read.run();
|
||||||
|
CardDb.setup(listCardRules.iterator());
|
||||||
}// readCard()
|
}// readCard()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user