diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/CardManager.java b/forge-gui-desktop/src/main/java/forge/itemmanager/CardManager.java index 8f69d994b4e..2e22066c5f5 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/CardManager.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/CardManager.java @@ -1,10 +1,12 @@ package forge.itemmanager; -import java.util.*; -import java.util.Map.Entry; - -import javax.swing.JMenu; - +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimaps; +import forge.StaticData; +import forge.card.CardEdition; import forge.game.GameFormat; import forge.gamemodes.quest.QuestWorld; import forge.gamemodes.quest.data.QuestPreferences; @@ -16,8 +18,13 @@ import forge.model.FModel; import forge.screens.home.quest.DialogChooseFormats; import forge.screens.home.quest.DialogChooseSets; import forge.screens.match.controllers.CDetailPicture; +import forge.util.CollectionSuppliers; import forge.util.Localizer; +import javax.swing.*; +import java.util.*; +import java.util.Map.Entry; + /** * ItemManager for cards * @@ -49,16 +56,96 @@ public class CardManager extends ItemManager { @Override protected Iterable> getUnique(Iterable> items) { - //use special technique for getting unique cards so that cards without art aren't shown - HashMap> map = new HashMap<>(); + ListMultimap> entriesByName = Multimaps.newListMultimap(new TreeMap<>(String.CASE_INSENSITIVE_ORDER), CollectionSuppliers.arrayLists()); for (Entry item : items) { - final String key = item.getKey().getName(); - final Entry oldValue = map.get(key); - if (oldValue == null || !oldValue.getKey().hasImage()) { //only replace in map if old value doesn't have image - map.put(key, item); + final String cardName = item.getKey().getName(); + entriesByName.put(cardName, item); + } + + // Now we're ready to go on with retrieving cards to be returned + Map cardsMap = new HashMap<>(); + for (String cardName : entriesByName.keySet()) { + List> entries = entriesByName.get(cardName); + + ListMultimap> entriesByEdition = Multimaps.newListMultimap(new HashMap<>(), CollectionSuppliers.arrayLists()); + for (Entry entry : entries) { + CardEdition ed = StaticData.instance().getCardEdition(entry.getKey().getEdition()); + if (ed != null && StaticData.instance().getCardArtPreference().accept(ed)) + entriesByEdition.put(ed, entry); + } + if (entriesByEdition.size() == 0) + continue; // skip card + // Try to retain only those editions accepted by the current Card Art Preference Policy + List acceptedEditions = Lists.newArrayList(Iterables.filter(entriesByEdition.keySet(), new Predicate() { + @Override + public boolean apply(CardEdition ed) { + return StaticData.instance().getCardArtPreference().accept(ed); + } + })); + // If policy too strict, fall back to getting all editions. + if (acceptedEditions.size() == 0) + // Policy is too strict for current PaperCard in Entry. Remove any filter + acceptedEditions.addAll(entriesByEdition.keySet()); + List> entriesToAdd = getEntriesToAdd(entriesByEdition, acceptedEditions); + for (Entry entry : entriesToAdd) + cardsMap.put(entry.getKey(), entry.getValue()); + } + return cardsMap.entrySet(); + } + + /* + Get all the Entries to Add, also accounting for missing images. + If in the end, not all entries found have image, the original ones are used to fill in the total number + of entries to return. + */ + private List> getEntriesToAdd(ListMultimap> entriesByEdition, + List acceptedEditions) { + // Use standard sort + index, for better performance! + Collections.sort(acceptedEditions); + int selectionIndex = 0; + if (StaticData.instance().cardArtPreferenceIsLatest()) + selectionIndex = acceptedEditions.size()-1; + CardEdition uniqueEdition = acceptedEditions.get(selectionIndex); + + // These are now the entries to add to Cards Map + List> uniqueEntries = entriesByEdition.get(uniqueEdition); + + // The last bit to check is whether all of them have a corresponding image. Otherwise, try to escalate + // others. + int entriesToReturn = uniqueEntries.size(); + List> entriesToAdd = new ArrayList<>(); + for (Entry entry : uniqueEntries) { + if (!entry.getKey().hasImage()) + continue; // Skip entries with no image + entriesToAdd.add(entry); + } + + if (entriesToAdd.size() < entriesToReturn) { + // some are missing, keep exploring other editions + int start = 1; + int end = acceptedEditions.size(); + if (selectionIndex != 0) { // latest art case: the last was selected + start = 0; + end = acceptedEditions.size() - 1; + } + for (int editionIndex = start; editionIndex < end; editionIndex++) { + CardEdition edition = acceptedEditions.get(editionIndex); + for (Entry entry : entriesByEdition.get(edition)) { + if (!entry.getKey().hasImage()) + continue; // Skip entries with no image + entriesToAdd.add(entry); + if (entriesToAdd.size() == entriesToReturn) + break; + } + } + // if at this stage, there are still entries to add, fill missing ones from the original list + for (Entry entry : uniqueEntries) { + entriesToAdd.add(entry); + if (entriesToAdd.size() == entriesToReturn) + break; } } - return map.values(); + return entriesToAdd; } /* Static overrides shared with SpellShopManager*/