lazycf, slight updates to classes - more parsing moved to appropiate class

This commit is contained in:
Maxmtg
2011-08-28 15:20:43 +00:00
parent 117d10fa74
commit af5948e344
6 changed files with 152 additions and 59 deletions

View File

@@ -47,7 +47,7 @@ public final class CardDb {
this(new MtgDataParser()); // I wish cardname.txt parser was be here. this(new MtgDataParser()); // I wish cardname.txt parser was be here.
} }
private CardDb(final Iterator<CardRules> parser) { private CardDb(final Iterator<CardRules> parser) {
while (parser.hasNext()) { while (parser.hasNext()) {
addNewCard(parser.next()); addNewCard(parser.next());
} }
@@ -57,33 +57,31 @@ public final class CardDb {
if (null == card) { return; } if (null == card) { return; }
//System.out.println(card.getName()); //System.out.println(card.getName());
String cardName = card.getName(); String cardName = card.getName();
// 1. register among oracle uniques // 1. register among oracle uniques
cards.put(cardName, card); cards.put(cardName, card);
// 2. fill refs into two lists: one with // 2. Save refs into two lists: one flat and other keyed with sets & name
CardPrinted lastAdded = null; CardPrinted lastAdded = null;
for (Entry<String, CardInSet> s : card.getSetsPrinted()) { for (Entry<String, CardInSet> s : card.getSetsPrinted()) {
String set = s.getKey(); String set = s.getKey();
// get this set storage, if not found, create it! // get this set storage, if not found, create it!
Map<String, CardPrinted[]> setMap = allCardsBySet.get(set); Map<String, CardPrinted[]> setMap = allCardsBySet.get(set);
if (null == setMap) { if (null == setMap) {
setMap = new Hashtable<String, CardPrinted[]>(); setMap = new Hashtable<String, CardPrinted[]>();
allCardsBySet.put(set, setMap); allCardsBySet.put(set, setMap);
} }
int count = s.getValue().getCopiesCount(); int count = s.getValue().getCopiesCount();
CardPrinted[] cards = new CardPrinted[count]; CardPrinted[] cardCopies = new CardPrinted[count];
setMap.put(cardName, cards); setMap.put(cardName, cardCopies);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
lastAdded = CardPrinted.build(card, set, s.getValue().getRarity(), i+1); lastAdded = CardPrinted.build(card, set, s.getValue().getRarity(), i);
allCardsFlat.add(lastAdded); allCardsFlat.add(lastAdded);
cards[i] = lastAdded; cardCopies[i] = lastAdded;
} }
} }
uniqueCards.put(cardName, lastAdded); uniqueCards.put(cardName, lastAdded);
} }
@@ -113,8 +111,8 @@ 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-1]; } 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. Note: artIndex is 1-based", 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);
} }

View File

@@ -8,38 +8,14 @@ package forge.card;
*/ */
public class CardInSet { public class CardInSet {
private CardRarity rarity; private final CardRarity rarity;
private int numCopies; private final int numCopies;
public CardInSet(final CardRarity rarity, final int cntCopies) { public CardInSet(final CardRarity rarity, final int cntCopies) {
this.rarity = rarity; this.rarity = rarity;
this.numCopies = cntCopies; this.numCopies = cntCopies;
} }
public static CardInSet parse(final String unparsed) {
int spaceAt = unparsed.indexOf(' ');
char rarity = unparsed.charAt(spaceAt + 1);
CardRarity rating;
switch (rarity) {
case 'L': rating = CardRarity.BasicLand; break;
case 'C': rating = CardRarity.Common; break;
case 'U': rating = CardRarity.Uncommon; break;
case 'R': rating = CardRarity.Rare; break;
case 'M': rating = CardRarity.MythicRare; break;
case 'S': rating = CardRarity.Special; break;
default: rating = CardRarity.MythicRare; break;
}
int number = 1;
int bracketAt = unparsed.indexOf('(');
if (-1 != bracketAt) {
String sN = unparsed.substring(bracketAt + 2, bracketAt + 3);
number = Integer.parseInt(sN);
}
return new CardInSet(rating, number);
}
public final int getCopiesCount() { return numCopies; } public final int getCopiesCount() { return numCopies; }
public final CardRarity getRarity() { return rarity; } public final CardRarity getRarity() { return rarity; }
} }

View File

@@ -1,6 +1,9 @@
package forge.card; package forge.card;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@@ -31,7 +34,7 @@ public final class CardRules {
private String loyalty = null; private String loyalty = null;
private HashMap<String, CardInSet> setsPrinted = null; private Map<String, CardInSet> setsPrinted = null;
// Ctor and builders are needed here // Ctor and builders are needed here
public String getName() { return name; } public String getName() { return name; }
@@ -54,7 +57,7 @@ public final class CardRules {
} }
public CardRules(final String cardName, final CardType cardType, final String manacost, public CardRules(final String cardName, final CardType cardType, final String manacost,
final String ptLine, final String[] cardRules, final String[] setsData) final String ptLine, final String[] cardRules, final Map<String, CardInSet> setsData)
{ {
this.name = cardName; this.name = cardName;
this.type = cardType; this.type = cardType;
@@ -73,12 +76,7 @@ public final class CardRules {
} else if (cardType.isPlaneswalker()) { } else if (cardType.isPlaneswalker()) {
this.loyalty = ptLine; this.loyalty = ptLine;
} }
setsPrinted = setsData;
this.setsPrinted = new HashMap<String, CardInSet>();
for (int iSet = 0; iSet < setsData.length; iSet++) {
String setCode = setsData[iSet].substring(0, setsData[iSet].indexOf(' '));
setsPrinted.put(setCode, CardInSet.parse(setsData[iSet]));
}
} }
public boolean rulesContain(final String text) { public boolean rulesContain(final String text) {
@@ -334,8 +332,20 @@ public final class CardRules {
public static final Predicate<CardRules> isBlack = isColor(CardColor.BLACK); public static final Predicate<CardRules> isBlack = isColor(CardColor.BLACK);
public static final Predicate<CardRules> isRed = isColor(CardColor.RED); public static final Predicate<CardRules> isRed = isColor(CardColor.RED);
public static final Predicate<CardRules> isGreen = isColor(CardColor.GREEN); public static final Predicate<CardRules> isGreen = isColor(CardColor.GREEN);
public static final Predicate<CardRules> isColorless = hasCntColors((byte) 0); public static final Predicate<CardRules> isColorless = hasCntColors((byte) 0);
public static final Predicate<CardRules> isMulticolor = hasAtLeastCntColors((byte) 2); public static final Predicate<CardRules> isMulticolor = hasAtLeastCntColors((byte) 2);
public static final List<Predicate<CardRules>> colors = new ArrayList<Predicate<CardRules>>();
static {
colors.add(isWhite);
colors.add(isBlue);
colors.add(isBlack);
colors.add(isRed);
colors.add(isGreen);
colors.add(isColorless);
}
// Think twice before using these, since rarity is a prop of printed card. // Think twice before using these, since rarity is a prop of printed card.
public static final Predicate<CardRules> isInLatestSetCommon = rarityInCardsLatestSet(true, CardRarity.Common); public static final Predicate<CardRules> isInLatestSetCommon = rarityInCardsLatestSet(true, CardRarity.Common);

View File

@@ -83,6 +83,9 @@ public final class CardType implements Comparable<CardType> {
public boolean isSorcery() { return coreType.contains(CardCoreType.Sorcery); } public boolean isSorcery() { return coreType.contains(CardCoreType.Sorcery); }
public boolean isEnchantment() { return coreType.contains(CardCoreType.Enchantment); } public boolean isEnchantment() { return coreType.contains(CardCoreType.Enchantment); }
public boolean isBasic() { return superType.contains(CardSuperType.Basic); }
public boolean isLegendary() { return superType.contains(CardSuperType.Legendary); }
public String getTypesBeforeDash() { public String getTypesBeforeDash() {
ArrayList<String> types = new ArrayList<String>(); ArrayList<String> types = new ArrayList<String>();
for (CardSuperType st : superType) { types.add(st.name()); } for (CardSuperType st : superType) { types.add(st.name()); }
@@ -109,5 +112,6 @@ public final class CardType implements Comparable<CardType> {
public int compareTo(final CardType o) { public int compareTo(final CardType o) {
return toString().compareTo(o.toString()); return toString().compareTo(o.toString());
} }
} }

View File

@@ -1,10 +1,16 @@
package forge.card; package forge.card;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.tools.ant.taskdefs.compilers.Sj;
import forge.FileUtil; import forge.FileUtil;
import forge.properties.ForgeProps; import forge.properties.ForgeProps;
@@ -19,6 +25,48 @@ public final class MtgDataParser implements Iterator<CardRules> {
it = mtgDataLines.iterator(); it = mtgDataLines.iterator();
skipSetList(); skipSetList();
} }
private static List<String> setsToSkipPrefixes = new ArrayList<String>();
private static List<String> unSets = new ArrayList<String>(); // take only lands from there
static {
setsToSkipPrefixes.add("VG"); // Vanguard
setsToSkipPrefixes.add("ME"); // Mtgo master's editions
setsToSkipPrefixes.add("FV"); // From the vaults
// Duel decks... or... should I keep them?
setsToSkipPrefixes.add("DVD");
setsToSkipPrefixes.add("EVT");
setsToSkipPrefixes.add("EVG");
setsToSkipPrefixes.add("GVL");
setsToSkipPrefixes.add("JVC");
setsToSkipPrefixes.add("DDG");
setsToSkipPrefixes.add("PVC");
// Archenemy - we cannot play it now anyway
setsToSkipPrefixes.add("ARC");
// Planechase - this too
setsToSkipPrefixes.add("HOP");
// Reprints
setsToSkipPrefixes.add("BRB");
setsToSkipPrefixes.add("BTD");
setsToSkipPrefixes.add("DKM");
//setsToSkipPrefixes.add("ATH"); // No need to skip it really.
// On gatherer's opinion this cards was releases twice in original set
// Promo sets - all cards have been issued in other sets
setsToSkipPrefixes.add("SDC");
setsToSkipPrefixes.add("ASTRAL");
// Premium decks
setsToSkipPrefixes.add("H09");
setsToSkipPrefixes.add("H10");
// Un-sets are weird, but lands from there are valuable
unSets.add("UNH");
unSets.add("UGL");
}
private boolean weHaveNext; private boolean weHaveNext;
private void skipSetList() { private void skipSetList() {
@@ -38,6 +86,7 @@ public final class MtgDataParser implements Iterator<CardRules> {
public CardRules next() { public CardRules next() {
if (!it.hasNext()) { weHaveNext = false; return null; } if (!it.hasNext()) { weHaveNext = false; return null; }
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();
CardType type = null; CardType type = null;
@@ -61,12 +110,55 @@ public final class MtgDataParser implements Iterator<CardRules> {
strs.add(nextLine); strs.add(nextLine);
nextLine = it.next(); nextLine = it.next();
} }
String[] sets = strs.remove(strs.size() - 1).split(", "); // feel free to return null after this line
String setsLine = strs.remove(strs.size() - 1);
boolean isBasicLand = type.isLand() && type.isBasic();
Map<String, CardInSet> sets = getValidEditions(setsLine, isBasicLand);
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, manaCost, ptOrLoyalty, strs.toArray(emptyArray), sets);
} }
@Override public void remove() { } private Map<String, CardInSet> getValidEditions(final String sets, final boolean isBasicLand) {
String[] setsData = sets.split(", ");
Map<String, CardInSet> result = new HashMap<String, CardInSet>();
for (int iSet = 0; iSet < setsData.length; iSet++) {
int spacePos = setsData[iSet].indexOf(' ');
String setCode = setsData[iSet].substring(0, spacePos);
boolean shouldSkip = false;
for (String s : setsToSkipPrefixes) { if (setCode.startsWith(s)) { shouldSkip = true; break; } }
for (String s : unSets) { if (setCode.startsWith(s) && !isBasicLand) { shouldSkip = true; break; } }
if (shouldSkip) { continue; }
result.put(setCode, parseCardInSet(setsData[iSet], spacePos));
}
return result;
}
public static CardInSet parseCardInSet(final String unparsed, final int spaceAt) {
char rarity = unparsed.charAt(spaceAt + 1);
CardRarity rating;
switch (rarity) {
case 'L': rating = CardRarity.BasicLand; break;
case 'C': rating = CardRarity.Common; break;
case 'U': rating = CardRarity.Uncommon; break;
case 'R': rating = CardRarity.Rare; break;
case 'M': rating = CardRarity.MythicRare; break;
case 'S': rating = CardRarity.Special; break;
default: rating = CardRarity.MythicRare; break;
}
int number = 1;
int bracketAt = unparsed.indexOf('(', spaceAt);
if (-1 != bracketAt) {
String sN = unparsed.substring(bracketAt + 2, unparsed.indexOf(')', bracketAt));
number = Integer.parseInt(sN);
}
return new CardInSet(rating, number);
}
@Override public void remove() { }
} }

View File

@@ -1,7 +1,9 @@
package forge.card.cardFactory; 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 java.util.Map; import java.util.Map;
import net.slightlymagic.braids.util.NotImplementedError; import net.slightlymagic.braids.util.NotImplementedError;
@@ -20,7 +22,8 @@ import forge.Player;
public class LazyCardFactory extends AbstractCardFactory { public class LazyCardFactory extends AbstractCardFactory {
private final CardReader cardReader; private final CardReader cardReader;
private final List<String> cardsFailedToLoad = new ArrayList<String>();
/** /**
* Construct an instance, pointing it to a specific cardsfolder. * Construct an instance, pointing it to a specific cardsfolder.
* *
@@ -65,18 +68,28 @@ public class LazyCardFactory extends AbstractCardFactory {
protected Card getCard2(final String cardName, final Player owner) { protected Card getCard2(final String cardName, final Player owner) {
final Map<String, Card> cardNamesToCards = getMap(); final Map<String, Card> cardNamesToCards = getMap();
Card result = null; Card result = null;
boolean cardExists = false; boolean wasLoaded = cardNamesToCards.containsKey(cardName);
if (!wasLoaded) {
if (cardsFailedToLoad.contains(cardName)) {
return null; // no more System.err, exceptions of other drama - just return null.
}
if (!cardNamesToCards.containsKey(cardName)) {
final String canonicalASCIIName = CardUtil.canonicalizeCardName(cardName); final String canonicalASCIIName = CardUtil.canonicalizeCardName(cardName);
getCardReader().findCard(canonicalASCIIName); Card cardRequested = getCardReader().findCard(canonicalASCIIName);
if (null != cardRequested) {
if (cardNamesToCards.containsKey(cardName)) { cardNamesToCards.put(cardName, cardRequested);
cardExists = true; wasLoaded = true;
} else {
cardsFailedToLoad.add(cardName);
System.err.println(String.format("LazyCF: Tried to read from disk card '%s' but not found it!", cardName));
return null;
} }
} }
if (cardExists) { // Factory should return us a copy, ready for changes.
if (wasLoaded) {
result = super.getCard2(cardName, owner); result = super.getCard2(cardName, owner);
} }