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 com.google.common.collect.Multimaps;
|
||||||
|
|
||||||
import forge.card.CardEdition.CardInSet;
|
import forge.card.CardEdition.CardInSet;
|
||||||
|
import forge.card.CardEdition.Type;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.CollectionSuppliers;
|
import forge.util.CollectionSuppliers;
|
||||||
@@ -46,6 +47,8 @@ import forge.util.TextUtil;
|
|||||||
|
|
||||||
public final class CardDb implements ICardDatabase {
|
public final class CardDb implements ICardDatabase {
|
||||||
public final static String foilSuffix = "+";
|
public final static String foilSuffix = "+";
|
||||||
|
public final static char NameSetSeparator = '|';
|
||||||
|
|
||||||
// need this to obtain cardReference by name+set+artindex
|
// 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 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);
|
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 {
|
public enum SetPreference {
|
||||||
Latest,
|
Latest,
|
||||||
|
LatestCoreExp,
|
||||||
Earliest,
|
Earliest,
|
||||||
|
EarliestCoreExp,
|
||||||
Random
|
Random
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,17 +86,23 @@ public final class CardDb implements ICardDatabase {
|
|||||||
if( isFoil )
|
if( isFoil )
|
||||||
name = name.substring(0, name.length() - foilSuffix.length());
|
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 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;
|
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;
|
int artIndex = artPos > 0 ? Integer.parseInt(nameParts[artPos]) : -1;
|
||||||
String setName = setPos > 0 ? nameParts[setPos] : null;
|
String setName = setPos > 0 ? nameParts[setPos] : null;
|
||||||
if( "???".equals(setName) )
|
if( "???".equals(setName) )
|
||||||
setName = null;
|
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);
|
return tryGetCard(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private PaperCard tryGetCard(CardRequest request) {
|
private PaperCard tryGetCard(CardRequest request) {
|
||||||
Collection<PaperCard> cards = allCardsByName.get(request.cardName);
|
Collection<PaperCard> cards = allCardsByName.get(request.cardName);
|
||||||
if ( null == cards ) return null;
|
if ( null == cards ) return null;
|
||||||
@@ -211,20 +221,37 @@ public final class CardDb implements ICardDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PaperCard getCardFromEdition(final String cardName, final Date printedBefore, final SetPreference fromSet) {
|
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);
|
List<PaperCard> cards = this.allCardsByName.get(cardName);
|
||||||
|
|
||||||
int sz = cards.size();
|
int sz = cards.size();
|
||||||
if( fromSet == SetPreference.Latest ) {
|
if( fromSet == SetPreference.Earliest || fromSet == SetPreference.EarliestCoreExp) {
|
||||||
for(int i = 0 ; i < sz ; i++)
|
for(int i = sz - 1 ; i >= 0 ; i--) {
|
||||||
if( printedBefore == null || editions.get(cards.get(i).getEdition()).getDate().after(printedBefore) )
|
PaperCard pc = cards.get(i);
|
||||||
return 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;
|
return null;
|
||||||
} else if( fromSet == SetPreference.Earliest || fromSet == null || fromSet == SetPreference.Random ) {
|
} else if( fromSet == SetPreference.LatestCoreExp || fromSet == SetPreference.Latest || fromSet == null || fromSet == SetPreference.Random ) {
|
||||||
for(int i = sz - 1 ; i >= 0 ; i--)
|
for(int i = 0 ; i < sz ; i++) {
|
||||||
if( printedBefore == null || editions.get(cards.get(i).getEdition()).getDate().after(printedBefore) ) {
|
PaperCard pc = cards.get(i);
|
||||||
if( fromSet == SetPreference.Earliest )
|
CardEdition ed = editions.get(pc.getEdition());
|
||||||
return cards.get(i);
|
if(fromSet == SetPreference.LatestCoreExp && ed.getType() != Type.CORE && ed.getType() != Type.EXPANSION)
|
||||||
return cards.get(MyRandom.getRandom().nextInt(i+1));
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,15 +415,21 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
|||||||
|
|
||||||
public CardEdition getEarliestEditionWithAllCards(CardPool cards) {
|
public CardEdition getEarliestEditionWithAllCards(CardPool cards) {
|
||||||
Set<String> minEditions = new HashSet<String>();
|
Set<String> minEditions = new HashSet<String>();
|
||||||
|
|
||||||
|
SetPreference strictness = SetPreference.EarliestCoreExp;
|
||||||
|
|
||||||
for(Entry<PaperCard, Integer> k : cards) {
|
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());
|
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()) {
|
for(CardEdition ed : getOrderedEditions()) {
|
||||||
if(minEditions.contains(ed.getCode()))
|
if(minEditions.contains(ed.getCode()))
|
||||||
return ed;
|
return ed;
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ public interface ICardDatabase extends Iterable<PaperCard> {
|
|||||||
PaperCard getCard(String cardName);
|
PaperCard getCard(String cardName);
|
||||||
PaperCard getCard(String cardName, String edition);
|
PaperCard getCard(String cardName, String edition);
|
||||||
PaperCard getCard(String cardName, String edition, int artIndex);
|
PaperCard getCard(String cardName, String edition, int artIndex);
|
||||||
PaperCard getCardFromEdition(final String cardName, final SetPreference fromSet);
|
PaperCard getCardFromEdition(String cardName, SetPreference fromSet);
|
||||||
PaperCard getCardFromEdition(final String cardName, final Date printedBefore, final SetPreference fromSet);
|
PaperCard getCardFromEdition(String cardName, Date printedBefore, SetPreference fromSet);
|
||||||
|
PaperCard getCardFromEdition(String cardName, Date printedBefore, SetPreference fromSet, int artIndex);
|
||||||
|
|
||||||
PaperCard getFoiled(PaperCard cpi);
|
PaperCard getFoiled(PaperCard cpi);
|
||||||
|
|
||||||
@@ -28,4 +29,5 @@ public interface ICardDatabase extends Iterable<PaperCard> {
|
|||||||
List<PaperCard> getAllCards(Predicate<PaperCard> predicate);
|
List<PaperCard> getAllCards(Predicate<PaperCard> predicate);
|
||||||
|
|
||||||
Predicate<? super PaperCard> wasPrintedInSets(List<String> allowedSetCodes);
|
Predicate<? super PaperCard> wasPrintedInSets(List<String> allowedSetCodes);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,8 +21,6 @@ import java.util.Iterator;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
@@ -45,6 +43,10 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
this.addAll(cards);
|
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) {
|
public void add(final String cardName, final String setCode) {
|
||||||
this.add(cardName, setCode, -1, 1);
|
this.add(cardName, setCode, -1, 1);
|
||||||
}
|
}
|
||||||
@@ -61,7 +63,8 @@ public class CardPool extends ItemPool<PaperCard> {
|
|||||||
isCommonCard = false;
|
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 ( cp != null) {
|
||||||
if (artIndex >= 0 || artCount <= 1) {
|
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
|
* returns n-th card from this DeckSection. LINEAR time. No fixed order between changes
|
||||||
* @param i
|
* @param i
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ package forge.deck;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,8 +38,10 @@ import com.google.common.collect.Lists;
|
|||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
|
|
||||||
import forge.card.CardDb;
|
import forge.card.CardDb;
|
||||||
|
import forge.card.CardEdition;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
|
import forge.card.CardDb.SetPreference;
|
||||||
import forge.deck.io.DeckFileHeader;
|
import forge.deck.io.DeckFileHeader;
|
||||||
import forge.deck.io.DeckSerializer;
|
import forge.deck.io.DeckSerializer;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -189,12 +193,18 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
d.setComment(dh.getComment());
|
d.setComment(dh.getComment());
|
||||||
d.tags.addAll(dh.getTags());
|
d.tags.addAll(dh.getTags());
|
||||||
|
|
||||||
|
boolean hasExplicitlySpecifiedSet = false;
|
||||||
|
|
||||||
for (Entry<String, List<String>> s : sections.entrySet()) {
|
for (Entry<String, List<String>> s : sections.entrySet()) {
|
||||||
DeckSection sec = DeckSection.smartValueOf(s.getKey());
|
DeckSection sec = DeckSection.smartValueOf(s.getKey());
|
||||||
if (sec == null) {
|
if (sec == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(String k : s.getValue())
|
||||||
|
if ( k.indexOf(CardDb.NameSetSeparator) > 0 )
|
||||||
|
hasExplicitlySpecifiedSet = true;
|
||||||
|
|
||||||
CardPool pool = CardPool.fromCardList(s.getValue());
|
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
|
// I used to store planes and schemes under sideboard header, so this will assign them to a correct section
|
||||||
IPaperCard sample = pool.get(0);
|
IPaperCard sample = pool.get(0);
|
||||||
@@ -207,9 +217,43 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
|
|||||||
|
|
||||||
d.parts.put(sec, pool);
|
d.parts.put(sec, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasExplicitlySpecifiedSet) {
|
||||||
|
d.convertByXitaxMethod();
|
||||||
|
}
|
||||||
|
|
||||||
return d;
|
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) {
|
private static List<String> writeCardPool(final ItemPool<PaperCard> pool) {
|
||||||
List<Entry<PaperCard, Integer>> main2sort = Lists.newArrayList(pool);
|
List<Entry<PaperCard, Integer>> main2sort = Lists.newArrayList(pool);
|
||||||
Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET);
|
Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET);
|
||||||
|
|||||||
Reference in New Issue
Block a user