diff --git a/res/quest/quest-opponent-icons.txt b/res/quest/quest-opponent-icons.txt index a75ec8758ec..bb8cd3f1e88 100644 --- a/res/quest/quest-opponent-icons.txt +++ b/res/quest/quest-opponent-icons.txt @@ -321,7 +321,7 @@ http://www.cardforge.org/fpics/questAvatars/Savra.jpg http://www.cardforge.org/fpics/questAvatars/Selesnya-precon.jpg http://www.cardforge.org/fpics/questAvatars/Simic-precon.jpg http://www.cardforge.org/fpics/questAvatars/Sisters%20of%20Stone%20Death.jpg -http://www.cardforge.org/fpics/questAvatars/Sus Antigoon.jpg +http://www.cardforge.org/fpics/questAvatars/Sus%20Antigoon.jpg http://www.cardforge.org/fpics/questAvatars/Szadek.jpg http://www.cardforge.org/fpics/questAvatars/Teysa.jpg http://www.cardforge.org/fpics/questAvatars/Token.jpg diff --git a/src/main/java/forge/gui/DialogMigrateProfile.java b/src/main/java/forge/gui/DialogMigrateProfile.java index c2a17e0cd82..03da67315ae 100644 --- a/src/main/java/forge/gui/DialogMigrateProfile.java +++ b/src/main/java/forge/gui/DialogMigrateProfile.java @@ -47,6 +47,7 @@ import net.miginfocom.swing.MigLayout; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import forge.error.BugReporter; import forge.gui.MigrationSourceAnalyzer.OpType; import forge.gui.toolbox.FButton; import forge.gui.toolbox.FCheckBox; @@ -345,57 +346,75 @@ public class DialogMigrateProfile { @Override protected Void doInBackground() throws Exception { - Map> selections = new HashMap>(); - for (Map.Entry>> entry : _selections.entrySet()) { - selections.put(entry.getKey(), entry.getValue().getRight()); - } + Timer timer = null; - MigrationSourceAnalyzer.AnalysisCallback cb = new MigrationSourceAnalyzer.AnalysisCallback() { - @Override - public boolean checkCancel() { return _cancel; } + try { + Map> selections = new HashMap>(); + for (Map.Entry>> entry : _selections.entrySet()) { + selections.put(entry.getKey(), entry.getValue().getRight()); + } - @Override - public void addOp(OpType type, File src, File dest) { - _selections.get(type).getRight().put(src, dest); - } - }; - - final MigrationSourceAnalyzer msa = new MigrationSourceAnalyzer(_srcDir, cb); - final int numFilesToAnalyze = msa.getNumFilesToAnalyze(); - - final Timer timer = new Timer(500, null); - timer.addActionListener(new ActionListener() { - @Override public void actionPerformed(ActionEvent arg0) { - if (_cancel) { - timer.stop(); - return; + MigrationSourceAnalyzer.AnalysisCallback cb = new MigrationSourceAnalyzer.AnalysisCallback() { + @Override + public boolean checkCancel() { return _cancel; } + + @Override + public void addOp(OpType type, File src, File dest) { + _selections.get(type).getRight().put(src, dest); } - - // timers run in the gui event loop, so it's ok to interact with widgets - _progressBar.setValue(msa.getNumFilesAnalyzed()); - - // only update if we don't already have an update pending. we may not be prompt in - // updating sometimes, but that's ok - if (!_uiUpdateAck) { return; } - _uiUpdateAck = false; - _stateChangedListener.stateChanged(null); + }; + + final MigrationSourceAnalyzer msa = new MigrationSourceAnalyzer(_srcDir, cb); + final int numFilesToAnalyze = msa.getNumFilesToAnalyze(); + + timer = new Timer(500, null); + final Timer finalTimer = timer; + timer.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent arg0) { + if (_cancel) { + finalTimer.stop(); + return; + } + + // timers run in the gui event loop, so it's ok to interact with widgets + _progressBar.setValue(msa.getNumFilesAnalyzed()); + + // only update if we don't already have an update pending. we may not be prompt in + // updating sometimes, but that's ok + if (!_uiUpdateAck) { return; } + _uiUpdateAck = false; + _stateChangedListener.stateChanged(null); + } + }); + + SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { + if (_cancel) { return; } + _progressBar.setMaximum(numFilesToAnalyze); + _progressBar.setValue(0); + _progressBar.setIndeterminate(false); + + // start update timer + finalTimer.start(); + } + }); + + msa.doAnalysis(); + } catch (final Exception e) { + _cancel = true; + + SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { + _progressBar.setString("Error"); + BugReporter.reportException(e); + } + }); + } finally { + if (null != timer) + { + timer.stop(); } - }); - - SwingUtilities.invokeLater(new Runnable() { - @Override public void run() { - if (_cancel) { return; } - _progressBar.setMaximum(numFilesToAnalyze); - _progressBar.setValue(0); - _progressBar.setIndeterminate(false); - - // start update timer - timer.start(); - } - }); - - msa.doAnalysis(); - timer.stop(); + } return null; } diff --git a/src/main/java/forge/gui/MigrationSourceAnalyzer.java b/src/main/java/forge/gui/MigrationSourceAnalyzer.java index 921ae62851e..4bac6496cb9 100644 --- a/src/main/java/forge/gui/MigrationSourceAnalyzer.java +++ b/src/main/java/forge/gui/MigrationSourceAnalyzer.java @@ -22,8 +22,10 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.TreeSet; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -36,6 +38,7 @@ import forge.item.CardDb; import forge.item.CardPrinted; import forge.item.IPaperCard; import forge.properties.NewConstants; +import forge.util.FileUtil; public class MigrationSourceAnalyzer { public static enum OpType { @@ -60,6 +63,8 @@ public class MigrationSourceAnalyzer { void addOp(OpType type, File src, File dest); } + private final Set _unmappableFiles = new TreeSet(); + private final File _source; private final AnalysisCallback _cb; private final int _numFilesToAnalyze; @@ -83,6 +88,10 @@ public class MigrationSourceAnalyzer { _analyzeResDir(_source); } + ////////////////////////////////////////////////////////////////////////// + // pre-profile res dir + // + private void _analyzeResDir(File root) { for (File file : root.listFiles()) { if (_cb.checkCancel()) { return; } @@ -100,6 +109,10 @@ public class MigrationSourceAnalyzer { } } + ////////////////////////////////////////////////////////////////////////// + // default card pics + // + private static String _oldCleanString(final String in) { final StringBuffer out = new StringBuffer(); char c; @@ -166,8 +179,8 @@ public class MigrationSourceAnalyzer { if (_defaultPicOldNameToCurrentName.containsKey(fileName)) { fileName = _defaultPicOldNameToCurrentName.get(fileName); } else if (!_defaultPicNames.contains(fileName)) { - // TODO: track the unmappables and prompt to delete them at the end System.out.println("skipping umappable default pic file: " + file); + _unmappableFiles.add(file); continue; } @@ -187,6 +200,10 @@ public class MigrationSourceAnalyzer { } } + ////////////////////////////////////////////////////////////////////////// + // set card pics + // + private static void _addSetCards(Set cardFileNames, Iterable library, Predicate filter) { for (CardPrinted c : Iterables.filter(library, filter)) { boolean hasBackFace = null != c.getRules().getPictureOtherSideUrl(); @@ -235,6 +252,7 @@ public class MigrationSourceAnalyzer { } } else { System.out.println("skipping umappable set pic file: " + file); + _unmappableFiles.add(file); } } else if (file.isDirectory()) { System.out.println("skipping umappable subdirectory: " + file); @@ -243,16 +261,87 @@ public class MigrationSourceAnalyzer { } } + ////////////////////////////////////////////////////////////////////////// + // other image dirs + // + + Set _iconFileNames; private void _analyzeIconsPicsDir(File root) { - // TODO: implement - _numFilesAnalyzed += _countFiles(root); + if (null == _iconFileNames) { + _iconFileNames = new HashSet(); + for (Pair nameurl : FileUtil.readNameUrlFile(NewConstants.IMAGE_LIST_QUEST_OPPONENT_ICONS_FILE)) { + _iconFileNames.add(nameurl.getLeft()); + } + for (Pair nameurl : FileUtil.readNameUrlFile(NewConstants.IMAGE_LIST_QUEST_PET_SHOP_ICONS_FILE)) { + _iconFileNames.add(nameurl.getLeft()); + } + } + + System.out.println("analyzing icon pics directory: " + root); + for (File file : root.listFiles()) { + if (_cb.checkCancel()) { return; } + + if (file.isFile()) { + ++_numFilesAnalyzed; + if (!_iconFileNames.contains(file.getName())) { + System.out.println("skipping umappable icon pic file: " + file); + _unmappableFiles.add(file); + continue; + } + + File targetFile = new File(NewConstants.CACHE_ICON_PICS_DIR, file.getName()); + if (!file.equals(targetFile)) { + _cb.addOp(OpType.QUEST_DATA, file, targetFile); + } + } else if (file.isDirectory()) { + System.out.println("skipping umappable subdirectory: " + file); + _numFilesAnalyzed += _countFiles(file); + } + } } + Set _tokenFileNames; + Set _questTokenFileNames; private void _analyzeTokenPicsDir(File root) { - // TODO: implement - _numFilesAnalyzed += _countFiles(root); + if (null == _tokenFileNames) { + _tokenFileNames = new HashSet(); + _questTokenFileNames = new HashSet(); + for (Pair nameurl : FileUtil.readNameUrlFile(NewConstants.IMAGE_LIST_TOKENS_FILE)) { + _tokenFileNames.add(nameurl.getLeft()); + } + for (Pair nameurl : FileUtil.readNameUrlFile(NewConstants.IMAGE_LIST_QUEST_TOKENS_FILE)) { + _questTokenFileNames.add(nameurl.getLeft()); + } + } + + System.out.println("analyzing token pics directory: " + root); + for (File file : root.listFiles()) { + if (_cb.checkCancel()) { return; } + + if (file.isFile()) { + ++_numFilesAnalyzed; + boolean isQuestToken = _questTokenFileNames.contains(file.getName()); + if (!isQuestToken && !_tokenFileNames.contains(file.getName())) { + System.out.println("skipping umappable token pic file: " + file); + _unmappableFiles.add(file); + continue; + } + + File targetFile = new File(NewConstants.CACHE_TOKEN_PICS_DIR, file.getName()); + if (!file.equals(targetFile)) { + _cb.addOp(isQuestToken ? OpType.QUEST_PIC : OpType.TOKEN_PIC, file, targetFile); + } + } else if (file.isDirectory()) { + System.out.println("skipping umappable subdirectory: " + file); + _numFilesAnalyzed += _countFiles(file); + } + } } + ////////////////////////////////////////////////////////////////////////// + // utility functions + // + private int _countFiles(File root) { int count = 0; for (File file : root.listFiles()) { diff --git a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java index 27558368950..235f4d1163e 100644 --- a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java @@ -51,7 +51,7 @@ public class GuiDownloadPicturesLQ extends GuiDownloader { } // Add missing tokens to the list of things to download. - for (final DownloadObject element : GuiDownloader.readFileWithNames(NewConstants.IMAGE_LIST_TOKENS_FILE, NewConstants.CACHE_TOKEN_PICS_DIR)) { + for (final DownloadObject element : GuiDownloader.readFile(NewConstants.IMAGE_LIST_TOKENS_FILE, NewConstants.CACHE_TOKEN_PICS_DIR)) { if (!element.getDestination().exists()) { downloads.add(element); } diff --git a/src/main/java/forge/gui/download/GuiDownloadQuestImages.java b/src/main/java/forge/gui/download/GuiDownloadQuestImages.java index 7833ee49aae..d333d74a0f7 100644 --- a/src/main/java/forge/gui/download/GuiDownloadQuestImages.java +++ b/src/main/java/forge/gui/download/GuiDownloadQuestImages.java @@ -75,13 +75,13 @@ public class GuiDownloadQuestImages extends GuiDownloader { } } - for (final DownloadObject petIcon : GuiDownloader.readFileWithNames(NewConstants.IMAGE_LIST_QUEST_PET_SHOP_ICONS_FILE, NewConstants.CACHE_ICON_PICS_DIR)) { + for (final DownloadObject petIcon : GuiDownloader.readFile(NewConstants.IMAGE_LIST_QUEST_PET_SHOP_ICONS_FILE, NewConstants.CACHE_ICON_PICS_DIR)) { if (!petIcon.getDestination().exists()) { urls.add(petIcon); } } - for (final DownloadObject questPet : GuiDownloader.readFileWithNames(NewConstants.IMAGE_LIST_QUEST_TOKENS_FILE, NewConstants.CACHE_TOKEN_PICS_DIR)) { + for (final DownloadObject questPet : GuiDownloader.readFile(NewConstants.IMAGE_LIST_QUEST_TOKENS_FILE, NewConstants.CACHE_TOKEN_PICS_DIR)) { if (!questPet.getDestination().exists()) { urls.add(questPet); } diff --git a/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java index 22a89520f4c..45f468105cb 100644 --- a/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java @@ -54,7 +54,7 @@ public class GuiDownloadSetPicturesLQ extends GuiDownloader { } // Add missing tokens to the list of things to download. - for (final DownloadObject element : GuiDownloader.readFileWithNames(NewConstants.IMAGE_LIST_TOKENS_FILE, NewConstants.CACHE_TOKEN_PICS_DIR)) { + for (final DownloadObject element : GuiDownloader.readFile(NewConstants.IMAGE_LIST_TOKENS_FILE, NewConstants.CACHE_TOKEN_PICS_DIR)) { if (!element.getDestination().exists()) { downloads.add(element); } diff --git a/src/main/java/forge/gui/download/GuiDownloader.java b/src/main/java/forge/gui/download/GuiDownloader.java index e806a630254..712fb2dcfb4 100644 --- a/src/main/java/forge/gui/download/GuiDownloader.java +++ b/src/main/java/forge/gui/download/GuiDownloader.java @@ -32,9 +32,7 @@ import java.net.MalformedURLException; import java.net.Proxy; import java.net.URL; import java.util.ArrayList; -import java.util.List; import java.util.Random; -import java.util.regex.Pattern; import javax.swing.AbstractButton; import javax.swing.DefaultBoundedRangeModel; @@ -50,7 +48,7 @@ import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import com.esotericsoftware.minlog.Log; @@ -374,50 +372,14 @@ public abstract class GuiDownloader extends DefaultBoundedRangeModel implements protected abstract ArrayList getNeededImages(); - protected static List readFile(final String urlsFile, String dir) { - List fileLines = FileUtil.readFile(urlsFile); + protected static ArrayList readFile(final String nameUrlFile, final String dir) { final ArrayList list = new ArrayList(); - final Pattern splitter = Pattern.compile(Pattern.quote("/")); - final Pattern replacer = Pattern.compile(Pattern.quote("%20")); - - for (String line : fileLines) { - - if (line.equals("") || line.startsWith("#")) { - continue; - } - - String[] parts = splitter.split(line); - - // Maybe there's a better way to do this, but I just want the - // filename from a URL - String last = parts[parts.length - 1]; - list.add(new DownloadObject(line, new File(dir, replacer.matcher(last).replaceAll(" ")))); + for (Pair nameUrlPair : FileUtil.readNameUrlFile(nameUrlFile)) { + list.add(new DownloadObject(nameUrlPair.getRight(), new File(dir, nameUrlPair.getLeft()))); } return list; } - protected static ArrayList readFileWithNames(final String urlNamesFile, final String dir) { - List fileLines = FileUtil.readFile(urlNamesFile); - final ArrayList list = new ArrayList(); - final Pattern splitter = Pattern.compile(Pattern.quote(" ")); - final Pattern replacer = Pattern.compile(Pattern.quote("%20")); - - for (String line : fileLines) { - - if (StringUtils.isBlank(line) || line.startsWith("#")) { - continue; - } - String[] parts = splitter.split(line, 2); - String url = parts.length > 1 ? parts[1] : null; - list.add(new DownloadObject(url, new File(dir, replacer.matcher(parts[0]).replaceAll(" ")))); - } - - return list; - } // readFile() - - /** - * The Class ProxyHandler. - */ protected class ProxyHandler implements ChangeListener { private final int type; @@ -450,7 +412,7 @@ public abstract class GuiDownloader extends DefaultBoundedRangeModel implements DownloadObject(final String srcUrl, final File destFile) { source = srcUrl; destination = destFile; - // System.out.println("Created download object: "+name+" "+url+" "+dir); + System.out.println(String.format("downloading %s to %s", srcUrl, destFile)); } /** @return {@link java.lang.String} */ diff --git a/src/main/java/forge/util/FileUtil.java b/src/main/java/forge/util/FileUtil.java index 2a652f28c0b..a391d57d501 100644 --- a/src/main/java/forge/util/FileUtil.java +++ b/src/main/java/forge/util/FileUtil.java @@ -17,22 +17,19 @@ */ package forge.util; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; -import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; -import java.net.Proxy; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.regex.Pattern; -import javax.swing.JOptionPane; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import forge.error.BugReporter; @@ -177,25 +174,30 @@ public final class FileUtil { return list; } - public static void downloadUrlIntoFile(final String url, final File target) { - try { - final byte[] buf = new byte[1024]; - int len; + // returns a list of pairs. if the name is not in the file, it is synthesized from the url + public static List> readNameUrlFile(String nameUrlFile) { + Pattern lineSplitter = Pattern.compile(Pattern.quote(" ")); + Pattern replacer = Pattern.compile(Pattern.quote("%20")); - final Proxy p = Proxy.NO_PROXY; - final BufferedInputStream in = new BufferedInputStream(new URL(url).openConnection(p).getInputStream()); - final BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(target)); + List> list = new ArrayList>(); - // while - read and write file - while ((len = in.read(buf)) != -1) { - out.write(buf, 0, len); - } // while - read and write file - in.close(); - out.flush(); - out.close(); - } catch (final IOException ioex) { - JOptionPane.showMessageDialog(null, String.format("Error connecting to: %s", url), - "Download error", JOptionPane.ERROR_MESSAGE); + for (String line : readFile(nameUrlFile)) { + if (StringUtils.isBlank(line) || line.startsWith("#")) { + continue; + } + + String[] parts = lineSplitter.split(line, 2); + if (2 == parts.length) { + list.add(Pair.of(replacer.matcher(parts[0]).replaceAll(" "), parts[1])); + } else { + // figure out the filename from the URL + Pattern pathSplitter = Pattern.compile(Pattern.quote("/")); + String[] pathParts = pathSplitter.split(parts[0]); + String last = pathParts[pathParts.length - 1]; + list.add(Pair.of(replacer.matcher(last).replaceAll(" "), parts[0])); + } } + + return list; } }