mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +00:00
Added advanced deck generator functions and tidied up the layout.
This commit is contained in:
parent
578cb128dd
commit
9dc71d2996
6 changed files with 665 additions and 155 deletions
|
@ -155,7 +155,10 @@ public class DeckGenerator {
|
||||||
* @return the final deck to use.
|
* @return the final deck to use.
|
||||||
*/
|
*/
|
||||||
private static Deck generateDeck(int deckSize, List<ColoredManaSymbol> allowedColors, List<String> setsToUse) {
|
private static Deck generateDeck(int deckSize, List<ColoredManaSymbol> allowedColors, List<String> setsToUse) {
|
||||||
genPool = new DeckGeneratorPool(deckSize, allowedColors, genDialog.isSingleton(), genDialog.isColorless());
|
|
||||||
|
genPool = new DeckGeneratorPool(deckSize, genDialog.getCreaturePercentage(), genDialog.getNonCreaturePercentage(),
|
||||||
|
genDialog.getLandPercentage(), allowedColors, genDialog.isSingleton(), genDialog.isColorless(),
|
||||||
|
genDialog.isAdvanced(), genDialog.getDeckGeneratorCMC());
|
||||||
|
|
||||||
final String[] sets = setsToUse.toArray(new String[setsToUse.size()]);
|
final String[] sets = setsToUse.toArray(new String[setsToUse.size()]);
|
||||||
|
|
||||||
|
@ -210,7 +213,7 @@ public class DeckGenerator {
|
||||||
private static void generateSpells(CardCriteria criteria, int spellCount) {
|
private static void generateSpells(CardCriteria criteria, int spellCount) {
|
||||||
List<CardInfo> cardPool = CardRepository.instance.findCards(criteria);
|
List<CardInfo> cardPool = CardRepository.instance.findCards(criteria);
|
||||||
int retrievedCount = cardPool.size();
|
int retrievedCount = cardPool.size();
|
||||||
List<DeckGeneratorCMC> deckCMCs = genPool.getCMCsForSpellCount(spellCount);
|
List<DeckGeneratorCMC.CMC> deckCMCs = genPool.getCMCsForSpellCount(spellCount);
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int reservesAdded = 0;
|
int reservesAdded = 0;
|
||||||
|
@ -221,7 +224,7 @@ public class DeckGenerator {
|
||||||
Card card = cardPool.get(random.nextInt(retrievedCount)).getMockCard();
|
Card card = cardPool.get(random.nextInt(retrievedCount)).getMockCard();
|
||||||
if (genPool.isValidSpellCard(card)) {
|
if (genPool.isValidSpellCard(card)) {
|
||||||
int cardCMC = card.getManaCost().convertedManaCost();
|
int cardCMC = card.getManaCost().convertedManaCost();
|
||||||
for (DeckGeneratorCMC deckCMC : deckCMCs) {
|
for (DeckGeneratorCMC.CMC deckCMC : deckCMCs) {
|
||||||
if (cardCMC >= deckCMC.min && cardCMC <= deckCMC.max) {
|
if (cardCMC >= deckCMC.min && cardCMC <= deckCMC.max) {
|
||||||
int currentAmount = deckCMC.getAmount();
|
int currentAmount = deckCMC.getAmount();
|
||||||
if (currentAmount > 0) {
|
if (currentAmount > 0) {
|
||||||
|
@ -339,8 +342,9 @@ public class DeckGenerator {
|
||||||
* database.
|
* database.
|
||||||
*/
|
*/
|
||||||
private static void addBasicLands(int landsNeeded, Map<String, Double> percentage, Map<String, Integer> count, Map<String, List<CardInfo>> basicLands) {
|
private static void addBasicLands(int landsNeeded, Map<String, Double> percentage, Map<String, Integer> count, Map<String, List<CardInfo>> basicLands) {
|
||||||
|
|
||||||
int colorTotal = 0;
|
int colorTotal = 0;
|
||||||
ColoredManaSymbol colorToAdd = null;
|
ColoredManaSymbol colorToAdd = ColoredManaSymbol.U;
|
||||||
|
|
||||||
// Add up the totals for all colors, to keep track of the percentage a color is.
|
// Add up the totals for all colors, to keep track of the percentage a color is.
|
||||||
for (Map.Entry<String, Integer> c : count.entrySet()) {
|
for (Map.Entry<String, Integer> c : count.entrySet()) {
|
||||||
|
@ -372,14 +376,12 @@ public class DeckGenerator {
|
||||||
minPercentage = (neededPercentage - thisPercentage);
|
minPercentage = (neededPercentage - thisPercentage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (colorToAdd != null) {
|
|
||||||
genPool.addCard(getBasicLand(colorToAdd, basicLands));
|
genPool.addCard(getBasicLand(colorToAdd, basicLands));
|
||||||
count.put(colorToAdd.toString(), count.get(colorToAdd.toString()) + 1);
|
count.put(colorToAdd.toString(), count.get(colorToAdd.toString()) + 1);
|
||||||
colorTotal++;
|
colorTotal++;
|
||||||
landsNeeded--;
|
landsNeeded--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a random basic land of the chosen color.
|
* Return a random basic land of the chosen color.
|
||||||
|
|
|
@ -27,11 +27,65 @@
|
||||||
*/
|
*/
|
||||||
package mage.client.deck.generator;
|
package mage.client.deck.generator;
|
||||||
|
|
||||||
/**
|
import java.util.ArrayList;
|
||||||
* Stores a range of converted mana costs (CMC) for use in deck generation.
|
|
||||||
*/
|
public enum DeckGeneratorCMC {
|
||||||
public class DeckGeneratorCMC
|
|
||||||
{
|
Low(
|
||||||
|
new ArrayList<CMC>() {{
|
||||||
|
add(new CMC(0, 2, 0.60f));
|
||||||
|
add(new CMC(3, 4, 0.30f));
|
||||||
|
add(new CMC(5, 6, 0.10f));
|
||||||
|
}},
|
||||||
|
new ArrayList<CMC>() {{
|
||||||
|
add(new CMC(0, 2, 0.65f));
|
||||||
|
add(new CMC(3, 4, 0.30f));
|
||||||
|
add(new CMC(5, 5, 0.05f));
|
||||||
|
}}),
|
||||||
|
Default(
|
||||||
|
new ArrayList<CMC>() {{
|
||||||
|
add(new CMC(0, 2, 0.20f));
|
||||||
|
add(new CMC(3, 5, 0.50f));
|
||||||
|
add(new CMC(6, 7, 0.25f));
|
||||||
|
add(new CMC(8, 100, 0.05f));
|
||||||
|
}},
|
||||||
|
new ArrayList<CMC>() {{
|
||||||
|
add(new CMC(0, 2, 0.30f));
|
||||||
|
add(new CMC(3, 4, 0.45f));
|
||||||
|
add(new CMC(5, 6, 0.20f));
|
||||||
|
add(new CMC(7, 100, 0.05f));
|
||||||
|
}}),
|
||||||
|
High(
|
||||||
|
new ArrayList<CMC>() {{
|
||||||
|
add(new CMC(0, 2, 0.05f));
|
||||||
|
add(new CMC(3, 5, 0.35f));
|
||||||
|
add(new CMC(6, 7, 0.40f));
|
||||||
|
add(new CMC(8, 100, 0.15f));
|
||||||
|
}},
|
||||||
|
new ArrayList<CMC>() {{
|
||||||
|
add(new CMC(0, 2, 0.10f));
|
||||||
|
add(new CMC(3, 4, 0.30f));
|
||||||
|
add(new CMC(5, 6, 0.45f));
|
||||||
|
add(new CMC(7, 100, 0.15f));
|
||||||
|
}});
|
||||||
|
|
||||||
|
private ArrayList<CMC> poolCMCs60, poolCMCs40;
|
||||||
|
|
||||||
|
DeckGeneratorCMC(ArrayList<CMC> CMCs60, ArrayList<CMC> CMCs40) {
|
||||||
|
this.poolCMCs60 = CMCs60;
|
||||||
|
this.poolCMCs40 = CMCs40;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<CMC> get40CardPoolCMC() {
|
||||||
|
return this.poolCMCs40;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<CMC> get60CardPoolCMC() {
|
||||||
|
return this.poolCMCs60;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CMC
|
||||||
|
{
|
||||||
public final int min;
|
public final int min;
|
||||||
public final int max;
|
public final int max;
|
||||||
public final float percentage;
|
public final float percentage;
|
||||||
|
@ -43,7 +97,7 @@ public class DeckGeneratorCMC
|
||||||
* @param max the maximum CMC a card in this range can be.
|
* @param max the maximum CMC a card in this range can be.
|
||||||
* @param percentage the percentage of cards in the range (min, max)
|
* @param percentage the percentage of cards in the range (min, max)
|
||||||
*/
|
*/
|
||||||
DeckGeneratorCMC(int min, int max, float percentage)
|
CMC(int min, int max, float percentage)
|
||||||
{
|
{
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
|
@ -67,4 +121,7 @@ public class DeckGeneratorCMC
|
||||||
{
|
{
|
||||||
return this.amount;
|
return this.amount;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,14 @@ import mage.client.util.gui.ColorsChooser;
|
||||||
import mage.client.util.sets.ConstructedFormats;
|
import mage.client.util.sets.ConstructedFormats;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.CompoundBorder;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.border.EtchedBorder;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -48,13 +53,14 @@ import java.util.Date;
|
||||||
*/
|
*/
|
||||||
public class DeckGeneratorDialog {
|
public class DeckGeneratorDialog {
|
||||||
|
|
||||||
private JDialog dlg;
|
private static JDialog dlg;
|
||||||
private String selectedColors;
|
private static String selectedColors;
|
||||||
private JComboBox<String> cbSets;
|
private static JComboBox cbSets, cbDeckSize, cbCMC;
|
||||||
private JComboBox<String> cbDeckSize;
|
private static JButton btnGenerate, btnCancel, btnReset;
|
||||||
private JButton btnGenerate, btnCancel;
|
private static JCheckBox cArtifacts, cSingleton, cNonBasicLands, cColorless, cAdvanced;
|
||||||
private JCheckBox cArtifacts, cSingleton, cNonBasicLands, cColorless;
|
private static JLabel averageCMCLabel;
|
||||||
private SimpleDateFormat dateFormat;
|
private static SimpleDateFormat dateFormat;
|
||||||
|
private static RatioAdjustingSliderPanel adjustingSliderPanel;
|
||||||
|
|
||||||
public DeckGeneratorDialog()
|
public DeckGeneratorDialog()
|
||||||
{
|
{
|
||||||
|
@ -63,59 +69,92 @@ public class DeckGeneratorDialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDialog() {
|
private void initDialog() {
|
||||||
JPanel p0 = new JPanel();
|
|
||||||
p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS));
|
|
||||||
|
|
||||||
JLabel text = new JLabel("Choose color for your deck: ");
|
JPanel mainPanel = new JPanel();
|
||||||
text.setAlignmentX(Component.CENTER_ALIGNMENT);
|
|
||||||
p0.add(text);
|
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
mainPanel.setLayout(new GridBagLayout());
|
||||||
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
c.insets = new Insets(0, 15, 0, 0);
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 0;
|
||||||
|
c.weightx = 0.10;
|
||||||
|
JLabel text = new JLabel("Choose color for your deck:");
|
||||||
|
mainPanel.add(text, c);
|
||||||
|
|
||||||
|
// Color selector dropdown
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.weightx = 0.80;
|
||||||
|
c.ipadx = 30;
|
||||||
|
c.insets = new Insets(5, 10, 0, 10);
|
||||||
|
c.gridx = 1;
|
||||||
|
c.gridy = 0;
|
||||||
String chosen = MageFrame.getPreferences().get("genDeckColor", "u");
|
String chosen = MageFrame.getPreferences().get("genDeckColor", "u");
|
||||||
final ColorsChooser colorsChooser = new ColorsChooser(chosen);
|
final ColorsChooser colorsChooser = new ColorsChooser(chosen);
|
||||||
p0.add(colorsChooser);
|
mainPanel.add(colorsChooser, c);
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
c.insets = new Insets(0, 15, 0, 0);
|
||||||
JLabel text2 = new JLabel("(X - random color)");
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
text2.setAlignmentX(Component.CENTER_ALIGNMENT);
|
c.weightx = 0.10;
|
||||||
p0.add(text2);
|
c.gridx = 2;
|
||||||
|
c.gridy = 0;
|
||||||
|
c.ipadx = 0;
|
||||||
|
JLabel text2 = new JLabel("(X = random color)");
|
||||||
|
mainPanel.add(text2);
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
// Format/set label
|
||||||
JPanel jPanel = new JPanel();
|
JLabel formatSetText = new JLabel("Choose format/set for your deck:");
|
||||||
JLabel text3 = new JLabel("Choose sets:");
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
cbSets = new JComboBox<String>(ConstructedFormats.getTypes());
|
c.gridx = 0;
|
||||||
|
c.gridy = 1;
|
||||||
|
c.weightx = 0.10;
|
||||||
|
mainPanel.add(formatSetText, c);
|
||||||
|
|
||||||
|
// Format/set dropdown
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.gridx = 1;
|
||||||
|
c.gridy = 1;
|
||||||
|
c.ipadx = 30;
|
||||||
|
c.insets = new Insets(5, 10, 0, 10);
|
||||||
|
c.weightx = 0.90;
|
||||||
|
cbSets = new JComboBox<>(ConstructedFormats.getTypes());
|
||||||
cbSets.setSelectedIndex(0);
|
cbSets.setSelectedIndex(0);
|
||||||
cbSets.setPreferredSize(new Dimension(300, 25));
|
mainPanel.add(cbSets, c);
|
||||||
cbSets.setMaximumSize(new Dimension(300, 25));
|
|
||||||
cbSets.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
||||||
jPanel.add(text3);
|
|
||||||
jPanel.add(cbSets);
|
|
||||||
p0.add(jPanel);
|
|
||||||
|
|
||||||
String prefSet = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_SET, null);
|
String prefSet = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_SET, null);
|
||||||
if (prefSet != null) {
|
if (prefSet != null) {
|
||||||
cbSets.setSelectedItem(prefSet);
|
cbSets.setSelectedItem(prefSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
// Deck size label
|
||||||
JPanel jPanel2 = new JPanel();
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.insets = new Insets(0, 15, 0, 0);
|
||||||
|
c.ipadx = 0;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 2;
|
||||||
|
c.weightx = 0.10;
|
||||||
JLabel textDeckSize = new JLabel("Deck size:");
|
JLabel textDeckSize = new JLabel("Deck size:");
|
||||||
cbDeckSize = new JComboBox<String>(new String[] { "40", "60" });
|
mainPanel.add(textDeckSize, c);
|
||||||
|
|
||||||
|
// Deck size dropdown
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.gridx = 1;
|
||||||
|
c.gridy = 2;
|
||||||
|
c.ipadx = 30;
|
||||||
|
c.insets = new Insets(5, 10, 0, 10);
|
||||||
|
c.weightx = 0.90;
|
||||||
|
cbDeckSize = new JComboBox<>(new String[] { "40", "60" });
|
||||||
cbDeckSize.setSelectedIndex(0);
|
cbDeckSize.setSelectedIndex(0);
|
||||||
cbDeckSize.setPreferredSize(new Dimension(300, 25));
|
|
||||||
cbDeckSize.setMaximumSize(new Dimension(300, 25));
|
|
||||||
cbDeckSize.setAlignmentX(Component.LEFT_ALIGNMENT);
|
cbDeckSize.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||||
jPanel2.add(textDeckSize);
|
mainPanel.add(cbDeckSize, c);
|
||||||
jPanel2.add(cbDeckSize);
|
|
||||||
p0.add(jPanel2);
|
|
||||||
|
|
||||||
String prefSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_DECK_SIZE, "60");
|
String prefSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_DECK_SIZE, "60");
|
||||||
if (prefSet != null) {
|
if (prefSet != null) {
|
||||||
cbDeckSize.setSelectedItem(prefSize);
|
cbDeckSize.setSelectedItem(prefSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
p0.add(Box.createVerticalStrut(5));
|
JPanel jCheckBoxes = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||||
JPanel jCheckBoxes = new JPanel();
|
|
||||||
|
|
||||||
// Singletons
|
// Singletons
|
||||||
cSingleton = new JCheckBox("Singleton", false);
|
cSingleton = new JCheckBox("Singleton", false);
|
||||||
|
@ -138,16 +177,47 @@ public class DeckGeneratorDialog {
|
||||||
cNonBasicLands.setSelected(Boolean.valueOf(nonBasicEnabled));
|
cNonBasicLands.setSelected(Boolean.valueOf(nonBasicEnabled));
|
||||||
jCheckBoxes.add(cNonBasicLands);
|
jCheckBoxes.add(cNonBasicLands);
|
||||||
|
|
||||||
// Non-basic lands
|
// Colorless mana
|
||||||
cColorless = new JCheckBox("Colorless mana", false);
|
cColorless = new JCheckBox("Colorless mana", false);
|
||||||
cColorless.setToolTipText("Allow cards with colorless mana cost.");
|
cColorless.setToolTipText("Allow cards with colorless mana cost.");
|
||||||
String colorlessEnabled = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_COLORLESS, "false");
|
String colorlessEnabled = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_COLORLESS, "false");
|
||||||
cColorless.setSelected(Boolean.valueOf(colorlessEnabled));
|
cColorless.setSelected(Boolean.valueOf(colorlessEnabled));
|
||||||
jCheckBoxes.add(cColorless);
|
jCheckBoxes.add(cColorless);
|
||||||
|
c.ipadx = 0;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 3;
|
||||||
|
c.weightx = 1;
|
||||||
|
c.gridwidth = 3;
|
||||||
|
mainPanel.add(jCheckBoxes, c);
|
||||||
|
|
||||||
|
// Create the advanced configuration panel
|
||||||
|
JPanel advancedPanel = createAdvancedPanel();
|
||||||
|
|
||||||
|
// Advanced checkbox (enable/disable advanced configuration)
|
||||||
|
cAdvanced = new JCheckBox("Advanced");
|
||||||
|
cAdvanced.setToolTipText("Enable advanced configuration options");
|
||||||
|
cAdvanced.addItemListener(new ItemListener() {
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(ItemEvent itemEvent) {
|
||||||
|
boolean enable = cAdvanced.isSelected();
|
||||||
|
enableAdvancedPanel(enable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Advanced Checkbox
|
||||||
|
String advancedSavedValue = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_ADVANCED, "false");
|
||||||
|
boolean advancedEnabled = Boolean.valueOf(advancedSavedValue);
|
||||||
|
enableAdvancedPanel(advancedEnabled);
|
||||||
|
cAdvanced.setSelected(advancedEnabled);
|
||||||
|
c.gridy = 4;
|
||||||
|
c.weightx = 0;
|
||||||
|
c.insets = new Insets(10, 15, 10, 0);
|
||||||
|
mainPanel.add(cAdvanced, c);
|
||||||
|
c.gridy = 5;
|
||||||
|
c.weightx = 1;
|
||||||
|
c.insets = new Insets(5, 10, 0, 5);
|
||||||
|
mainPanel.add(advancedPanel, c);
|
||||||
|
|
||||||
jCheckBoxes.setPreferredSize(new Dimension(450, 25));
|
|
||||||
jCheckBoxes.setMaximumSize(new Dimension(450, 25));
|
|
||||||
p0.add(jCheckBoxes);
|
|
||||||
|
|
||||||
btnGenerate = new JButton("Ok");
|
btnGenerate = new JButton("Ok");
|
||||||
btnGenerate.addActionListener(new ActionListener() {
|
btnGenerate.addActionListener(new ActionListener() {
|
||||||
|
@ -169,12 +239,95 @@ public class DeckGeneratorDialog {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
JButton[] options = {btnGenerate, btnCancel};
|
JButton[] options = {btnGenerate, btnCancel};
|
||||||
JOptionPane optionPane = new JOptionPane(p0, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options, options[1]);
|
JOptionPane optionPane = new JOptionPane(mainPanel, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options, options[1]);
|
||||||
dlg = optionPane.createDialog("Generating deck");
|
dlg = optionPane.createDialog("Generating Deck");
|
||||||
|
dlg.setResizable(false);
|
||||||
dlg.setVisible(true);
|
dlg.setVisible(true);
|
||||||
dlg.dispose();
|
dlg.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enableAdvancedPanel(boolean enable) {
|
||||||
|
adjustingSliderPanel.setEnabled(enable);
|
||||||
|
btnReset.setEnabled(enable);
|
||||||
|
cbCMC.setEnabled(enable);
|
||||||
|
averageCMCLabel.setEnabled(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel createAdvancedPanel() {
|
||||||
|
|
||||||
|
JPanel advancedPanel = new JPanel(new GridBagLayout());
|
||||||
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
|
||||||
|
// Average CMC Label
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 0;
|
||||||
|
c.weightx = 0.10;
|
||||||
|
averageCMCLabel = new JLabel("Average CMC:");
|
||||||
|
advancedPanel.add(averageCMCLabel, c);
|
||||||
|
|
||||||
|
// CMC selection dropdown
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.weightx = 0.90;
|
||||||
|
c.gridx = 2;
|
||||||
|
c.gridy = 0;
|
||||||
|
cbCMC = new JComboBox<>(DeckGeneratorCMC.values());
|
||||||
|
cbCMC.setSelectedItem(DeckGeneratorCMC.Default);
|
||||||
|
String cmcSelected = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_ADVANCED_CMC, DeckGeneratorCMC.Default.name());
|
||||||
|
cbCMC.setSelectedItem(DeckGeneratorCMC.valueOf(cmcSelected));
|
||||||
|
advancedPanel.add(cbCMC, c);
|
||||||
|
|
||||||
|
// Advanced percentage sliders
|
||||||
|
c.fill = GridBagConstraints.HORIZONTAL;
|
||||||
|
c.ipady = 20;
|
||||||
|
c.ipadx = 40;
|
||||||
|
c.weightx = 1;
|
||||||
|
c.gridwidth = 3;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 1;
|
||||||
|
c.insets = new Insets(10, 0, 0, 0);
|
||||||
|
adjustingSliderPanel = new RatioAdjustingSliderPanel();
|
||||||
|
|
||||||
|
// Restore saved slider values
|
||||||
|
String creaturePercentage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_CREATURE_PERCENTAGE,
|
||||||
|
Integer.toString(DeckGeneratorPool.DEFAULT_CREATURE_PERCENTAGE));
|
||||||
|
adjustingSliderPanel.setCreaturePercentage(Integer.parseInt(creaturePercentage));
|
||||||
|
String nonCreaturePercentage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_NON_CREATURE_PERCENTAGE,
|
||||||
|
Integer.toString(DeckGeneratorPool.DEFAULT_NON_CREATURE_PERCENTAGE));
|
||||||
|
adjustingSliderPanel.setNonCreaturePercentage(Integer.parseInt(nonCreaturePercentage));
|
||||||
|
String landPercentage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE,
|
||||||
|
Integer.toString(DeckGeneratorPool.DEFAULT_LAND_PERCENTAGE));
|
||||||
|
adjustingSliderPanel.setLandPercentage(Integer.parseInt(landPercentage));
|
||||||
|
advancedPanel.add(adjustingSliderPanel, c);
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
c.fill = GridBagConstraints.NONE;
|
||||||
|
c.ipadx = 0;
|
||||||
|
c.ipady = 0;
|
||||||
|
c.weightx = 1.0;
|
||||||
|
c.anchor = GridBagConstraints.LAST_LINE_END;
|
||||||
|
c.insets = new Insets(10,10, 0, 0);
|
||||||
|
c.gridx = 2;
|
||||||
|
c.gridwidth = 1;
|
||||||
|
c.gridy = 2;
|
||||||
|
btnReset = new JButton("Reset");
|
||||||
|
btnReset.setToolTipText("Reset advanced dialog to default values");
|
||||||
|
btnReset.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent actionEvent) {
|
||||||
|
cbCMC.setSelectedItem(DeckGeneratorCMC.Default);
|
||||||
|
adjustingSliderPanel.resetValues();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
advancedPanel.add(btnReset, c);
|
||||||
|
|
||||||
|
// Add a border around the advanced bits
|
||||||
|
CompoundBorder border = BorderFactory.createCompoundBorder(new EtchedBorder(), new EmptyBorder(10, 10, 10, 10));
|
||||||
|
advancedPanel.setBorder(border);
|
||||||
|
|
||||||
|
return advancedPanel;
|
||||||
|
}
|
||||||
|
|
||||||
public void cleanUp() {
|
public void cleanUp() {
|
||||||
for (ActionListener al: btnGenerate.getActionListeners()) {
|
for (ActionListener al: btnGenerate.getActionListeners()) {
|
||||||
btnGenerate.removeActionListener(al);
|
btnGenerate.removeActionListener(al);
|
||||||
|
@ -182,6 +335,12 @@ public class DeckGeneratorDialog {
|
||||||
for (ActionListener al: btnCancel.getActionListeners()) {
|
for (ActionListener al: btnCancel.getActionListeners()) {
|
||||||
btnCancel.removeActionListener(al);
|
btnCancel.removeActionListener(al);
|
||||||
}
|
}
|
||||||
|
for (ActionListener al: btnReset.getActionListeners()) {
|
||||||
|
btnReset.removeActionListener(al);
|
||||||
|
}
|
||||||
|
for(ItemListener il: cAdvanced.getItemListeners()) {
|
||||||
|
cAdvanced.removeItemListener(il);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String saveDeck(Deck deck) {
|
public String saveDeck(Deck deck) {
|
||||||
|
@ -189,7 +348,7 @@ public class DeckGeneratorDialog {
|
||||||
// Random directory through the system property to avoid random numeric string attached to temp files.
|
// Random directory through the system property to avoid random numeric string attached to temp files.
|
||||||
String tempDir = System.getProperty("java.io.tmpdir");
|
String tempDir = System.getProperty("java.io.tmpdir");
|
||||||
// Generated deck has a nice unique name which corresponds to the timestamp at which it was created.
|
// Generated deck has a nice unique name which corresponds to the timestamp at which it was created.
|
||||||
String deckName = "Generated-Deck-" + dateFormat.format( new Date());
|
String deckName = "Generated-Deck-" + dateFormat.format(new Date());
|
||||||
File tmp = new File(tempDir + File.separator + deckName + ".dck");
|
File tmp = new File(tempDir + File.separator + deckName + ".dck");
|
||||||
tmp.createNewFile();
|
tmp.createNewFile();
|
||||||
deck.setName(deckName);
|
deck.setName(deckName);
|
||||||
|
@ -230,10 +389,42 @@ public class DeckGeneratorDialog {
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAdvanced() {
|
||||||
|
boolean selected = cAdvanced.isSelected();
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_ADVANCED, Boolean.toString(selected));
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCreaturePercentage() {
|
||||||
|
int percentage = adjustingSliderPanel.getCreaturePercentage();
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_CREATURE_PERCENTAGE, Integer.toString(percentage));
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNonCreaturePercentage() {
|
||||||
|
int percentage = adjustingSliderPanel.getNonCreaturePercentage();
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_NON_CREATURE_PERCENTAGE, Integer.toString(percentage));
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLandPercentage() {
|
||||||
|
int percentage = adjustingSliderPanel.getLandPercentage();
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE, Integer.toString(percentage));
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
public int getDeckSize() {
|
public int getDeckSize() {
|
||||||
return Integer.parseInt(cbDeckSize.getSelectedItem().toString());
|
return Integer.parseInt(cbDeckSize.getSelectedItem().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DeckGeneratorCMC getDeckGeneratorCMC() {
|
||||||
|
DeckGeneratorCMC selectedCMC = (DeckGeneratorCMC)cbCMC.getSelectedItem();
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_ADVANCED_CMC, selectedCMC.name());
|
||||||
|
return selectedCMC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public String getSelectedColors() {
|
public String getSelectedColors() {
|
||||||
if (selectedColors != null) {
|
if (selectedColors != null) {
|
||||||
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_DECK_SIZE, cbDeckSize.getSelectedItem().toString());
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_DECK_GENERATOR_DECK_SIZE, cbDeckSize.getSelectedItem().toString());
|
||||||
|
|
|
@ -41,18 +41,15 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
public class DeckGeneratorPool
|
public class DeckGeneratorPool
|
||||||
{
|
{
|
||||||
// Constants for a 40 card deck
|
|
||||||
private static final int CREATURE_COUNT_40 = 15;
|
|
||||||
private static final int LAND_COUNT_40 = 17;
|
public static int DEFAULT_CREATURE_PERCENTAGE = 38;
|
||||||
private static final int NONCREATURE_COUNT_40 = 8;
|
public static int DEFAULT_NON_CREATURE_PERCENTAGE = 21;
|
||||||
// Constants for a 60 card deck
|
public static int DEFAULT_LAND_PERCENTAGE = 41;
|
||||||
private static final int CREATURE_COUNT_60 = 23;
|
|
||||||
private static final int LAND_COUNT_60 = 24;
|
|
||||||
private static final int NONCREATURE_COUNT_60 = 13;
|
|
||||||
|
|
||||||
private final List<ColoredManaSymbol> allowedColors;
|
private final List<ColoredManaSymbol> allowedColors;
|
||||||
private boolean colorlessAllowed;
|
private boolean colorlessAllowed;
|
||||||
private final List<DeckGeneratorCMC> poolCMCs;
|
private final List<DeckGeneratorCMC.CMC> poolCMCs;
|
||||||
private final int creatureCount;
|
private final int creatureCount;
|
||||||
private final int nonCreatureCount;
|
private final int nonCreatureCount;
|
||||||
private final int landCount;
|
private final int landCount;
|
||||||
|
@ -69,7 +66,21 @@ public class DeckGeneratorPool
|
||||||
private List<Card> reserveSpells = new ArrayList<>();
|
private List<Card> reserveSpells = new ArrayList<>();
|
||||||
private Deck deck;
|
private Deck deck;
|
||||||
|
|
||||||
public DeckGeneratorPool(final int deckSize, final List<ColoredManaSymbol> allowedColors, boolean isSingleton, boolean colorlessAllowed)
|
/**
|
||||||
|
* Creates a card pool with specified criterea used when generating a deck.
|
||||||
|
*
|
||||||
|
* @param deckSize the size of the complete deck
|
||||||
|
* @param creaturePercentage what percentage of creatures to use when generating the deck.
|
||||||
|
* @param nonCreaturePercentage percentage of non-creatures to use when generating the deck.
|
||||||
|
* @param landPercentage percentage of lands to use when generating the deck.
|
||||||
|
* @param allowedColors which card colors are allowed in the generated deck.
|
||||||
|
* @param isSingleton if the deck only has 1 copy of each non-land card.
|
||||||
|
* @param colorlessAllowed if colourless mana symbols are allowed in costs in the deck.
|
||||||
|
* @param isAdvanced if the user has provided advanced options to generate the deck.
|
||||||
|
* @param deckGeneratorCMC the CMC curve to use for this deck
|
||||||
|
*/
|
||||||
|
public DeckGeneratorPool(final int deckSize, final int creaturePercentage, final int nonCreaturePercentage, final int landPercentage,
|
||||||
|
final List<ColoredManaSymbol> allowedColors, boolean isSingleton, boolean colorlessAllowed, boolean isAdvanced, DeckGeneratorCMC deckGeneratorCMC)
|
||||||
{
|
{
|
||||||
this.deckSize = deckSize;
|
this.deckSize = deckSize;
|
||||||
this.allowedColors = allowedColors;
|
this.allowedColors = allowedColors;
|
||||||
|
@ -78,28 +89,26 @@ public class DeckGeneratorPool
|
||||||
|
|
||||||
this.deck = new Deck();
|
this.deck = new Deck();
|
||||||
|
|
||||||
if(this.deckSize > 40) {
|
// Advanced (CMC Slider panel and curve drop-down in the dialog)
|
||||||
this.creatureCount = CREATURE_COUNT_60;
|
if(isAdvanced) {
|
||||||
this.nonCreatureCount = NONCREATURE_COUNT_60;
|
this.creatureCount = (int)Math.ceil((deckSize / 100.0) * creaturePercentage);
|
||||||
this.landCount = LAND_COUNT_60;
|
this.nonCreatureCount = (int)Math.ceil((deckSize / 100.0)* nonCreaturePercentage);
|
||||||
poolCMCs = new ArrayList<DeckGeneratorCMC>() {{
|
this.landCount = (int)Math.ceil((deckSize / 100.0)* landPercentage);
|
||||||
add(new DeckGeneratorCMC(0, 2, 0.20f));
|
if(this.deckSize == 60) {
|
||||||
add(new DeckGeneratorCMC(3, 5, 0.50f));
|
this.poolCMCs = deckGeneratorCMC.get60CardPoolCMC();
|
||||||
add(new DeckGeneratorCMC(6, 7, 0.25f));
|
} else {
|
||||||
add(new DeckGeneratorCMC(8, 100, 0.05f));
|
this.poolCMCs = deckGeneratorCMC.get40CardPoolCMC();
|
||||||
}};
|
}
|
||||||
|
} else {
|
||||||
|
// Ignore the advanced group, just use defaults
|
||||||
|
this.creatureCount = (int)Math.ceil((deckSize / 100.0) * DEFAULT_CREATURE_PERCENTAGE);
|
||||||
|
this.nonCreatureCount = (int)Math.ceil((deckSize / 100.0) * DEFAULT_NON_CREATURE_PERCENTAGE);
|
||||||
|
this.landCount = (int)Math.ceil((deckSize / 100.0) * DEFAULT_LAND_PERCENTAGE);
|
||||||
|
if(this.deckSize == 60) {
|
||||||
|
this.poolCMCs = DeckGeneratorCMC.Default.get60CardPoolCMC();
|
||||||
|
} else {
|
||||||
|
this.poolCMCs = DeckGeneratorCMC.Default.get40CardPoolCMC();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
this.creatureCount = CREATURE_COUNT_40;
|
|
||||||
this.nonCreatureCount = NONCREATURE_COUNT_40;
|
|
||||||
this.landCount = LAND_COUNT_40;
|
|
||||||
poolCMCs = new ArrayList<DeckGeneratorCMC>() {{
|
|
||||||
add(new DeckGeneratorCMC(0, 2, 0.30f));
|
|
||||||
add(new DeckGeneratorCMC(3, 4, 0.45f));
|
|
||||||
add(new DeckGeneratorCMC(5, 6, 0.20f));
|
|
||||||
add(new DeckGeneratorCMC(7, 100, 0.05f));
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allowedColors.size() == 1) {
|
if(allowedColors.size() == 1) {
|
||||||
|
@ -114,16 +123,15 @@ public class DeckGeneratorPool
|
||||||
* @param cardsCount the number of total cards.
|
* @param cardsCount the number of total cards.
|
||||||
* @return a list of CMC ranges, with the amount of cards for each CMC range
|
* @return a list of CMC ranges, with the amount of cards for each CMC range
|
||||||
*/
|
*/
|
||||||
public List<DeckGeneratorCMC> getCMCsForSpellCount(int cardsCount) {
|
public List<DeckGeneratorCMC.CMC> getCMCsForSpellCount(int cardsCount) {
|
||||||
List<DeckGeneratorCMC> adjustedCMCs = new ArrayList<>(this.poolCMCs);
|
List<DeckGeneratorCMC.CMC> adjustedCMCs = new ArrayList<>(this.poolCMCs);
|
||||||
// For each CMC calculate how many spell cards are needed, given the total amount of cards
|
// For each CMC calculate how many spell cards are needed, given the total amount of cards
|
||||||
for(DeckGeneratorCMC deckCMC : adjustedCMCs) {
|
for(DeckGeneratorCMC.CMC deckCMC : adjustedCMCs) {
|
||||||
deckCMC.setAmount((int)Math.ceil(deckCMC.percentage * cardsCount));
|
deckCMC.setAmount((int)Math.ceil(deckCMC.percentage * cardsCount));
|
||||||
}
|
}
|
||||||
return adjustedCMCs;
|
return adjustedCMCs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies if the spell card supplied is valid for this pool of cards.
|
* Verifies if the spell card supplied is valid for this pool of cards.
|
||||||
* Checks that there isn't too many copies of this card in the deck.
|
* Checks that there isn't too many copies of this card in the deck.
|
||||||
|
@ -391,18 +399,16 @@ public class DeckGeneratorPool
|
||||||
|
|
||||||
int spellsNeeded = nonLandSize-spellSize;
|
int spellsNeeded = nonLandSize-spellSize;
|
||||||
|
|
||||||
// If we haven't got enough spells in reserve to fulfil the amount we need, we can't continue.
|
// If we haven't got enough spells in reserve to fulfil the amount we need, skip adding any.
|
||||||
if(reserveSpells.size() < spellsNeeded) {
|
if(reserveSpells.size() >= spellsNeeded) {
|
||||||
throw new IllegalStateException("Not enough cards found to generate deck. Please try again");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Card> spellsToAdd = new ArrayList<>(spellsNeeded);
|
List<Card> spellsToAdd = new ArrayList<>(spellsNeeded);
|
||||||
|
|
||||||
// Initial reservoir
|
// Initial reservoir
|
||||||
for(int i = 0; i < spellsNeeded; i++)
|
for (int i = 0; i < spellsNeeded; i++)
|
||||||
spellsToAdd.add(reserveSpells.get(i));
|
spellsToAdd.add(reserveSpells.get(i));
|
||||||
|
|
||||||
for(int i = spellsNeeded+1; i < reserveSpells.size()-1; i++) {
|
for (int i = spellsNeeded + 1; i < reserveSpells.size() - 1; i++) {
|
||||||
int j = random.nextInt(i);
|
int j = random.nextInt(i);
|
||||||
Card randomCard = reserveSpells.get(j);
|
Card randomCard = reserveSpells.get(j);
|
||||||
if (isValidSpellCard(randomCard) && j < spellsToAdd.size()) {
|
if (isValidSpellCard(randomCard) && j < spellsToAdd.size()) {
|
||||||
|
@ -412,24 +418,35 @@ public class DeckGeneratorPool
|
||||||
// Add randomly selected spells needed
|
// Add randomly selected spells needed
|
||||||
deckCards.addAll(spellsToAdd);
|
deckCards.addAll(spellsToAdd);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// More spells than needed
|
// More spells than needed
|
||||||
else if(spellSize > (deckSize - landCount)) {
|
else if(spellSize > (deckSize - landCount)) {
|
||||||
|
|
||||||
int spellsRemoved = (spellSize)-(deckSize-landCount);
|
int spellsRemoved = (spellSize)-(deckSize-landCount);
|
||||||
for(int i = 0; i < spellsRemoved; ++i) {
|
for(int i = 0; i < spellsRemoved; ++i) {
|
||||||
deckCards.remove(random.nextInt(deckCards.size()));
|
deckCards.remove(random.nextInt(deckCards.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not strictly necessary as we check when adding cards, but worth double checking anyway.
|
// Check we have exactly the right amount of cards for a deck.
|
||||||
if(deckCards.size() != nonLandSize) {
|
if(deckCards.size() != nonLandSize) {
|
||||||
throw new IllegalStateException("Not enough cards found to generate deck. Please try again");
|
throw new IllegalStateException("Not enough cards found to generate deck.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the fixed amount
|
// Return the fixed amount
|
||||||
return deckCards;
|
return deckCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if this land taps for the given color.
|
||||||
|
* Basic string matching to check the ability adds one of the chosen mana when tapped.
|
||||||
|
* @param ability MockAbility of the land card
|
||||||
|
* @param symbol colored mana symbol.
|
||||||
|
* @return if the ability is tapping to produce the mana the symbol represents.
|
||||||
|
*/
|
||||||
|
private boolean landTapsForAllowedColor(String ability, String symbol) {
|
||||||
|
return ability.matches(".*Add \\{" + symbol + "\\} to your mana pool.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if this land will produce the chosen colors for this pool.
|
* Returns if this land will produce the chosen colors for this pool.
|
||||||
* @param card a non-basic land card.
|
* @param card a non-basic land card.
|
||||||
|
@ -455,17 +472,6 @@ public class DeckGeneratorPool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if this land taps for the given color.
|
|
||||||
* Basic string matching to check the ability adds one of the chosen mana when tapped.
|
|
||||||
* @param ability MockAbility of the land card
|
|
||||||
* @param symbol colored mana symbol.
|
|
||||||
* @return if the ability is tapping to produce the mana the symbol represents.
|
|
||||||
*/
|
|
||||||
private boolean landTapsForAllowedColor(String ability, String symbol) {
|
|
||||||
return ability.matches(".*Add \\{" + symbol + "\\} to your mana pool.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the symbol is a colored mana symbol.
|
* Returns if the symbol is a colored mana symbol.
|
||||||
* @param symbol the symbol to check.
|
* @param symbol the symbol to check.
|
||||||
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mage.client.deck.generator;
|
||||||
|
|
||||||
|
import mage.client.deck.generator.DeckGeneratorPool;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.CompoundBorder;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.border.EtchedBorder;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Simown
|
||||||
|
*/
|
||||||
|
public class RatioAdjustingSliderPanel extends JPanel {
|
||||||
|
|
||||||
|
private JStorageSlider creatureSlider, nonCreatureSlider, landSlider;
|
||||||
|
private List<JLabel> textLabels = new ArrayList<>();
|
||||||
|
private AdjustingSliderGroup sg;
|
||||||
|
|
||||||
|
private class JStorageSlider extends JSlider {
|
||||||
|
|
||||||
|
// Slider stores its initial value to revert to when reset
|
||||||
|
private int defaultValue;
|
||||||
|
private int previousValue;
|
||||||
|
|
||||||
|
public JStorageSlider(int min, int max, int value) {
|
||||||
|
super(min, max, value);
|
||||||
|
previousValue = value;
|
||||||
|
defaultValue = value;
|
||||||
|
setMinorTickSpacing(5);
|
||||||
|
setMajorTickSpacing(10);
|
||||||
|
setPaintTicks(true);
|
||||||
|
setPaintLabels(true);
|
||||||
|
setLabelTable(createStandardLabels(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPreviousValue() {
|
||||||
|
return previousValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreviousValue(int value) {
|
||||||
|
previousValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetDefault() {
|
||||||
|
this.setValue(defaultValue);
|
||||||
|
previousValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AdjustingSliderGroup
|
||||||
|
{
|
||||||
|
private final ArrayList<JStorageSlider> storageSliders;
|
||||||
|
private int sliderIndex = 0;
|
||||||
|
|
||||||
|
AdjustingSliderGroup(JStorageSlider... sliders)
|
||||||
|
{
|
||||||
|
storageSliders = new ArrayList<>();
|
||||||
|
for(JStorageSlider slider: sliders) {
|
||||||
|
storageSliders.add(slider);
|
||||||
|
slider.addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
fireSliderChangedEvent((JStorageSlider) e.getSource());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void fireSliderChangedEvent(JStorageSlider source) {
|
||||||
|
// We don't want to do anything if the value isn't changing
|
||||||
|
if(!source.getValueIsAdjusting())
|
||||||
|
return;
|
||||||
|
// Update the slider depending on how much it's changed relative to its previous position
|
||||||
|
int change = (source.getValue() - source.getPreviousValue());
|
||||||
|
updateSliderPosition(change, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSliderPosition(int change, JStorageSlider source) {
|
||||||
|
int remaining = change;
|
||||||
|
while (remaining != 0) {
|
||||||
|
// Get the currently indexed slider
|
||||||
|
JStorageSlider slider = storageSliders.get(sliderIndex);
|
||||||
|
// If it's not the slider that fired the event
|
||||||
|
if (slider != source) {
|
||||||
|
// Check we don't go over the upper and lower bounds
|
||||||
|
if (remaining < 0 || (remaining > 0 && slider.getValue() > 0)) {
|
||||||
|
// Adjust the currently selected slider by +/- 1
|
||||||
|
int adjustment = Integer.signum(remaining);
|
||||||
|
slider.setValue(slider.getValue() - adjustment);
|
||||||
|
remaining -= adjustment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Select the next slider in the list of sliders
|
||||||
|
sliderIndex = (sliderIndex + 1) % storageSliders.size();
|
||||||
|
}
|
||||||
|
for (JStorageSlider slider : storageSliders) {
|
||||||
|
slider.setPreviousValue(slider.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JStorageSlider> getSliders() {
|
||||||
|
return storageSliders;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public RatioAdjustingSliderPanel() {
|
||||||
|
initPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPanel() {
|
||||||
|
|
||||||
|
// Create three sliders with default values
|
||||||
|
creatureSlider = new JStorageSlider(0, 100, DeckGeneratorPool.DEFAULT_CREATURE_PERCENTAGE);
|
||||||
|
nonCreatureSlider = new JStorageSlider(0, 100, DeckGeneratorPool.DEFAULT_NON_CREATURE_PERCENTAGE);
|
||||||
|
landSlider = new JStorageSlider(0, 100, DeckGeneratorPool.DEFAULT_LAND_PERCENTAGE);
|
||||||
|
|
||||||
|
sg = new AdjustingSliderGroup(creatureSlider, nonCreatureSlider, landSlider);
|
||||||
|
|
||||||
|
this.setLayout(new GridLayout(3, 1));
|
||||||
|
|
||||||
|
this.add(createSliderPanel("Creatures ", creatureSlider));
|
||||||
|
this.add(createSliderPanel("Non-creatures ", nonCreatureSlider));
|
||||||
|
this.add(createSliderPanel("Lands ", landSlider));
|
||||||
|
|
||||||
|
setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel createSliderPanel(String label, JStorageSlider slider) {
|
||||||
|
|
||||||
|
JPanel sliderPanel = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
|
// Title
|
||||||
|
JLabel titleLabel = new JLabel(label);
|
||||||
|
textLabels.add(titleLabel);
|
||||||
|
sliderPanel.add(titleLabel, BorderLayout.WEST);
|
||||||
|
// Slider
|
||||||
|
slider.setToolTipText("Percentage of " + label.trim().toLowerCase() + " in the generated deck.");
|
||||||
|
sliderPanel.add(slider, BorderLayout.CENTER);
|
||||||
|
// Percentage
|
||||||
|
JLabel percentageLabel = createChangingPercentageLabel(slider);
|
||||||
|
textLabels.add(percentageLabel);
|
||||||
|
sliderPanel.add(percentageLabel, BorderLayout.EAST);
|
||||||
|
|
||||||
|
return sliderPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JLabel createChangingPercentageLabel(final JSlider slider) {
|
||||||
|
|
||||||
|
final JLabel label = new JLabel(" " + String.valueOf(slider.getValue()) + "%");
|
||||||
|
|
||||||
|
slider.addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
String value = String.valueOf(slider.getValue());
|
||||||
|
StringBuilder labelBuilder = new StringBuilder();
|
||||||
|
// Pad with spaces so all percentage labels are of equal size
|
||||||
|
for(int i = 0; i < (5-value.length()); i++) {
|
||||||
|
labelBuilder.append(" ");
|
||||||
|
}
|
||||||
|
labelBuilder.append(value);
|
||||||
|
labelBuilder.append("%");
|
||||||
|
label.setText(labelBuilder.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
for(JStorageSlider slider: sg.getSliders()) {
|
||||||
|
slider.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
for(JLabel label: textLabels) {
|
||||||
|
label.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetValues() {
|
||||||
|
for(JStorageSlider slider: sg.getSliders()) {
|
||||||
|
slider.resetDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCreaturePercentage() {
|
||||||
|
return creatureSlider.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNonCreaturePercentage() {
|
||||||
|
return nonCreatureSlider.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLandPercentage() {
|
||||||
|
return landSlider.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreaturePercentage(int percentage) {
|
||||||
|
creatureSlider.setValue(percentage);
|
||||||
|
creatureSlider.previousValue = percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonCreaturePercentage(int percentage) {
|
||||||
|
nonCreatureSlider.setValue(percentage);
|
||||||
|
nonCreatureSlider.previousValue = percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLandPercentage(int percentage) {
|
||||||
|
landSlider.setValue(percentage);
|
||||||
|
landSlider.previousValue = percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -236,6 +236,12 @@ public class PreferencesDialog extends javax.swing.JDialog {
|
||||||
public static final String KEY_NEW_DECK_GENERATOR_ARTIFACTS = "newDeckGeneratorArtifacts";
|
public static final String KEY_NEW_DECK_GENERATOR_ARTIFACTS = "newDeckGeneratorArtifacts";
|
||||||
public static final String KEY_NEW_DECK_GENERATOR_NON_BASIC_LANDS = "newDeckGeneratorNonBasicLands";
|
public static final String KEY_NEW_DECK_GENERATOR_NON_BASIC_LANDS = "newDeckGeneratorNonBasicLands";
|
||||||
public static final String KEY_NEW_DECK_GENERATOR_COLORLESS = "newDeckGeneratorColorless";
|
public static final String KEY_NEW_DECK_GENERATOR_COLORLESS = "newDeckGeneratorColorless";
|
||||||
|
public static final String KEY_NEW_DECK_GENERATOR_ADVANCED = "newDeckGeneratorAdvanced";
|
||||||
|
public static final String KEY_NEW_DECK_GENERATOR_CREATURE_PERCENTAGE = "newDeckGeneratorCreaturePercentage";
|
||||||
|
public static final String KEY_NEW_DECK_GENERATOR_NON_CREATURE_PERCENTAGE = "newDeckGeneratorNonCreaturePercentage";
|
||||||
|
public static final String KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE = "newDeckGeneratorLandPercentage";
|
||||||
|
public static final String KEY_NEW_DECK_GENERATOR_ADVANCED_CMC = "newDeckGeneratorAdvancedCMC";
|
||||||
|
|
||||||
|
|
||||||
// used to save and restore the settings for the cardArea (draft, sideboarding, deck builder)
|
// used to save and restore the settings for the cardArea (draft, sideboarding, deck builder)
|
||||||
public static final String KEY_DRAFT_VIEW = "draftView";
|
public static final String KEY_DRAFT_VIEW = "draftView";
|
||||||
|
|
Loading…
Reference in a new issue