diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index 670cfdcacf0..dcb23eb7871 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -37,6 +37,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Multimaps; import forge.card.CardEdition.CardInSet; +import forge.card.CardEdition.Type; import forge.item.PaperCard; import forge.util.Aggregates; import forge.util.CollectionSuppliers; @@ -46,6 +47,8 @@ import forge.util.TextUtil; public final class CardDb implements ICardDatabase { public final static String foilSuffix = "+"; + public final static char NameSetSeparator = '|'; + // need this to obtain cardReference by name+set+artindex private final ListMultimap allCardsByName = Multimaps.newListMultimap(new TreeMap>(String.CASE_INSENSITIVE_ORDER), CollectionSuppliers.arrayLists()); private final Map uniqueCardsByName = new TreeMap(String.CASE_INSENSITIVE_ORDER); @@ -58,7 +61,9 @@ public final class CardDb implements ICardDatabase { public enum SetPreference { Latest, + LatestCoreExp, Earliest, + EarliestCoreExp, Random } @@ -81,17 +86,23 @@ public final class CardDb implements ICardDatabase { if( isFoil ) name = name.substring(0, name.length() - foilSuffix.length()); - String[] nameParts = TextUtil.split(name, '|'); + String[] nameParts = TextUtil.split(name, NameSetSeparator); int setPos = nameParts.length >= 2 && !StringUtils.isNumeric(nameParts[1]) ? 1 : -1; int artPos = nameParts.length >= 2 && StringUtils.isNumeric(nameParts[1]) ? 1 : nameParts.length >= 3 && StringUtils.isNumeric(nameParts[2]) ? 2 : -1; + String cardName = nameParts[0]; + if( cardName.endsWith(foilSuffix)) { + cardName = cardName.substring(0, cardName.length() - foilSuffix.length()); + isFoil = true; + } + int artIndex = artPos > 0 ? Integer.parseInt(nameParts[artPos]) : -1; String setName = setPos > 0 ? nameParts[setPos] : null; if( "???".equals(setName) ) setName = null; - return new CardRequest(nameParts[0], setName, artIndex, isFoil); + return new CardRequest(cardName, setName, artIndex, isFoil); } } @@ -172,8 +183,7 @@ public final class CardDb implements ICardDatabase { request.edition = setName; request.artIndex = artIndex; return tryGetCard(request); - } - + } private PaperCard tryGetCard(CardRequest request) { Collection cards = allCardsByName.get(request.cardName); @@ -211,21 +221,38 @@ public final class CardDb implements ICardDatabase { @Override public PaperCard getCardFromEdition(final String cardName, final Date printedBefore, final SetPreference fromSet) { + return getCardFromEdition(cardName, null, fromSet, -1); + } + + @Override + public PaperCard getCardFromEdition(final String cardName, final Date printedBefore, final SetPreference fromSet, int artIndex) { List cards = this.allCardsByName.get(cardName); int sz = cards.size(); - if( fromSet == SetPreference.Latest ) { - for(int i = 0 ; i < sz ; i++) - if( printedBefore == null || editions.get(cards.get(i).getEdition()).getDate().after(printedBefore) ) - return cards.get(i); + if( fromSet == SetPreference.Earliest || fromSet == SetPreference.EarliestCoreExp) { + for(int i = sz - 1 ; i >= 0 ; i--) { + PaperCard pc = cards.get(i); + CardEdition ed = editions.get(pc.getEdition()); + if(fromSet == SetPreference.EarliestCoreExp && ed.getType() != Type.CORE && ed.getType() != Type.EXPANSION) + continue; + + if((artIndex < 0 || pc.getArtIndex() == artIndex) && (printedBefore == null || ed.getDate().before(printedBefore))) + return pc; + } return null; - } else if( fromSet == SetPreference.Earliest || fromSet == null || fromSet == SetPreference.Random ) { - for(int i = sz - 1 ; i >= 0 ; i--) - if( printedBefore == null || editions.get(cards.get(i).getEdition()).getDate().after(printedBefore) ) { - if( fromSet == SetPreference.Earliest ) - return cards.get(i); - return cards.get(MyRandom.getRandom().nextInt(i+1)); + } else if( fromSet == SetPreference.LatestCoreExp || fromSet == SetPreference.Latest || fromSet == null || fromSet == SetPreference.Random ) { + for(int i = 0 ; i < sz ; i++) { + PaperCard pc = cards.get(i); + CardEdition ed = editions.get(pc.getEdition()); + if(fromSet == SetPreference.LatestCoreExp && ed.getType() != Type.CORE && ed.getType() != Type.EXPANSION) + continue; + + if((artIndex < 0 || pc.getArtIndex() == artIndex) && (printedBefore == null || ed.getDate().before(printedBefore))) { + if( fromSet == SetPreference.LatestCoreExp || fromSet == SetPreference.Latest ) + return pc; + return cards.get(i + MyRandom.getRandom().nextInt(sz-i)); } + } return null; } return null; diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index 628c5948d2f..d1cc7b9587d 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -415,15 +415,21 @@ public final class CardEdition implements Comparable { // immutable public CardEdition getEarliestEditionWithAllCards(CardPool cards) { Set minEditions = new HashSet(); + + SetPreference strictness = SetPreference.EarliestCoreExp; + for(Entry k : cards) { - PaperCard cp = StaticData.instance().getCommonCards().getCardFromEdition(k.getKey().getName(), SetPreference.Earliest); + PaperCard cp = StaticData.instance().getCommonCards().getCardFromEdition(k.getKey().getName(), strictness); + if( cp == null && strictness == SetPreference.EarliestCoreExp) { + strictness = SetPreference.Earliest; // card is not found in core and expansions only (probably something CMD or C13) + cp = StaticData.instance().getCommonCards().getCardFromEdition(k.getKey().getName(), strictness); + } + if ( cp == null ) + cp = k.getKey(); // it's unlikely, this code will ever run + minEditions.add(cp.getEdition()); } - for(CardEdition ed : getOrderedEditions()) { - if( minEditions.contains(ed.getCode()) && ( ed.getType() == Type.CORE || ed.getType() == Type.EXPANSION ) ) - return ed; - } for(CardEdition ed : getOrderedEditions()) { if(minEditions.contains(ed.getCode())) return ed; diff --git a/forge-core/src/main/java/forge/card/ICardDatabase.java b/forge-core/src/main/java/forge/card/ICardDatabase.java index 0a39a1c8f51..b22d065e920 100644 --- a/forge-core/src/main/java/forge/card/ICardDatabase.java +++ b/forge-core/src/main/java/forge/card/ICardDatabase.java @@ -13,8 +13,9 @@ public interface ICardDatabase extends Iterable { PaperCard getCard(String cardName); PaperCard getCard(String cardName, String edition); PaperCard getCard(String cardName, String edition, int artIndex); - PaperCard getCardFromEdition(final String cardName, final SetPreference fromSet); - PaperCard getCardFromEdition(final String cardName, final Date printedBefore, final SetPreference fromSet); + PaperCard getCardFromEdition(String cardName, SetPreference fromSet); + PaperCard getCardFromEdition(String cardName, Date printedBefore, SetPreference fromSet); + PaperCard getCardFromEdition(String cardName, Date printedBefore, SetPreference fromSet, int artIndex); PaperCard getFoiled(PaperCard cpi); @@ -28,4 +29,5 @@ public interface ICardDatabase extends Iterable { List getAllCards(Predicate predicate); Predicate wasPrintedInSets(List allowedSetCodes); + } \ No newline at end of file diff --git a/forge-core/src/main/java/forge/deck/CardPool.java b/forge-core/src/main/java/forge/deck/CardPool.java index 4555e313087..0d221f8c24b 100644 --- a/forge-core/src/main/java/forge/deck/CardPool.java +++ b/forge-core/src/main/java/forge/deck/CardPool.java @@ -21,8 +21,6 @@ import java.util.Iterator; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.NoSuchElementException; - import org.apache.commons.lang3.StringUtils; import forge.StaticData; @@ -44,6 +42,10 @@ public class CardPool extends ItemPool { this(); this.addAll(cards); } + + public void add(final String cardName, final int amount) { + this.add(cardName, null, -1, amount); + } public void add(final String cardName, final String setCode) { this.add(cardName, setCode, -1, 1); @@ -61,7 +63,8 @@ public class CardPool extends ItemPool { isCommonCard = false; } - int artCount = isCommonCard ? StaticData.instance().getCommonCards().getArtCount(cardName, setCode) : StaticData.instance().getVariantCards().getArtCount(cardName, setCode); + int artCount = isCommonCard + ? StaticData.instance().getCommonCards().getArtCount(cardName, setCode) : 1; if ( cp != null) { if (artIndex >= 0 || artCount <= 1) { @@ -93,26 +96,6 @@ public class CardPool extends ItemPool { } } - /** - * TODO: Write javadoc for this method. - * - * @param cardName the card name - */ - public void add(final String cardName, int cnt) { - // in order to account for art index randomization we have to add cards one by one instead of in a batch - // TODO: somehow optimize this algorithm?... - for (int i = 0; i < cnt; i++) { - PaperCard cp = StaticData.instance().getCommonCards().getCard(cardName); - if ( cp == null ) - cp = StaticData.instance().getVariantCards().getCard(cardName); - - if ( cp != null) - this.add(cp); - else - throw new NoSuchElementException(String.format("Card %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName)); - } - } - /** * returns n-th card from this DeckSection. LINEAR time. No fixed order between changes * @param i diff --git a/forge-core/src/main/java/forge/deck/Deck.java b/forge-core/src/main/java/forge/deck/Deck.java index af15c6925c6..69eabb61aba 100644 --- a/forge-core/src/main/java/forge/deck/Deck.java +++ b/forge-core/src/main/java/forge/deck/Deck.java @@ -19,7 +19,9 @@ package forge.deck; import java.io.File; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collections; +import java.util.Date; import java.util.EnumMap; import java.util.Iterator; import java.util.List; @@ -36,8 +38,10 @@ import com.google.common.collect.Lists; import forge.StaticData; import forge.card.CardDb; +import forge.card.CardEdition; import forge.card.ColorSet; import forge.card.MagicColor; +import forge.card.CardDb.SetPreference; import forge.deck.io.DeckFileHeader; import forge.deck.io.DeckSerializer; import forge.item.PaperCard; @@ -189,11 +193,17 @@ public class Deck extends DeckBase implements Iterable> s : sections.entrySet()) { DeckSection sec = DeckSection.smartValueOf(s.getKey()); if (sec == null) { continue; } + + for(String k : s.getValue()) + if ( k.indexOf(CardDb.NameSetSeparator) > 0 ) + hasExplicitlySpecifiedSet = true; CardPool pool = CardPool.fromCardList(s.getValue()); // I used to store planes and schemes under sideboard header, so this will assign them to a correct section @@ -207,9 +217,43 @@ public class Deck extends DeckBase implements Iterable p : parts.entrySet()) { + CardPool newPool = new CardPool(); + + for(Entry cp : p.getValue()){ + String cardName = cp.getKey().getName(); + int artIndex = cp.getKey().getArtIndex(); + + PaperCard c = StaticData.instance().getCommonCards().getCardFromEdition(cardName, dayAfterNewestSetRelease, SetPreference.LatestCoreExp, artIndex); + if( null == c ) { + c = StaticData.instance().getCommonCards().getCardFromEdition(cardName, dayAfterNewestSetRelease, SetPreference.Latest, -1); + // this is to randomize art of all those cards + newPool.add(cardName, c.getEdition(), cp.getValue()); + } else + newPool.add(c, cp.getValue()); + } + parts.put(p.getKey(), newPool); + } + + + } + private static List writeCardPool(final ItemPool pool) { List> main2sort = Lists.newArrayList(pool); Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET);