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;