diff --git a/.gitattributes b/.gitattributes
index 13161ebccf8..7d97d4b9036 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9543,6 +9543,7 @@ src/main/java/forge/GuiQuestFilter.java svneol=native#text/plain
src/main/java/forge/Gui_BoosterDraft.java svneol=native#text/plain
src/main/java/forge/Gui_CardShop.java svneol=native#text/plain
src/main/java/forge/Gui_DeckEditor.java svneol=native#text/plain
+src/main/java/forge/Gui_DeckEditorBase.java -text
src/main/java/forge/Gui_DeckEditor_Menu.java svneol=native#text/plain
src/main/java/forge/Gui_DownloadPictures_LQ.java svneol=native#text/plain
src/main/java/forge/Gui_DownloadPrices.java svneol=native#text/plain
diff --git a/pom.xml b/pom.xml
index 566ab34baa6..2baae4a21fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -587,6 +587,11 @@
commons-lang3
3.0.1
+
+ org.apache.commons
+ commons-io
+ 1.3.2
+
commons-discovery
commons-discovery
diff --git a/res/blockdata/setdata.txt b/res/blockdata/setdata.txt
index 2025bbb27fe..7d8591091c9 100644
--- a/res/blockdata/setdata.txt
+++ b/res/blockdata/setdata.txt
@@ -23,7 +23,7 @@ Index:19|Code2:WL|Code3:WTH|Name:Weatherlight
Index:20|Code2:TE|Code3:TMP|Name:Tempest
Index:21|Code2:SH|Code3:STH|Name:Stronghold
Index:22|Code2:EX|Code3:EXO|Name:Exodus
-Index:23|Code2:P2|Code3:PO2|Name:Portal Second Age
+Index:23|Code2:P2|Code3:PO2|Name:Portal Second Age|Alias:P02
Index:24|Code2:US|Code3:USG|Name:Urza's Saga
Index:25|Code2:UL|Code3:ULG|Name:Urza's Legacy
Index:26|Code2:6E|Code3:6ED|Name:Classic (Sixth Edition)
@@ -68,7 +68,7 @@ Index:60|Code2:10E|Code3:10E|Name:Core Set - Tenth Edition
Index:61|Code2:LRW|Code3:LRW|Name:Lorwyn
Index:62|Code2:MOR|Code3:MOR|Name:Morningtide
Index:63|Code2:SHM|Code3:SHM|Name:Shadowmoor
-Index:64|Code2:EVE|Code3:EVE|Name:Eventide
+Index:64|Code2:EVE|Code3:EVE|Name:Eventide|Alias:EVT
Index:65|Code2:ALA|Code3:ALA|Name:Shards of Alara
Index:66|Code2:CFX|Code3:CFX|Name:Conflux|Alias:CON
Index:67|Code2:ARB|Code3:ARB|Name:Alara Reborn
diff --git a/src/main/java/forge/Gui_DeckEditorBase.java b/src/main/java/forge/Gui_DeckEditorBase.java
new file mode 100644
index 00000000000..3013a8fb0e8
--- /dev/null
+++ b/src/main/java/forge/Gui_DeckEditorBase.java
@@ -0,0 +1,75 @@
+package forge;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+
+import net.slightlymagic.maxmtg.Predicate;
+
+import forge.card.CardCoreType;
+import forge.card.CardRules;
+import forge.card.CardRules.Predicates;
+import forge.card.CardPoolView;
+
+public class Gui_DeckEditorBase extends JFrame {
+ private static final long serialVersionUID = -401223933343539977L;
+
+ //public JCheckBox whiteCheckBox = new GuiFilterCheckBox("white", "White");
+ public JCheckBox whiteCheckBox = new JCheckBox("W", true);
+ public JCheckBox blueCheckBox = new JCheckBox("U", true);
+ public JCheckBox blackCheckBox = new JCheckBox("B", true);
+ public JCheckBox redCheckBox = new JCheckBox("R", true);
+ public JCheckBox greenCheckBox = new JCheckBox("G", true);
+ public JCheckBox colorlessCheckBox = new JCheckBox("C", true);
+
+ public JCheckBox landCheckBox = new JCheckBox("Land", true);
+ public JCheckBox creatureCheckBox = new JCheckBox("Creature", true);
+ public JCheckBox sorceryCheckBox = new JCheckBox("Sorcery", true);
+ public JCheckBox instantCheckBox = new JCheckBox("Instant", true);
+ public JCheckBox planeswalkerCheckBox = new JCheckBox("Planeswalker", true);
+ public JCheckBox artifactCheckBox = new JCheckBox("Artifact", true);
+ public JCheckBox enchantmentCheckBox = new JCheckBox("Enchant", true);
+
+ public static String getStats(CardPoolView deck) {
+ int total = deck.countAll();
+ int creature = CardRules.Predicates.Presets.isCreature.aggregate(deck, CardPoolView.fnToCard, CardPoolView.fnToCount);
+ int land = CardRules.Predicates.Presets.isLand.aggregate(deck, CardPoolView.fnToCard, CardPoolView.fnToCount);
+
+ StringBuffer show = new StringBuffer();
+ show.append("Total - ").append(total).append(", Creatures - ").append(creature).append(", Land - ")
+ .append(land);
+ String[] color = Constant.Color.onlyColors;
+ List> predicates = CardRules.Predicates.Presets.colors;
+ for (int i = 0; i < color.length; ++i) {
+ show.append(String.format(", %s - %d", color[i], predicates.get(i).count(deck, CardPoolView.fnToCard)));
+ }
+
+ return show.toString();
+ }// getStats()
+
+ public final Predicate buildFilter() {
+ List> colors = new ArrayList>();
+ if (whiteCheckBox.isSelected()) { colors.add(CardRules.Predicates.Presets.isWhite); }
+ if (blueCheckBox.isSelected()) { colors.add(CardRules.Predicates.Presets.isBlue); }
+ if (blackCheckBox.isSelected()) { colors.add(CardRules.Predicates.Presets.isBlack); }
+ if (redCheckBox.isSelected()) { colors.add(CardRules.Predicates.Presets.isRed); }
+ if (greenCheckBox.isSelected()) { colors.add(CardRules.Predicates.Presets.isGreen); }
+ if (colorlessCheckBox.isSelected()) { colors.add(CardRules.Predicates.Presets.isColorless); }
+ Predicate filterByColor = colors.size() == 6 ? Predicate.getTrue(CardRules.class) : Predicate.or(colors);
+
+ List> types = new ArrayList>();
+ if (landCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isLand); }
+ if (creatureCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isCreature); }
+ if (sorceryCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isSorcery); }
+ if (instantCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isInstant); }
+ if (planeswalkerCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isPlaneswalker); }
+ if (artifactCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isArtifact); }
+ if (enchantmentCheckBox.isSelected()) { types.add(CardRules.Predicates.Presets.isEnchantment); }
+ Predicate filterByType = colors.size() == 7 ? Predicate.getTrue(CardRules.class) : Predicate.or(types);
+
+ return Predicate.and(filterByColor, filterByType);
+ }
+
+}
diff --git a/src/main/java/net/slightlymagic/maxmtg/Predicate.java b/src/main/java/net/slightlymagic/maxmtg/Predicate.java
index b3f57dad0f2..793e696fe35 100644
--- a/src/main/java/net/slightlymagic/maxmtg/Predicate.java
+++ b/src/main/java/net/slightlymagic/maxmtg/Predicate.java
@@ -117,7 +117,7 @@ public abstract class Predicate {
}
// Random - algorithm adapted from Braid's GeneratorFunctions
- public final T random(final Iterable source) { //
+ public final T random(final Iterable source) {
int n = 0;
T candidate = null;
for (T item : source) {
@@ -126,7 +126,7 @@ public abstract class Predicate {
}
return candidate;
}
- public final U random(final Iterable source, final Lambda1 accessor) {
+ public final U random(final Iterable source, final Lambda1 accessor) {
int n = 0;
U candidate = null;
for (U item : source) {
@@ -135,6 +135,28 @@ public abstract class Predicate {
}
return candidate;
}
+
+ // Get several random values
+ // should improve to make 1 pass over source and track N candidates at once
+ public final List random(final Iterable source, final int count) {
+ List result = new ArrayList();
+ for (int i = 0; i < count; ++i) {
+ T toAdd = random(source);
+ if (toAdd == null) { break; }
+ result.add(toAdd);
+ }
+ return result;
+ }
+ public final List random(final Iterable source, final Lambda1 accessor, final int count) {
+ List result = new ArrayList();
+ for (int i = 0; i < count; ++i) {
+ U toAdd = random(source, accessor);
+ if (toAdd == null) { break; }
+ result.add(toAdd);
+ }
+ return result;
+ }
+
// Static builder methods - they choose concrete implementation by themselves
public static Predicate not(final Predicate operand1) { return new Not(operand1); }
public static Predicate compose(final Predicate operand1,
@@ -142,14 +164,14 @@ public abstract class Predicate {
{
return new Node(operand1, operator, operand2);
}
- public static Predicate and(final Predicate operand1, final Predicate operand2) {
- return new NodeAnd(operand1, operand2);
- }
+ // Predefined operators: and, or
+ public static Predicate and(final Predicate operand1, final Predicate operand2) { return new NodeAnd(operand1, operand2); }
public static Predicate and(final Iterable> operand) { return new MultiNodeAnd(operand); }
- public static Predicate or(final Predicate operand1, final Predicate operand2) {
- return new NodeOr(operand1, operand2);
- }
+ public static Predicate and(final Predicate operand1, final Predicate operand2, Lambda1 bridge) { return new NodeAndBridged(operand1, operand2, bridge); }
+
+ public static Predicate or(final Predicate operand1, final Predicate operand2) { return new NodeOr(operand1, operand2); }
public static Predicate or(final Iterable> operand) { return new MultiNodeOr(operand); }
+ public static Predicate or(final Predicate operand1, final Predicate operand2, Lambda1 bridge) { return new NodeOrBridged(operand1, operand2, bridge); }
// Concrete implementations
// unary operators
@@ -197,6 +219,30 @@ public abstract class Predicate {
@Override public boolean isTrue(final T card) { return filter1.isTrue(card) && filter2.isTrue(card); }
}
+ // Bridged OR and AND
+ protected static final class NodeOrBridged extends Predicate {
+ private final Predicate filter1;
+ private final Predicate filter2;
+ private final Lambda1 bridge;
+ public NodeOrBridged(final Predicate operand1, final Predicate operand2, final Lambda1 accessor) {
+ filter1 = operand1;
+ filter2 = operand2;
+ bridge = accessor;
+ }
+ @Override public boolean isTrue(final T card) { return filter1.isTrue(card) || filter2.isTrue(bridge.apply(card)); }
+ }
+ protected static final class NodeAndBridged extends Predicate {
+ private final Predicate filter1;
+ private final Predicate filter2;
+ private final Lambda1 bridge;
+ public NodeAndBridged(final Predicate operand1, final Predicate operand2, final Lambda1 accessor) {
+ filter1 = operand1;
+ filter2 = operand2;
+ bridge = accessor;
+ }
+ @Override public boolean isTrue(final T card) { return filter1.isTrue(card) && filter2.isTrue(bridge.apply(card)); }
+ }
+
// multi-operand operators
protected abstract static class MultiNode extends Predicate {
protected final Iterable> operands;