diff --git a/src/main/java/forge/card/BoosterGenerator.java b/src/main/java/forge/card/BoosterGenerator.java index 1faa36ddad6..d4749e1fa59 100644 --- a/src/main/java/forge/card/BoosterGenerator.java +++ b/src/main/java/forge/card/BoosterGenerator.java @@ -18,9 +18,9 @@ package forge.card; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; @@ -47,7 +47,7 @@ import forge.util.TextUtil; * @version $Id$ */ public class BoosterGenerator { - private final static Map cachedSheets = new HashMap(); + private final static Map cachedSheets = new TreeMap(String.CASE_INSENSITIVE_ORDER); private static final synchronized PrintSheet getPrintSheet(String key) { if( !cachedSheets.containsKey(key) ) cachedSheets.put(key, makeSheet(key, CardDb.instance().getAllCards())); @@ -69,26 +69,8 @@ public class BoosterGenerator { return result; } - // If they request cards from an arbitrary pool, there's no use to cache printsheets. - public static final List getBoosterPack(SealedProductTemplate booster, Iterable sourcePool) { - if(sourcePool == CardDb.instance().getAllCards()) - throw new IllegalArgumentException("Do not use this overload to obtain boosters based on complete cardDb"); - if(null == sourcePool) - return getBoosterPack(booster); - - List result = new ArrayList(); - for(Pair slot : booster.getSlots()) { - String slotType = slot.getLeft(); // add expansion symbol here? - int numCards = slot.getRight().intValue(); - - PrintSheet ps = makeSheet(slotType, sourcePool); - result.addAll(ps.random(numCards, true)); - } - return result; - } - @SuppressWarnings("unchecked") - private static final PrintSheet makeSheet(String sheetKey, Iterable src) { + public static final PrintSheet makeSheet(String sheetKey, Iterable src) { PrintSheet ps = new PrintSheet(sheetKey); String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', '(', ')', 2); diff --git a/src/main/java/forge/card/MetaSet.java b/src/main/java/forge/card/MetaSet.java index dc37be2d0b3..c560a8e2e83 100644 --- a/src/main/java/forge/card/MetaSet.java +++ b/src/main/java/forge/card/MetaSet.java @@ -22,11 +22,8 @@ import java.io.File; import java.util.List; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; - import forge.Singletons; import forge.game.limited.CustomLimited; -import forge.item.CardDb; import forge.item.CardPrinted; import forge.item.IPaperCard; import forge.util.FileUtil; @@ -168,8 +165,7 @@ public class MetaSet { case JoinedSet: Predicate predicate = IPaperCard.Predicates.printedInSets(data.split(" ")); - Iterable pool = Iterables.filter(CardDb.instance().getAllCards(), predicate); - return new UnOpenedProduct(BoosterTemplate.genericBooster, pool); + return new UnOpenedProduct(BoosterTemplate.genericBooster, predicate); case Choose: return new UnOpenedMeta(data, true); diff --git a/src/main/java/forge/card/SealedProductTemplate.java b/src/main/java/forge/card/SealedProductTemplate.java index c04953ca35b..34e98d1dede 100644 --- a/src/main/java/forge/card/SealedProductTemplate.java +++ b/src/main/java/forge/card/SealedProductTemplate.java @@ -29,25 +29,20 @@ public class SealedProductTemplate { protected final List> slots; - public String getEdition() { - return null; - } - public final List> getSlots() { return slots; } + public String getEdition() { + return null; + } + public SealedProductTemplate(Iterable> itrSlots) { slots = Lists.newArrayList(itrSlots); } - @SuppressWarnings("unchecked") - public SealedProductTemplate(int qty) { - this(Lists.newArrayList(Pair.of("any", qty))); - } - - public int getTotal() { + public int getNumberOfCardsExpected() { int sum = 0; for(Pair p : slots) { sum += p.getRight().intValue(); diff --git a/src/main/java/forge/card/UnOpenedProduct.java b/src/main/java/forge/card/UnOpenedProduct.java index 65a8974f18e..a590a398984 100644 --- a/src/main/java/forge/card/UnOpenedProduct.java +++ b/src/main/java/forge/card/UnOpenedProduct.java @@ -1,41 +1,83 @@ package forge.card; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; +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.CardPrinted; import forge.item.ItemPoolView; +import forge.item.PrintSheet; public class UnOpenedProduct implements IUnOpenedProduct { - private final ItemPoolView cards; - private final Iterable cardPoolFlat; private final SealedProductTemplate tpl; - /** - * TODO: Write javadoc for Constructor. - */ + private final Map sheets; + private boolean poolLimited = false; // if true after successful generation cards are removed from printsheets. + + public final boolean isPoolLimited() { + return poolLimited; + } + + public final void setLimitedPool(boolean considerNumbersInPool) { + this.poolLimited = considerNumbersInPool; // TODO: Add 0 to parameter's name. + } + + + // Means to select from all unique cards (from base game, ie. no schemes or avatars) public UnOpenedProduct(SealedProductTemplate template) { tpl = template; - cards = null; - cardPoolFlat = null; + sheets = null; } + // Invoke this constructor only if you are sure that the pool is not equal to deafult carddb public UnOpenedProduct(SealedProductTemplate template, ItemPoolView pool) { - cards = pool; - cardPoolFlat = null; - tpl = template; + this(template, pool.toFlatList()); } - public UnOpenedProduct(SealedProductTemplate template, Iterable pool) { - cardPoolFlat = pool; + public UnOpenedProduct(SealedProductTemplate template, Iterable cards) { tpl = template; - cards = null; - } + sheets = new TreeMap(); + prebuildSheets(cards); + } + + public UnOpenedProduct(SealedProductTemplate sealedProductTemplate, Predicate filterPrinted) { + this(sealedProductTemplate, Iterables.filter(CardDb.instance().getAllCards(), filterPrinted)); + } + + private void prebuildSheets(Iterable sourceList) { + for(Pair cc : tpl.getSlots()) { + sheets.put(cc.getKey(), BoosterGenerator.makeSheet(cc.getKey(), sourceList)); + } + } @Override public List get() { - return cards == null && cardPoolFlat == null ? BoosterGenerator.getBoosterPack(tpl) - : BoosterGenerator.getBoosterPack(tpl, cardPoolFlat == null ? cards.toFlatList() : cardPoolFlat); + return sheets == null ? BoosterGenerator.getBoosterPack(tpl) : getBoosterPack(); + } + + // If they request cards from an arbitrary pool, there's no use to cache printsheets. + private final List getBoosterPack() { + List result = new ArrayList(); + for(Pair slot : tpl.getSlots()) { + PrintSheet ps = sheets.get(slot.getLeft()); + if(ps.isEmpty() && poolLimited ) { + throw new IllegalStateException("The cardpool has been depleted and has no more cards for slot " + slot.getKey()); + } + + List foundCards = ps.random(slot.getRight().intValue(), true); + if(poolLimited) + ps.removeAll(foundCards); + result.addAll(foundCards); + } + return result; } } + \ No newline at end of file diff --git a/src/main/java/forge/game/limited/BoosterDraft.java b/src/main/java/forge/game/limited/BoosterDraft.java index 78e54f0cc6b..b0f6398cc18 100644 --- a/src/main/java/forge/game/limited/BoosterDraft.java +++ b/src/main/java/forge/game/limited/BoosterDraft.java @@ -36,7 +36,6 @@ import com.google.common.base.Supplier; import forge.Card; import forge.Constant.Preferences; import forge.Singletons; -import forge.card.BoosterGenerator; import forge.card.BoosterTemplate; import forge.card.CardBlock; import forge.card.CardEdition; @@ -89,9 +88,7 @@ public final class BoosterDraft implements IBoosterDraft { switch (draftType) { case Full: // Draft from all cards in Forge - Supplier> s = new Supplier>() { - @Override public List get() { return BoosterGenerator.getBoosterPack(BoosterTemplate.genericBooster); } - }; + Supplier> s = new UnOpenedProduct(BoosterTemplate.genericBooster); for (int i = 0; i < 3; i++) this.product.add(s); IBoosterDraft.LAND_SET_CODE[0] = CardDb.instance().getCard("Plains").getEdition(); @@ -167,8 +164,9 @@ public final class BoosterDraft implements IBoosterDraft { final SealedProductTemplate tpl = draft.getSealedProductTemplate(); + UnOpenedProduct toAdd = new UnOpenedProduct(tpl, dPool); for (int i = 0; i < draft.getNumPacks(); i++) { - this.product.add(new UnOpenedProduct(tpl, dPool)); + this.product.add(toAdd); } IBoosterDraft.LAND_SET_CODE[0] = draft.getLandSetCode(); diff --git a/src/main/java/forge/game/limited/SealedDeckFormat.java b/src/main/java/forge/game/limited/SealedDeckFormat.java index 13d07b7b399..7f9bd62635c 100644 --- a/src/main/java/forge/game/limited/SealedDeckFormat.java +++ b/src/main/java/forge/game/limited/SealedDeckFormat.java @@ -246,19 +246,17 @@ public class SealedDeckFormat { if (element.endsWith(".sealed")) { final List dfData = FileUtil.readFile("res/sealed/" + element); final CustomLimited cs = CustomLimited.parse(dfData, Singletons.getModel().getDecks().getCubes()); - if (cs.getSealedProductTemplate().getTotal() > 5) { // Do not allow too small cubes to be played as 'stand-alone'! + if (cs.getSealedProductTemplate().getNumberOfCardsExpected() > 5) { // Do not allow too small cubes to be played as 'stand-alone'! customs.add(cs); } } } // present list to user - if (customs.size() < 1) { - JOptionPane.showMessageDialog(null, "No custom sealed files found.", "", - JOptionPane.INFORMATION_MESSAGE); + if (customs.isEmpty()) { + JOptionPane.showMessageDialog(null, "No custom sealed files found.", "", JOptionPane.INFORMATION_MESSAGE); } else { - final CustomLimited draft = GuiChoose.one("Choose Custom Sealed Pool", - customs); + final CustomLimited draft = GuiChoose.one("Choose Custom Sealed Pool", customs); // Choose number of boosters @@ -270,8 +268,9 @@ public class SealedDeckFormat { Integer nrBoosters = GuiChoose.one("How many booster packs?", integers); + IUnOpenedProduct toAdd = new UnOpenedProduct(draft.getSealedProductTemplate(), draft.getCardPool()); for (int i = 0; i < nrBoosters; i++) { - this.product.add(new UnOpenedProduct(draft.getSealedProductTemplate(), draft.getCardPool())); + this.product.add(toAdd); } this.getLandSetCode()[0] = draft.getLandSetCode(); diff --git a/src/main/java/forge/item/FatPack.java b/src/main/java/forge/item/FatPack.java index cb879e0953d..496993c114e 100644 --- a/src/main/java/forge/item/FatPack.java +++ b/src/main/java/forge/item/FatPack.java @@ -71,6 +71,6 @@ public class FatPack extends OpenablePack { @Override public int getTotalCards() { - return super.getTotalCards() * fpData.getCntBoosters() + fpData.getTotal(); + return super.getTotalCards() * fpData.getCntBoosters() + fpData.getNumberOfCardsExpected(); } } diff --git a/src/main/java/forge/item/OpenablePack.java b/src/main/java/forge/item/OpenablePack.java index e8678f1c494..bff908ebe82 100644 --- a/src/main/java/forge/item/OpenablePack.java +++ b/src/main/java/forge/item/OpenablePack.java @@ -68,7 +68,7 @@ public abstract class OpenablePack implements InventoryItemFromSet { } public int getTotalCards() { - return contents.getTotal(); + return contents.getNumberOfCardsExpected(); } @Override diff --git a/src/main/java/forge/item/PrintSheet.java b/src/main/java/forge/item/PrintSheet.java index 85ee5a1c4eb..ba2631a9540 100644 --- a/src/main/java/forge/item/PrintSheet.java +++ b/src/main/java/forge/item/PrintSheet.java @@ -50,7 +50,14 @@ public class PrintSheet { public void addAll(Iterable cards, int weight) { for(CardPrinted card : cards) cardsWithWeights.add(card, weight); - } + } + + /** Cuts cards out of a sheet - they won't be printed again. + * Please use mutable sheets for cubes only.*/ + public void removeAll(Iterable cards) { + for(CardPrinted card : cards) + cardsWithWeights.remove(card); + } private CardPrinted fetchRoulette(int start, int roulette, Collection toSkip) { int sum = start; @@ -107,5 +114,9 @@ public class PrintSheet { } + public boolean isEmpty() { + return cardsWithWeights.isEmpty(); + } + } diff --git a/src/main/java/forge/quest/QuestUtilCards.java b/src/main/java/forge/quest/QuestUtilCards.java index 901ad9d2e3c..7694149537b 100644 --- a/src/main/java/forge/quest/QuestUtilCards.java +++ b/src/main/java/forge/quest/QuestUtilCards.java @@ -29,12 +29,13 @@ import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import forge.Constant; import forge.Singletons; -import forge.card.BoosterGenerator; import forge.card.CardEdition; import forge.card.CardRarity; import forge.card.FormatCollection; import forge.card.SealedProductTemplate; +import forge.card.UnOpenedProduct; import forge.deck.Deck; import forge.deck.DeckSection; import forge.item.BoosterPack; @@ -120,11 +121,10 @@ public final class QuestUtilCards { landCode = "M10"; } - pool.add(db.getCard("Forest", landCode), nBasic); - pool.add(db.getCard("Mountain", landCode), nBasic); - pool.add(db.getCard("Swamp", landCode), nBasic); - pool.add(db.getCard("Island", landCode), nBasic); - pool.add(db.getCard("Plains", landCode), nBasic); + for(String landName : Constant.Color.BASIC_LANDS) { + pool.add(db.getCard(landName, landCode), nBasic); + } + if (!snowLandCodes.isEmpty()) { String snowLandCode = Aggregates.random(snowLandCodes); @@ -517,10 +517,7 @@ public final class QuestUtilCards { * Generate cards in shop. */ private void generateCardsInShop() { - Iterable cardList = null; - if (qc.getFormat() != null) { - cardList = Iterables.filter(CardDb.instance().getAllCards(), qc.getFormat().getFilterPrinted()); - } + int nLevel = this.qc.getAchievements().getLevel(); @@ -537,12 +534,11 @@ public final class QuestUtilCards { final int totalPacks = Math.min(levelPacks + winPacks, maxPacks); @SuppressWarnings("unchecked") - SealedProductTemplate template = new SealedProductTemplate(Lists.newArrayList( - Pair.of("Common", common), Pair.of("uncommon", uncommon), Pair.of("RareMythic", rare) - )); + SealedProductTemplate tpl = new SealedProductTemplate(Lists.newArrayList( Pair.of("Common", common), Pair.of("Uncommon", uncommon), Pair.of("RareMythic", rare))); + UnOpenedProduct unopened = qc.getFormat() == null ? new UnOpenedProduct( tpl ) : new UnOpenedProduct( tpl, qc.getFormat().getFilterPrinted()); for (int i = 0; i < totalPacks; i++) { - this.qa.getShopList().addAllFlat(BoosterGenerator.getBoosterPack(template, cardList)); + this.qa.getShopList().addAllFlat(unopened.get()); } this.generateBoostersInShop(totalPacks);