mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
226 lines
8.7 KiB
Java
226 lines
8.7 KiB
Java
package forge.card;
|
|
|
|
import java.lang.reflect.Array;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
import net.slightlymagic.braids.util.lambda.Lambda1;
|
|
import net.slightlymagic.maxmtg.Predicate;
|
|
import net.slightlymagic.maxmtg.Predicate.StringOp;
|
|
import forge.AllZone;
|
|
import forge.Card;
|
|
import forge.CardUtil;
|
|
|
|
/**
|
|
* <p>CardReference class.</p>
|
|
*
|
|
* @author Forge
|
|
* @version $Id: CardReference.java 9708 2011-08-09 19:34:12Z jendave $
|
|
*/
|
|
public final class CardPrinted implements Comparable<CardPrinted> {
|
|
// Reference to rules
|
|
private final transient CardRules card;
|
|
|
|
// These fields are kinda PK for PrintedCard
|
|
private final String name;
|
|
private final String cardSet;
|
|
private final int artIndex;
|
|
private final boolean foiled;
|
|
|
|
// Calculated fields are below:
|
|
private final transient CardRarity rarity; // rarity is given in ctor when set is assigned
|
|
|
|
// need this to be sure that different cased names won't break the system (and create uniqie cardref entries)
|
|
private final transient String nameLcase;
|
|
|
|
// image filename is calculated only after someone request it
|
|
private transient String imageFilename = null;
|
|
|
|
// field RO accessors
|
|
public String getName() { return name; }
|
|
public String getSet() { return cardSet; }
|
|
public int getArtIndex() { return artIndex; }
|
|
public boolean isFoil() { return foiled; }
|
|
public CardRules getCard() { return card; }
|
|
public CardRarity getRarity() { return rarity; }
|
|
public String getImageFilename() {
|
|
if (imageFilename == null) { imageFilename = CardUtil.buildFilename(this); }
|
|
return imageFilename;
|
|
}
|
|
|
|
// Lambda to get rules for selects from list of printed cards
|
|
public static final Lambda1<CardRules, CardPrinted> fnGetRules = new Lambda1<CardRules, CardPrinted>() {
|
|
@Override public CardRules apply(final CardPrinted from) { return from.card; }
|
|
};
|
|
|
|
// Constructor is private. All non-foiled instances are stored in CardDb
|
|
private CardPrinted(final CardRules c, final String set, final CardRarity rare,
|
|
final int index, final boolean foil)
|
|
{
|
|
card = c;
|
|
name = c.getName();
|
|
cardSet = set;
|
|
artIndex = index;
|
|
foiled = foil;
|
|
rarity = rare;
|
|
nameLcase = name.toLowerCase();
|
|
}
|
|
|
|
/* package visibility */
|
|
static CardPrinted build(final CardRules c, final String set, final CardRarity rare, final int index) {
|
|
return new CardPrinted(c, set, rare, index, false);
|
|
}
|
|
|
|
/* foiled don't need to stay in CardDb's structures, so u'r free to create */
|
|
public static CardPrinted makeFoiled(final CardPrinted c) {
|
|
return new CardPrinted(c.card, c.cardSet, c.rarity, c.artIndex, true);
|
|
}
|
|
|
|
// Want this class to be a key for HashTable
|
|
@Override
|
|
public boolean equals(final Object obj) {
|
|
if (this == obj) { return true; }
|
|
if (obj == null) { return false; }
|
|
if (getClass() != obj.getClass()) { return false; }
|
|
|
|
CardPrinted other = (CardPrinted) obj;
|
|
if (!name.equals(other.name)) { return false; }
|
|
if (!cardSet.equals(other.cardSet)) { return false; }
|
|
if (other.foiled != this.foiled || other.artIndex != this.artIndex) { return false; }
|
|
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
int code = nameLcase.hashCode() * 11 + cardSet.hashCode() * 59 + artIndex * 2;
|
|
if (foiled) { return code + 1; }
|
|
return code;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return name;
|
|
// cannot still decide, if this "name|set" format is needed anymore
|
|
//return String.format("%s|%s", name, cardSet);
|
|
}
|
|
|
|
public Card toForgeCard() {
|
|
Card c = AllZone.getCardFactory().getCard(name, null);
|
|
if (c != null) {
|
|
c.setCurSetCode(getSet());
|
|
c.setRandomPicture(artIndex);
|
|
c.setImageFilename(getImageFilename());
|
|
}
|
|
// else throw "Unsupported card";
|
|
return c;
|
|
}
|
|
|
|
@Override
|
|
public int compareTo(final CardPrinted o) {
|
|
int nameCmp = nameLcase.compareTo(o.nameLcase);
|
|
if (0 != nameCmp) { return nameCmp; }
|
|
// TODO: compare sets properly
|
|
return cardSet.compareTo(o.cardSet);
|
|
}
|
|
|
|
/**
|
|
* Number of filters based on CardPrinted values.
|
|
*/
|
|
public abstract static class Predicates {
|
|
public static Predicate<CardPrinted> rarity(final boolean isEqual, final CardRarity value)
|
|
{
|
|
return new PredicateRarity(value, isEqual);
|
|
}
|
|
public static Predicate<CardPrinted> printedInSets(final List<String> value, final boolean shouldContain)
|
|
{
|
|
if (value == null || value.isEmpty()) {
|
|
return Predicate.getTrue(CardPrinted.class);
|
|
}
|
|
return new PredicateSets(value, shouldContain);
|
|
}
|
|
public static Predicate<CardPrinted> printedInSets(final String value) {
|
|
if (value == null || value.isEmpty()) {
|
|
return Predicate.getTrue(CardPrinted.class);
|
|
}
|
|
return new PredicateSets(Arrays.asList(new String[]{value}), true);
|
|
}
|
|
public static Predicate<CardPrinted> name(final StringOp op, final String what) {
|
|
return new PredicateName(op, what);
|
|
}
|
|
|
|
private static class PredicateRarity extends Predicate<CardPrinted> {
|
|
private final CardRarity operand;
|
|
private final boolean shouldBeEqual;
|
|
|
|
@Override
|
|
public boolean isTrue(final CardPrinted card) {
|
|
return card.rarity.equals(operand) == shouldBeEqual;
|
|
}
|
|
|
|
public PredicateRarity(final CardRarity type, final boolean wantEqual) {
|
|
operand = type;
|
|
shouldBeEqual = wantEqual;
|
|
}
|
|
}
|
|
|
|
private static class PredicateSets extends Predicate<CardPrinted> {
|
|
private final List<String> sets;
|
|
private final boolean mustContain;
|
|
@Override public boolean isTrue(final CardPrinted card) {
|
|
return sets.contains(card.cardSet) == mustContain;
|
|
}
|
|
public PredicateSets(final List<String> wantSets, final boolean shouldContain) {
|
|
sets = wantSets; // maybe should make a copy here?
|
|
mustContain = shouldContain;
|
|
}
|
|
}
|
|
|
|
private static class PredicateName extends Predicate<CardPrinted> {
|
|
private final String operand;
|
|
private final StringOp operator;
|
|
|
|
@Override
|
|
public boolean isTrue(final CardPrinted card) {
|
|
return op(card.getName(), operand);
|
|
}
|
|
|
|
private boolean op(final String op1, final String op2) {
|
|
switch (operator) {
|
|
case CONTAINS: return StringUtils.containsIgnoreCase(op1, op2);
|
|
case NOT_CONTAINS: return !StringUtils.containsIgnoreCase(op1, op2);
|
|
case EQUALS: return op1.equalsIgnoreCase(op2);
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
public PredicateName(final StringOp operator, final String operand)
|
|
{
|
|
this.operand = operand;
|
|
this.operator = operator;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pre-built predicates are stored here to allow their re-usage and easier access from code.
|
|
*/
|
|
public abstract static class Presets {
|
|
// Think twice before using these, since rarity is a prop of printed card.
|
|
public static final Predicate<CardPrinted> isCommon = rarity(true, CardRarity.Common);
|
|
public static final Predicate<CardPrinted> isUncommon = rarity(true, CardRarity.Uncommon);
|
|
public static final Predicate<CardPrinted> isRare = rarity(true, CardRarity.Rare);
|
|
public static final Predicate<CardPrinted> isMythicRare = rarity(true, CardRarity.MythicRare);
|
|
public static final Predicate<CardPrinted> isRareOrMythic = Predicate.or(isRare, isMythicRare);
|
|
public static final Predicate<CardPrinted> isSpecial = rarity(true, CardRarity.Special);
|
|
public static final Predicate<CardPrinted> exceptLands = rarity(false, CardRarity.BasicLand);
|
|
|
|
// TODO: Update this code on each rotation (or move this list to a file)
|
|
public static final Predicate<CardPrinted> isStandard = printedInSets(
|
|
Arrays.asList(new String[] {"M12", "NPH", "MBS", "SOM", "M11", "ROE", "WWK", "ZEN"}), true);
|
|
|
|
}
|
|
}
|
|
}
|