From d003cd898fb2aeda7f87277e71fdf2a5426e1ea8 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 4 Sep 2017 07:57:10 +0200 Subject: [PATCH] Image download by set with source restriction to supported sets. --- .../card/dl/sources/CardImageSource.java | 18 ++ .../dl/sources/MythicspoilerComSource.java | 37 ++- .../dl/sources/WizardCardsImageSource.java | 273 +++++++++++++++-- .../plugins/card/images/DownloadPictures.java | 286 +++++++++++------- .../target/maven-archiver/pom.properties | 10 +- 5 files changed, 488 insertions(+), 136 deletions(-) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java index 0f25bba72c1..f76aeb953da 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/CardImageSource.java @@ -1,5 +1,6 @@ package org.mage.plugins.card.dl.sources; +import java.util.ArrayList; import org.mage.plugins.card.images.CardDownloadData; /** @@ -9,12 +10,29 @@ import org.mage.plugins.card.images.CardDownloadData; public interface CardImageSource { String generateURL(CardDownloadData card) throws Exception; + String generateTokenUrl(CardDownloadData card) throws Exception; + String getNextHttpImageUrl(); + String getFileForHttpImage(String httpImageUrl); + String getSourceName(); + float getAverageSize(); + int getTotalImages(); + boolean isTokenSource(); + void doPause(String httpImageUrl); + + default ArrayList getSupportedSets() { + return null; + } + + default boolean providesTokenImages() { + return false; + } +; } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java index 8368c76c45d..d8ceaf19f26 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/MythicspoilerComSource.java @@ -35,9 +35,11 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.prefs.Preferences; @@ -57,10 +59,11 @@ import org.mage.plugins.card.images.CardDownloadData; public enum MythicspoilerComSource implements CardImageSource { instance; - private Map setsAliases; - private Map cardNameAliases; - private Map> cardNameAliasesStart; + private final Map setsAliases; + private final Map cardNameAliases; + private final Map> cardNameAliasesStart; private final Map> sets; + private final Set supportedSets; @Override public String getSourceName() { @@ -68,6 +71,26 @@ public enum MythicspoilerComSource implements CardImageSource { } MythicspoilerComSource() { + supportedSets = new LinkedHashSet<>(); + supportedSets.add("V16"); + supportedSets.add("CN2"); + supportedSets.add("DDR"); + supportedSets.add("KLD"); + supportedSets.add("MPS"); + supportedSets.add("PZ2"); + supportedSets.add("C16"); + supportedSets.add("PCA"); + supportedSets.add("AER"); + supportedSets.add("MM3"); + supportedSets.add("DDS"); + supportedSets.add("W17"); + supportedSets.add("AKH"); + supportedSets.add("MPS"); + supportedSets.add("CMA"); + supportedSets.add("E01"); + supportedSets.add("HOU"); + supportedSets.add("C17"); + sets = new LinkedHashMap<>(); setsAliases = new HashMap<>(); setsAliases.put("exp", "bfz"); @@ -243,4 +266,12 @@ public enum MythicspoilerComSource implements CardImageSource { @Override public void doPause(String httpImageUrl) { } + + @Override + public ArrayList getSupportedSets() { + ArrayList supportedSetsCopy = new ArrayList<>(); + supportedSetsCopy.addAll(supportedSets); + return supportedSetsCopy; + } + } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java index a42cc1633a6..4939fdcbe2f 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/WizardCardsImageSource.java @@ -34,10 +34,13 @@ import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; -import java.net.URLEncoder; +import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -46,6 +49,7 @@ import mage.client.MageFrame; import mage.client.dialog.PreferencesDialog; import mage.remote.Connection; import mage.remote.Connection.ProxyType; +import org.apache.log4j.Logger; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -58,10 +62,13 @@ import org.mage.plugins.card.images.CardDownloadData; public enum WizardCardsImageSource implements CardImageSource { instance; - private Map setsAliases; - private Map languageAliases; - private final Map> sets; + private static final Logger logger = Logger.getLogger(WizardCardsImageSource.class); + + private final Map setsAliases; + private final Map languageAliases; + private final Map> sets; + private final Set supportedSets; @Override public String getSourceName() { @@ -69,6 +76,197 @@ public enum WizardCardsImageSource implements CardImageSource { } WizardCardsImageSource() { + supportedSets = new LinkedHashSet<>(); + supportedSets.add("LEA"); + supportedSets.add("LEB"); + supportedSets.add("2ED"); + supportedSets.add("ARN"); + supportedSets.add("ATQ"); + supportedSets.add("3ED"); + supportedSets.add("LEG"); + supportedSets.add("DRK"); + supportedSets.add("FEM"); + supportedSets.add("4ED"); + supportedSets.add("ICE"); + supportedSets.add("CHR"); + supportedSets.add("HML"); + supportedSets.add("ALL"); + supportedSets.add("MIR"); + supportedSets.add("VIS"); + supportedSets.add("5ED"); + supportedSets.add("POR"); + supportedSets.add("WTH"); + supportedSets.add("TMP"); + supportedSets.add("STH"); + supportedSets.add("EXO"); + supportedSets.add("P02"); + supportedSets.add("UGL"); + supportedSets.add("USG"); + supportedSets.add("DD3DVD"); + supportedSets.add("DD3EVG"); + supportedSets.add("DD3GVL"); + supportedSets.add("DD3JVC"); + + supportedSets.add("ULG"); + supportedSets.add("6ED"); + supportedSets.add("UDS"); + supportedSets.add("PTK"); + supportedSets.add("S99"); + supportedSets.add("MMQ"); + // supportedSets.add("BRB");Battle Royale Box Set + supportedSets.add("NEM"); + supportedSets.add("S00"); + supportedSets.add("PCY"); + supportedSets.add("INV"); + // supportedSets.add("BTD"); // Beatdown Boxset + supportedSets.add("PLS"); + supportedSets.add("7ED"); + supportedSets.add("APC"); + supportedSets.add("ODY"); + // supportedSets.add("DKM"); // Deckmasters 2001 + supportedSets.add("TOR"); + supportedSets.add("JUD"); + supportedSets.add("ONS"); + supportedSets.add("LGN"); + supportedSets.add("SCG"); + supportedSets.add("8ED"); + supportedSets.add("MRD"); + supportedSets.add("DST"); + supportedSets.add("5DN"); + supportedSets.add("CHK"); + supportedSets.add("UNH"); + supportedSets.add("BOK"); + supportedSets.add("SOK"); + supportedSets.add("9ED"); + supportedSets.add("RAV"); + supportedSets.add("GPT"); + supportedSets.add("DIS"); + supportedSets.add("CSP"); + supportedSets.add("TSP"); + supportedSets.add("TSB"); + supportedSets.add("PLC"); + supportedSets.add("FUT"); + supportedSets.add("10E"); + supportedSets.add("MED"); + supportedSets.add("LRW"); + supportedSets.add("EVG"); + supportedSets.add("MOR"); + supportedSets.add("SHM"); + supportedSets.add("EVE"); + supportedSets.add("DRB"); + supportedSets.add("ME2"); + supportedSets.add("ALA"); + supportedSets.add("DD2"); + supportedSets.add("CON"); + supportedSets.add("DDC"); + supportedSets.add("ARB"); + supportedSets.add("M10"); + // supportedSets.add("TD0"); // Magic Online Deck Series + supportedSets.add("V09"); + supportedSets.add("HOP"); + supportedSets.add("ME3"); + supportedSets.add("ZEN"); + supportedSets.add("DDD"); + supportedSets.add("H09"); + supportedSets.add("WWK"); + supportedSets.add("DDE"); + supportedSets.add("ROE"); + supportedSets.add("DPA"); + supportedSets.add("ARC"); + supportedSets.add("M11"); + supportedSets.add("V10"); + supportedSets.add("DDF"); + supportedSets.add("SOM"); + // supportedSets.add("TD0"); // Commander Theme Decks + supportedSets.add("PD2"); + supportedSets.add("ME4"); + supportedSets.add("MBS"); + supportedSets.add("DDG"); + supportedSets.add("NPH"); + supportedSets.add("CMD"); + supportedSets.add("M12"); + supportedSets.add("V11"); + supportedSets.add("DDH"); + supportedSets.add("ISD"); + supportedSets.add("PD3"); + supportedSets.add("DKA"); + supportedSets.add("DDI"); + supportedSets.add("AVR"); + supportedSets.add("PC2"); + supportedSets.add("M13"); + supportedSets.add("V12"); + supportedSets.add("DDJ"); + supportedSets.add("RTR"); + supportedSets.add("CM1"); + // supportedSets.add("TD2"); // Duel Decks: Mirrodin Pure vs. New Phyrexia + supportedSets.add("GTC"); + supportedSets.add("DDK"); + supportedSets.add("DGM"); + supportedSets.add("MMA"); + supportedSets.add("M14"); + supportedSets.add("V13"); + supportedSets.add("DDL"); + supportedSets.add("THS"); + supportedSets.add("C13"); + supportedSets.add("BNG"); + supportedSets.add("DDM"); + supportedSets.add("JOU"); + // supportedSets.add("MD1"); // Modern Event Deck + supportedSets.add("CNS"); + supportedSets.add("VMA"); + supportedSets.add("M15"); + supportedSets.add("V14"); + supportedSets.add("DDN"); + supportedSets.add("KTK"); + supportedSets.add("C14"); + // supportedSets.add("DD3"); // Duel Decks Anthology + supportedSets.add("FRF"); + supportedSets.add("DDO"); + supportedSets.add("DTK"); + supportedSets.add("TPR"); + supportedSets.add("MM2"); + supportedSets.add("ORI"); + supportedSets.add("V15"); + supportedSets.add("DDP"); + supportedSets.add("BFZ"); + supportedSets.add("EXP"); + supportedSets.add("C15"); + // supportedSets.add("PZ1"); // Legendary Cube + supportedSets.add("OGW"); + supportedSets.add("DDQ"); + supportedSets.add("W16"); + supportedSets.add("SOI"); + supportedSets.add("EMA"); + supportedSets.add("EMN"); + supportedSets.add("V16"); + supportedSets.add("CN2"); + supportedSets.add("DDR"); + supportedSets.add("KLD"); + supportedSets.add("MPS"); + // supportedSets.add("PZ2"); // Treasure Chests + supportedSets.add("C16"); + supportedSets.add("PCA"); + supportedSets.add("AER"); + supportedSets.add("MM3"); + supportedSets.add("DDS"); + supportedSets.add("W17"); + supportedSets.add("AKH"); + supportedSets.add("MPS"); + supportedSets.add("CMA"); + supportedSets.add("E01"); + supportedSets.add("HOU"); + supportedSets.add("C17"); +// supportedSets.add("XLN"); +// supportedSets.add("DDT"); +// supportedSets.add("IMA"); +// supportedSets.add("E02"); +// supportedSets.add("V17"); +// supportedSets.add("UST"); +// supportedSets.add("RIX"); +// supportedSets.add("A25"); +// supportedSets.add("DOM"); +// supportedSets.add("M19"); + sets = new HashMap<>(); setsAliases = new HashMap<>(); setsAliases.put("2ED", "Unlimited Edition"); @@ -102,6 +300,7 @@ public enum WizardCardsImageSource implements CardImageSource { setsAliases.put("C14", "Commander 2014"); setsAliases.put("C15", "Commander 2015"); setsAliases.put("C16", "Commander 2016"); + setsAliases.put("C17", "Commander 2017"); setsAliases.put("CMA", "Commander Anthology"); setsAliases.put("CHK", "Champions of Kamigawa"); setsAliases.put("CHR", "Chronicles"); @@ -140,6 +339,7 @@ public enum WizardCardsImageSource implements CardImageSource { setsAliases.put("DRK", "The Dark"); setsAliases.put("DST", "Darksteel"); setsAliases.put("DTK", "Dragons of Tarkir"); + setsAliases.put("E01", "Archenemy: Nicol Bolas"); setsAliases.put("EMN", "Eldritch Moon"); setsAliases.put("EMA", "Eternal Masters"); setsAliases.put("EVE", "Eventide"); @@ -272,18 +472,20 @@ public enum WizardCardsImageSource implements CardImageSource { } private Map getSetLinks(String cardSet) { - ConcurrentHashMap setLinks = new ConcurrentHashMap<>(); + LinkedHashMap setLinks = new LinkedHashMap<>(); ExecutorService executor = Executors.newFixedThreadPool(10); try { String setNames = setsAliases.get(cardSet); String preferedLanguage = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_PREF_LANGUAGE, "en"); for (String setName : setNames.split("\\^")) { - String URLSetName = URLEncoder.encode(setName, "UTF-8"); + // String URLSetName = URLEncoder.encode(setName, "UTF-8"); + String URLSetName = setName.replaceAll(" ", "%20"); int page = 0; int firstMultiverseIdLastPage = 0; Pages: while (page < 999) { - String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?page=" + page + "&output=spoiler&method=visual&action=advanced&set=+[%22" + URLSetName + "%22]"; + String searchUrl = "http://gatherer.wizards.com/Pages/Search/Default.aspx?sort=cn+&page=" + page + "&action=advanced&output=spoiler&method=visual&set=+%5B%22" + URLSetName + "%22%5D"; + logger.debug("URL: " + searchUrl); Document doc = getDocument(searchUrl); Elements cardsImages = doc.select("img[src^=../../Handlers/]"); if (cardsImages.isEmpty()) { @@ -307,7 +509,7 @@ public enum WizardCardsImageSource implements CardImageSource { } } } catch (IOException ex) { - System.out.println("Exception when parsing the wizards page: " + ex.getMessage()); + logger.error("Exception when parsing the wizards page: " + ex.getMessage()); } executor.shutdown(); @@ -327,14 +529,15 @@ public enum WizardCardsImageSource implements CardImageSource { Connection.ProxyType proxyType = Connection.ProxyType.valueByText(prefs.get("proxyType", "None")); Document doc; if (proxyType == ProxyType.NONE) { - doc = Jsoup.connect(urlString).get(); + doc = Jsoup.connect(urlString).timeout(60 * 1000).get(); } else { String proxyServer = prefs.get("proxyAddress", ""); int proxyPort = Integer.parseInt(prefs.get("proxyPort", "0")); URL url = new URL(urlString); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, proxyPort)); HttpURLConnection uc = (HttpURLConnection) url.openConnection(proxy); - + uc.setConnectTimeout(10000); + uc.setReadTimeout(60000); uc.connect(); String line; @@ -356,7 +559,7 @@ public enum WizardCardsImageSource implements CardImageSource { if (!variations.isEmpty()) { int landNumber = 1; for (Element variation : variations) { - Integer landMultiverseId = Integer.parseInt(variation.attr("onclick").replaceAll("[^\\d]", "")); + Integer landMultiverseId = Integer.parseInt(variation.attr("href").replaceAll("[^\\d]", "")); links.put((cardName + landNumber).toLowerCase(), generateLink(landMultiverseId)); landNumber++; } @@ -444,11 +647,11 @@ public enum WizardCardsImageSource implements CardImageSource { } int number = Integer.parseInt(collectorId.substring(0, length)); - - if (setLinks.size() >= number) { - link = setLinks.get(Integer.toString(number - 1)); - } else { - link = setLinks.get(Integer.toString(number - 21)); + List l = new ArrayList<>(setLinks.values()); + if (l.size() >= number) { + link = l.get(number - 1); + } else {; + link = l.get(number - 21); if (link != null) { link = link.replace(Integer.toString(number - 20), (Integer.toString(number - 20) + 'a')); } @@ -474,16 +677,24 @@ public enum WizardCardsImageSource implements CardImageSource { private final class GetImageLinkTask implements Runnable { - private final int multiverseId; - private final String cardName; - private final String preferedLanguage; - private final ConcurrentHashMap setLinks; + private int multiverseId; + private String cardName; + private String preferedLanguage; + private LinkedHashMap setLinks; - public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, ConcurrentHashMap setLinks) { - this.multiverseId = multiverseId; - this.cardName = cardName; - this.preferedLanguage = preferedLanguage; - this.setLinks = setLinks; + public GetImageLinkTask(int multiverseId, String cardName, String preferedLanguage, LinkedHashMap setLinks) { + try { + this.multiverseId = multiverseId; + this.cardName = cardName; + this.preferedLanguage = preferedLanguage; + this.setLinks = setLinks; + } catch (Exception ex) { + logger.error(ex.getMessage()); + logger.error("multiverseId: " + multiverseId); + logger.error("cardName: " + cardName); + logger.error("preferedLanguage: " + preferedLanguage); + logger.error("setLinks: " + setLinks.toString()); + } } @Override @@ -496,7 +707,7 @@ public enum WizardCardsImageSource implements CardImageSource { setLinks.put(cardName.toLowerCase(), generateLink(preferedMultiverseId)); } } catch (IOException | NumberFormatException ex) { - System.out.println("Exception when parsing the wizards page: " + ex.getMessage()); + logger.error("Exception when parsing the wizards page: " + ex.getMessage()); } } @@ -515,4 +726,12 @@ public enum WizardCardsImageSource implements CardImageSource { @Override public void doPause(String httpImageUrl) { } + + @Override + public ArrayList getSupportedSets() { + ArrayList supportedSetsCopy = new ArrayList<>(); + supportedSetsCopy.addAll(supportedSets); + return supportedSetsCopy; + } + } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java index 02e639ba193..c9b9a25d1b5 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/DownloadPictures.java @@ -21,11 +21,16 @@ import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.FileImageOutputStream; import javax.swing.*; +import mage.cards.ExpansionSet; +import mage.cards.Sets; import mage.cards.repository.CardInfo; import mage.client.constants.Constants; import mage.client.dialog.PreferencesDialog; import mage.client.util.sets.ConstructedFormats; import mage.remote.Connection; +import static mage.remote.Connection.ProxyType.HTTP; +import static mage.remote.Connection.ProxyType.NONE; +import static mage.remote.Connection.ProxyType.SOCKS; import net.java.truevfs.access.TFile; import net.java.truevfs.access.TFileOutputStream; import net.java.truevfs.access.TVFS; @@ -39,18 +44,31 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab private static final Logger logger = Logger.getLogger(DownloadPictures.class); + public static final String ALL_CARDS = "- All cards from that source"; + public static final String ALL_STANDARD_CARDS = "- All cards from standard from that source"; + public static final String ALL_TOKENS = "- All token images from that source"; + private final JProgressBar bar; private final JOptionPane dlg; private boolean cancel; private final JButton closeButton; private final JButton startDownloadButton; private int cardIndex; - private List cards; - private List type2cards; - private final JComboBox jComboBox1; - private final JLabel jLabel1; - private static boolean offlineMode = false; - private JCheckBox checkBox; + private List allCardsMissingImage; + List cardsToDownload = new ArrayList<>(); + + private int missingCards = 0; + private int missingTokens = 0; + + List selectedSetCodes = new ArrayList<>(); + + private final JComboBox jComboBoxServer; + private final JLabel jLabelAllMissing; + private final JLabel jLabelServer; + + private final JComboBox jComboBoxSet; + private final JLabel jLabelSet; + private final Object sync = new Object(); private static CardImageSource cardImageSource; @@ -90,7 +108,7 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } public DownloadPictures(List cards) { - this.cards = cards; + this.allCardsMissingImage = cards; bar = new JProgressBar(this); @@ -98,15 +116,21 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab p0.setLayout(new BoxLayout(p0, BoxLayout.Y_AXIS)); p0.add(Box.createVerticalStrut(5)); - jLabel1 = new JLabel(); - jLabel1.setText("Please select server:"); - jLabel1.setAlignmentX(Component.LEFT_ALIGNMENT); + jLabelAllMissing = new JLabel(); - p0.add(jLabel1); + jLabelAllMissing.setAlignmentX(Component.LEFT_ALIGNMENT); + p0.add(jLabelAllMissing); p0.add(Box.createVerticalStrut(5)); - ComboBoxModel jComboBox1Model = new DefaultComboBoxModel(new String[]{ - // "magiccards.info", + + jLabelServer = new JLabel(); + jLabelServer.setText("Please select server:"); + jLabelServer.setAlignmentX(Component.LEFT_ALIGNMENT); + p0.add(jLabelServer); + + p0.add(Box.createVerticalStrut(5)); + + ComboBoxModel jComboBoxDownloadSourcesModel = new DefaultComboBoxModel(new String[]{ "wizards.com", "mythicspoiler.com", "tokens.mtg.onl", //"mtgimage.com (HQ)", @@ -114,50 +138,45 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab "alternative.mtg.onl", "GrabBag", "magidex.com", - "scryfall.com", //"mtgathering.ru HQ", + "scryfall.com", + "magiccards.info" + //"mtgathering.ru HQ", //"mtgathering.ru MQ", //"mtgathering.ru LQ", }); - jComboBox1 = new JComboBox(); + jComboBoxServer = new JComboBox(); - cardImageSource = MagicCardsImageSource.instance; + cardImageSource = WizardCardsImageSource.instance; - jComboBox1.setModel(jComboBox1Model); - jComboBox1.setAlignmentX(Component.LEFT_ALIGNMENT); - jComboBox1.addActionListener(e -> { - JComboBox cb = (JComboBox) e.getSource(); - switch (cb.getSelectedIndex() + 1) { - case 0: - cardImageSource = MagicCardsImageSource.instance; - break; - case 1: - cardImageSource = WizardCardsImageSource.instance; - break; - case 2: - cardImageSource = MythicspoilerComSource.instance; - break; - case 3: - cardImageSource = TokensMtgImageSource.instance; - break; - case 4: - cardImageSource = MtgOnlTokensImageSource.instance; - break; - case 5: - cardImageSource = AltMtgOnlTokensImageSource.instance; - break; - case 6: - cardImageSource = GrabbagImageSource.instance; - break; - case 7: - cardImageSource = MagidexImageSource.instance; - break; - case 8: - cardImageSource = ScryfallImageSource.instance; - break; + jComboBoxServer.setModel(jComboBoxDownloadSourcesModel); + jComboBoxServer.setAlignmentX(Component.LEFT_ALIGNMENT); + jComboBoxServer.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboBoxServerActionPerformed(evt); } - updateCardsToDownload(); }); - p0.add(jComboBox1); + p0.add(jComboBoxServer); + + p0.add(Box.createVerticalStrut(5)); + + // Set selection --------------------------------- + jLabelSet = new JLabel(); + jLabelSet.setText("Please select sets to download images for:"); + jLabelSet.setAlignmentX(Component.LEFT_ALIGNMENT); + p0.add(jLabelSet); + + jComboBoxSet = new JComboBox(); + jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource())); + jComboBoxSet.setAlignmentX(Component.LEFT_ALIGNMENT); + jComboBoxSet.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboBoxSetActionPerformed(evt); + } + }); + p0.add(jComboBoxSet); + p0.add(Box.createVerticalStrut(5)); // Start @@ -165,31 +184,21 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab startDownloadButton.addActionListener(e -> { new Thread(DownloadPictures.this).start(); startDownloadButton.setEnabled(false); - checkBox.setEnabled(false); }); p0.add(Box.createVerticalStrut(5)); // Progress p0.add(bar); bar.setStringPainted(true); - int count = cards.size(); - float mb = (count * cardImageSource.getAverageSize()) / 1024; - bar.setString(String.format(cardIndex == cards.size() ? "%d of %d cards finished! Please close!" - : "%d of %d cards finished! Please wait! [%.1f Mb]", 0, cards.size(), mb)); Dimension d = bar.getPreferredSize(); d.width = 300; bar.setPreferredSize(d); - p0.add(Box.createVerticalStrut(5)); - checkBox = new JCheckBox("Download images for Standard (Type2) only"); - p0.add(checkBox); - p0.add(Box.createVerticalStrut(5)); - - checkBox.addActionListener(e -> updateCardsToDownload()); - // JOptionPane Object[] options = {startDownloadButton, closeButton = new JButton("Cancel")}; dlg = new JOptionPane(p0, JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, options, options[1]); + + updateCardsToDownload(); } public static boolean checkForMissingCardImages(List allCards) { @@ -209,31 +218,120 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab return missedCardTFiles.get(); } + private void comboBoxServerActionPerformed(java.awt.event.ActionEvent evt) { + JComboBox cb = (JComboBox) evt.getSource(); + switch (cb.getSelectedIndex()) { + case 0: + cardImageSource = WizardCardsImageSource.instance; + break; + case 1: + cardImageSource = MythicspoilerComSource.instance; + break; + case 2: + cardImageSource = TokensMtgImageSource.instance; + break; + case 3: + cardImageSource = MtgOnlTokensImageSource.instance; + break; + case 4: + cardImageSource = AltMtgOnlTokensImageSource.instance; + break; + case 5: + cardImageSource = GrabbagImageSource.instance; + break; + case 6: + cardImageSource = MagidexImageSource.instance; + break; + case 7: + cardImageSource = ScryfallImageSource.instance; + break; + case 8: + cardImageSource = MagicCardsImageSource.instance; + break; + } + jComboBoxSet.setModel(new DefaultComboBoxModel<>(getSetsForCurrentImageSource())); + updateCardsToDownload(); + } + + private Object[] getSetsForCurrentImageSource() { + // Set the available sets to the combo box + ArrayList supportedSets = cardImageSource.getSupportedSets(); + List setNames = new ArrayList<>(); + setNames.add(ALL_CARDS); + setNames.add(ALL_STANDARD_CARDS); + if (cardImageSource.providesTokenImages()) { + setNames.add(ALL_TOKENS); + } + if (supportedSets != null) { + for (String setCode : supportedSets) { + ExpansionSet expansionSet = Sets.findSet(setCode); + if (expansionSet != null) { + setNames.add(expansionSet.getName()); + } else { + logger.error(cardImageSource.getSourceName() + ": Expansion set for code " + setCode + " not found!"); + } + } + + } + return setNames.toArray(new String[0]); + } + private void updateCardsToDownload() { - List cardsToDownload = cards; - if (type2cardsOnly()) { - selectType2andTokenCardsIfNotYetDone(); - cardsToDownload = type2cards; + String expansionSelection = jComboBoxSet.getSelectedItem().toString(); + selectedSetCodes.clear(); + boolean tokens = false; + switch (expansionSelection) { + case ALL_CARDS: + if (cardImageSource.getSupportedSets() == null) { + selectedSetCodes = cardImageSource.getSupportedSets(); + } else { + selectedSetCodes.addAll(cardImageSource.getSupportedSets()); + } + break; + case ALL_STANDARD_CARDS: + List standardSets = ConstructedFormats.getSetsByFormat(ConstructedFormats.STANDARD); + for (String setCode : cardImageSource.getSupportedSets()) { + if (standardSets.contains(setCode)) { + selectedSetCodes.add(setCode); + } else { + logger.debug("Set code " + setCode + " from download source " + cardImageSource.getSourceName()); + } + } + break; + case ALL_TOKENS: + tokens = true; + default: + int nonSetEntries = 2; + if (cardImageSource.providesTokenImages()) { + nonSetEntries++; + } + selectedSetCodes.add(cardImageSource.getSupportedSets().get(jComboBoxSet.getSelectedIndex() - nonSetEntries)); + } + cardsToDownload.clear(); + for (CardDownloadData data : allCardsMissingImage) { + if ((data.isToken() && tokens) + || (!data.isToken() && selectedSetCodes.contains(data.getSet()))) { + cardsToDownload.add(data); + } } updateProgressText(cardsToDownload.size()); } - private boolean type2cardsOnly() { - return checkBox.isSelected(); - } - - private void selectType2andTokenCardsIfNotYetDone() { - if (type2cards == null) { - type2cards = new ArrayList<>(); - for (CardDownloadData data : cards) { - if (data.isType2() || data.isToken()) { - type2cards.add(data); - } - } - } + private void comboBoxSetActionPerformed(java.awt.event.ActionEvent evt) { + // Update the cards to download related to the selected set + updateCardsToDownload(); } private void updateProgressText(int cardCount) { + missingTokens = 0; + for (CardDownloadData card : allCardsMissingImage) { + if (card.isToken()) { + missingTokens++; + } + } + missingCards = allCardsMissingImage.size() - missingTokens; + jLabelAllMissing.setText("Missing: " + missingCards + " cards / " + missingTokens + " tokens"); + float mb = (cardCount * cardImageSource.getAverageSize()) / 1024; bar.setString(String.format(cardIndex == cardCount ? "%d of %d cards finished! Please close!" : "%d of %d cards finished! Please wait! [%.1f Mb]", 0, cardCount, mb)); @@ -262,11 +360,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab logger.warn("No formats defined. Try connecting to a server first!"); } - int numberCardImages = allCards.size(); - int numberWithoutTokens = 0; List allCardsUrls = Collections.synchronizedList(new ArrayList<>()); try { - offlineMode = true; allCards.parallelStream().forEach(card -> { if (!card.getCardNumber().isEmpty() && !"0".equals(card.getCardNumber()) && !card.getSetCode().isEmpty() && !ignoreUrls.contains(card.getSetCode())) { @@ -308,14 +403,11 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab logger.error("Card has no set name and won't be sent to client:" + card.getName()); } }); - numberWithoutTokens = allCards.size(); allCardsUrls.addAll(getTokenCardUrls()); } catch (Exception e) { logger.error(e); } - int numberAllTokenImages = allCardsUrls.size() - numberWithoutTokens; - /** * check to see which cards we already have */ @@ -329,22 +421,13 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab } }); - int tokenImages = 0; - for (CardDownloadData card : cardsToDownload) { - logger.debug((card.isToken() ? "Token" : "Card") + " image to download: " + card.getName() + " (" + card.getSet() + ')'); - if (card.isToken()) { - tokenImages++; - } - } - logger.info("Check download images (total card images: " + numberCardImages + ", total token images: " + numberAllTokenImages + ')'); - logger.info(" => Missing card images: " + (cardsToDownload.size() - tokenImages)); - logger.info(" => Missing token images: " + tokenImages); return new ArrayList<>(cardsToDownload); } public static ArrayList getTokenCardUrls() throws RuntimeException { ArrayList list = new ArrayList<>(); - InputStream in = DownloadPictures.class.getClassLoader().getResourceAsStream("card-pictures-tok.txt"); + InputStream in = DownloadPictures.class + .getClassLoader().getResourceAsStream("card-pictures-tok.txt"); if (in == null) { logger.error("resources input stream is null"); @@ -446,9 +529,8 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab if (p != null) { HashSet ignoreUrls = SettingsManager.getIntance().getIgnoreUrls(); - List cardsToDownload = this.checkBox.isSelected() ? type2cards : cards; - update(0, cardsToDownload.size()); + logger.info("Started download of " + cardsToDownload.size() + " cards from source: " + cardImageSource.getSourceName()); int numberOfThreads = Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_IMAGES_THREADS, "10")); ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); @@ -712,16 +794,18 @@ public class DownloadPictures extends DefaultBoundedRangeModel implements Runnab card, count, mb)); } else { List remainingCards = Collections.synchronizedList(new ArrayList<>()); - DownloadPictures.this.cards.parallelStream().forEach(cardDownloadData -> { + DownloadPictures.this.allCardsMissingImage.parallelStream().forEach(cardDownloadData -> { TFile file = new TFile(CardImageUtils.generateImagePath(cardDownloadData)); if (!file.exists()) { remainingCards.add(cardDownloadData); } }); - DownloadPictures.this.cards = new ArrayList<>(remainingCards); + // remove the cards not downloaded to get the siccessfull downloaded cards + DownloadPictures.this.cardsToDownload.removeAll(remainingCards); + DownloadPictures.this.allCardsMissingImage.removeAll(DownloadPictures.this.cardsToDownload); - count = DownloadPictures.this.cards.size(); + count = remainingCards.size(); if (count == 0) { bar.setString("0 cards remaining! Please close!"); diff --git a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target/maven-archiver/pom.properties b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target/maven-archiver/pom.properties index d7097083df5..03ac9e7681d 100644 --- a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target/maven-archiver/pom.properties +++ b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/target/maven-archiver/pom.properties @@ -1,5 +1,5 @@ -#Generated by Maven -#Mon Aug 28 09:53:46 CEST 2017 -version=1.4.26 -groupId=org.mage -artifactId=mage-game-pennydreadfulcommanderfreeforall +#Generated by Maven +#Sun Sep 03 07:46:59 CEST 2017 +version=1.4.26 +groupId=org.mage +artifactId=mage-game-pennydreadfulcommanderfreeforall