mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
RENEWED and Refined implementation of getUnique for cards, also taking into account current Card Art Preference
getUnique previously returned random results, based on the internal order in which entries were found. Now, filtering by Unique Cards in Catalog is aware of the current Cart Art Preference Also, the algorithm takes into account the case in which card image is missing. In that case, the method tries to fill in the gaps with those alternatives having images. If not possible, the original entries are returned.
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
package forge.itemmanager;
|
package forge.itemmanager;
|
||||||
|
|
||||||
import java.util.*;
|
import com.google.common.base.Predicate;
|
||||||
import java.util.Map.Entry;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
import javax.swing.JMenu;
|
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.game.GameFormat;
|
||||||
import forge.gamemodes.quest.QuestWorld;
|
import forge.gamemodes.quest.QuestWorld;
|
||||||
import forge.gamemodes.quest.data.QuestPreferences;
|
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.DialogChooseFormats;
|
||||||
import forge.screens.home.quest.DialogChooseSets;
|
import forge.screens.home.quest.DialogChooseSets;
|
||||||
import forge.screens.match.controllers.CDetailPicture;
|
import forge.screens.match.controllers.CDetailPicture;
|
||||||
|
import forge.util.CollectionSuppliers;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ItemManager for cards
|
* ItemManager for cards
|
||||||
*
|
*
|
||||||
@@ -49,16 +56,96 @@ public class CardManager extends ItemManager<PaperCard> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Iterable<Entry<PaperCard, Integer>> getUnique(Iterable<Entry<PaperCard, Integer>> items) {
|
protected Iterable<Entry<PaperCard, Integer>> getUnique(Iterable<Entry<PaperCard, Integer>> items) {
|
||||||
//use special technique for getting unique cards so that cards without art aren't shown
|
ListMultimap<String, Entry<PaperCard, Integer>> entriesByName = Multimaps.newListMultimap(new TreeMap<>(String.CASE_INSENSITIVE_ORDER), CollectionSuppliers.arrayLists());
|
||||||
HashMap<String, Entry<PaperCard, Integer>> map = new HashMap<>();
|
|
||||||
for (Entry<PaperCard, Integer> item : items) {
|
for (Entry<PaperCard, Integer> item : items) {
|
||||||
final String key = item.getKey().getName();
|
final String cardName = item.getKey().getName();
|
||||||
final Entry<PaperCard, Integer> oldValue = map.get(key);
|
entriesByName.put(cardName, item);
|
||||||
if (oldValue == null || !oldValue.getKey().hasImage()) { //only replace in map if old value doesn't have image
|
}
|
||||||
map.put(key, item);
|
|
||||||
|
// Now we're ready to go on with retrieving cards to be returned
|
||||||
|
Map<PaperCard, Integer> cardsMap = new HashMap<>();
|
||||||
|
for (String cardName : entriesByName.keySet()) {
|
||||||
|
List<Entry<PaperCard, Integer>> entries = entriesByName.get(cardName);
|
||||||
|
|
||||||
|
ListMultimap<CardEdition, Entry<PaperCard, Integer>> entriesByEdition = Multimaps.newListMultimap(new HashMap<>(), CollectionSuppliers.arrayLists());
|
||||||
|
for (Entry<PaperCard, Integer> 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<CardEdition> acceptedEditions = Lists.newArrayList(Iterables.filter(entriesByEdition.keySet(), new Predicate<CardEdition>() {
|
||||||
|
@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<Entry<PaperCard, Integer>> entriesToAdd = getEntriesToAdd(entriesByEdition, acceptedEditions);
|
||||||
|
for (Entry<PaperCard, Integer> 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<Entry<PaperCard, Integer>> getEntriesToAdd(ListMultimap<CardEdition, Entry<PaperCard, Integer>> entriesByEdition,
|
||||||
|
List<CardEdition> 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<Entry<PaperCard, Integer>> 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<Entry<PaperCard, Integer>> entriesToAdd = new ArrayList<>();
|
||||||
|
for (Entry<PaperCard, Integer> 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<PaperCard, Integer> 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<PaperCard, Integer> entry : uniqueEntries) {
|
||||||
|
entriesToAdd.add(entry);
|
||||||
|
if (entriesToAdd.size() == entriesToReturn)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map.values();
|
return entriesToAdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Static overrides shared with SpellShopManager*/
|
/* Static overrides shared with SpellShopManager*/
|
||||||
|
|||||||
Reference in New Issue
Block a user