mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
fixed a bug with deckeditor filters: (1) when you select 6 core types of 7, all 7 are shown anyway, (2) with active set filter didn't show some cards issued in other sets
This commit is contained in:
@@ -24,11 +24,14 @@ public class CardPoolView implements Iterable<Entry<CardPrinted, Integer>> {
|
||||
new Lambda1<CardRules, Entry<CardPrinted, Integer>>() {
|
||||
@Override public CardRules apply(final Entry<CardPrinted, Integer> from) { return from.getKey().getCard(); }
|
||||
};
|
||||
public final static Lambda1<CardPrinted, Entry<CardPrinted, Integer>> fnToReference =
|
||||
public final static Lambda1<CardPrinted, Entry<CardPrinted, Integer>> fnToPrinted =
|
||||
new Lambda1<CardPrinted, Entry<CardPrinted, Integer>>() {
|
||||
@Override public CardPrinted apply(final Entry<CardPrinted, Integer> from) { return from.getKey(); }
|
||||
};
|
||||
|
||||
public final static Lambda1<String, Entry<CardPrinted, Integer>> fnToCardName =
|
||||
new Lambda1<String, Entry<CardPrinted, Integer>>() {
|
||||
@Override public String apply(final Entry<CardPrinted, Integer> from) { return from.getKey().getName(); }
|
||||
};
|
||||
public final static Lambda1<Integer, Entry<CardPrinted, Integer>> fnToCount =
|
||||
new Lambda1<Integer, Entry<CardPrinted, Integer>>() {
|
||||
@Override public Integer apply(final Entry<CardPrinted, Integer> from) { return from.getValue(); }
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package forge.card;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import net.slightlymagic.braids.util.lambda.Lambda1;
|
||||
import net.slightlymagic.maxmtg.Predicate;
|
||||
import net.slightlymagic.maxmtg.Predicate.StringOp;
|
||||
import forge.AllZone;
|
||||
import forge.Card;
|
||||
import forge.CardUtil;
|
||||
@@ -122,8 +126,10 @@ public final class CardPrinted implements Comparable<CardPrinted> {
|
||||
return cardSet.compareTo(o.cardSet);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class Predicates {
|
||||
/**
|
||||
* Number of filters based on CardPrinted values.
|
||||
*/
|
||||
public abstract static class Predicates {
|
||||
public static Predicate<CardPrinted> rarity(final boolean isEqual, final CardRarity value)
|
||||
{
|
||||
return new PredicateRarity(value, isEqual);
|
||||
@@ -135,6 +141,15 @@ public final class CardPrinted implements Comparable<CardPrinted> {
|
||||
}
|
||||
return new PredicateSets(value, shouldContain);
|
||||
}
|
||||
public static Predicate<CardPrinted> printedInSets(final String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return Predicate.getTrue(CardPrinted.class);
|
||||
}
|
||||
return new PredicateSets(Arrays.asList(new String[]{value}), true);
|
||||
}
|
||||
public static Predicate<CardPrinted> name(final StringOp op, final String what) {
|
||||
return new PredicateName(op, what);
|
||||
}
|
||||
|
||||
private static class PredicateRarity extends Predicate<CardPrinted> {
|
||||
private final CardRarity operand;
|
||||
@@ -157,14 +172,39 @@ public final class CardPrinted implements Comparable<CardPrinted> {
|
||||
@Override public boolean isTrue(final CardPrinted card) {
|
||||
return sets.contains(card.cardSet) == mustContain;
|
||||
}
|
||||
public PredicateSets(final List<String> wantSets, boolean shouldContain) {
|
||||
public PredicateSets(final List<String> wantSets, final boolean shouldContain) {
|
||||
sets = wantSets; // maybe should make a copy here?
|
||||
mustContain = shouldContain;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PredicateName extends Predicate<CardPrinted> {
|
||||
private final String operand;
|
||||
private final StringOp operator;
|
||||
|
||||
@Override
|
||||
public boolean isTrue(final CardPrinted card) {
|
||||
return op(card.getName(), operand);
|
||||
}
|
||||
|
||||
private boolean op(final String op1, final String op2) {
|
||||
switch (operator) {
|
||||
case CONTAINS: return StringUtils.containsIgnoreCase(op1, op2);
|
||||
case NOT_CONTAINS: return !StringUtils.containsIgnoreCase(op1, op2);
|
||||
case EQUALS: return op1.equalsIgnoreCase(op2);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
public PredicateName(final StringOp operator, final String operand)
|
||||
{
|
||||
this.operand = operand;
|
||||
this.operator = operator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-built predicates are stored here to allow their re-usage and easier access from code
|
||||
* Pre-built predicates are stored here to allow their re-usage and easier access from code.
|
||||
*/
|
||||
public abstract static class Presets {
|
||||
// Think twice before using these, since rarity is a prop of printed card.
|
||||
|
||||
@@ -223,10 +223,12 @@ public final class CardRules {
|
||||
}
|
||||
|
||||
private boolean op(final String op1, final String op2) {
|
||||
if (operator == StringOp.CONTAINS) { return StringUtils.containsIgnoreCase(op1, op2); }
|
||||
if (operator == StringOp.NOT_CONTAINS) { return !StringUtils.containsIgnoreCase(op1, op2); }
|
||||
if (operator == StringOp.EQUALS) { return op1.equalsIgnoreCase(op2); }
|
||||
return false;
|
||||
switch (operator) {
|
||||
case CONTAINS: return StringUtils.containsIgnoreCase(op1, op2);
|
||||
case NOT_CONTAINS: return !StringUtils.containsIgnoreCase(op1, op2);
|
||||
case EQUALS: return op1.equalsIgnoreCase(op2);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
public LeafString(final CardField field, final StringOp operator, final String operand)
|
||||
@@ -394,6 +396,8 @@ public final class CardRules {
|
||||
colors.add(isColorless);
|
||||
}
|
||||
|
||||
public static final Predicate<CardRules> constantTrue = Predicate.getTrue(CardRules.class);
|
||||
|
||||
// Think twice before using these, since rarity is a prop of printed card.
|
||||
public static final Predicate<CardRules> isInLatestSetCommon = rarityInCardsLatestSet(true, CardRarity.Common);
|
||||
public static final Predicate<CardRules> isInLatestSetUncommon = rarityInCardsLatestSet(true, CardRarity.Uncommon);
|
||||
|
||||
@@ -156,7 +156,7 @@ public final class DeckEditor extends DeckEditorBase implements NewConstants {
|
||||
public DeckEditor() {
|
||||
try {
|
||||
filterBoxes = new FilterCheckBoxes(true);
|
||||
top = new TableWithCards("Avaliable Cards", true);
|
||||
top = new TableWithCards("Avaliable Cards", true, true);
|
||||
bottom = new TableWithCards("Deck", true);
|
||||
cardView = new CardPanelHeavy();
|
||||
|
||||
@@ -311,24 +311,24 @@ public final class DeckEditor extends DeckEditorBase implements NewConstants {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Predicate<CardRules> buildFilter() {
|
||||
List<Predicate<CardRules>> rules = new ArrayList<Predicate<CardRules>>(5);
|
||||
protected Predicate<CardPrinted> buildFilter() {
|
||||
List<Predicate<CardPrinted>> rules = new ArrayList<Predicate<CardPrinted>>(5);
|
||||
rules.add(super.buildFilter());
|
||||
if (StringUtils.isNotBlank(txtCardName.getText())) {
|
||||
rules.add(CardRules.Predicates.name(StringOp.CONTAINS, txtCardName.getText()));
|
||||
rules.add(CardPrinted.Predicates.name(StringOp.CONTAINS, txtCardName.getText()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(txtCardType.getText())) {
|
||||
rules.add(CardRules.Predicates.joinedType(StringOp.CONTAINS, txtCardType.getText()));
|
||||
rules.add(Predicate.brigde(CardRules.Predicates.joinedType(StringOp.CONTAINS, txtCardType.getText()), CardPrinted.fnGetRules));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(txtCardRules.getText())) {
|
||||
rules.add(CardRules.Predicates.rules(StringOp.CONTAINS, txtCardRules.getText()));
|
||||
rules.add(Predicate.brigde(CardRules.Predicates.rules(StringOp.CONTAINS, txtCardRules.getText()), CardPrinted.fnGetRules));
|
||||
}
|
||||
|
||||
if (searchSetCombo.getSelectedIndex() != 0) {
|
||||
String setCode = SetUtils.getCode3ByName(searchSetCombo.getSelectedItem().toString());
|
||||
rules.add(CardRules.Predicates.wasPrintedInSet(setCode));
|
||||
rules.add(CardPrinted.Predicates.printedInSets(setCode));
|
||||
}
|
||||
|
||||
return rules.size() == 1 ? rules.get(0) : Predicate.and(rules);
|
||||
|
||||
@@ -10,6 +10,7 @@ import javax.swing.JOptionPane;
|
||||
import net.slightlymagic.maxmtg.Predicate;
|
||||
|
||||
import forge.GUI_DeckAnalysis;
|
||||
import forge.card.CardPrinted;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardPoolView;
|
||||
|
||||
@@ -38,9 +39,9 @@ public abstract class DeckEditorBase extends JFrame implements DeckDisplay {
|
||||
|
||||
// THIS IS HERE FOR OVERLOADING!!!1
|
||||
// or may be return abstract getFilter from derived class + this filter ... virtual protected member, but later
|
||||
protected Predicate<CardRules> buildFilter() {
|
||||
protected Predicate<CardPrinted> buildFilter() {
|
||||
if (null == filterBoxes) {
|
||||
return Predicate.getTrue(CardRules.class);
|
||||
return Predicate.getTrue(CardPrinted.class);
|
||||
}
|
||||
return filterBoxes.buildFilter();
|
||||
}
|
||||
|
||||
@@ -246,13 +246,10 @@ public class DeckEditorMenu extends JMenuBar implements NewConstants {
|
||||
currentGameType = Constant.GameType.Constructed;
|
||||
setDeckData("", false);
|
||||
|
||||
// This is an expensive heap operation.
|
||||
|
||||
|
||||
CardPool allCards = new CardPool();
|
||||
allCards.addAllCards(CardDb.instance().getAllUniqueCards());
|
||||
allCards.addAllCards(CardDb.instance().getAllCards());
|
||||
|
||||
deckDisplay.setDecks(allCards, new CardPoolView());
|
||||
deckDisplay.setDecks(allCards, null);
|
||||
}//new constructed
|
||||
|
||||
/**
|
||||
@@ -302,7 +299,7 @@ public class DeckEditorMenu extends JMenuBar implements NewConstants {
|
||||
GenerateConstructedDeck gen = new GenerateConstructedDeck();
|
||||
|
||||
// This is an expensive heap operation.
|
||||
CardPool allCards = new CardPool( CardDb.instance().getAllUniqueCards() );
|
||||
CardPool allCards = new CardPool( CardDb.instance().getAllCards() );
|
||||
|
||||
CardPool generated = new CardPool();
|
||||
for (Card c : gen.generateDeck()) { generated.add( CardDb.instance().getCard(c)); }
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
import javax.swing.JCheckBox;
|
||||
|
||||
import net.slightlymagic.maxmtg.Predicate;
|
||||
import forge.card.CardPrinted;
|
||||
import forge.card.CardRules;
|
||||
|
||||
/**
|
||||
@@ -71,7 +72,7 @@ class FilterCheckBoxes {
|
||||
}
|
||||
|
||||
|
||||
public final Predicate<CardRules> buildFilter() {
|
||||
public final Predicate<CardPrinted> buildFilter() {
|
||||
List<Predicate<CardRules>> colors = new ArrayList<Predicate<CardRules>>();
|
||||
if (white.isSelected()) { colors.add(CardRules.Predicates.Presets.isWhite); }
|
||||
if (blue.isSelected()) { colors.add(CardRules.Predicates.Presets.isBlue); }
|
||||
@@ -89,9 +90,9 @@ class FilterCheckBoxes {
|
||||
if (planeswalker.isSelected()) { types.add(CardRules.Predicates.Presets.isPlaneswalker); }
|
||||
if (artifact.isSelected()) { types.add(CardRules.Predicates.Presets.isArtifact); }
|
||||
if (enchantment.isSelected()) { types.add(CardRules.Predicates.Presets.isEnchantment); }
|
||||
Predicate<CardRules> filterByType = colors.size() == 7 ? Predicate.getTrue(CardRules.class) : Predicate.or(types);
|
||||
Predicate<CardRules> filterByType = types.size() == 7 ? Predicate.getTrue(CardRules.class) : Predicate.or(types);
|
||||
|
||||
return Predicate.and(filterByColor, filterByType);
|
||||
return Predicate.brigde(Predicate.and(filterByColor, filterByType), CardPrinted.fnGetRules);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,9 @@ public final class TableWithCards {
|
||||
protected JTable table = new JTable();
|
||||
protected JScrollPane jScrollPane = new JScrollPane();
|
||||
protected JLabel statsLabel = new JLabel();
|
||||
protected Predicate<CardRules> filter = null;
|
||||
protected Predicate<CardPrinted> filter = null;
|
||||
protected boolean isTrackingStats = false;
|
||||
protected boolean wantUnique = false;
|
||||
|
||||
// need this to allow users place its contents
|
||||
public JComponent getTableDecorated() { return jScrollPane; }
|
||||
@@ -42,6 +43,9 @@ public final class TableWithCards {
|
||||
public JComponent getLabel() { return statsLabel; }
|
||||
|
||||
public TableWithCards(final String title, final boolean showStats) {
|
||||
this(title, showStats, false);
|
||||
}
|
||||
public TableWithCards(final String title, final boolean showStats, final boolean forceUnique) {
|
||||
// components
|
||||
Color gray = new Color(148, 145, 140);
|
||||
TitledBorder titledBorder = new TitledBorder(BorderFactory.createEtchedBorder(Color.white, gray), title);
|
||||
@@ -56,6 +60,7 @@ public final class TableWithCards {
|
||||
|
||||
// class data
|
||||
isTrackingStats = showStats;
|
||||
wantUnique = forceUnique;
|
||||
}
|
||||
|
||||
public void setup(final List<TableColumnInfo<CardPrinted>> columns, final CardPanelBase cardView)
|
||||
@@ -137,7 +142,7 @@ public final class TableWithCards {
|
||||
private boolean isUnfiltered() { return filter == null || filter.is1(); }
|
||||
private boolean isFiltered() { return filter != null && !filter.is1(); }
|
||||
|
||||
public void setFilter(final Predicate<CardRules> filterToSet) {
|
||||
public void setFilter(final Predicate<CardPrinted> filterToSet) {
|
||||
filter = filterToSet;
|
||||
updateView();
|
||||
}
|
||||
@@ -158,10 +163,18 @@ public final class TableWithCards {
|
||||
}
|
||||
|
||||
public void updateView() {
|
||||
if (isFiltered()) {
|
||||
if (isFiltered() || wantUnique) {
|
||||
model.clear();
|
||||
model.addCards(filter.select(pool, CardPoolView.fnToCard));
|
||||
}
|
||||
|
||||
if (isFiltered() && wantUnique) {
|
||||
model.addCards(filter.uniqueByLast(pool, CardPoolView.fnToCardName, CardPoolView.fnToPrinted));
|
||||
} else if (isFiltered()) {
|
||||
model.addCards(filter.select(pool, CardPoolView.fnToPrinted));
|
||||
} else if (wantUnique) {
|
||||
model.addCards(CardRules.Predicates.Presets.constantTrue.uniqueByLast(pool, CardPoolView.fnToCardName, CardPoolView.fnToCard));
|
||||
}
|
||||
|
||||
model.resort();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
package net.slightlymagic.maxmtg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.card.CardPrinted;
|
||||
import forge.card.CardRules;
|
||||
|
||||
import net.slightlymagic.braids.util.lambda.Lambda1;
|
||||
/**
|
||||
@@ -104,6 +110,38 @@ public abstract class Predicate<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// Unique
|
||||
public final <K> Iterable<T> uniqueByLast(final Iterable<T> source, final Lambda1<K, T> fnUniqueKey)
|
||||
{
|
||||
Map<K, T> uniques = new Hashtable<K, T>();
|
||||
for (T c : source) { if (isTrue(c)) { uniques.put(fnUniqueKey.apply(c), c); } }
|
||||
return uniques.values();
|
||||
}
|
||||
public final <K, U> Iterable<U> uniqueByLast(final Iterable<U> source, final Lambda1<K, U> fnUniqueKey, final Lambda1<T, U> accessor)
|
||||
{ // this might be exotic
|
||||
Map<K, U> uniques = new Hashtable<K, U>();
|
||||
for (U c : source) { if (isTrue(accessor.apply(c))) { uniques.put(fnUniqueKey.apply(c), c); } }
|
||||
return uniques.values();
|
||||
}
|
||||
public final <K> Iterable<T> uniqueByFirst(final Iterable<T> source, final Lambda1<K, T> fnUniqueKey)
|
||||
{
|
||||
Map<K, T> uniques = new Hashtable<K, T>();
|
||||
for (T c : source) {
|
||||
K key = fnUniqueKey.apply(c);
|
||||
if (isTrue(c) && !uniques.containsKey(key)) { uniques.put(fnUniqueKey.apply(c), c); }
|
||||
}
|
||||
return uniques.values();
|
||||
}
|
||||
public final <K, U> Iterable<U> uniqueByFirst(final Iterable<U> source, final Lambda1<K, U> fnUniqueKey, final Lambda1<T, U> accessor)
|
||||
{ // this might be exotic
|
||||
Map<K, U> uniques = new Hashtable<K, U>();
|
||||
for (U c : source) {
|
||||
K key = fnUniqueKey.apply(c);
|
||||
if (isTrue(accessor.apply(c)) && !uniques.containsKey(key)) { uniques.put(fnUniqueKey.apply(c), c); }
|
||||
}
|
||||
return uniques.values();
|
||||
}
|
||||
|
||||
// Count
|
||||
public final int count(final Iterable<T> source) {
|
||||
int result = 0;
|
||||
@@ -167,6 +205,11 @@ public abstract class Predicate<T> {
|
||||
}
|
||||
|
||||
// Static builder methods - they choose concrete implementation by themselves
|
||||
public static <U, T> Predicate<U> brigde(Predicate<T> predicate, Lambda1<T, U> fnBridge) {
|
||||
// TODO Auto-generated method stub
|
||||
return new Bridge<T, U>(predicate, fnBridge);
|
||||
}
|
||||
|
||||
public static <T> Predicate<T> not(final Predicate<T> operand1) { return new Not<T>(operand1); }
|
||||
public static <T> Predicate<T> compose(final Predicate<T> operand1,
|
||||
final PredicatesOp operator, final Predicate<T> operand2)
|
||||
@@ -193,7 +236,12 @@ public abstract class Predicate<T> {
|
||||
public Not(final Predicate<T> operand) { filter = operand; }
|
||||
@Override public boolean isTrue(final T card) { return !filter.isTrue(card); }
|
||||
}
|
||||
|
||||
protected static final class Bridge<T, U> extends Predicate<U> {
|
||||
protected final Predicate<T> filter;
|
||||
protected final Lambda1<T, U> fnBridge;
|
||||
public Bridge(final Predicate<T> operand, final Lambda1<T, U> fnTfromU) { filter = operand; fnBridge = fnTfromU; }
|
||||
@Override public boolean isTrue(final U card) { return filter.isTrue(fnBridge.apply(card)); }
|
||||
}
|
||||
// binary operators
|
||||
protected static class Node<T> extends Predicate<T> {
|
||||
private final PredicatesOp operator;
|
||||
|
||||
@@ -25,7 +25,7 @@ public class BoosterDraft_1Test {
|
||||
while (draft.hasNextChoice()) {
|
||||
CardPoolView list = draft.nextChoice();
|
||||
System.out.println(list.countAll());
|
||||
draft.setChoice(Predicate.getTrue(CardRules.class).first(list, CardPoolView.fnToCard, CardPoolView.fnToReference));
|
||||
draft.setChoice(Predicate.getTrue(CardRules.class).first(list, CardPoolView.fnToCard, CardPoolView.fnToPrinted));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user