mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
lazycf, slight updates to classes - more parsing moved to appropiate class
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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() { }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user