From 66e52cbd6ab3b8c0f2a95d2b5a67412c7c00b37c Mon Sep 17 00:00:00 2001 From: NikolayHD Date: Wed, 29 Aug 2018 01:13:43 +0300 Subject: [PATCH] Support Import, Open, New deck, Save As in all deck editors with finite catalog --- forge-core/src/main/java/forge/deck/Deck.java | 17 +- .../src/main/java/forge/deck/DeckBase.java | 13 +- .../src/main/java/forge/deck/DeckGroup.java | 102 +----------- .../src/main/java/forge/deck/DeckSection.java | 4 +- .../screens/deckeditor/CDeckEditorUI.java | 2 +- .../forge/screens/deckeditor/DeckImport.java | 16 +- .../deckeditor/controllers/ACEditorBase.java | 16 +- .../deckeditor/controllers/CCurrentDeck.java | 19 +-- .../deckeditor/controllers/CDeckEditor.java | 52 +++++++ .../controllers/CEditorCommander.java | 7 +- .../controllers/CEditorConstructed.java | 7 +- .../controllers/CEditorLimited.java | 30 ++-- .../deckeditor/controllers/CEditorQuest.java | 16 +- .../controllers/CEditorQuestLimited.java | 21 ++- .../controllers/CEditorVariant.java | 7 +- .../controllers/DeckController.java | 146 +++++++++++++++++- .../src/forge/deck/FDeckEditor.java | 13 +- .../java/forge/limited/CustomLimited.java | 32 ++-- 18 files changed, 300 insertions(+), 220 deletions(-) create mode 100644 forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CDeckEditor.java diff --git a/forge-core/src/main/java/forge/deck/Deck.java b/forge-core/src/main/java/forge/deck/Deck.java index 6f0be2bbd95..cd36aebfcb4 100644 --- a/forge-core/src/main/java/forge/deck/Deck.java +++ b/forge-core/src/main/java/forge/deck/Deck.java @@ -24,6 +24,7 @@ import forge.StaticData; import forge.card.CardDb; import forge.item.IPaperCard; import forge.item.PaperCard; +import forge.util.ItemPool; import java.util.*; import java.util.Map.Entry; @@ -291,17 +292,13 @@ public class Deck extends DeckBase implements Iterable. */ package forge.deck; import forge.item.InventoryItem; - import java.io.Serializable; - public abstract class DeckBase implements Serializable, Comparable, InventoryItem { private static final long serialVersionUID = -7538150536939660052L; // gameType is from Constant.GameType, like GameType.Regular @@ -59,7 +57,7 @@ public abstract class DeckBase implements Serializable, Comparable, In /* * (non-Javadoc) - * + * * @see java.lang.Object#hashCode() */ @Override @@ -74,6 +72,7 @@ public abstract class DeckBase implements Serializable, Comparable, In public String getDirectory() { return directory; } + public void setDirectory(String directory0) { directory = directory0; } @@ -101,7 +100,7 @@ public abstract class DeckBase implements Serializable, Comparable, In *

* getComment. *

- * + * * @return a {@link java.lang.String} object. */ public String getComment() { @@ -149,5 +148,5 @@ public abstract class DeckBase implements Serializable, Comparable, In public abstract boolean isEmpty(); - public abstract void importDeck(Deck deck); + public abstract Deck getHumanDeck(); } diff --git a/forge-core/src/main/java/forge/deck/DeckGroup.java b/forge-core/src/main/java/forge/deck/DeckGroup.java index 599449d69a2..1a48f019d25 100644 --- a/forge-core/src/main/java/forge/deck/DeckGroup.java +++ b/forge-core/src/main/java/forge/deck/DeckGroup.java @@ -18,9 +18,6 @@ package forge.deck; import com.google.common.base.Function; -import forge.StaticData; -import forge.item.PaperCard; - import java.util.*; /** @@ -47,7 +44,8 @@ public class DeckGroup extends DeckBase { * * @return the human deck */ - public final Deck getHumanDeck() { + @Override + public Deck getHumanDeck() { return humanDeck; } @@ -160,100 +158,4 @@ public class DeckGroup extends DeckBase { public String getImageKey(boolean altState) { return null; } - - - @Override - public void importDeck(Deck deck) { - CardPool draftedCards = this.getHumanDeck().getAllCardsInASinglePool(false); - - this.getHumanDeck().putSection(DeckSection.Main, new CardPool()); - this.getHumanDeck().putSection(DeckSection.Sideboard, new CardPool()); - - HashMap countByName = getCountByName(deck); - - addFromDraftedCardPool(countByName, draftedCards); - addBasicLands(deck, countByName, draftedCards); - } - - private HashMap getCountByName(Deck deck) { - HashMap result = new HashMap(); - - for (Map.Entry entry: deck.getMain()) { - PaperCard importedCard = entry.getKey(); - - Integer previousCount = result.getOrDefault(importedCard.getName(), 0); - int countToAdd = entry.getValue(); - - result.put(importedCard.getName(), countToAdd + previousCount); - } - - return result; - } - - private void addFromDraftedCardPool(HashMap countByName, CardPool availableCards) { - for (Map.Entry entry: availableCards) { - - PaperCard availableCard = entry.getKey(); - Integer availableCount = entry.getValue(); - int countToAdd = countByName.getOrDefault(availableCard.getName(), 0); - - if (availableCard.getRules().getType().isBasicLand()) { - // basic lands are added regardless from drafted cards - continue; - } - - int countMain = Math.min(availableCount, countToAdd); - - if (countMain > 0) { - this.getHumanDeck().getMain().add(availableCard, countMain); - countByName.put(availableCard.getName(), countToAdd - countMain); - } - - int countSideboard = availableCount - countMain; - - if (countSideboard > 0) { - CardPool sideboard = this.getHumanDeck().getOrCreate(DeckSection.Sideboard); - sideboard.add(availableCard, countSideboard); - } - } - } - - private void addBasicLands(Deck deck, HashMap countByName, CardPool availableCards) { - HashMap basicLandsByName = getBasicLandsByName(deck, countByName); - - Date dateWithAllCards = StaticData.instance().getEditions().getEarliestDateWithAllCards(availableCards); - for (String cardName: countByName.keySet()) { - - PaperCard card = basicLandsByName.getOrDefault(cardName, null); - - if (card == null) { - continue; - } - - int countToAdd = countByName.get(cardName); - - card = StaticData.instance().getCardByEditionDate(card, dateWithAllCards); - this.getHumanDeck().getMain().add(card.getName(), card.getEdition(), countToAdd); - } - } - - private HashMap getBasicLandsByName(Deck deck, HashMap countByName) { - HashMap result = new HashMap(); - - for (Map.Entry entry: deck.getMain()) { - PaperCard card = entry.getKey(); - - if (!card.getRules().getType().isBasicLand()) { - continue; - } - - if (result.containsKey(card.getName())) { - continue; - } - - result.put(card.getName(), card); - } - - return result; - } } diff --git a/forge-core/src/main/java/forge/deck/DeckSection.java b/forge-core/src/main/java/forge/deck/DeckSection.java index 7974d1e1677..90d2b91d17e 100644 --- a/forge-core/src/main/java/forge/deck/DeckSection.java +++ b/forge-core/src/main/java/forge/deck/DeckSection.java @@ -21,9 +21,9 @@ public enum DeckSection { return null; } - final String valToCompate = value.trim(); + final String valToCompare = value.trim(); for (final DeckSection v : DeckSection.values()) { - if (v.name().compareToIgnoreCase(valToCompate) == 0) { + if (v.name().compareToIgnoreCase(valToCompare) == 0) { return v; } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/CDeckEditorUI.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/CDeckEditorUI.java index a2808b8af7a..5d2e6db4421 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/CDeckEditorUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/CDeckEditorUI.java @@ -303,7 +303,7 @@ public enum CDeckEditorUI implements ICDoc { final DeckProxy deck = vAllDecks.getLstDecks().stringToItem(currentDeckStr); if (deck != null) { vAllDecks.getLstDecks().setSelectedItem(deck); - childController.getDeckController().load(deck.getPath(), deck.getName()); + getCurrentEditorController().getDeckController().load(deck.getPath(), deck.getName()); } } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java index bef0304d2f6..d82b0652b1c 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java @@ -20,20 +20,16 @@ package forge.screens.deckeditor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; -import java.util.List; +import java.util.*; import javax.swing.BorderFactory; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -import forge.deck.Deck; -import forge.deck.DeckBase; -import forge.deck.DeckImportController; -import forge.deck.DeckRecognizer; +import forge.deck.*; import forge.deck.DeckRecognizer.TokenType; import forge.item.InventoryItem; import forge.screens.deckeditor.controllers.ACEditorBase; -import forge.screens.deckeditor.controllers.DeckController; import forge.toolbox.FButton; import forge.toolbox.FCheckBox; import forge.toolbox.FComboBox; @@ -148,12 +144,7 @@ public class DeckImport ex final Deck deck = controller.accept(); if (deck == null) { return; } - DeckController controller = DeckImport.this.host.getDeckController(); - TModel model = controller.getModel(); - - model.importDeck(deck); - controller.setModel(model); - + DeckImport.this.host.getDeckController().loadDeck(deck); DeckImport.this.processWindowEvent(new WindowEvent(DeckImport.this, WindowEvent.WINDOW_CLOSING)); } }); @@ -173,6 +164,7 @@ public class DeckImport ex parseAndDisplay(); } }; + this.newEditionCheck.addActionListener(reparse); this.onlyCoreExpCheck.addActionListener(reparse); this.yearDropdown.addActionListener(reparse); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java index 8e54b6a07e3..14ea6d1de34 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/ACEditorBase.java @@ -49,7 +49,6 @@ import javax.swing.*; import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import java.util.Arrays; import java.util.List; import java.util.Map.Entry; @@ -186,14 +185,7 @@ public abstract class ACEditorBase controller = getDeckController(); - Deck deck = null; - if (controller != null) { - if (controller.getModel() instanceof Deck) { - deck = (Deck)controller.getModel(); // constructed deck - } else if (controller.getModel() instanceof DeckGroup) { - deck = ((DeckGroup)controller.getModel()).getHumanDeck(); // limited deck - } - } + Deck deck = getHumanDeck(); Iterable> cardsByName = null; if (deck != null) { @@ -248,6 +240,7 @@ public abstract class ACEditorBase> items, boolean toAlternate); protected abstract void buildAddContextMenu(EditorContextMenuBuilder cmb); + protected abstract void buildRemoveContextMenu(EditorContextMenuBuilder cmb); /** @@ -262,6 +255,10 @@ public abstract class ACEditorBase getDeckController(); + protected Deck getHumanDeck() { + return getDeckController().getModel().getHumanDeck(); + } + /** * Called when switching away from or closing the editor wants to exit. Should confirm save options. * @@ -598,5 +595,4 @@ public abstract class ACEditorBase
(C at beginning of class name denotes a control class.) - * */ public enum CCurrentDeck implements ICDoc { SINGLETON_INSTANCE; @@ -142,7 +141,7 @@ public enum CCurrentDeck implements ICDoc { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - ((DeckController) CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckController()).newModel(); + CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckController().loadDeck(new Deck()); VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().requestFocusInWindow(); } }); @@ -161,9 +160,9 @@ public enum CCurrentDeck implements ICDoc { if (file != null) { try { - ((DeckController) CDeckEditorUI.SINGLETON_INSTANCE - .getCurrentEditorController().getDeckController()) - .setModel(DeckSerializer.fromFile(file)); + CDeckEditorUI.SINGLETON_INSTANCE + .getCurrentEditorController().getDeckController() + .loadDeck(DeckSerializer.fromFile(file)); } catch (final Exception ex) { //BugReporter.reportException(ex); @@ -193,8 +192,8 @@ public enum CCurrentDeck implements ICDoc { /** */ @SuppressWarnings("unchecked") private void exportDeck() { - final DeckController controller = (DeckController) - CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckController(); + final DeckController controller = + CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckController(); final File filename = this.getExportFilename(); if (filename == null) { @@ -204,11 +203,13 @@ public enum CCurrentDeck implements ICDoc { //create copy of deck to save under new name String name = filename.getName(); name = name.substring(0, name.lastIndexOf(".")); //remove extension - final Deck deck = (Deck)controller.getModel().copyTo(name); + Deck deck = (Deck) controller.getModel().getHumanDeck().copyTo(name); try { DeckSerializer.writeDeck(deck, filename); - controller.setModel(DeckSerializer.fromFile(filename)); //reload deck from file so everything is in sync + final Deck deserialized = DeckSerializer.fromFile(filename); + //reload deck from file so everything is in sync + CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController().getDeckController().loadDeck(deserialized); } catch (final Exception ex) { //BugReporter.reportException(ex); throw new RuntimeException("Error exporting deck." + ex); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CDeckEditor.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CDeckEditor.java new file mode 100644 index 00000000000..60cc606fb33 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CDeckEditor.java @@ -0,0 +1,52 @@ +package forge.screens.deckeditor.controllers; + +import forge.deck.*; +import forge.gui.framework.FScreen; +import forge.item.PaperCard; +import forge.screens.match.controllers.CDetailPicture; + +import java.util.*; + +public abstract class CDeckEditor extends ACEditorBase { + + protected CDeckEditor(FScreen screen0, CDetailPicture cDetailPicture) { + super(screen0, cDetailPicture); + } + + /** + * While user edits the deck, the catalog content changes. + * In order to keep deck loading logic simple we need an initial card pool state to pick cards from. + * + * The method should only be used when the catalog is non infinite. + */ + protected CardPool getInitialCatalog() { + if (getCatalogManager().isInfinite()) { + throw new UnsupportedOperationException("Currently used catalog is infinite"); + } + + CardPool result = new CardPool(); + result.addAll(getCatalogManager().getPool()); + + for (DeckSection section: EnumSet.allOf(DeckSection.class)) { + if (isSectionPickableFromCatalog(section)) { + result.addAll(getHumanDeck().getOrCreate(section)); + } + } + + return result; + } + + protected Boolean isSectionImportable(DeckSection section) { + return section == DeckSection.Main; + } + + /** + * Can user pick a card from the catalog into specific section + * + * The returned value is only used when the catalog is non infinite. + * When it is infinite, the implementation may safely return null. + */ + protected Boolean isSectionPickableFromCatalog(DeckSection section) { + return isSectionImportable(section); + } +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorCommander.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorCommander.java index 5c2020eef3c..b769d07efb4 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorCommander.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorCommander.java @@ -51,7 +51,7 @@ import java.util.Map.Entry; * @author Forge * @version $Id: CEditorCommander.java 18430 2012-11-27 22:42:36Z Hellfish $ */ -public final class CEditorCommander extends ACEditorBase { +public final class CEditorCommander extends CDeckEditor { private final DeckController controller; private DragCell allDecksParent = null; private DragCell deckGenParent = null; @@ -164,6 +164,11 @@ public final class CEditorCommander extends ACEditorBase { this.getDeckManager().setPool(this.controller.getModel().getOrCreate(DeckSection.Main)); } + @Override + protected Boolean isSectionImportable(DeckSection section) { + return allSections.contains(section); + } + /* * (non-Javadoc) * diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java index 319cb3fc0b1..30a840212f1 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorConstructed.java @@ -49,7 +49,7 @@ import java.util.Map.Entry; * @author Forge * @version $Id: CEditorConstructed.java 24868 2014-02-17 05:08:05Z drdev $ */ -public final class CEditorConstructed extends ACEditorBase { +public final class CEditorConstructed extends CDeckEditor { private final DeckController controller; private final List allSections = new ArrayList(); private final ItemPool normalPool, avatarPool, planePool, schemePool, conspiracyPool; @@ -278,6 +278,11 @@ public final class CEditorConstructed extends ACEditorBase { this.getDeckManager().setPool(this.controller.getModel().getMain()); } + @Override + protected Boolean isSectionImportable(DeckSection section) { + return allSections.contains(section); + } + /* * (non-Javadoc) * diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorLimited.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorLimited.java index 48af02325b1..0628856de52 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorLimited.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorLimited.java @@ -40,11 +40,8 @@ import forge.screens.home.sanctioned.CSubmenuSealed; import forge.screens.match.controllers.CDetailPicture; import forge.util.storage.IStorage; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; /** * Child controller for limited deck editor UI. @@ -54,7 +51,7 @@ import java.util.Set; * @author Forge * @version $Id: DeckEditorCommon.java 12850 2011-12-26 14:55:09Z slapshot5 $ */ -public final class CEditorLimited extends ACEditorBase { +public final class CEditorLimited extends CDeckEditor { private final DeckController controller; private DragCell allDecksParent = null; @@ -109,10 +106,6 @@ public final class CEditorLimited extends ACEditorBase { }); } - private Deck getSelectedDeck() { - return controller.getModel().getHumanDeck(); - } - //========== Overridden from ACEditorBase @Override @@ -163,9 +156,13 @@ public final class CEditorLimited extends ACEditorBase { */ @Override public void resetTables() { - final Deck toEdit = this.getSelectedDeck(); - this.getCatalogManager().setPool(toEdit.getOrCreate(DeckSection.Sideboard)); - this.getDeckManager().setPool(toEdit.getMain()); + this.getCatalogManager().setPool(getHumanDeck().getOrCreate(DeckSection.Sideboard)); + this.getDeckManager().setPool(getHumanDeck().getMain()); + } + + @Override + protected Boolean isSectionImportable(DeckSection section) { + return section != DeckSection.Sideboard && allSections.contains(section); } /* @@ -179,7 +176,7 @@ public final class CEditorLimited extends ACEditorBase { } public static void addBasicLands(ACEditorBase editor) { - Deck deck = editor.getDeckController().getModel().getHumanDeck(); + Deck deck = editor.getHumanDeck(); if (deck == null) { return; } Set availableEditionCodes = new HashSet<>(); @@ -204,11 +201,11 @@ public final class CEditorLimited extends ACEditorBase { switch(sectionMode) { case Conspiracy: this.getCatalogManager().setup(ItemManagerConfig.DRAFT_CONSPIRACY); - this.getDeckManager().setPool(this.getSelectedDeck().getOrCreate(DeckSection.Conspiracy)); + this.getDeckManager().setPool(getHumanDeck().getOrCreate(DeckSection.Conspiracy)); break; case Main: this.getCatalogManager().setup(getScreen() == FScreen.DECK_EDITOR_DRAFT ? ItemManagerConfig.DRAFT_POOL : ItemManagerConfig.SEALED_POOL); - this.getDeckManager().setPool(this.getSelectedDeck().getOrCreate(DeckSection.Main)); + this.getDeckManager().setPool(getHumanDeck().getOrCreate(DeckSection.Main)); break; default: break; @@ -228,9 +225,6 @@ public final class CEditorLimited extends ACEditorBase { resetUI(); VCurrentDeck.SINGLETON_INSTANCE.getBtnPrintProxies().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnSaveAs().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnNew().setVisible(false); - VCurrentDeck.SINGLETON_INSTANCE.getBtnOpen().setVisible(false); VCurrentDeck.SINGLETON_INSTANCE.getTxfTitle().setEnabled(false); this.getBtnCycleSection().setVisible(true); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuest.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuest.java index 3c126ff3461..d54b9de65e9 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuest.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuest.java @@ -61,7 +61,7 @@ import java.util.Map.Entry; * @author Forge * @version $Id: CEditorQuest.java 24868 2014-02-17 05:08:05Z drdev $ */ -public final class CEditorQuest extends ACEditorBase { +public final class CEditorQuest extends CDeckEditor { private final QuestController questData; private final DeckController controller; private final List allSections = new ArrayList(); @@ -244,8 +244,7 @@ public final class CEditorQuest extends ACEditorBase { final Deck deck = this.controller.getModel(); - final ItemPool cardpool = new ItemPool(PaperCard.class); - cardpool.addAll(this.questData.getCards().getCardpool()); + final CardPool cardpool = getInitialCatalog(); // remove bottom cards that are in the deck from the card pool cardpool.removeAll(deck.getMain()); // remove sideboard cards from the catalog @@ -255,6 +254,16 @@ public final class CEditorQuest extends ACEditorBase { this.getDeckManager().setPool(deck.getMain()); } + @Override + protected CardPool getInitialCatalog() { + return new CardPool(this.questData.getCards().getCardpool()); + } + + @Override + protected Boolean isSectionImportable(DeckSection section) { + return allSections.contains(section); + } + //=========== Overridden from ACEditorBase /* @@ -306,7 +315,6 @@ public final class CEditorQuest extends ACEditorBase { resetUI(); VCurrentDeck.SINGLETON_INSTANCE.getBtnSave().setVisible(true); - VCurrentDeck.SINGLETON_INSTANCE.getBtnImport().setVisible(false); this.getBtnCycleSection().setVisible(true); this.getBtnCycleSection().setCommand(new UiCommand() { diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java index 33e25f87d38..1a819e64dbe 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestLimited.java @@ -20,6 +20,7 @@ package forge.screens.deckeditor.controllers; import com.google.common.base.Function; import com.google.common.base.Supplier; import forge.UiCommand; +import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckGroup; import forge.deck.DeckSection; @@ -58,7 +59,7 @@ import java.util.Map.Entry; * @author Forge * @version $Id: CEditorQuest.java 24868 2014-02-17 05:08:05Z drdev $ */ -public final class CEditorQuestLimited extends ACEditorBase { +public final class CEditorQuestLimited extends CDeckEditor { private final QuestController questData; private final DeckController controller; private final List allSections = new ArrayList(); @@ -198,10 +199,6 @@ public final class CEditorQuestLimited extends ACEditorBase { +public final class CEditorVariant extends CDeckEditor { private final DeckController controller; private DragCell allDecksParent = null; private DragCell deckGenParent = null; @@ -153,6 +153,11 @@ public final class CEditorVariant extends ACEditorBase { this.getDeckManager().setPool(this.controller.getModel().getOrCreate(this.sectionMode)); } + @Override + protected Boolean isSectionImportable(DeckSection section) { + return true; + } + /* * (non-Javadoc) * diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java index b5036d256aa..af35f26d89a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/DeckController.java @@ -17,12 +17,14 @@ */ package forge.screens.deckeditor.controllers; +import forge.StaticData; +import forge.deck.*; +import forge.item.PaperCard; +import forge.util.ItemPool; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Supplier; -import forge.deck.DeckBase; -import forge.deck.DeckProxy; import forge.screens.deckeditor.menus.DeckFileMenu; import forge.screens.deckeditor.views.VCurrentDeck; import forge.screens.home.gauntlet.VSubmenuGauntletBuild; @@ -31,6 +33,11 @@ import forge.screens.home.gauntlet.VSubmenuGauntletQuick; import forge.screens.home.sanctioned.VSubmenuConstructed; import forge.util.storage.IStorage; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + public class DeckController { private T model; private boolean saved; @@ -38,7 +45,7 @@ public class DeckController { private final IStorage rootFolder; private IStorage currentFolder; private String modelPath; - private final ACEditorBase view; + private final CDeckEditor view; private final Supplier newModelCreator; /** @@ -48,7 +55,7 @@ public class DeckController { * @param view0 the view0 * @param newModelCreator0 the new model creator0 */ - public DeckController(final IStorage folder0, final ACEditorBase view0, final Supplier newModelCreator0) { + public DeckController(final IStorage folder0, final CDeckEditor view0, final Supplier newModelCreator0) { rootFolder = folder0; currentFolder = rootFolder; view = view0; @@ -76,6 +83,128 @@ public class DeckController { return model == null || model.isEmpty(); } + /** + * Load deck from file or clipboard + */ + public void loadDeck(Deck deck) { + + if (!view.getCatalogManager().isInfinite()) { + CardPool catalogClone = new CardPool(view.getInitialCatalog()); + deck = pickFromCatalog(deck, catalogClone); + ItemPool catalogPool = view.getCatalogManager().getPool(); + catalogPool.clear(); + catalogPool.addAll(catalogClone); + } + + for (DeckSection section: EnumSet.allOf(DeckSection.class)) { + if (view.isSectionImportable(section)) { + CardPool sectionCards = view.getHumanDeck().getOrCreate(section); + sectionCards.clear(); + sectionCards.addAll(deck.getOrCreate(section)); + } + } + + onModelChanged(false); + } + + private Deck pickFromCatalog(Deck deck, CardPool catalog) { + Date dateWithAllCards = StaticData.instance().getEditions().getEarliestDateWithAllCards(catalog); + Deck result = new Deck(); + for (DeckSection section: EnumSet.allOf(DeckSection.class)) { + if (view.isSectionImportable(section)) { + CardPool cards = pickSectionFromCatalog(catalog, deck.getOrCreate(section), dateWithAllCards); + result.putSection(section, cards); + } + } + + return result; + } + + private CardPool pickSectionFromCatalog(CardPool catalog, CardPool sourceSection, Date dateWithAllCards) { + HashMap countByName = groupByName(sourceSection); + HashMap basicLandsByName = getBasicLandsByName(sourceSection); + + CardPool targetSection = new CardPool(); + pickFromCatalog(countByName, catalog, targetSection); + importBasicLands(countByName, basicLandsByName, dateWithAllCards, targetSection); + + return targetSection; + } + + private HashMap groupByName(CardPool section) { + HashMap result = new HashMap(); + + for (Map.Entry entry : section) { + PaperCard importedCard = entry.getKey(); + + Integer previousCount = result.getOrDefault(importedCard.getName(), 0); + int countToAdd = entry.getValue(); + + result.put(importedCard.getName(), countToAdd + previousCount); + } + + return result; + } + + private void pickFromCatalog(HashMap countByName, CardPool catalog, CardPool targetSection) { + + CardPool catalogClone = new CardPool(catalog); // clone to iterate modified collection + for (Map.Entry entry : catalogClone) { + + PaperCard availableCard = entry.getKey(); + if (availableCard.getRules().getType().isBasicLand()) { + // basic lands are added regardless of catalog cards + continue; + } + + Integer availableCount = entry.getValue(); + int toAddByName = countByName.getOrDefault(availableCard.getName(), 0); + int toAdd = Math.min(availableCount, toAddByName); + + if (toAdd > 0) { + targetSection.add(availableCard, toAdd); + countByName.put(availableCard.getName(), toAddByName - toAdd); + catalog.remove(availableCard, toAdd); + } + } + } + + private void importBasicLands(HashMap countByName, HashMap basicLandsByName, Date dateWithAllCards, CardPool targetSection) { + for (String cardName : countByName.keySet()) { + + PaperCard card = basicLandsByName.getOrDefault(cardName, null); + + if (card == null) { + continue; + } + + int countToAdd = countByName.get(cardName); + + card = StaticData.instance().getCardByEditionDate(card, dateWithAllCards); + targetSection.add(card.getName(), card.getEdition(), countToAdd); + } + } + + private HashMap getBasicLandsByName(CardPool sourceSection) { + HashMap result = new HashMap(); + + for (Map.Entry entry : sourceSection) { + PaperCard card = entry.getKey(); + + if (!card.getRules().getType().isBasicLand()) { + continue; + } + + if (result.containsKey(card.getName())) { + continue; + } + + result.put(card.getName(), card); + } + + return result; + } + /** * Sets the model. * @@ -83,9 +212,14 @@ public class DeckController { public void setModel(final T document) { setModel(document, false); } - public void setModel(final T document, final boolean isStored) { - modelInStorage = isStored; + + private void setModel(final T document, final boolean isStored) { model = document; + onModelChanged(isStored); + } + + private void onModelChanged(boolean isStored) { + modelInStorage = isStored; view.resetTables(); CStatistics.SINGLETON_INSTANCE.update(); diff --git a/forge-gui-mobile/src/forge/deck/FDeckEditor.java b/forge-gui-mobile/src/forge/deck/FDeckEditor.java index 607d697e53c..95e9ebb0da1 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckEditor.java +++ b/forge-gui-mobile/src/forge/deck/FDeckEditor.java @@ -1490,15 +1490,6 @@ public class FDeckEditor extends TabPageScreen { modelPath = ""; } - public Deck getDeck() { - if (model == null) { return null; } - - if (model instanceof Deck) { - return (Deck) model; - } - return ((DeckGroup) model).getHumanDeck(); - } - public T getModel() { return model; } @@ -1537,7 +1528,7 @@ public class FDeckEditor extends TabPageScreen { modelPath = ""; setSaved(true); } - editor.setDeck(getDeck()); + editor.setDeck(model.getHumanDeck()); } private boolean isModelInSyncWithFolder() { @@ -1661,7 +1652,7 @@ public class FDeckEditor extends TabPageScreen { default: break; } - editor.setDeck(getDeck()); + editor.setDeck(model.getHumanDeck()); if (editor.saveHandler != null) { editor.saveHandler.handleEvent(new FEvent(editor, FEventType.SAVE)); } diff --git a/forge-gui/src/main/java/forge/limited/CustomLimited.java b/forge-gui/src/main/java/forge/limited/CustomLimited.java index 5cecbfc5fd1..2fa28091406 100644 --- a/forge-gui/src/main/java/forge/limited/CustomLimited.java +++ b/forge-gui/src/main/java/forge/limited/CustomLimited.java @@ -18,8 +18,10 @@ package forge.limited; import forge.card.CardEdition; +import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckBase; +import forge.deck.DeckSection; import forge.item.PaperCard; import forge.item.SealedProduct; import forge.model.FModel; @@ -45,12 +47,12 @@ import java.util.List; */ public class CustomLimited extends DeckBase { private final SealedProduct.Template tpl; - + /** * TODO: Write javadoc for Constructor. * * @param name0 the name0 - * @param slots + * @param slots */ public CustomLimited(final String name0, List> slots) { super(name0); @@ -67,7 +69,7 @@ public class CustomLimited extends DeckBase { /** The Land set code. */ private String landSetCode = CardEdition.Predicates.getRandomSetWithAllBasicLands(FModel.getMagicDb().getEditions()).getCode(); - private boolean singleton; + private boolean singleton; /** Name of the file containing custom card rankings. */ private String customRankingsFile = ""; @@ -82,27 +84,27 @@ public class CustomLimited extends DeckBase { public String toString() { return this.getName(); } - + @Override public String getItemType() { return "Limited deck"; - } + } /** * Parses the. * * @param dfData the df data - * @param cubes the cubes + * @param cubes the cubes * @return the custom limited */ public static CustomLimited parse(final List dfData, final IStorage cubes) { final FileSection data = FileSection.parse(dfData, ":"); - List> slots = new ArrayList>(); + List> slots = new ArrayList>(); String boosterData = data.get("Booster"); - if(StringUtils.isNotEmpty(boosterData)){ + if (StringUtils.isNotEmpty(boosterData)) { final String[] booster = TextUtil.splitWithParenthesis(boosterData, ','); - for(String slotDesc : booster) { + for (String slotDesc : booster) { String[] kv = TextUtil.splitWithParenthesis(slotDesc, ' ', 2); slots.add(ImmutablePair.of(kv[1], Integer.parseInt(kv[0]))); } @@ -188,13 +190,13 @@ public class CustomLimited extends DeckBase { return cardPool.isEmpty(); } - @Override - public void importDeck(Deck deck) { - throw new UnsupportedOperationException("CustomDraft does not support deck import"); - } - @Override public String getImageKey(boolean altState) { return null; } -} + + @Override + public Deck getHumanDeck() { + return null; + } +} \ No newline at end of file