Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion forge-core/src/main/java/forge/StaticData.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import java.io.File;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
Expand Down Expand Up @@ -64,9 +65,12 @@ public class StaticData {
private static StaticData lastInstance = null;

public StaticData(CardStorageReader cardReader, CardStorageReader customCardReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards) {
this(cardReader, null, customCardReader, null, editionFolder, customEditionsFolder, blockDataFolder, "", cardArtPreference, enableUnknownCards, loadNonLegalCards, false, false);
this(cardReader, null, customCardReader, null, editionFolder, customEditionsFolder, blockDataFolder, "", cardArtPreference, enableUnknownCards, loadNonLegalCards, false, false, null);
}
public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, CardStorageReader customCardReader, CardStorageReader customTokenReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String setLookupFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards, boolean allowCustomCardsInDecksConformance, boolean enableSmartCardArtSelection) {
this(cardReader, tokenReader, customCardReader, customTokenReader, editionFolder, customEditionsFolder, blockDataFolder, setLookupFolder, cardArtPreference, enableUnknownCards, loadNonLegalCards, allowCustomCardsInDecksConformance, enableSmartCardArtSelection, null);
}
public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, CardStorageReader customCardReader, CardStorageReader customTokenReader, String editionFolder, String customEditionsFolder, String blockDataFolder, String setLookupFolder, String cardArtPreference, boolean enableUnknownCards, boolean loadNonLegalCards, boolean allowCustomCardsInDecksConformance, boolean enableSmartCardArtSelection, BiPredicate<String, String> preferredLanguageAvailability) {
this.cardReader = cardReader;
this.tokenReader = tokenReader;
this.editions = new CardEdition.Collection(new CardEdition.Reader(new File(editionFolder)));
Expand Down Expand Up @@ -131,6 +135,8 @@ public StaticData(CardStorageReader cardReader, CardStorageReader tokenReader, C

commonCards.setCardArtPreference(cardArtPreference);
variantCards.setCardArtPreference(cardArtPreference);
commonCards.setPreferredLanguageAvailability(preferredLanguageAvailability);
variantCards.setPreferredLanguageAvailability(preferredLanguageAvailability);

//must initialize after establish field values for the sake of card image logic
commonCards.initialize(false, false, enableUnknownCards);
Expand Down Expand Up @@ -956,6 +962,11 @@ public void setCardArtPreference(String artPreference) {
this.variantCards.setCardArtPreference(artPreference);
}

public void setPreferredLanguageAvailability(BiPredicate<String, String> availability) {
this.commonCards.setPreferredLanguageAvailability(availability);
this.variantCards.setPreferredLanguageAvailability(availability);
}

public boolean isEnabledCardArtSmartSelection() {
return this.enableSmartCardArtSelection;
}
Expand Down
25 changes: 24 additions & 1 deletion forge-core/src/main/java/forge/card/CardDb.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import java.util.*;
import java.util.Map.Entry;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -98,6 +99,8 @@ public int compare(CardEdition o1, CardEdition o2) {

// Placeholder to setup default art Preference - to be moved from Static Data!
private CardArtPreference defaultCardArtPreference;
private BiPredicate<String, String> preferredLanguageAvailability;
private boolean initialized;

public static class CardRequest {
public String cardName;
Expand Down Expand Up @@ -536,6 +539,7 @@ public void initialize(boolean logMissingPerEdition, boolean logMissingSummary,
}
}

initialized = true;
reIndex();
}

Expand Down Expand Up @@ -583,11 +587,23 @@ private void reIndex() {
private PaperCard getBestUniquePrint(final Collection<PaperCard> cards) {
return cards.stream()
.filter(pc -> !pc.getRarity().equals(CardRarity.Special))
.min(Comparator.comparing((PaperCard pc) -> editions.get(pc.getEdition()), defaultCardArtPreference)
.min(Comparator.comparing((PaperCard pc) -> isPreferredLanguagePrint(pc) ? 0 : 1)
.thenComparing((PaperCard pc) -> editions.get(pc.getEdition()), defaultCardArtPreference)
.thenComparing(PaperCard::getCollectorNumber))
.orElseGet(() -> cards.iterator().next());
}

private boolean isPreferredLanguagePrint(PaperCard pc) {
if (preferredLanguageAvailability == null) {
return false;
}
CardEdition edition = editions.get(pc.getEdition());
if (edition == null) {
return false;
}
return preferredLanguageAvailability.test(edition.getScryfallCode(), pc.getCollectorNumber());
}

public boolean setPreferredArt(String cardName, String setCode, int artIndex) {
String cardRequestForPreferredArt = CardRequest.compose(cardName, setCode, artIndex);
PaperCard pc = this.getCard(cardRequestForPreferredArt);
Expand All @@ -613,6 +629,13 @@ public void setCardArtPreference(boolean latestArt, boolean coreExpansionOnly){
}
}

public void setPreferredLanguageAvailability(BiPredicate<String, String> availability) {
this.preferredLanguageAvailability = availability;
if (initialized) {
reIndex();
}
}

/**
* Retrieves a CardRules matching the provided name.
* @param allowAltNames If false, the name must be the exact name of the card in its default state. If true, flavor
Expand Down
30 changes: 28 additions & 2 deletions forge-gui-desktop/src/main/java/forge/itemmanager/CardManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import forge.screens.home.quest.DialogChooseFormats;
import forge.screens.home.quest.DialogChooseSets;
import forge.screens.match.controllers.CDetailPicture;
import forge.util.CardLanguageIndex;
import forge.util.Localizer;

import javax.swing.*;
Expand Down Expand Up @@ -62,6 +63,9 @@ protected Iterable<Entry<PaperCard, Integer>> getUnique(Iterable<Entry<PaperCard
entriesByName.put(cardName, item);
}

final String preferredLang = FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_PREFER_LANG_FOR_UNIQUE_CARDS)
? CardLanguageIndex.getPreferredCardLangCode() : null;

// Now we're ready to go on with retrieving cards to be returned
Map<PaperCard, Integer> cardsMap = new HashMap<>();
for (String cardName : entriesByName.keySet()) {
Expand All @@ -85,7 +89,7 @@ protected Iterable<Entry<PaperCard, Integer>> getUnique(Iterable<Entry<PaperCard
// Policy is too strict for current PaperCard in Entry. Remove any filter
acceptedEditions.addAll(entriesByEdition.keySet());

Entry<PaperCard, Integer> cardEntry = getCardEntryToAdd(entriesByEdition, acceptedEditions);
Entry<PaperCard, Integer> cardEntry = getCardEntryToAdd(entriesByEdition, acceptedEditions, preferredLang);
if (cardEntry != null)
cardsMap.put(cardEntry.getKey(), cardEntry.getValue());
}
Expand All @@ -95,7 +99,7 @@ protected Iterable<Entry<PaperCard, Integer>> getUnique(Iterable<Entry<PaperCard
// Select the Card Art Entry to add, based on current Card Art Preference Order.
// This method will prefer the entry currently having an image. If that's not the case,
private Entry<PaperCard, Integer> getCardEntryToAdd(ListMultimap<CardEdition, Entry<PaperCard, Integer>> entriesByEdition,
List<CardEdition> acceptedEditions) {
List<CardEdition> acceptedEditions, String preferredLang) {
// Use standard sort + index, for better performance!
Collections.sort(acceptedEditions);
if (StaticData.instance().cardArtPreferenceIsLatest())
Expand All @@ -107,6 +111,20 @@ private Entry<PaperCard, Integer> getCardEntryToAdd(ListMultimap<CardEdition, En
CardEdition cardEdition = editionIterator.next();
// These are now the entries to add to Cards Map
List<Entry<PaperCard, Integer>> cardEntries = entriesByEdition.get(cardEdition);

if (preferredLang != null) {
for (Entry<PaperCard, Integer> entry : cardEntries) {
if (isPreferredLanguagePrint(entry.getKey(), preferredLang)) {
if (firstCandidateEntryFound == null)
firstCandidateEntryFound = entry;
candidateEntry = entry;
break;
}
}
if (candidateEntry != null)
break;
}

Iterator<Entry<PaperCard, Integer>> entriesIterator = cardEntries.iterator();
candidateEntry = entriesIterator.hasNext() ? entriesIterator.next() : null;
if (candidateEntry != null && firstCandidateEntryFound == null)
Expand All @@ -123,6 +141,14 @@ private Entry<PaperCard, Integer> getCardEntryToAdd(ListMultimap<CardEdition, En
return candidateEntry != null ? candidateEntry : firstCandidateEntryFound;
}

private boolean isPreferredLanguagePrint(PaperCard card, String preferredLang) {
CardEdition edition = StaticData.instance().getEditions().get(card.getEdition());
if (edition == null) {
return false;
}
return CardLanguageIndex.instance().isAvailableInLanguage(edition.getScryfallCode(), card.getCollectorNumber(), preferredLang);
}

/* Static overrides shared with SpellShopManager*/

public static void addDefaultFilters(final ItemManager<? super PaperCard> itemManager) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@
package forge.itemmanager;

import com.google.common.collect.Lists;
import forge.StaticData;
import forge.card.CardEdition;
import forge.gui.GuiUtils;
import forge.gui.UiCommand;
import forge.item.IPaperCard;
import forge.item.InventoryItem;
import forge.item.PaperCard;
import forge.itemmanager.filters.ItemFilter;
import forge.localinstance.properties.ForgePreferences.FPref;
import forge.model.FModel;
import forge.itemmanager.views.ImageView;
import forge.itemmanager.views.ItemListView;
import forge.itemmanager.views.ItemTableColumn;
Expand Down Expand Up @@ -998,7 +1003,35 @@ public void refresh() {
}

protected Iterable<Entry<T, Integer>> getUnique(final Iterable<Entry<T, Integer>> items) {
return Aggregates.uniqueByLast(items, from -> from.getKey().getName());
if (!FModel.getPreferences().getPrefBoolean(FPref.UI_PREFER_LANG_FOR_UNIQUE_CARDS)) {
return Aggregates.uniqueByLast(items, from -> from.getKey().getName());
}
final String preferredLang = CardLanguageIndex.getPreferredCardLangCode();
if (preferredLang == null) {
return Aggregates.uniqueByLast(items, from -> from.getKey().getName());
}

final Map<String, Entry<T, Integer>> uniques = new LinkedHashMap<>();
for (final Entry<T, Integer> entry : items) {
final String key = entry.getKey().getName();
final Entry<T, Integer> existing = uniques.get(key);
if (existing == null || isPreferredLanguagePrint(entry.getKey(), preferredLang)) {
uniques.put(key, entry);
}
}
return uniques.values();
}

private boolean isPreferredLanguagePrint(final T item, final String preferredLang) {
if (!(item instanceof IPaperCard)) {
return false;
}
final IPaperCard card = (IPaperCard) item;
final CardEdition edition = StaticData.instance().getEditions().get(card.getEdition());
if (edition == null) {
return false;
}
return CardLanguageIndex.instance().isAvailableInLanguage(edition.getScryfallCode(), card.getCollectorNumber(), preferredLang);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import forge.toolbox.FComboBoxPanel;
import forge.toolbox.FLabel;
import forge.toolbox.FOptionPane;
import forge.util.CardLanguageIndex;
import forge.util.Localizer;
import forge.view.arcane.PlayArea;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -206,6 +207,7 @@ public void initialize() {
initializeDefaultFontSizeComboBox();
initializeCardArtFormatComboBox();
initializeCardArtPreference();
initializeCardDownloadLanguageComboBox();
initializeAutoUpdaterComboBox();
initializeServerUPnPComboBox();
initializeMulliganRuleComboBox();
Expand Down Expand Up @@ -419,6 +421,46 @@ private void initializeAutoUpdaterComboBox() {
panel.setComboBox(comboBox, selectedItem);
}

private void initializeCardDownloadLanguageComboBox() {
final Map<String, String> cardLangMapping = ForgeConstants.getScryfallCardLanguageMapping();
final String[] localizedOptions = cardLangMapping.keySet().toArray(new String[0]);

final FPref cardLangPreference = FPref.UI_CARD_DOWNLOAD_LANG;

final FComboBoxPanel<String> panel = this.view.getCbpCardDownloadLangComboBoxPanel();
final FComboBox<String> comboBox = createLocalizedComboBox(localizedOptions, cardLangPreference, cardLangMapping);
comboBox.addItemListener(e -> applyPreferredLanguageAvailability());

final String savedCode = this.prefs.getPref(cardLangPreference);
final String selectedDisplayName = cardLangMapping.entrySet().stream()
.filter(entry -> entry.getValue().equals(savedCode))
.map(Map.Entry::getKey)
.findFirst()
.orElse("English");

panel.setComboBox(comboBox, selectedDisplayName);

final JCheckBox cbPreferLang = this.view.getCbPreferLangForUniqueCards();
cbPreferLang.setSelected(this.prefs.getPrefBoolean(FPref.UI_PREFER_LANG_FOR_UNIQUE_CARDS));
cbPreferLang.addItemListener(e -> {
this.prefs.setPref(FPref.UI_PREFER_LANG_FOR_UNIQUE_CARDS, String.valueOf(cbPreferLang.isSelected()));
this.prefs.save();
applyPreferredLanguageAvailability();
});

applyPreferredLanguageAvailability();
}

private void applyPreferredLanguageAvailability() {
String langCode = this.prefs.getPref(FPref.UI_CARD_DOWNLOAD_LANG);
boolean preferForUnique = this.prefs.getPrefBoolean(FPref.UI_PREFER_LANG_FOR_UNIQUE_CARDS);
if (!preferForUnique || langCode == null || langCode.isEmpty() || "en".equalsIgnoreCase(langCode)) {
FModel.getMagicDb().setPreferredLanguageAvailability(null);
} else {
FModel.getMagicDb().setPreferredLanguageAvailability((setCode, cn) -> CardLanguageIndex.instance().isAvailableInLanguage(setCode, cn, langCode));
}
}

private void initializeServerUPnPComboBox() {
// Step 1: Define the localized strings and mappings
final Map<String, String> upnpPreferenceMapping = ForgeConstants.getUPnPPreferenceMapping();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
private final JCheckBox cbSROptimize = new OptionsCheckBox(localizer.getMessage("cbSROptimize"));
private final JCheckBox cbFilteredHands = new OptionsCheckBox(localizer.getMessage("cbFilteredHands"));
private final JCheckBox cbImageFetcher = new OptionsCheckBox(localizer.getMessage("cbImageFetcher"));
private final JCheckBox cbPreferLangForUniqueCards = new OptionsCheckBox(localizer.getMessage("cbPreferLangForUniqueCards"));
private final JCheckBox cbDisableCardImages = new OptionsCheckBox(localizer.getMessage("lblDisableCardImages"));
private final JCheckBox cbCloneImgSource = new OptionsCheckBox(localizer.getMessage("cbCloneImgSource"));
private final JCheckBox cbScaleLarger = new OptionsCheckBox(localizer.getMessage("cbScaleLarger"));
Expand Down Expand Up @@ -145,6 +146,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
private final FComboBoxPanel<String> cbpDefaultFontSize = new FComboBoxPanel<>(localizer.getMessage("cbpDefaultFontSize")+":");
private final FComboBoxPanel<String> cbpCardArtFormat = new FComboBoxPanel<>(localizer.getMessage("cbpCardArtFormat")+":");
private final FComboBoxPanel<String> cbpCardArtPreference = new FComboBoxPanel<>(localizer.getMessage("lblPreferredArt")+":");
private final FComboBoxPanel<String> cbpCardDownloadLang = new FComboBoxPanel<>(localizer.getMessage("cbpCardDownloadLang")+":");
private final FComboBoxPanel<String> cbpMulliganRule = new FComboBoxPanel<>(localizer.getMessage("cbpMulliganRule")+":");
private final FComboBoxPanel<String> cbpSoundSets = new FComboBoxPanel<>(localizer.getMessage("cbpSoundSets")+":");
private final FComboBoxPanel<String> cbpMusicSets = new FComboBoxPanel<>(localizer.getMessage("cbpMusicSets")+":");
Expand Down Expand Up @@ -396,6 +398,12 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
pnlPrefs.add(cbImageFetcher, titleConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlImageFetcher")), descriptionConstraints);

pnlPrefs.add(cbpCardDownloadLang, comboBoxConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCardDownloadLang")), descriptionConstraints);

pnlPrefs.add(cbPreferLangForUniqueCards, titleConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlPreferLangForUniqueCards")), descriptionConstraints);

pnlPrefs.add(cbDisableCardImages, titleConstraints);
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDisableCardImages")), descriptionConstraints);

Expand Down Expand Up @@ -782,6 +790,14 @@ public JCheckBox getCbImageFetcher() {
return cbImageFetcher;
}

public JCheckBox getCbPreferLangForUniqueCards() {
return cbPreferLangForUniqueCards;
}

public FComboBoxPanel<String> getCbpCardDownloadLangComboBoxPanel() {
return cbpCardDownloadLang;
}

/** @return {@link javax.swing.JCheckBox} */
public JCheckBox getCbDisableCardImages() {
return cbDisableCardImages;
Expand Down
Loading
Loading