mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 18:28:00 +00:00
Xitax's deck convertor integrated into Forge - applies on load to decks where no card has explicitly defined set.
This commit is contained in:
@@ -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<String, PaperCard> allCardsByName = Multimaps.newListMultimap(new TreeMap<String,Collection<PaperCard>>(String.CASE_INSENSITIVE_ORDER), CollectionSuppliers.<PaperCard>arrayLists());
|
||||
private final Map<String, PaperCard> uniqueCardsByName = new TreeMap<String, PaperCard>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +185,6 @@ public final class CardDb implements ICardDatabase {
|
||||
return tryGetCard(request);
|
||||
}
|
||||
|
||||
|
||||
private PaperCard tryGetCard(CardRequest request) {
|
||||
Collection<PaperCard> cards = allCardsByName.get(request.cardName);
|
||||
if ( null == cards ) return null;
|
||||
@@ -211,20 +221,37 @@ 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<PaperCard> 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;
|
||||
}
|
||||
|
||||
@@ -415,15 +415,21 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
||||
|
||||
public CardEdition getEarliestEditionWithAllCards(CardPool cards) {
|
||||
Set<String> minEditions = new HashSet<String>();
|
||||
|
||||
SetPreference strictness = SetPreference.EarliestCoreExp;
|
||||
|
||||
for(Entry<PaperCard, Integer> 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;
|
||||
|
||||
@@ -13,8 +13,9 @@ public interface ICardDatabase extends Iterable<PaperCard> {
|
||||
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<PaperCard> {
|
||||
List<PaperCard> getAllCards(Predicate<PaperCard> predicate);
|
||||
|
||||
Predicate<? super PaperCard> wasPrintedInSets(List<String> allowedSetCodes);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -45,6 +43,10 @@ public class CardPool extends ItemPool<PaperCard> {
|
||||
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<PaperCard> {
|
||||
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<PaperCard> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -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,12 +193,18 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
d.setComment(dh.getComment());
|
||||
d.tags.addAll(dh.getTags());
|
||||
|
||||
boolean hasExplicitlySpecifiedSet = false;
|
||||
|
||||
for (Entry<String, List<String>> 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
|
||||
IPaperCard sample = pool.get(0);
|
||||
@@ -207,9 +217,43 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
||||
|
||||
d.parts.put(sec, pool);
|
||||
}
|
||||
|
||||
if (!hasExplicitlySpecifiedSet) {
|
||||
d.convertByXitaxMethod();
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
private void convertByXitaxMethod() {
|
||||
CardEdition earliestSet = StaticData.instance().getEditions().getEarliestEditionWithAllCards(getAllCardsInASinglePool());
|
||||
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(earliestSet.getDate());
|
||||
cal.add(Calendar.DATE, 1);
|
||||
Date dayAfterNewestSetRelease = cal.getTime();
|
||||
|
||||
for(Entry<DeckSection, CardPool> p : parts.entrySet()) {
|
||||
CardPool newPool = new CardPool();
|
||||
|
||||
for(Entry<PaperCard, Integer> 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<String> writeCardPool(final ItemPool<PaperCard> pool) {
|
||||
List<Entry<PaperCard, Integer>> main2sort = Lists.newArrayList(pool);
|
||||
Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET);
|
||||
|
||||
Reference in New Issue
Block a user