Merge remote-tracking branch 'upstream/master' into deck-importer-decks-file-format

This commit is contained in:
leriomaggio
2021-10-28 23:20:48 +01:00
76 changed files with 874 additions and 277 deletions

View File

@@ -165,11 +165,10 @@ public class StaticData {
return this.editions;
}
public final CardEdition.Collection getCustomEditions(){
public final CardEdition.Collection getCustomEditions() {
return this.customEditions;
}
private List<CardEdition> sortedEditions;
public final List<CardEdition> getSortedEditions() {
if (sortedEditions == null) {
@@ -189,13 +188,13 @@ public class StaticData {
}
private TreeMap<CardEdition.Type, List<CardEdition>> editionsTypeMap;
public final Map<CardEdition.Type, List<CardEdition>> getEditionsTypeMap(){
if (editionsTypeMap == null){
public final Map<CardEdition.Type, List<CardEdition>> getEditionsTypeMap() {
if (editionsTypeMap == null) {
editionsTypeMap = new TreeMap<>();
for (CardEdition.Type editionType : CardEdition.Type.values()){
for (CardEdition.Type editionType : CardEdition.Type.values()) {
editionsTypeMap.put(editionType, new ArrayList<>());
}
for (CardEdition edition : this.getSortedEditions()){
for (CardEdition edition : this.getSortedEditions()) {
CardEdition.Type key = edition.getType();
List<CardEdition> editionsOfType = editionsTypeMap.get(key);
editionsOfType.add(edition);
@@ -204,9 +203,9 @@ public class StaticData {
return editionsTypeMap;
}
public CardEdition getCardEdition(String setCode){
public CardEdition getCardEdition(String setCode) {
CardEdition edition = this.editions.get(setCode);
if (edition == null) // try custom editions
if (edition == null) // try custom editions
edition = this.customEditions.get(setCode);
return edition;
}
@@ -231,8 +230,7 @@ public class StaticData {
public void attemptToLoadCard(String cardName){
this.attemptToLoadCard(cardName, null);
}
public void attemptToLoadCard(String cardName, String setCode){
public void attemptToLoadCard(String cardName, String setCode) {
CardRules rules = cardReader.attemptToLoadCard(cardName);
CardRules customRules = null;
if (customCardReader != null) {
@@ -257,7 +255,7 @@ public class StaticData {
* @param collectorNumber Card's collector Number
* @return PaperCard instance found in one of the available CardDb databases, or <code>null</code> if not found.
*/
public PaperCard fetchCard(final String cardName, final String setCode, final String collectorNumber){
public PaperCard fetchCard(final String cardName, final String setCode, final String collectorNumber) {
PaperCard card = null;
for (CardDb db : this.getAvailableDatabases().values()) {
card = db.getCard(cardName, setCode, collectorNumber);
@@ -345,7 +343,7 @@ public class StaticData {
return result;
}
private CardDb matchTargetCardDb(final String cardName){
private CardDb matchTargetCardDb(final String cardName) {
// NOTE: any foil request in cardName is NOT taken into account here.
// It's a private method, so it's a fair assumption.
for (CardDb targetDb : this.getAvailableDatabases().values()){
@@ -360,7 +358,7 @@ public class StaticData {
* @param cardName Name of the Card to verify (CASE SENSITIVE)
* @return True if a card with the given input string can be found. False otherwise.
*/
public boolean isMTGCard(final String cardName){
public boolean isMTGCard(final String cardName) {
if (cardName == null || cardName.trim().length() == 0)
return false;
CardDb.CardRequest cr = CardDb.CardRequest.fromString(cardName); // accounts for any foil request ending with +
@@ -450,10 +448,6 @@ public class StaticData {
public Predicate<PaperCard> getBrawlPredicate() { return brawlPredicate; }
public void setFilteredHandsEnabled(boolean filteredHandsEnabled){
this.filteredHandsEnabled = filteredHandsEnabled;
}
/**
* Get an alternative card print for the given card wrt. the input setReleaseDate.
* The reference release date will be used to retrieve the alternative art, according
@@ -501,7 +495,7 @@ public class StaticData {
*/
public PaperCard getAlternativeCardPrint(PaperCard card, Date setReleaseDate,
boolean isCardArtPreferenceLatestArt,
boolean cardArtPreferenceHasFilter){
boolean cardArtPreferenceHasFilter) {
Date searchReferenceDate = getReferenceDate(setReleaseDate, isCardArtPreferenceLatestArt);
CardDb.CardArtPreference searchCardArtStrategy = getSearchStrategyForAlternativeCardArt(isCardArtPreferenceLatestArt,
cardArtPreferenceHasFilter);
@@ -537,7 +531,6 @@ public class StaticData {
public PaperCard getAlternativeCardPrint(PaperCard card, Date setReleaseDate, boolean isCardArtPreferenceLatestArt,
boolean cardArtPreferenceHasFilter,
boolean preferCandidatesFromExpansionSets, boolean preferModernFrame) {
PaperCard altCard = this.getAlternativeCardPrint(card, setReleaseDate, isCardArtPreferenceLatestArt,
cardArtPreferenceHasFilter);
if (altCard == null)
@@ -618,7 +611,7 @@ public class StaticData {
private PaperCard tryToGetCardPrintFromExpansionSet(PaperCard altCard,
boolean isCardArtPreferenceLatestArt,
boolean preferModernFrame){
boolean preferModernFrame) {
CardEdition altCardEdition = editions.get(altCard.getEdition());
if (altCardEdition.getType() == CardEdition.Type.EXPANSION)
return null; // Nothing to do here!
@@ -628,7 +621,7 @@ public class StaticData {
CardDb.CardArtPreference searchStrategy = getSearchStrategyForAlternativeCardArt(searchStrategyFlag,
true);
PaperCard altCandidate = altCard;
while (altCandidate != null){
while (altCandidate != null) {
Date referenceDate = editions.get(altCandidate.getEdition()).getDate();
altCandidate = this.searchAlternativeCardCandidate(altCandidate, preferModernFrame,
referenceDate, searchStrategy);
@@ -645,7 +638,7 @@ public class StaticData {
private PaperCard tryToGetCardPrintWithMatchingFrame(PaperCard altCard,
boolean isCardArtPreferenceLatestArt,
boolean cardArtHasFilter,
boolean preferModernFrame){
boolean preferModernFrame) {
CardEdition altCardEdition = editions.get(altCard.getEdition());
boolean frameIsCompliantAlready = (altCardEdition.isModern() == preferModernFrame);
if (frameIsCompliantAlready)
@@ -654,7 +647,7 @@ public class StaticData {
CardDb.CardArtPreference searchStrategy = getSearchStrategyForAlternativeCardArt(searchStrategyFlag,
cardArtHasFilter);
PaperCard altCandidate = altCard;
while (altCandidate != null){
while (altCandidate != null) {
Date referenceDate = editions.get(altCandidate.getEdition()).getDate();
altCandidate = this.searchAlternativeCardCandidate(altCandidate, preferModernFrame,
referenceDate, searchStrategy);
@@ -677,7 +670,7 @@ public class StaticData {
* @param card Instance of target <code>PaperCard</code>
* @return The number of available arts for the given card in the corresponding set, or 0 if not found.
*/
public int getCardArtCount(PaperCard card){
public int getCardArtCount(PaperCard card) {
Collection<CardDb> databases = this.getAvailableDatabases().values();
for (CardDb db: databases){
int artCount = db.getArtCount(card.getName(), card.getEdition());
@@ -687,9 +680,12 @@ public class StaticData {
return 0;
}
public boolean getFilteredHandsEnabled(){
public boolean getFilteredHandsEnabled() {
return filteredHandsEnabled;
}
public void setFilteredHandsEnabled(boolean filteredHandsEnabled) {
this.filteredHandsEnabled = filteredHandsEnabled;
}
public void setMulliganRule(MulliganDefs.MulliganRule rule) {
mulliganRule = rule;
@@ -699,21 +695,21 @@ public class StaticData {
return mulliganRule;
}
public void setCardArtPreference(boolean latestArt, boolean coreExpansionOnly){
public void setCardArtPreference(boolean latestArt, boolean coreExpansionOnly) {
this.commonCards.setCardArtPreference(latestArt, coreExpansionOnly);
this.variantCards.setCardArtPreference(latestArt, coreExpansionOnly);
this.customCards.setCardArtPreference(latestArt, coreExpansionOnly);
}
public String getCardArtPreferenceName(){
public String getCardArtPreferenceName() {
return this.commonCards.getCardArtPreference().toString();
}
public CardDb.CardArtPreference getCardArtPreference(){
public CardDb.CardArtPreference getCardArtPreference() {
return this.commonCards.getCardArtPreference();
}
public CardDb.CardArtPreference getCardArtPreference(boolean latestArt, boolean coreExpansionOnly){
public CardDb.CardArtPreference getCardArtPreference(boolean latestArt, boolean coreExpansionOnly) {
if (latestArt){
return coreExpansionOnly ? CardDb.CardArtPreference.LATEST_ART_CORE_EXPANSIONS_REPRINT_ONLY : CardDb.CardArtPreference.LATEST_ART_ALL_EDITIONS;
}
@@ -721,15 +717,15 @@ public class StaticData {
}
public boolean isCoreExpansionOnlyFilterSet(){ return this.commonCards.getCardArtPreference().filterSets; }
public boolean isCoreExpansionOnlyFilterSet() { return this.commonCards.getCardArtPreference().filterSets; }
public boolean cardArtPreferenceIsLatest(){
public boolean cardArtPreferenceIsLatest() {
return this.commonCards.getCardArtPreference().latestFirst;
}
// === MOBILE APP Alternative Methods (using String Labels, not yet localised!!) ===
// Note: only used in mobile
public String[] getCardArtAvailablePreferences(){
public String[] getCardArtAvailablePreferences() {
CardDb.CardArtPreference[] preferences = CardDb.CardArtPreference.values();
String[] preferences_avails = new String[preferences.length];
for (int i = 0; i < preferences.length; i++)
@@ -745,17 +741,16 @@ public class StaticData {
return label.toString().trim();
}
public void setCardArtPreference(String artPreference){
public void setCardArtPreference(String artPreference) {
this.commonCards.setCardArtPreference(artPreference);
this.variantCards.setCardArtPreference(artPreference);
this.customCards.setCardArtPreference(artPreference);
}
//
public boolean isEnabledCardArtSmartSelection(){
public boolean isEnabledCardArtSmartSelection() {
return this.enableSmartCardArtSelection;
}
public void setEnableSmartCardArtSelection(boolean isEnabled){
public void setEnableSmartCardArtSelection(boolean isEnabled) {
this.enableSmartCardArtSelection = isEnabled;
}

View File

@@ -53,7 +53,7 @@ public class CardPool extends ItemPool<PaperCard> {
public void add(final String cardRequest, final int amount) {
CardDb.CardRequest request = CardDb.CardRequest.fromString(cardRequest);
this.add(request.cardName, request.edition, request.artIndex, amount);
this.add(CardDb.CardRequest.compose(request.cardName, request.isFoil), request.edition, request.artIndex, amount);
}
public void add(final String cardName, final String setCode) {
@@ -100,7 +100,7 @@ public class CardPool extends ItemPool<PaperCard> {
paperCard = StaticData.instance().getCommonCards().getCard(cardName);
selectedDbName = "Common";
}
if (paperCard == null){
if (paperCard == null) {
// after all still null
System.err.println("An unsupported card was requested: \"" + cardName + "\" from \"" + setCode + "\". \n");
paperCard = StaticData.instance().getCommonCards().createUnsupportedCard(cardName);
@@ -130,7 +130,6 @@ public class CardPool extends ItemPool<PaperCard> {
}
}
/**
* Add all from a List of CardPrinted.
*
@@ -222,10 +221,10 @@ public class CardPool extends ItemPool<PaperCard> {
*
* @see CardPool#getCardEditionStatistics(boolean)
*/
public Map<CardEdition.Type, Integer> getCardEditionTypeStatistics(boolean includeBasicLands){
public Map<CardEdition.Type, Integer> getCardEditionTypeStatistics(boolean includeBasicLands) {
Map<CardEdition.Type, Integer> editionTypeStats = new HashMap<>();
Map<CardEdition, Integer> editionStatistics = this.getCardEditionStatistics(includeBasicLands);
for(Entry<CardEdition, Integer> entry : editionStatistics.entrySet()) {
for (Entry<CardEdition, Integer> entry : editionStatistics.entrySet()) {
CardEdition edition = entry.getKey();
int count = entry.getValue();
CardEdition.Type key = edition.getType();
@@ -242,11 +241,11 @@ public class CardPool extends ItemPool<PaperCard> {
*
* @return The most frequent CardEdition.Type in the pool, or null if the Pool is empty
*/
public CardEdition.Type getTheMostFrequentEditionType(){
public CardEdition.Type getTheMostFrequentEditionType() {
Map<CardEdition.Type, Integer> editionTypeStats = this.getCardEditionTypeStatistics(false);
Integer mostFrequentType = 0;
List<CardEdition.Type> mostFrequentEditionTypes = new ArrayList<>();
for (Map.Entry<CardEdition.Type, Integer> entry : editionTypeStats.entrySet()){
for (Map.Entry<CardEdition.Type, Integer> entry : editionTypeStats.entrySet()) {
if (entry.getValue() > mostFrequentType) {
mostFrequentType = entry.getValue();
mostFrequentEditionTypes.add(entry.getKey());
@@ -271,11 +270,11 @@ public class CardPool extends ItemPool<PaperCard> {
* If the count of Modern and PreModern cards is tied, the return value is determined
* by the preferred Card Art Preference settings, namely True if Latest Art, False otherwise.
*/
public boolean isModern(){
public boolean isModern() {
int modernEditionsCount = 0;
int preModernEditionsCount = 0;
Map<CardEdition, Integer> editionStats = this.getCardEditionStatistics(false);
for (Map.Entry<CardEdition, Integer> entry: editionStats.entrySet()){
for (Map.Entry<CardEdition, Integer> entry: editionStats.entrySet()) {
CardEdition edition = entry.getKey();
if (edition.isModern())
modernEditionsCount += entry.getValue();
@@ -364,7 +363,7 @@ public class CardPool extends ItemPool<PaperCard> {
private static int getMedianFrequency(List<Integer> frequencyValues, float meanFrequency) {
int medianFrequency = frequencyValues.get(0);
float refDelta = Math.abs(meanFrequency - medianFrequency);
for (int i = 1; i < frequencyValues.size(); i++){
for (int i = 1; i < frequencyValues.size(); i++) {
int currentFrequency = frequencyValues.get(i);
float delta = Math.abs(meanFrequency - currentFrequency);
if (delta < refDelta) {
@@ -411,7 +410,7 @@ public class CardPool extends ItemPool<PaperCard> {
return pool;
}
public static List<Pair<String, Integer>> processCardList(final Iterable<String> lines){
public static List<Pair<String, Integer>> processCardList(final Iterable<String> lines) {
List<Pair<String, Integer>> cardRequests = new ArrayList<>();
if (lines == null)
return cardRequests; // empty list
@@ -466,7 +465,7 @@ public class CardPool extends ItemPool<PaperCard> {
public CardPool getFilteredPool(Predicate<PaperCard> predicate) {
CardPool filteredPool = new CardPool();
Iterator<PaperCard> cardsInPool = this.items.keySet().iterator();
while (cardsInPool.hasNext()){
while (cardsInPool.hasNext()) {
PaperCard c = cardsInPool.next();
if (predicate.apply(c))
filteredPool.add(c, this.items.get(c));
@@ -479,12 +478,12 @@ public class CardPool extends ItemPool<PaperCard> {
* @param predicate the Predicate to apply to this CardPool
* @return a new CardPool made from this CardPool with only the cards that agree with the provided Predicate
*/
public CardPool getFilteredPoolWithCardsCount(Predicate<PaperCard> predicate){
public CardPool getFilteredPoolWithCardsCount(Predicate<PaperCard> predicate) {
CardPool filteredPool = new CardPool();
for(Entry<PaperCard, Integer> entry : this.items.entrySet()){
for (Entry<PaperCard, Integer> entry : this.items.entrySet()) {
PaperCard pc = entry.getKey();
int count = entry.getValue();
if(predicate.apply(pc))
if (predicate.apply(pc))
filteredPool.add(pc, count);
}
return filteredPool;

View File

@@ -25,6 +25,7 @@ import forge.card.CardDb;
import forge.card.CardEdition;
import forge.item.IPaperCard;
import forge.item.PaperCard;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import java.util.*;
@@ -216,7 +217,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
}
private void loadDeferredSections() {
if ((deferredSections == null) && (loadedSections == null))
if (deferredSections == null && loadedSections == null)
return;
if (loadedSections != null && !includeCardsFromUnspecifiedSet)
@@ -236,8 +237,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
if (deferredSections != null) {
this.validateDeferredSections();
referenceDeckLoadingMap = new HashMap<>(this.deferredSections);
}
else
} else
referenceDeckLoadingMap = new HashMap<>(loadedSections);
loadedSections = new HashMap<>();
@@ -255,7 +255,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
continue;
final List<String> cardsInSection = s.getValue();
ArrayList<String> cardNamesWithNoEdition = getAllCardNamesWithNoSpecifiedEdition(cardsInSection);
if (cardNamesWithNoEdition.size() > 0){
if (cardNamesWithNoEdition.size() > 0) {
includeCardsFromUnspecifiedSet = true;
if (smartCardArtSelection)
cardsWithNoEdition.put(sec, cardNamesWithNoEdition);
@@ -267,10 +267,9 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
deferredSections = null; // set to null, just in case!
if (includeCardsFromUnspecifiedSet && smartCardArtSelection)
optimiseCardArtSelectionInDeckSections(cardsWithNoEdition);
}
private void validateDeferredSections(){
private void validateDeferredSections() {
/*
Construct a temporary (DeckSection, CardPool) Maps, to be sanitised and finalised
before copying into `this.parts`. This sanitisation is applied because of the
@@ -285,6 +284,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
}
final List<String> cardsInSection = s.getValue();
List<Pair<String, Integer>> originalCardRequests = CardPool.processCardList(cardsInSection);
CardPool pool = CardPool.fromCardList(cardsInSection);
if (pool.countDistinct() == 0)
continue; // pool empty, no card has been found!
@@ -301,13 +301,12 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
if (whiteList == null)
whiteList = new ArrayList<>();
for (Entry<PaperCard, Integer> entry : filteredPool) {
String poolRequest = getPoolRequest(entry);
String poolRequest = getPoolRequest(entry, originalCardRequests);
whiteList.add(poolRequest);
}
validatedSections.put(s.getKey(), whiteList);
if (filteredPool.countDistinct() != pool.countDistinct()){
if (filteredPool.countDistinct() != pool.countDistinct()) {
CardPool blackList = pool.getFilteredPoolWithCardsCount(new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard input) {
@@ -317,7 +316,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
for (Entry<PaperCard, Integer> entry : blackList) {
DeckSection cardSection = DeckSection.matchingSection(entry.getKey());
String poolRequest = getPoolRequest(entry);
String poolRequest = getPoolRequest(entry, originalCardRequests);
List<String> sectionCardList = validatedSections.getOrDefault(cardSection.name(), null);
if (sectionCardList == null)
sectionCardList = new ArrayList<>();
@@ -331,11 +330,26 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
this.deferredSections = validatedSections;
}
private String getPoolRequest(Entry<PaperCard, Integer> entry) {
private String getPoolRequest(Entry<PaperCard, Integer> entry, List<Pair<String, Integer>> originalCardRequests) {
PaperCard card = entry.getKey();
int amount = entry.getValue();
String cardRequest = CardDb.CardRequest.compose(card.getName(), card.getEdition(), card.getArtIndex());
return String.format("%d %s", amount, cardRequest);
String poolCardRequest = CardDb.CardRequest.compose(
card.isFoil() ? CardDb.CardRequest.compose(card.getName(), true) : card.getName(),
card.getEdition(), card.getArtIndex());
String originalRequestCandidate = null;
for (Pair<String, Integer> originalRequest : originalCardRequests){
String cardRequest = originalRequest.getLeft();
if (!StringUtils.startsWithIgnoreCase(poolCardRequest, cardRequest))
continue;
originalRequestCandidate = cardRequest;
int cardAmount = originalRequest.getRight();
if (amount == cardAmount)
return String.format("%d %s", cardAmount, cardRequest);
}
// This is just in case, it should never happen as we're
if (originalRequestCandidate != null)
return String.format("%d %s", amount, originalRequestCandidate);
return String.format("%d %s", amount, poolCardRequest);
}
private ArrayList<String> getAllCardNamesWithNoSpecifiedEdition(List<String> cardsInSection) {
@@ -356,9 +370,9 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
boolean isCardArtPreferenceLatestArt = data.cardArtPreferenceIsLatest();
boolean cardArtPreferenceHasFilter = data.isCoreExpansionOnlyFilterSet();
for(Entry<DeckSection, CardPool> part : parts.entrySet()) {
for (Entry<DeckSection, CardPool> part : parts.entrySet()) {
DeckSection deckSection = part.getKey();
if(deckSection == DeckSection.Planes || deckSection == DeckSection.Schemes || deckSection == DeckSection.Avatar)
if (deckSection != DeckSection.Main && deckSection != DeckSection.Sideboard && deckSection != DeckSection.Commander)
continue;
// == 0. First Off, check if there is anything at all to do for the current section
@@ -432,7 +446,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
cardsPerArtIndex = Math.max(1, cardsPerArtIndex); // make sure is never zero
int cardsAdded = 0;
PaperCard alternativeCardArt = null;
for (int artIndex = 1; artIndex <= nrOfAvailableArts; artIndex++){
for (int artIndex = 1; artIndex <= nrOfAvailableArts; artIndex++) {
alternativeCardArt = data.getOrLoadCommonCard(cardName, setCode, artIndex, isFoil);
cardsAdded += cardsPerArtIndex;
pool.add(alternativeCardArt, cardsPerArtIndex);
@@ -461,7 +475,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
if (card.getRules().isVariant())
return false; // skip variant cards
if (StaticData.instance().getCommonCards().hasPreferredArt(card.getName())){
if (StaticData.instance().getCommonCards().hasPreferredArt(card.getName())) {
// if there is any preferred art, never update it!
CardDb.CardRequest request = CardDb.CardRequest.fromString(card.getName());
if (request.edition.equals(card.getEdition()) && request.artIndex == card.getArtIndex())
@@ -478,8 +492,6 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
return releaseDate.compareTo(referenceReleaseDate) < 0;
}
public static final Function<Deck, String> FN_NAME_SELECTOR = new Function<Deck, String>() {
@Override
public String apply(Deck arg1) {

View File

@@ -123,6 +123,14 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
}
return this.foiledVersion;
}
public PaperCard getUnFoiled() {
if (!this.foil)
return this;
PaperCard unFoiledVersion = new PaperCard(this.rules, this.edition, this.rarity,
this.artIndex, false, String.valueOf(collectorNumber), this.artist);
return unFoiledVersion;
}
// @Override
// public String getImageKey() {
@@ -260,7 +268,6 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
return sortableCNKey;
}
@Override
public int compareTo(final IPaperCard o) {
final int nameCmp = name.compareToIgnoreCase(o.getName());