diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java index 91e4b40f405..58deb3885bc 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/CSubmenuSealed.java @@ -2,40 +2,24 @@ package forge.screens.home.sanctioned; import forge.UiCommand; import forge.Singletons; -import forge.card.MagicColor; import forge.deck.*; import forge.game.GameType; -import forge.gui.GuiChoose; import forge.deck.DeckProxy; import forge.gui.framework.FScreen; import forge.gui.framework.ICDoc; import forge.item.InventoryItem; -import forge.item.PaperCard; import forge.itemmanager.ItemManagerConfig; -import forge.limited.DraftRankCache; -import forge.limited.LimitedPoolType; import forge.limited.SealedCardPoolGenerator; -import forge.limited.SealedDeckBuilder; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.controllers.ACEditorBase; import forge.screens.deckeditor.controllers.CEditorLimited; import forge.toolbox.FOptionPane; -import forge.util.MyRandom; -import forge.util.storage.IStorage; - -import org.apache.commons.lang3.StringUtils; - import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; /** * Controls the sealed submenu in the home UI. @@ -48,8 +32,6 @@ public enum CSubmenuSealed implements ICDoc { /** */ SINGLETON_INSTANCE; - private Map aiDecks; - private final UiCommand cmdDeckSelect = new UiCommand() { @Override public void run() { @@ -93,16 +75,6 @@ public enum CSubmenuSealed implements ICDoc { */ @Override public void update() { - final List humanDecks = new ArrayList(); - aiDecks = new HashMap(); - - // Since AI decks are tied directly to the human choice, - // they're just mapped in a parallel map and grabbed when the game starts. - for (final DeckGroup d : FModel.getDecks().getSealed()) { - aiDecks.put(d.getName(), d.getAiDecks().get(0)); - humanDecks.add(d.getHumanDeck()); - } - final VSubmenuSealed view = VSubmenuSealed.SINGLETON_INSTANCE; view.getLstDecks().setPool(DeckProxy.getAllSealedDecks(FModel.getDecks().getSealed())); view.getLstDecks().setup(ItemManagerConfig.SEALED_DECKS); @@ -141,81 +113,8 @@ public enum CSubmenuSealed implements ICDoc { @SuppressWarnings("unchecked") private void setupSealed() { - final String prompt = "Choose Sealed Deck Format"; - final LimitedPoolType poolType = GuiChoose.oneOrNone(prompt, LimitedPoolType.values()); - if (poolType == null) { return; } - - SealedCardPoolGenerator sd = new SealedCardPoolGenerator(poolType); - if (sd.isEmpty()) { return; } - - final CardPool humanPool = sd.getCardPool(true); - if (humanPool == null) { return; } - - // System.out.println(humanPool); - - // This seems to be limited by the MAX_DRAFT_PLAYERS constant - // in DeckGroupSerializer.java. You could create more AI decks - // but only the first seven would load. --BBU - Integer rounds = GuiChoose.getInteger("How many opponents are you willing to face?", 1, 7); - if (rounds == null) { return; } - - final String sDeckName = FOptionPane.showInputDialog( - "Save this card pool as:", - "Save Card Pool", - FOptionPane.QUESTION_ICON); - - if (StringUtils.isBlank(sDeckName)) { - return; - } - - final Deck deck = new Deck(sDeckName); - deck.getOrCreate(DeckSection.Sideboard).addAll(humanPool); - - final int landsCount = 10; - - final boolean isZendikarSet = sd.getLandSetCode().equals("ZEN"); // we want to generate one kind of Zendikar lands at a time only - final boolean zendikarSetMode = MyRandom.getRandom().nextBoolean(); - - for (final String element : MagicColor.Constant.BASIC_LANDS) { - int numArt = FModel.getMagicDb().getCommonCards().getArtCount(element, sd.getLandSetCode()); - int minArtIndex = isZendikarSet ? (zendikarSetMode ? 1 : 5) : 1; - int maxArtIndex = isZendikarSet ? minArtIndex + 3 : numArt; - - if (FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_ART_IN_POOLS)) { - - for (int i = minArtIndex; i <= maxArtIndex; i++) { - deck.get(DeckSection.Sideboard).add(element, sd.getLandSetCode(), i, numArt > 1 ? landsCount : 30); - } - } else { - deck.get(DeckSection.Sideboard).add(element, sd.getLandSetCode(), 30); - } - } - - final IStorage sealedDecks = FModel.getDecks().getSealed(); - - if (sealedDecks.contains(sDeckName)) { - if (!FOptionPane.showConfirmDialog( - "'" + sDeckName + "' already exists. Do you want to replace it?", - "Sealed Deck Game Exists")) { - return; - } - sealedDecks.delete(sDeckName); - } - - final DeckGroup sealed = new DeckGroup(sDeckName); - sealed.setHumanDeck(deck); - for (int i = 0; i < rounds; i++) { - // Generate other decks for next N opponents - final CardPool aiPool = sd.getCardPool(false); - if (aiPool == null) { return; } - - sealed.addAiDeck(new SealedDeckBuilder(aiPool.toFlatList()).buildDeck()); - } - - // Rank the AI decks - sealed.rankAiDecks(new DeckComparer()); - - FModel.getDecks().getSealed().add(sealed); + final DeckGroup sealed = SealedCardPoolGenerator.generateSealedDeck(); + if (sealed == null) { return; } final ACEditorBase editor = (ACEditorBase) new CEditorLimited( FModel.getDecks().getSealed(), FScreen.DECK_EDITOR_SEALED); @@ -232,47 +131,4 @@ public enum CSubmenuSealed implements ICDoc { public UiCommand getCommandOnSelect() { return null; } - - static class DeckComparer implements java.util.Comparator { - public double getDraftValue(Deck d) { - double value = 0; - double divider = 0; - - if (d.getMain().isEmpty()) { - return 0; - } - - double best = 1.0; - - for (Entry kv : d.getMain()) { - PaperCard evalCard = kv.getKey(); - int count = kv.getValue(); - if (DraftRankCache.getRanking(evalCard.getName(), evalCard.getEdition()) != null) { - double add = DraftRankCache.getRanking(evalCard.getName(), evalCard.getEdition()); - // System.out.println(evalCard.getName() + " is worth " + add); - value += add * count; - divider += count; - if (best > add) { - best = add; - } - } - } - - if (divider == 0 || value == 0) { - return 0; - } - - value /= divider; - - return (20.0 / (best + (2 * value))); - } - - @Override - public int compare(Deck o1, Deck o2) { - double delta = getDraftValue(o1) - getDraftValue(o2); - if ( delta > 0 ) return 1; - if ( delta < 0 ) return -1; - return 0; - } - } } diff --git a/forge-gui-mobile/src/forge/deck/FDeckEditor.java b/forge-gui-mobile/src/forge/deck/FDeckEditor.java index 12f628630e3..a479963720f 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckEditor.java +++ b/forge-gui-mobile/src/forge/deck/FDeckEditor.java @@ -115,6 +115,11 @@ public class FDeckEditor extends TabPageScreen { } tabPage.initialize(); } + + //if opening brand new sealed deck, show sideboard (card pool) by default + if (editorType == EditorType.Sealed && deck.getMain().isEmpty()) { + setSelectedPage(sideboardPage); + } } public EditorType getEditorType() { diff --git a/forge-gui-mobile/src/forge/screens/draft/DraftScreen.java b/forge-gui-mobile/src/forge/screens/draft/DraftScreen.java index 3f0f6c1e4ab..3fb43198a46 100644 --- a/forge-gui-mobile/src/forge/screens/draft/DraftScreen.java +++ b/forge-gui-mobile/src/forge/screens/draft/DraftScreen.java @@ -38,6 +38,12 @@ public class DraftScreen extends LaunchScreen { lstDecks.setPool(DeckProxy.getDraftDecks(FModel.getDecks().getDraft())); lstDecks.setup(ItemManagerConfig.DRAFT_DECKS); + lstDecks.setItemActivateHandler(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + editSelectedDeck(); + } + }); btnNewDraft.setFont(FSkinFont.get(16)); btnNewDraft.setCommand(new FEventHandler() { @@ -71,14 +77,18 @@ public class DraftScreen extends LaunchScreen { btnEditDeck.setCommand(new FEventHandler() { @Override public void handleEvent(FEvent e) { - final DeckProxy deck = lstDecks.getSelectedItem(); - if (deck == null) { return; } - - Forge.openScreen(new FDeckEditor(EditorType.Draft, deck.getDeck())); + editSelectedDeck(); } }); } + private void editSelectedDeck() { + final DeckProxy deck = lstDecks.getSelectedItem(); + if (deck == null) { return; } + + Forge.openScreen(new FDeckEditor(EditorType.Draft, deck.getDeck())); + } + @Override protected void doLayoutAboveBtnStart(float startY, float width, float height) { float x = ItemFilter.PADDING; diff --git a/forge-gui-mobile/src/forge/screens/home/HomeScreen.java b/forge-gui-mobile/src/forge/screens/home/HomeScreen.java index dd1ab6872d5..5a31902c65a 100644 --- a/forge-gui-mobile/src/forge/screens/home/HomeScreen.java +++ b/forge-gui-mobile/src/forge/screens/home/HomeScreen.java @@ -42,7 +42,7 @@ public class HomeScreen extends FScreen { public void handleEvent(FEvent e) { Forge.openScreen(new SealedScreen()); } - }, false); + }, true); addButton("Quest Mode", new FEventHandler() { @Override public void handleEvent(FEvent e) { diff --git a/forge-gui-mobile/src/forge/screens/sealed/SealedScreen.java b/forge-gui-mobile/src/forge/screens/sealed/SealedScreen.java index 23da6adcd83..dc532d7e878 100644 --- a/forge-gui-mobile/src/forge/screens/sealed/SealedScreen.java +++ b/forge-gui-mobile/src/forge/screens/sealed/SealedScreen.java @@ -1,17 +1,91 @@ package forge.screens.sealed; +import forge.FThreads; +import forge.Forge; +import forge.assets.FSkinFont; +import forge.deck.DeckGroup; +import forge.deck.DeckProxy; +import forge.deck.FDeckChooser; +import forge.deck.FDeckEditor; +import forge.deck.FDeckEditor.EditorType; import forge.game.GameType; +import forge.itemmanager.DeckManager; +import forge.itemmanager.ItemManagerConfig; +import forge.itemmanager.filters.ItemFilter; +import forge.limited.SealedCardPoolGenerator; +import forge.model.FModel; import forge.screens.LaunchScreen; +import forge.toolbox.FButton; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; +import forge.util.ThreadUtil; public class SealedScreen extends LaunchScreen { + private final DeckManager lstDecks = add(new DeckManager(GameType.Draft)); + private final FButton btnNewDeck = add(new FButton("New Deck")); + private final FButton btnEditDeck = add(new FButton("Edit Deck")); + public SealedScreen() { super("Sealed Deck"); + + lstDecks.setPool(DeckProxy.getAllSealedDecks(FModel.getDecks().getSealed())); + lstDecks.setup(ItemManagerConfig.SEALED_DECKS); + lstDecks.setItemActivateHandler(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + editSelectedDeck(); + } + }); + + btnNewDeck.setFont(FSkinFont.get(16)); + btnNewDeck.setCommand(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + ThreadUtil.invokeInGameThread(new Runnable() { //must run in game thread to prevent blocking UI thread + @Override + public void run() { + final DeckGroup sealed = SealedCardPoolGenerator.generateSealedDeck(); + if (sealed == null) { return; } + + FThreads.invokeInEdtLater(new Runnable() { + @Override + public void run() { + Forge.openScreen(new FDeckEditor(EditorType.Sealed, sealed.getHumanDeck())); + } + }); + } + }); + } + }); + btnEditDeck.setFont(btnNewDeck.getFont()); + btnEditDeck.setCommand(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + editSelectedDeck(); + } + }); + } + + private void editSelectedDeck() { + final DeckProxy deck = lstDecks.getSelectedItem(); + if (deck == null) { return; } + + Forge.openScreen(new FDeckEditor(EditorType.Sealed, deck.getDeck())); } @Override protected void doLayoutAboveBtnStart(float startY, float width, float height) { - // TODO Auto-generated method stub - + float x = ItemFilter.PADDING; + float y = startY; + float w = width - 2 * x; + float buttonWidth = (w - FDeckChooser.PADDING) / 2; + float buttonHeight = btnNewDeck.getAutoSizeBounds().height * 1.2f; + float listHeight = height - buttonHeight - y - FDeckChooser.PADDING; + + lstDecks.setBounds(x, y, w, listHeight); + y += listHeight + FDeckChooser.PADDING; + btnNewDeck.setBounds(x, y, buttonWidth, buttonHeight); + btnEditDeck.setBounds(x + buttonWidth + FDeckChooser.PADDING, y, buttonWidth, buttonHeight); } @Override diff --git a/forge-gui-mobile/src/forge/toolbox/FOptionPane.java b/forge-gui-mobile/src/forge/toolbox/FOptionPane.java index 32c4ce7cf02..e7a335386be 100644 --- a/forge-gui-mobile/src/forge/toolbox/FOptionPane.java +++ b/forge-gui-mobile/src/forge/toolbox/FOptionPane.java @@ -110,7 +110,7 @@ public class FOptionPane extends FDialog { inputField = cbInput; } - final FOptionPane optionPane = new FOptionPane(message, title, icon, inputField, new String[] {"OK", "Cancel"}, -1, new Callback() { + final FOptionPane optionPane = new FOptionPane(message, title, icon, inputField, new String[] {"OK", "Cancel"}, 0, new Callback() { @SuppressWarnings("unchecked") @Override public void run(Integer result) { diff --git a/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java b/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java index ef5e43f6d26..b724d61c4dc 100644 --- a/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java +++ b/forge-gui/src/main/java/forge/limited/SealedCardPoolGenerator.java @@ -17,27 +17,37 @@ */ package forge.limited; +import forge.assets.FSkinProp; import forge.card.CardEdition; import forge.card.IUnOpenedProduct; +import forge.card.MagicColor; import forge.card.UnOpenedProduct; import forge.deck.CardPool; +import forge.deck.Deck; +import forge.deck.DeckGroup; +import forge.deck.DeckSection; import forge.item.PaperCard; import forge.item.SealedProduct; import forge.model.CardBlock; import forge.model.FModel; import forge.model.UnOpenedMeta; import forge.properties.ForgeConstants; +import forge.properties.ForgePreferences.FPref; import forge.util.FileUtil; +import forge.util.MyRandom; import forge.util.TextUtil; import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; +import forge.util.storage.IStorage; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Stack; +import java.util.Map.Entry; /** *

@@ -56,6 +66,84 @@ public class SealedCardPoolGenerator { /** The Land set code. */ private String landSetCode = null; + public static DeckGroup generateSealedDeck() { + final String prompt = "Choose Sealed Deck Format"; + final LimitedPoolType poolType = SGuiChoose.oneOrNone(prompt, LimitedPoolType.values()); + if (poolType == null) { return null; } + + SealedCardPoolGenerator sd = new SealedCardPoolGenerator(poolType); + if (sd.isEmpty()) { return null; } + + final CardPool humanPool = sd.getCardPool(true); + if (humanPool == null) { return null; } + + // System.out.println(humanPool); + + // This seems to be limited by the MAX_DRAFT_PLAYERS constant + // in DeckGroupSerializer.java. You could create more AI decks + // but only the first seven would load. --BBU + Integer rounds = SGuiChoose.getInteger("How many opponents are you willing to face?", 1, 7); + if (rounds == null) { return null; } + + final String sDeckName = SOptionPane.showInputDialog( + "Save this card pool as:", + "Save Card Pool", + FSkinProp.ICO_QUESTION); + + if (StringUtils.isBlank(sDeckName)) { + return null; + } + + final IStorage sealedDecks = FModel.getDecks().getSealed(); + if (sealedDecks.contains(sDeckName)) { + if (!SOptionPane.showConfirmDialog( + "'" + sDeckName + "' already exists. Do you want to replace it?", + "Sealed Deck Game Exists")) { + return null; + } + sealedDecks.delete(sDeckName); + } + + final Deck deck = new Deck(sDeckName); + deck.getOrCreate(DeckSection.Sideboard).addAll(humanPool); + + final int landsCount = 10; + + final boolean isZendikarSet = sd.getLandSetCode().equals("ZEN"); // we want to generate one kind of Zendikar lands at a time only + final boolean zendikarSetMode = MyRandom.getRandom().nextBoolean(); + + for (final String element : MagicColor.Constant.BASIC_LANDS) { + int numArt = FModel.getMagicDb().getCommonCards().getArtCount(element, sd.getLandSetCode()); + int minArtIndex = isZendikarSet ? (zendikarSetMode ? 1 : 5) : 1; + int maxArtIndex = isZendikarSet ? minArtIndex + 3 : numArt; + + if (FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_ART_IN_POOLS)) { + for (int i = minArtIndex; i <= maxArtIndex; i++) { + deck.get(DeckSection.Sideboard).add(element, sd.getLandSetCode(), i, numArt > 1 ? landsCount : 30); + } + } + else { + deck.get(DeckSection.Sideboard).add(element, sd.getLandSetCode(), 30); + } + } + + final DeckGroup sealed = new DeckGroup(sDeckName); + sealed.setHumanDeck(deck); + for (int i = 0; i < rounds; i++) { + // Generate other decks for next N opponents + final CardPool aiPool = sd.getCardPool(false); + if (aiPool == null) { return null; } + + sealed.addAiDeck(new SealedDeckBuilder(aiPool.toFlatList()).buildDeck()); + } + + // Rank the AI decks + sealed.rankAiDecks(new SealedDeckComparer()); + + FModel.getDecks().getSealed().add(sealed); + return sealed; + } + /** *

* Constructor for SealedDeck. @@ -64,7 +152,7 @@ public class SealedCardPoolGenerator { * @param poolType * a {@link java.lang.String} object. */ - public SealedCardPoolGenerator(final LimitedPoolType poolType) { + private SealedCardPoolGenerator(final LimitedPoolType poolType) { switch(poolType) { case Full: // Choose number of boosters @@ -368,4 +456,47 @@ public class SealedCardPoolGenerator { public boolean isEmpty() { return product.isEmpty(); } + + private static class SealedDeckComparer implements java.util.Comparator { + public double getDraftValue(Deck d) { + double value = 0; + double divider = 0; + + if (d.getMain().isEmpty()) { + return 0; + } + + double best = 1.0; + + for (Entry kv : d.getMain()) { + PaperCard evalCard = kv.getKey(); + int count = kv.getValue(); + if (DraftRankCache.getRanking(evalCard.getName(), evalCard.getEdition()) != null) { + double add = DraftRankCache.getRanking(evalCard.getName(), evalCard.getEdition()); + // System.out.println(evalCard.getName() + " is worth " + add); + value += add * count; + divider += count; + if (best > add) { + best = add; + } + } + } + + if (divider == 0 || value == 0) { + return 0; + } + + value /= divider; + + return (20.0 / (best + (2 * value))); + } + + @Override + public int compare(Deck o1, Deck o2) { + double delta = getDraftValue(o1) - getDraftValue(o2); + if ( delta > 0 ) return 1; + if ( delta < 0 ) return -1; + return 0; + } + } }