CardDb moved to forge.card package,

CardDb is initialized with list of CardRules and CardEditions.
Rules no longer aware of sets they were issued in
This commit is contained in:
Maxmtg
2013-06-05 15:34:26 +00:00
parent 43b4ae6b23
commit 045cd2b0fb
57 changed files with 585 additions and 663 deletions

View File

@@ -40,6 +40,7 @@ import com.google.common.collect.ImmutableList;
import forge.CardPredicates.Presets;
import forge.card.CardCharacteristics;
import forge.card.CardDb;
import forge.card.CardRarity;
import forge.card.CardRules;
import forge.card.ColorSet;
@@ -75,7 +76,6 @@ import forge.game.phase.Combat;
import forge.game.player.Player;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.item.CardDb;
import forge.util.Expressions;
/**

View File

@@ -34,6 +34,7 @@ import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.LoadingCache;
import com.mortennobel.imagescaling.ResampleOp;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.game.player.IHasIcon;
@@ -247,7 +248,7 @@ public class ImageCache {
final int cntPictures;
final boolean hasManyPictures;
if (includeSet) {
cntPictures = card.getEditionInfo(edition).getCopiesCount();
cntPictures = card.isTraditional() ? CardDb.instance().getPrintCount(card.getName(), edition) : CardDb.variants().getPrintCount(card.getName(), edition);
hasManyPictures = cntPictures > 1;
} else {
// without set number of pictures equals number of urls provided in Svar:Picture
@@ -255,10 +256,7 @@ public class ImageCache {
cntPictures = StringUtils.countMatches(urls, "\\") + 1;
// raise the art index limit to the maximum of the sets this card was printed in
int maxCntPictures = 1;
for (String set : card.getSets()) {
maxCntPictures = Math.max(maxCntPictures, card.getEditionInfo(set).getCopiesCount());
}
int maxCntPictures = card.isTraditional() ? CardDb.instance().getMaxPrintCount(card.getName()) : CardDb.variants().getMaxPrintCount(card.getName());
hasManyPictures = maxCntPictures > 1;
}

View File

@@ -35,7 +35,6 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.PrintSheet;

View File

@@ -0,0 +1,349 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.card;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Card;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.MyRandom;
import forge.util.maps.CollectionSuppliers;
import forge.util.maps.MapOfLists;
import forge.util.maps.TreeMapOfLists;
public final class CardDb implements ICardDatabase {
private static volatile CardDb commonCards = null; // 'volatile' keyword makes this working
private static volatile CardDb variantCards = null; // 'volatile' keyword makes this working
public final static String foilSuffix = " foil";
private final static int foilSuffixLength = foilSuffix.length();
public static ICardDatabase instance() {
if (CardDb.commonCards == null) {
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
}
return CardDb.commonCards;
}
public static ICardDatabase variants() {
if (CardDb.variantCards == null) {
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
}
return CardDb.variantCards;
}
public static void setup(final Iterable<CardRules> rules, Iterable<CardEdition> editions) {
if (CardDb.commonCards != null) {
throw new RuntimeException("CardDb has already been initialized, don't do it twice please");
}
synchronized (CardDb.class) {
if (CardDb.commonCards == null) { // It's broken under 1.4 and below, on 1.5+ works again!
CardSorter cs = new CardSorter(rules);
commonCards = new CardDb(cs.regularCards, editions);
variantCards = new CardDb(cs.variantsCards, editions);
}
}
}
// need this to obtain cardReference by name+set+artindex
private final MapOfLists<String, PaperCard> allCardsByName = new TreeMapOfLists<String, PaperCard>(String.CASE_INSENSITIVE_ORDER, CollectionSuppliers.<PaperCard>arrayLists());
private final Map<String, PaperCard> uniqueCardsByName = new TreeMap<String, PaperCard>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, CardRules> rulesByName;
private final List<PaperCard> allCards = new ArrayList<PaperCard>();
private final List<PaperCard> roAllCards = Collections.unmodifiableList(allCards);
private final Collection<PaperCard> roUniqueCards = Collections.unmodifiableCollection(uniqueCardsByName.values());
// Lambda to get rules for selects from list of printed cards
/** The Constant fnGetCardPrintedByForgeCard. */
public static final Function<Card, PaperCard> FN_GET_CARD_PRINTED_BY_FORGE_CARD = new Function<Card, PaperCard>() {
@Override
public PaperCard apply(final Card from) {
return CardDb.instance().getCard(from.getName());
}
};
private CardDb(Map<String, CardRules> rules, Iterable<CardEdition> editions) {
this.rulesByName = rules;
for(CardEdition e : editions) {
String lastCardName = null;
int artIdx = 0;
for(CardEdition.CardInSet cis : e.getCards()) {
if ( cis.name.equals(lastCardName) )
artIdx++;
else {
artIdx = 0;
lastCardName = cis.name;
}
CardRules cr = rulesByName.get(lastCardName);
if( cr != null )
addCard(new PaperCard(cr, e.getCode(), cis.rarity, artIdx));
// else card is not scripted yet
}
}
reIndex();
}
private void addCard(PaperCard paperCard) {
allCardsByName.add(paperCard.name, paperCard);
}
private void reIndex() {
uniqueCardsByName.clear();
allCards.clear();
for(Entry<String, Collection<PaperCard>> kv : allCardsByName.entrySet()) {
uniqueCardsByName.put(kv.getKey(), Iterables.get(kv.getValue(), 0));
allCards.addAll(kv.getValue());
}
}
/**
* Splits cardname into Name and set whenever deck line reads as name|set.
*/
private static ImmutablePair<String, String> splitCardName(final String name) {
String cardName = name; // .trim() ?
final int pipePos = cardName.indexOf('|');
if (pipePos >= 0) {
final String setName = cardName.substring(pipePos + 1).trim();
cardName = cardName.substring(0, pipePos);
// only if set is not blank try to load it
if (StringUtils.isNotBlank(setName) && !"???".equals(setName)) {
return new ImmutablePair<String, String>(cardName, setName);
}
}
return new ImmutablePair<String, String>(cardName, null);
}
private boolean isFoil(final String cardName) {
return cardName.toLowerCase().endsWith(CardDb.foilSuffix) && (cardName.length() > CardDb.foilSuffixLength);
}
/**
* Removes the foil suffix.
*
* @param cardName the card name
* @return the string
*/
public String removeFoilSuffix(final String cardName) {
return cardName.substring(0, cardName.length() - CardDb.foilSuffixLength);
}
/**
* Checks if is card supported.
*/
@Override
public PaperCard tryGetCard(final String cardName0) {
return tryGetCard(cardName0, true);
}
@Override
public PaperCard tryGetCard(final String cardName0, boolean fromLastSet) {
if (null == cardName0) {
return null; // obviously
}
final boolean isFoil = this.isFoil(cardName0);
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
final PaperCard res = nameWithSet.right == null
? ( fromLastSet ? this.uniqueCardsByName.get(nameWithSet.left) : Aggregates.random(this.allCardsByName.get(nameWithSet.left)) )
: tryGetCard(nameWithSet.left, nameWithSet.right);
return null != res && isFoil ? PaperCard.makeFoiled(res) : res;
}
@Override
public PaperCard tryGetCard(final String cardName, String setName) {
return tryGetCard(cardName, setName, -1);
}
@Override
public int getPrintCount(String cardName, String edition) {
int cnt = 0;
for( PaperCard pc : allCardsByName.get(cardName) ) {
if( pc.getEdition().equals(edition) )
cnt++;
}
return cnt;
}
@Override
public int getMaxPrintCount(String cardName) {
int max = -1;
for( PaperCard pc : allCardsByName.get(cardName) ) {
if ( max < pc.getArtIndex() )
max = pc.getArtIndex();
}
return max + 1;
}
@Override
public PaperCard tryGetCard(final String cardName, String setName, int index) {
Collection<PaperCard> cards = allCardsByName.get(cardName);
if ( null == cards ) return null;
if ( index < 0 ) { // this stands for 'random art'
PaperCard[] candidates = new PaperCard[8]; // 8 cards with same name per set is a maximum of what has been printed (lands of Zendikar)
int cnt = 0;
for( PaperCard pc : cards ) {
if( pc.getEdition().equals(setName) )
candidates[cnt++] = pc;
}
if (candidates.length == 0 ) return null;
if (candidates.length == 1 ) return candidates[0];
return candidates[MyRandom.getRandom().nextInt(cnt)];
} else
for( PaperCard pc : cards ) {
if( pc.getEdition().equals(setName) && index == pc.getArtIndex() )
return pc;
}
return null;
}
// Single fetch
@Override
public PaperCard getCard(final String name) {
return this.getCard(name, false);
}
@Override
public PaperCard getCard(final String name0, final boolean fromLatestSet) {
// Sometimes they read from decks things like "CardName|Set" - but we
// can handle it
final PaperCard result = tryGetCard(name0, fromLatestSet);
if (null == result) {
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name0));
}
return result;
}
// Advanced fetch by name+set
@Override
public PaperCard getCard(final String name, final String set) {
return this.getCard(name, set, -1);
}
@Override
public PaperCard getCard(final String name, final String set, final int artIndex) {
final PaperCard result = tryGetCard(name, set, artIndex);
if (null == result) {
final String message = String.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
throw new NoSuchElementException(message);
}
return result;
}
// Fetch from Forge's Card instance. Well, there should be no errors, but
// we'll still check
public static PaperCard getCard(final Card forgeCard) {
final String name = forgeCard.getName();
final String set = forgeCard.getCurSetCode();
if (StringUtils.isNotBlank(set)) {
PaperCard cp = variants().tryGetCard(name, set);
return cp == null ? instance().getCard(name, set) : cp;
}
PaperCard cp = variants().tryGetCard(name, true);
return cp == null ? instance().getCard(name) : cp;
}
// returns a list of all cards from their respective latest editions
@Override
public Collection<PaperCard> getUniqueCards() {
return roUniqueCards;
}
@Override
public List<PaperCard> getAllCards() {
return roAllCards;
}
/** Returns a modifiable list of cards matching the given predicate */
@Override
public List<PaperCard> getAllCards(Predicate<PaperCard> predicate) {
return Lists.newArrayList(Iterables.filter(this.roAllCards, predicate));
}
private static class CardSorter{
// Here are refs, get them by name
public final Map<String, CardRules> regularCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
public final Map<String, CardRules> variantsCards = new TreeMap<String, CardRules>(String.CASE_INSENSITIVE_ORDER);
private void addNewCard(final CardRules card) {
if (null == card) {
return;
} // consider that a success
// System.out.println(card.getName());
final String cardName = card.getName();
if ( card.isTraditional() )
regularCards.put(cardName, card);
else
variantsCards.put(cardName, card);
}
CardSorter(final Iterable<CardRules> parser) {
for (CardRules cr : parser) {
this.addNewCard(cr);
}
}
}
public Predicate<? super PaperCard> wasPrintedInSets(List<String> setCodes) {
return new PredicateExistsInSets(setCodes);
}
private class PredicateExistsInSets implements Predicate<PaperCard> {
private final List<String> sets;
public PredicateExistsInSets(final List<String> wantSets) {
this.sets = wantSets; // maybe should make a copy here?
}
@Override
public boolean apply(final PaperCard subject) {
Collection<PaperCard> cc = allCardsByName.get(subject.getName());
for(PaperCard c : cc) if (sets.contains(c.getEdition())) return true;
return false;
}
}
}

View File

@@ -17,16 +17,26 @@
*/
package forge.card;
import java.io.File;
import java.io.FilenameFilter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import forge.Singletons;
import forge.game.GameFormat;
import forge.item.CardDb;
import forge.util.FileSection;
import forge.util.storage.StorageReaderFile;
import forge.util.FileUtil;
import forge.util.storage.StorageReaderFolder;
/**
@@ -40,23 +50,45 @@ import forge.util.storage.StorageReaderFile;
public final class CardEdition implements Comparable<CardEdition> { // immutable
public enum Type {
UNKNOWN,
CORE,
EXPANSION,
REPRINT,
STARTER,
OTHER
DUEL_DECKS,
PREMIUM_DECK_SERIES,
FROM_THE_VAULT,
OTHER,
THIRDPARTY // custom sets
}
/** The Constant unknown. */
public static final CardEdition UNKNOWN = new CardEdition(-1, "??", "???", Type.UNKNOWN, "Undefined", null, false);
public static class CardInSet {
public final CardRarity rarity;
public final String name;
private final int index;
public CardInSet(final String name, final CardRarity rarity) {
this.rarity = rarity;
this.name = name;
}
}
/** The Constant unknown. */
private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
public static final CardEdition UNKNOWN = new CardEdition("1990-01-01", "??", "???", Type.UNKNOWN, "Undefined", null, false, new CardInSet[]{});
private Date date;
private final String code2;
private final String code;
private final Type type;
private final String name;
private final String alias;
private final boolean whiteBorder;
private final CardInSet[] cards;
/**
* Instantiates a new card set.
@@ -71,22 +103,30 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
* @param name the name of the set
* @param an optional secondary code alias for the set
*/
private CardEdition(int index, String code2, String code, Type type, String name, String alias, boolean whiteBorder) {
this.index = index;
private CardEdition(String date, String code2, String code, Type type, String name, String alias, boolean whiteBorder, CardInSet[] cards) {
this.code2 = code2;
this.code = code;
this.type = type;
this.name = name;
this.alias = alias;
this.whiteBorder = whiteBorder;
this.cards = cards;
if( date.length() <= 7 )
date = date + "-01";
try {
this.date = formatter.parse(date);
} catch (ParseException e) {
this.date = new Date();
}
}
public int getIndex() { return index; }
public Date getDate() { return date; }
public String getCode2() { return code2; }
public String getCode() { return code; }
public Type getType() { return type; }
public String getName() { return name; }
public String getAlias() { return alias; }
public CardInSet[] getCards() { return cards; }
/** The Constant fnGetName. */
public static final Function<CardEdition, String> FN_GET_CODE = new Function<CardEdition, String>() {
@@ -101,7 +141,7 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
if (o == null) {
return 1;
}
return o.index - this.index;
return date.compareTo(o.date);
}
@Override
@@ -202,19 +242,26 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
}
public static class Reader extends StorageReaderFile<CardEdition> {
public Reader(String pathname) {
super(pathname, CardEdition.FN_GET_CODE);
public static class EditionReader extends StorageReaderFolder<CardEdition> {
public EditionReader(File path) {
super(path, CardEdition.FN_GET_CODE);
}
public final static CardInSet[] arrCards = new CardInSet[] {};
@Override
protected CardEdition read(String line, int i) {
FileSection section = FileSection.parse(line, ":", "|");
int index = 1+i;
String code2 = section.get("code2");
String code = section.get("code3");
String type = section.get("type");
protected CardEdition read(File file) {
final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file));
FileSection section = FileSection.parse(contents.get("metadata"), "=");
String name = section.get("name");
String date = section.get("date");
String code = section.get("code");
String code2 = section.get("code2");
if( code2 == null )
code2 = code;
String type = section.get("type");
String alias = section.get("alias");
boolean borderWhite = "white".equalsIgnoreCase(section.get("border"));
@@ -228,10 +275,33 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
}
}
// if( !code2.equals(code) ) System.out.printf("%s->%s|", code, code);
List<CardEdition.CardInSet> processedCards = new ArrayList<CardEdition.CardInSet>();
for(String line : contents.get("cards")) {
if (StringUtils.isBlank(line))
continue;
return new CardEdition(index, code2, code, enumType, name, alias, borderWhite);
// You may omit rarity for early development
CardRarity r = CardRarity.smartValueOf(line.substring(0, 1));
boolean hadRarity = r != CardRarity.Unknown && line.charAt(1) == ' ';
String cardName = hadRarity ? line.substring(2) : line;
CardInSet cis = new CardInSet(cardName, r);
processedCards.add(cis);
}
return new CardEdition(date, code2, code, enumType, name, alias, borderWhite, processedCards.toArray(arrCards));
}
@Override
protected FilenameFilter getFileFilter() {
return TXT_FILE_FILTER;
}
public static final FilenameFilter TXT_FILE_FILTER = new FilenameFilter() {
@Override
public boolean accept(final File dir, final String name) {
return name.endsWith(".txt");
}
};
}
}

View File

@@ -1,64 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.card;
/**
* <p>
* CardInSet class.
* </p>
*
* @author Forge
* @version $Id: CardInSet.java 9708 2011-08-09 19:34:12Z jendave $
*/
public class CardInSet {
private final CardRarity rarity;
private final int numCopies;
/**
* Instantiates a new card in set.
*
* @param rarity
* the rarity
* @param cntCopies
* the cnt copies
*/
public CardInSet(final CardRarity rarity, final int cntCopies ) {
this.rarity = rarity;
this.numCopies = cntCopies;
}
/**
* Gets the copies count.
*
* @return the copies count
*/
public final int getCopiesCount() {
return this.numCopies;
}
/**
* Gets the rarity.
*
* @return the rarity
*/
public final CardRarity getRarity() {
return this.rarity;
}
}

View File

@@ -36,4 +36,12 @@ public enum CardRarity {
public String toString() {
return this.strValue;
}
public static CardRarity smartValueOf(String input) {
for(CardRarity r : CardRarity.values()) {
if( r.name().equalsIgnoreCase(input) || r.strValue.equalsIgnoreCase(input))
return r;
}
return Unknown;
}
}

View File

@@ -19,10 +19,6 @@ package forge.card;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import forge.card.mana.ManaCost;
/**
@@ -36,13 +32,13 @@ public final class CardRules implements ICardCharacteristics {
private final CardSplitType splitType;
private final ICardFace mainPart;
private final ICardFace otherPart;
private final Map<String, CardInSet> setsPrinted = new TreeMap<String, CardInSet>(String.CASE_INSENSITIVE_ORDER);
//private final Map<String, CardInSet> setsPrinted = new TreeMap<String, CardInSet>(String.CASE_INSENSITIVE_ORDER);
private CardAiHints aiHints;
private ColorSet colorIdentity = null;
public CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah, Map<String, CardInSet> sets) {
public CardRules(ICardFace[] faces, CardSplitType altMode, CardAiHints cah) {
splitType = altMode;
mainPart = faces[0];
otherPart = faces[1];
@@ -50,16 +46,16 @@ public final class CardRules implements ICardCharacteristics {
//System.out.print(faces[0].getName());
for (Entry<String, CardInSet> cs : sets.entrySet()) {
if( CardRulesReader.editions.get(cs.getKey()) != null )
setsPrinted.put(cs.getKey(), cs.getValue());
}
if ( setsPrinted.isEmpty() ) {
System.err.println(getName() + " was not assigned any set.");
setsPrinted.put(CardEdition.UNKNOWN.getCode(), new CardInSet(CardRarity.Common, 1) );
}
// for (Entry<String, CardInSet> cs : sets.entrySet()) {
// if( CardRulesReader.editions.get(cs.getKey()) != null )
// setsPrinted.put(cs.getKey(), cs.getValue());
// }
//
// if ( setsPrinted.isEmpty() ) {
// System.err.println(getName() + " was not assigned any set.");
// setsPrinted.put(CardEdition.UNKNOWN.getCode(), new CardInSet(CardRarity.Common, 1) );
// }
//
//Calculate Color Identity
byte colMask = calculateColorIdentity(mainPart);
@@ -176,11 +172,11 @@ public final class CardRules implements ICardCharacteristics {
}
}
public Set<String> getSets() { return this.setsPrinted.keySet(); }
public CardInSet getEditionInfo(final String setCode) {
final CardInSet result = this.setsPrinted.get(setCode);
return result; // if returns null, String.format("Card '%s' was never printed in set '%s'", this.getName(), setCode);
}
// public Set<String> getSets() { return this.setsPrinted.keySet(); }
// public CardInSet getEditionInfo(final String setCode) {
// final CardInSet result = this.setsPrinted.get(setCode);
// return result; // if returns null, String.format("Card '%s' was never printed in set '%s'", this.getName(), setCode);
// }
// vanguard card fields, they don't use sides.
private int deltaHand;

View File

@@ -159,17 +159,6 @@ public final class CardRulesPredicates {
};
}
/**
* Was printed in sets.
*
* @param setCodes
* the set codes
* @return the predicate
*/
public static Predicate<CardRules> wasPrintedInSets(final List<String> setCodes) {
return new PredicateExistsInSets(setCodes);
}
/**
* Core type.
*
@@ -439,22 +428,6 @@ public final class CardRulesPredicates {
}
}
private static class PredicateExistsInSets implements Predicate<CardRules> {
private final List<String> sets;
public PredicateExistsInSets(final List<String> wantSets) {
this.sets = wantSets; // maybe should make a copy here?
}
@Override
public boolean apply(final CardRules subject) {
for (final String s : this.sets)
if ( null != subject.getEditionInfo(s) )
return true;
return false;
}
}
private static class PredicateSplitType implements Predicate<CardRules> {
private final CardSplitType cst;

View File

@@ -17,10 +17,7 @@
*/
package forge.card;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import forge.card.mana.IParserManaCost;
@@ -38,8 +35,6 @@ import forge.card.mana.ManaCostShard;
* @version $Id$
*/
public class CardRulesReader {
public final static EditionCollection editions = new EditionCollection(); // create a copy here, Singletons.model... is not initialized yet.
// fields to build
private CardFace[] faces = new CardFace[] { null, null };
private String[] pictureUrl = new String[] { null, null };
@@ -47,8 +42,6 @@ public class CardRulesReader {
private CardSplitType altMode = CardSplitType.None;
private String handLife = null;
private Map<String,CardInSet> sets = new TreeMap<String, CardInSet>(String.CASE_INSENSITIVE_ORDER);
// fields to build CardAiHints
private boolean removedFromAIDecks = false;
private boolean removedFromRandomDecks = false;
@@ -68,8 +61,6 @@ public class CardRulesReader {
this.faces[1] = null;
this.pictureUrl[0] = null;
this.pictureUrl[1] = null;
this.sets.clear();
this.handLife = null;
this.altMode = CardSplitType.None;
@@ -89,7 +80,7 @@ public class CardRulesReader {
CardAiHints cah = new CardAiHints(removedFromAIDecks, removedFromRandomDecks, hints, needs );
faces[0].assignMissingFields();
if (null != faces[1]) faces[1].assignMissingFields();
final CardRules result = new CardRules(faces, altMode, cah, sets);
final CardRules result = new CardRules(faces, altMode, cah);
result.setDlUrls(pictureUrl);
if (StringUtils.isNotBlank(handLife))
result.setVanguardProperties(handLife);
@@ -219,7 +210,7 @@ public class CardRulesReader {
} else
this.faces[curFace].addSVar(variable, value);
} else if ("SetInfo".equals(key)) {
parseSetInfoLine(value);
// deprecated
}
break;
@@ -236,64 +227,6 @@ public class CardRulesReader {
}
/**
* Parse a SetInfo line from a card txt file.
*
* @param line
* must begin with "SetInfo:"
* @param setsData
* the current mapping of set names to CardInSet instances
*/
private void parseSetInfoLine(final String value) {
// Sample SetInfo line:
// SetInfo:POR Land x4
int i = 0;
String setCode = null;
String txtRarity = "Common";
String txtCount = "x1";
StringTokenizer stt = new StringTokenizer(value, " ");
while(stt.hasMoreTokens()) {
if( i == 0 ) setCode = stt.nextToken();
if( i == 1 ) txtRarity = stt.nextToken();
if( i == 2 ) txtCount = stt.nextToken();
i++;
}
int numIllustrations = 1;
if ( i > 2 )
numIllustrations = Integer.parseInt(txtCount.substring(1));
if (sets.containsKey(setCode)) {
System.err.print(faces[0].getName());
throw new RuntimeException("Found multiple SetInfo lines for set code <<" + setCode + ">>");
}
CardRarity rarity = null;
if ("Land".equals(txtRarity)) {
rarity = CardRarity.BasicLand;
} else if ("Common".equals(txtRarity)) {
rarity = CardRarity.Common;
} else if ("Uncommon".equals(txtRarity)) {
rarity = CardRarity.Uncommon;
} else if ("Rare".equals(txtRarity)) {
rarity = CardRarity.Rare;
} else if ("Mythic".equals(txtRarity)) {
rarity = CardRarity.MythicRare;
} else if ("Special".equals(txtRarity)) {
rarity = CardRarity.Special;
} else {
throw new RuntimeException("Unrecognized rarity string <<" + txtRarity + ">>");
}
final CardInSet cardInSet = new CardInSet(rarity, numIllustrations);
sets.put(setCode, cardInSet);
}
/**
* Instantiates class, reads a card. Do not use for batch operations.
* @param script

View File

@@ -17,6 +17,7 @@
*/
package forge.card;
import java.io.File;
import java.util.Map;
import java.util.TreeMap;
@@ -28,8 +29,8 @@ public final class EditionCollection extends StorageView<CardEdition> {
private final Map<String, CardEdition> aliasToEdition = new TreeMap<String, CardEdition>();
public EditionCollection() {
super(new CardEdition.Reader("res/blockdata/setdata.txt"));
public EditionCollection(File folder) {
super(new CardEdition.EditionReader(folder));
for (CardEdition ee : this) {
String alias = ee.getAlias();
@@ -54,7 +55,7 @@ public final class EditionCollection extends StorageView<CardEdition> {
}
/**
* Gets the sets the by code or throw.
* Gets the sets by code or throw.
*
* @param code
* the code

View File

@@ -0,0 +1,27 @@
package forge.card;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Predicate;
import forge.item.PaperCard;
public interface ICardDatabase {
PaperCard tryGetCard(String cardName);
PaperCard tryGetCard(String cardName, boolean fromLastSet);
PaperCard tryGetCard(String cardName, String edition);
int getPrintCount(String cardName, String edition);
int getMaxPrintCount(String cardName);
PaperCard tryGetCard(String cardName, String edition, int artIndex);
PaperCard getCard(String cardName);
PaperCard getCard(String cardName, boolean fromLastSet);
PaperCard getCard(String cardName, String edition);
PaperCard getCard(String cardName, String edition, int artIndex);
Collection<PaperCard> getUniqueCards();
List<PaperCard> getAllCards();
List<PaperCard> getAllCards(Predicate<PaperCard> predicate);
Predicate<? super PaperCard> wasPrintedInSets(List<String> allowedSetCodes);
}

View File

@@ -10,7 +10,6 @@ import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPoolView;
import forge.item.PrintSheet;

View File

@@ -13,6 +13,7 @@ import com.google.common.collect.Lists;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates.Presets;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.ability.AbilityUtils;
@@ -23,7 +24,6 @@ import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.ComparableOp;

View File

@@ -16,6 +16,7 @@ import forge.CardCharacteristicName;
import forge.CardLists;
import forge.Command;
import forge.GameEntity;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
@@ -30,7 +31,6 @@ import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.util.Aggregates;
import forge.util.PredicateString.StringOp;

View File

@@ -13,6 +13,7 @@ import com.google.common.collect.Lists;
import forge.Card;
import forge.CardCharacteristicName;
import forge.CardLists;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
@@ -27,7 +28,6 @@ import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.gui.GuiDialog;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.util.Aggregates;

View File

@@ -30,6 +30,7 @@ import forge.Command;
import forge.CounterType;
import forge.ImageCache;
import forge.card.CardCharacteristics;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardSplitType;
import forge.card.ICardFace;
@@ -46,7 +47,6 @@ import forge.card.spellability.Target;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler;
import forge.game.player.Player;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;

View File

@@ -27,7 +27,7 @@ import java.util.NoSuchElementException;
import org.apache.commons.lang3.StringUtils;
import forge.Card;
import forge.item.CardDb;
import forge.card.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPool;

View File

@@ -31,10 +31,10 @@ import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
import forge.card.CardDb;
import forge.deck.io.DeckFileHeader;
import forge.deck.io.DeckSerializer;
import forge.gui.deckeditor.tables.TableSorter;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.ItemPoolView;

View File

@@ -26,8 +26,8 @@ import org.apache.commons.lang.math.IntRange;
import forge.Singletons;
import forge.card.CardCoreType;
import forge.card.CardDb;
import forge.card.ColorSet;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.properties.ForgePreferences.FPref;

View File

@@ -22,7 +22,7 @@ import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import forge.item.CardDb;
import forge.card.CardDb;
import forge.item.PaperCard;
/**

View File

@@ -15,13 +15,13 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.Singletons;
import forge.card.CardDb;
import forge.deck.generate.Generate2ColorDeck;
import forge.deck.generate.Generate3ColorDeck;
import forge.deck.generate.Generate5ColorDeck;
import forge.deck.generate.GenerateColoredDeckBase;
import forge.deck.generate.GenerateMonoColorDeck;
import forge.deck.generate.GenerateThemeDeck;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPoolView;
import forge.item.PreconDeck;

View File

@@ -33,12 +33,12 @@ import com.google.common.collect.Lists;
import forge.Constant;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPool;
import forge.item.ItemPoolView;
@@ -133,7 +133,7 @@ public abstract class GenerateColoredDeckBase {
// not an error if looped too much - could play singleton mode, with 6 slots for 3 non-basic lands.
PaperCard cp = CardDb.instance().getCard(s);
tDeck.add(CardDb.instance().getCard(cp.getName(), Aggregates.random(cp.getRules().getSets())));
tDeck.add(CardDb.instance().getCard(cp.getName(), false));
final int n = this.cardCounts.get(s);
this.cardCounts.put(s, n + 1);
@@ -170,7 +170,7 @@ public abstract class GenerateColoredDeckBase {
this.cardCounts.put(color, nLand);
PaperCard cp = CardDb.instance().getCard(color);
String basicLandSet = Aggregates.random(cp.getRules().getSets());
String basicLandSet = cp.getEdition();
tDeck.add(CardDb.instance().getCard(cp.getName(), basicLandSet), nLand);
landsLeft -= nLand;
@@ -222,8 +222,7 @@ public abstract class GenerateColoredDeckBase {
final List<PaperCard> curvedRandomized = Lists.newArrayList();
for (PaperCard c : curved) {
this.cardCounts.put(c.getName(), 0);
PaperCard cpRandomSet = CardDb.instance().getCard(c.getName(), Aggregates.random(c.getRules().getSets()));
curvedRandomized.add(cpRandomSet);
curvedRandomized.add(CardDb.instance().getCard(c.getName(), false));
}
addSome(addOfThisCmc, curvedRandomized);

View File

@@ -22,8 +22,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import forge.card.CardDb;
import forge.error.BugReporter;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPoolView;
import forge.util.FileUtil;

View File

@@ -26,6 +26,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.item.PaperCard;
import forge.item.IPaperCard;
@@ -90,7 +91,7 @@ public class GameFormat implements Comparable<GameFormat> {
if (this.allowedSetCodes == null || this.allowedSetCodes.isEmpty()) {
return banNames;
}
return Predicates.and(banNames, Predicates.compose(CardRulesPredicates.wasPrintedInSets(this.allowedSetCodes), PaperCard.FN_GET_RULES));
return Predicates.and(banNames, CardDb.instance().wasPrintedInSets(this.allowedSetCodes));
}
/**

View File

@@ -19,6 +19,7 @@ import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.GameLogEntryType;
import forge.card.CardDb;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler;
import forge.deck.CardPool;
@@ -29,7 +30,6 @@ import forge.game.player.PlayerType;
import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType;
import forge.gui.GuiDialog;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.properties.ForgePreferences;
@@ -122,12 +122,9 @@ public class GameNew {
PaperCard cpi = cp;
// apply random pictures for cards
if (preferences.getPrefBoolean(FPref.UI_RANDOM_CARD_ART)) {
final int cntVariants = cp.getRules().getEditionInfo(cp.getEdition()).getCopiesCount();
if (cntVariants > 1) {
cpi = CardDb.instance().getCard(cp.getName(), cp.getEdition(), generator.nextInt(cntVariants));
if ( cp.isFoil() )
cpi = PaperCard.makeFoiled(cpi);
}
cpi = CardDb.instance().getCard(cp.getName(), cp.getEdition(), -1);
if ( cp.isFoil() )
cpi = PaperCard.makeFoiled(cpi);
}
final Card card = cpi.toForgeCard(player);

View File

@@ -38,13 +38,13 @@ import forge.Constant.Preferences;
import forge.Singletons;
import forge.card.BoosterTemplate;
import forge.card.CardBlock;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.card.IUnOpenedProduct;
import forge.card.SealedProductTemplate;
import forge.card.UnOpenedProduct;
import forge.deck.Deck;
import forge.gui.GuiChoose;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.ItemPool;

View File

@@ -25,10 +25,10 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import forge.card.BoosterTemplate;
import forge.card.CardDb;
import forge.card.SealedProductTemplate;
import forge.deck.Deck;
import forge.deck.DeckBase;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPool;
import forge.item.ItemPoolView;

View File

@@ -19,6 +19,7 @@ import com.google.common.collect.Lists;
import forge.Constant.Preferences;
import forge.card.CardAiHints;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.ColorSet;
@@ -30,7 +31,6 @@ import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.generate.GenerateDeckUtil;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.util.MyRandom;

View File

@@ -29,13 +29,13 @@ import org.apache.commons.lang.ArrayUtils;
import forge.Singletons;
import forge.card.BoosterTemplate;
import forge.card.CardBlock;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.card.IUnOpenedProduct;
import forge.card.UnOpenedMeta;
import forge.card.UnOpenedProduct;
import forge.deck.CardPool;
import forge.gui.GuiChoose;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.ItemPool;
import forge.util.FileUtil;

View File

@@ -20,9 +20,9 @@ import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import forge.card.CardDb;
import forge.deck.CardPool;
import forge.error.BugReporter;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.properties.NewConstants;
import forge.util.IgnoringXStream;

View File

@@ -41,6 +41,7 @@ import forge.CardLists;
import forge.CardPredicates;
import forge.CounterType;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility;
import forge.card.trigger.TriggerType;
@@ -52,7 +53,6 @@ import forge.game.player.HumanPlay;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.input.InputSelectCardsFromList;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;

View File

@@ -30,10 +30,10 @@ import com.google.common.collect.Iterables;
import forge.ImageCache;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.card.CardRules;
import forge.card.EditionCollection;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.properties.NewConstants;

View File

@@ -5,6 +5,7 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import forge.Command;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.deck.Deck;
import forge.deck.DeckBase;
@@ -16,7 +17,6 @@ import forge.gui.deckeditor.SEditorIO;
import forge.gui.deckeditor.views.VDeckgen;
import forge.gui.framework.ICDoc;
import forge.gui.toolbox.FLabel;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.util.Aggregates;

View File

@@ -26,6 +26,7 @@ import com.google.common.base.Supplier;
import forge.Command;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.deck.Deck;
import forge.deck.DeckSection;
@@ -41,7 +42,6 @@ import forge.gui.deckeditor.views.VCardCatalog;
import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.framework.EDocID;
import forge.gui.toolbox.FLabel;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.item.ItemPool;

View File

@@ -21,6 +21,7 @@ import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import forge.Singletons;
import forge.card.CardDb;
import forge.control.FControl;
import forge.deck.CardPool;
import forge.deck.Deck;
@@ -37,7 +38,6 @@ import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.deckeditor.views.VDeckgen;
import forge.gui.framework.DragCell;
import forge.gui.home.sanctioned.CSubmenuDraft;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.item.ItemPoolView;

View File

@@ -33,6 +33,7 @@ import com.google.common.base.Function;
import forge.Command;
import forge.Singletons;
import forge.card.CardDb;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckBase;
@@ -54,7 +55,6 @@ import forge.gui.home.quest.CSubmenuQuestDecks;
import forge.gui.toolbox.FLabel;
import forge.gui.toolbox.FSkin;
import forge.item.BoosterPack;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.FatPack;
import forge.item.IPaperCard;

View File

@@ -24,6 +24,7 @@ import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import forge.Singletons;
import forge.card.CardDb;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.gui.deckeditor.SEditorIO;
@@ -39,7 +40,6 @@ import forge.gui.deckeditor.views.VCurrentDeck;
import forge.gui.deckeditor.views.VDeckgen;
import forge.gui.framework.DragCell;
import forge.gui.framework.EDocID;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.item.ItemPool;

View File

@@ -24,8 +24,8 @@ import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import forge.ImageCache;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.properties.NewConstants;

View File

@@ -26,8 +26,8 @@ import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Iterables;
import forge.ImageCache;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.properties.NewConstants;

View File

@@ -17,6 +17,7 @@ import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.miginfocom.swing.MigLayout;
import forge.card.CardDb;
import forge.gui.CardDetailPanel;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
@@ -35,7 +36,6 @@ import forge.gui.toolbox.FRadioButton;
import forge.gui.toolbox.FScrollPane;
import forge.gui.toolbox.FSkin;
import forge.gui.toolbox.FTabbedPane;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;

View File

@@ -9,6 +9,7 @@ import javax.swing.JButton;
import forge.Card;
import forge.Singletons;
import forge.card.CardDb;
import forge.control.FControl;
import forge.deck.Deck;
import forge.game.GameOutcome;
@@ -19,7 +20,6 @@ import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.gui.SOverlayUtils;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.properties.ForgePreferences.FPref;

View File

@@ -35,6 +35,7 @@ import org.apache.commons.lang.StringUtils;
import forge.Card;
import forge.Singletons;
import forge.card.BoosterTemplate;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.card.IUnOpenedProduct;
import forge.card.UnOpenedProduct;
@@ -55,7 +56,6 @@ import forge.gui.home.quest.CSubmenuChallenges;
import forge.gui.home.quest.CSubmenuDuels;
import forge.gui.toolbox.FSkin;
import forge.item.BoosterPack;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.item.OpenablePack;

View File

@@ -1,330 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.item;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Card;
import forge.card.CardInSet;
import forge.card.CardRules;
import forge.util.Aggregates;
public final class CardDb {
private static volatile CardDb commonCards = null; // 'volatile' keyword makes this working
private static volatile CardDb variantCards = null; // 'volatile' keyword makes this working
public final static String foilSuffix = " foil";
private final static int foilSuffixLength = foilSuffix.length();
public static CardDb instance() {
if (CardDb.commonCards == null) {
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
}
return CardDb.commonCards;
}
public static CardDb variants() {
if (CardDb.variantCards == null) {
throw new NullPointerException("CardDb has not yet been initialized, run setup() first");
}
return CardDb.variantCards;
}
public static void setup(final Iterable<CardRules> list) {
if (CardDb.commonCards != null) {
throw new RuntimeException("CardDb has already been initialized, don't do it twice please");
}
synchronized (CardDb.class) {
if (CardDb.commonCards == null) { // It's broken under 1.4 and below, on 1.5+ works again!
CardSorter cs = new CardSorter(list);
commonCards = new CardDb(cs.uniqueCommonCards, cs.allCommonCardsFlat, cs.allCommonCardsBySet);
variantCards = new CardDb(cs.uniqueSpecialCards, cs.allSpecialCardsFlat, cs.allSpecialCardsBySet);
}
}
}
// Here are refs, get them by name
private final Map<String, PaperCard> uniqueCards;
// need this to obtain cardReference by name+set+artindex
private final Map<String, Map<String, PaperCard[]>> allCardsBySet;
// this is the same list in flat storage
private final List<PaperCard> allCardsFlat;
// Lambda to get rules for selects from list of printed cards
/** The Constant fnGetCardPrintedByForgeCard. */
public static final Function<Card, PaperCard> FN_GET_CARD_PRINTED_BY_FORGE_CARD = new Function<Card, PaperCard>() {
@Override
public PaperCard apply(final Card from) {
return CardDb.instance().getCard(from.getName());
}
};
private CardDb(Map<String, PaperCard> uniqueCards, List<PaperCard> cardsFlat, Map<String, Map<String, PaperCard[]>> cardsBySet) {
this.uniqueCards = Collections.unmodifiableMap(uniqueCards);
this.allCardsFlat = Collections.unmodifiableList(cardsFlat);
this.allCardsBySet = cardsBySet;
}
/**
* Splits cardname into Name and set whenever deck line reads as name|set.
*/
private static ImmutablePair<String, String> splitCardName(final String name) {
String cardName = name; // .trim() ?
final int pipePos = cardName.indexOf('|');
if (pipePos >= 0) {
final String setName = cardName.substring(pipePos + 1).trim();
cardName = cardName.substring(0, pipePos);
// only if set is not blank try to load it
if (StringUtils.isNotBlank(setName) && !"???".equals(setName)) {
return new ImmutablePair<String, String>(cardName, setName);
}
}
return new ImmutablePair<String, String>(cardName, null);
}
private boolean isFoil(final String cardName) {
return cardName.toLowerCase().endsWith(CardDb.foilSuffix) && (cardName.length() > CardDb.foilSuffixLength);
}
/**
* Removes the foil suffix.
*
* @param cardName the card name
* @return the string
*/
public String removeFoilSuffix(final String cardName) {
return cardName.substring(0, cardName.length() - CardDb.foilSuffixLength);
}
/**
* Checks if is card supported.
*/
public PaperCard tryGetCard(final String cardName0) {
if (null == cardName0) {
return null; // obviously
}
final boolean isFoil = this.isFoil(cardName0);
final String cardName = isFoil ? this.removeFoilSuffix(cardName0) : cardName0;
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(cardName);
if (nameWithSet.right == null) {
return this.uniqueCards.get(nameWithSet.left);
}
PaperCard res = tryGetCard(nameWithSet.left, nameWithSet.right);
if ( null != res && isFoil )
return PaperCard.makeFoiled(res);
return res;
}
public PaperCard tryGetCard(final String cardName, String setName) {
return tryGetCard(cardName, setName, 0);
}
public PaperCard tryGetCard(final String cardName, String setName, int index) {
// Set exists?
final Map<String, PaperCard[]> cardsFromset = this.allCardsBySet.get(setName);
if (cardsFromset == null) {
return null;
}
// Card exists?
final PaperCard[] cardCopies = cardsFromset.get(cardName);
return cardCopies != null && index < cardCopies.length ? cardCopies[index] : null;
}
// Single fetch
public PaperCard getCard(final String name) {
return this.getCard(name, false);
}
// Advanced fetch by name+set
public PaperCard getCard(final String name, final String set) {
return this.getCard(name, set, 0);
}
public PaperCard getCard(final String name, final String set, final int artIndex) {
// 1. get set
final Map<String, PaperCard[]> cardsFromset = this.allCardsBySet.get(set.toUpperCase());
if (null == cardsFromset) {
final String err = String
.format("Asked for card '%s' from set '%s': that set was not found. :(", name, set);
throw new NoSuchElementException(err);
}
// 2. Find the card itself
final PaperCard[] cardCopies = cardsFromset.get(name.toLowerCase());
if (null == cardCopies) {
final String err = String.format("Asked for card '%s' from '%s': set found, but the card wasn't. :(", name,
set);
throw new NoSuchElementException(err);
}
// 3. Get the proper copy
if ((artIndex >= 0) && (artIndex <= cardCopies.length)) {
return cardCopies[artIndex];
}
final String err = String
.format("Asked for '%s' from '%s' #%d: db didn't find that copy.", name, set, artIndex);
throw new NoSuchElementException(err);
}
// Fetch from Forge's Card instance. Well, there should be no errors, but
// we'll still check
public static PaperCard getCard(final Card forgeCard) {
final String name = forgeCard.getName();
final String set = forgeCard.getCurSetCode();
if (StringUtils.isNotBlank(set)) {
PaperCard cp = variants().tryGetCard(name, set);
return cp == null ? instance().getCard(name, set) : cp;
}
PaperCard cp = variants().tryGetCard(name);
return cp == null ? instance().getCard(name) : cp;
}
// returns a list of all cards from their respective latest editions
public Collection<PaperCard> getUniqueCards() {
return this.uniqueCards.values();
}
public List<PaperCard> getAllCards() {
return this.allCardsFlat;
}
/** Returns a modifiable list of cards matching the given predicate */
public List<PaperCard> getAllCards(Predicate<PaperCard> predicate) {
return Lists.newArrayList(Iterables.filter(this.allCardsFlat, predicate));
}
public PaperCard getCard(final String name0, final boolean fromLatestSet) {
// Sometimes they read from decks things like "CardName|Set" - but we
// can handle it
final boolean isFoil = this.isFoil(name0);
final String name = isFoil ? this.removeFoilSuffix(name0) : name0;
PaperCard result = null;
final ImmutablePair<String, String> nameWithSet = CardDb.splitCardName(name);
if (nameWithSet.right != null) {
result = this.getCard(nameWithSet.left, nameWithSet.right);
} else {
if (!fromLatestSet) {
result = this.uniqueCards.get(nameWithSet.left.toLowerCase());
if (null == result) {
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
}
} else {
// OK, plain name here
final Predicate<PaperCard> predicate = IPaperCard.Predicates.name(nameWithSet.left);
final Iterable<PaperCard> namedCards = Iterables.filter(this.allCardsFlat, predicate);
// Find card with maximal set index
result = Aggregates.itemWithMax(namedCards, PaperCard.FN_GET_EDITION_INDEX);
if (null == result) {
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
}
}
}
if (isFoil) {
result = PaperCard.makeFoiled(result);
}
return result;
}
private static class CardSorter{
// need this to obtain cardReference by name+set+artindex
public final Map<String, Map<String, PaperCard[]>> allCommonCardsBySet = new TreeMap<String, Map<String, PaperCard[]>>(String.CASE_INSENSITIVE_ORDER);
public final Map<String, Map<String, PaperCard[]>> allSpecialCardsBySet = new TreeMap<String, Map<String, PaperCard[]>>(String.CASE_INSENSITIVE_ORDER);
// Here are refs, get them by name
public final Map<String, PaperCard> uniqueCommonCards = new TreeMap<String, PaperCard>(String.CASE_INSENSITIVE_ORDER);
public final Map<String, PaperCard> uniqueSpecialCards = new TreeMap<String, PaperCard>(String.CASE_INSENSITIVE_ORDER);
// this is the same list in flat storage
public final List<PaperCard> allCommonCardsFlat = new ArrayList<PaperCard>();
public final List<PaperCard> allSpecialCardsFlat = new ArrayList<PaperCard>();
public PaperCard addToLists(final CardRules card, final String cardName, final String set, CardInSet cs) {
PaperCard lastAdded = null;
final Map<String, Map<String, PaperCard[]>> allCardsBySet = card.isTraditional() ? allCommonCardsBySet : allSpecialCardsBySet;
// get this set storage, if not found, create it!
Map<String, PaperCard[]> setMap = allCardsBySet.get(set);
if (null == setMap) {
setMap = new TreeMap<String, PaperCard[]>(String.CASE_INSENSITIVE_ORDER);
allCardsBySet.put(set, setMap);
}
final int count = cs.getCopiesCount();
final PaperCard[] cardCopies = new PaperCard[count];
setMap.put(cardName, cardCopies);
for (int i = 0; i < count; i++) {
lastAdded = PaperCard.build(card, set, cs.getRarity(), i);
if (card.isTraditional()) {
this.allCommonCardsFlat.add(lastAdded);
} else {
this.allSpecialCardsFlat.add(lastAdded);
}
cardCopies[i] = lastAdded;
}
return lastAdded;
}
private void addNewCard(final CardRules card) {
if (null == card) {
return;
} // consider that a success
// System.out.println(card.getName());
final String cardName = card.getName().toLowerCase();
// 1. register among oracle uniques
// cards.put(cardName, card);
// 2. Save refs into two lists: one flat and other keyed with sets &
// name
PaperCard lastAdded = null;
for (final String s : card.getSets()) {
lastAdded = this.addToLists(card, cardName, s, card.getEditionInfo(s));
}
if ( lastAdded.getRules().isTraditional() )
uniqueCommonCards.put(cardName, lastAdded);
else
uniqueSpecialCards.put(cardName, lastAdded);
}
CardSorter(final Iterable<CardRules> parser) {
for (CardRules cr : parser) {
this.addNewCard(cr);
}
}
}
}

View File

@@ -28,6 +28,7 @@ import com.google.common.collect.Iterables;
import forge.card.BoosterTemplate;
import forge.card.BoosterGenerator;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.util.Aggregates;

View File

@@ -44,10 +44,10 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
private final transient CardRules card;
// These fields are kinda PK for PrintedCard
private final String name;
private final String edition;
private final int artIndex;
private final boolean foiled;
public final String name;
public final String edition;
public final int artIndex;
public final boolean foil;
// Calculated fields are below:
private final transient CardRarity rarity; // rarity is given in ctor when set is assigned
@@ -69,7 +69,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
@Override
public boolean isFoil() {
return this.foiled;
return this.foil;
}
@Override
@@ -117,59 +117,24 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
}
};
public static final Function<PaperCard, Integer> FN_GET_EDITION_INDEX = new Function<PaperCard, Integer>() {
@Override
public Integer apply(final PaperCard from) {
return Integer.valueOf(Singletons.getModel().getEditions().get(from.getEdition()).getIndex());
}
};
// Constructor is private. All non-foiled instances are stored in CardDb
private PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index, final boolean foil) {
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index) {
this(c, edition0, rare, index, false);
}
public PaperCard(final CardRules c, final String edition0, final CardRarity rare, final int index, final boolean foil) {
this.card = c;
this.name = c.getName();
this.edition = edition0;
this.artIndex = index;
this.foiled = foil;
this.foil = foil;
this.rarity = rare;
}
/* package visibility */
/**
* Builds the.
*
* @param c
* the c
* @param edition
* the set
* @param rare
* the rare
* @param index
* the index
* @return the card printed
*/
static PaperCard build(final CardRules c, final String edition, final CardRarity rare, final int index) {
return new PaperCard(c, edition, rare, index, false);
}
/* foiled don't need to stay in CardDb's structures, so u'r free to create */
/**
* Make foiled.
*
* @param c
* the c
* @return the card printed
*/
public static PaperCard makeFoiled(final PaperCard c) {
return new PaperCard(c.card, c.edition, c.rarity, c.artIndex, true);
}
// Want this class to be a key for HashTable
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
@@ -189,7 +154,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
if (!this.edition.equals(other.edition)) {
return false;
}
if ((other.foiled != this.foiled) || (other.artIndex != this.artIndex)) {
if ((other.foil != this.foil) || (other.artIndex != this.artIndex)) {
return false;
}
@@ -204,7 +169,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
@Override
public int hashCode() {
final int code = (this.name.hashCode() * 11) + (this.edition.hashCode() * 59) + (this.artIndex * 2);
if (this.foiled) {
if (this.foil) {
return code + 1;
}
return code;

View File

@@ -30,7 +30,7 @@ import forge.Constant.Preferences;
import forge.FThreads;
import forge.card.BoosterTemplate;
import forge.card.CardBlock;
import forge.card.CardRulesReader;
import forge.card.CardDb;
import forge.card.EditionCollection;
import forge.card.FatPackTemplate;
import forge.card.FormatCollection;
@@ -41,7 +41,6 @@ import forge.error.BugReporter;
import forge.error.ExceptionHandler;
import forge.game.limited.GauntletMini;
import forge.gauntlet.GauntletData;
import forge.item.CardDb;
import forge.item.PrintSheet;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
@@ -143,7 +142,15 @@ public enum FModel {
this.questPreferences = new QuestPreferences();
this.gauntletData = new GauntletData();
this.editions = CardRulesReader.editions; // CardRules ctor cannot refer to FModel, since it is not yet build by that moment
this.editions = new EditionCollection(new File("res/cardeditions"));
// Loads all cards (using progress bar).
FThreads.assertExecutedByEdt(false);
final CardStorageReader reader = new CardStorageReader(NewConstants.CARD_DATA_DIR, true);
// this fills in our map of card names to Card instances.
CardDb.setup(reader.loadCards(), editions);
this.formats = new FormatCollection("res/blockdata/formats.txt");
this.boosters = new StorageView<BoosterTemplate>(new BoosterTemplate.Reader("res/blockdata/boosters.txt"));
this.specialBoosters = new StorageView<SealedProductTemplate>(new SealedProductTemplate.Reader("res/blockdata/boosters-special.txt"));
@@ -157,16 +164,6 @@ public enum FModel {
this.loadDynamicGamedata();
// Loads all cards (using progress bar).
FThreads.assertExecutedByEdt(false);
final CardStorageReader reader = new CardStorageReader(NewConstants.CARD_DATA_DIR, true);
try {
// this fills in our map of card names to Card instances.
CardDb.setup(reader.loadCards());
} catch (final Exception ex) {
BugReporter.reportException(ex);
}
this.decks = new CardCollections();
this.quest = new QuestController();

View File

@@ -29,11 +29,11 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.MagicColor;
import forge.item.BoosterPack;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.item.InventoryItem;

View File

@@ -9,7 +9,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.Singletons;
import forge.item.CardDb;
import forge.card.CardDb;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.item.ItemPool;

View File

@@ -7,7 +7,7 @@ import java.util.List;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.item.CardDb;
import forge.card.CardDb;
import forge.item.PaperCard;
/**

View File

@@ -21,9 +21,9 @@ import java.util.ArrayList;
import java.util.List;
import forge.Card;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.card.CardRulesReader;
import forge.item.CardDb;
import forge.item.PaperToken;
import forge.item.IPaperCard;
import forge.quest.bazaar.QuestPetController;

View File

@@ -32,15 +32,16 @@ import com.google.common.collect.Lists;
import forge.Constant;
import forge.Singletons;
import forge.card.BoosterGenerator;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.card.CardRarity;
import forge.card.FormatCollection;
import forge.card.ICardDatabase;
import forge.card.SealedProductTemplate;
import forge.card.UnOpenedProduct;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.item.BoosterPack;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.FatPack;
import forge.item.IPaperCard;
@@ -89,7 +90,7 @@ public final class QuestUtilCards {
* @return the item pool view
*/
public static ItemPoolView<PaperCard> generateBasicLands(final int nBasic, final int nSnow, final GameFormatQuest usedFormat) {
final CardDb db = CardDb.instance();
final ICardDatabase db = CardDb.instance();
final ItemPool<PaperCard> pool = new ItemPool<PaperCard>(PaperCard.class);
List<String> landCodes = new ArrayList<String>();

View File

@@ -136,7 +136,7 @@ public class QuestUtilUnlockSets {
Collections.sort(excludedSets);
// get a number of sets between an excluded and any included set
List<ImmutablePair<CardEdition, Integer>> excludedWithDistances = new ArrayList<ImmutablePair<CardEdition, Integer>>();
List<ImmutablePair<CardEdition, Long>> excludedWithDistances = new ArrayList<ImmutablePair<CardEdition, Long>>();
for (CardEdition ex : excludedSets) {
switch (ex.getType()) {
case CORE: case EXPANSION: case REPRINT: case STARTER: break;
@@ -147,9 +147,9 @@ public class QuestUtilUnlockSets {
default:
throw new RuntimeException("unhandled card edition type: " + ex.getType());
}
int distance = Integer.MAX_VALUE;
long distance = Integer.MAX_VALUE;
for (CardEdition in : allowedSets) {
int d = Math.abs(ex.getIndex() - in.getIndex());
long d = Math.abs(ex.getDate().getTime() - in.getDate().getTime());
if (d < distance) {
distance = d;
}
@@ -158,16 +158,16 @@ public class QuestUtilUnlockSets {
}
// sort by distance, then by code desc
Collections.sort(excludedWithDistances, new Comparator<ImmutablePair<CardEdition, Integer>>() {
Collections.sort(excludedWithDistances, new Comparator<ImmutablePair<CardEdition, Long>>() {
@Override
public int compare(ImmutablePair<CardEdition, Integer> o1, ImmutablePair<CardEdition, Integer> o2) {
int d1 = o2.right - o1.right;
return d1 != 0 ? d1 : o1.left.getIndex() - o2.left.getIndex();
public int compare(ImmutablePair<CardEdition, Long> o1, ImmutablePair<CardEdition, Long> o2) {
long delta = o2.right - o1.right;
return delta < 0 ? -1 : delta == 0 ? 0 : 1;
}
});
for (ImmutablePair<CardEdition, Integer> set : excludedWithDistances) {
for (ImmutablePair<CardEdition, Long> set : excludedWithDistances) {
options.add(set.left);
// System.out.println("Padded with: " + fillers.get(i).getName());
}

View File

@@ -54,13 +54,13 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.CardEdition;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.error.BugReporter;
import forge.item.BoosterPack;
import forge.item.CardDb;
import forge.item.PaperCard;
import forge.item.FatPack;
import forge.item.InventoryItem;

View File

@@ -76,6 +76,8 @@ public class Aggregates {
* @return the t
*/
public static final <T> T random(final Iterable<T> source) {
if( null == source )
return null;
Random rnd = MyRandom.getRandom();
if ( source instanceof List<?> )
{