diff --git a/res/cardsfolder/s/snow_covered_forest.txt b/res/cardsfolder/s/snow_covered_forest.txt index af52b46506b..4c7522c9213 100644 --- a/res/cardsfolder/s/snow_covered_forest.txt +++ b/res/cardsfolder/s/snow_covered_forest.txt @@ -1,7 +1,7 @@ Name:Snow-Covered Forest ManaCost:no cost Types:Basic Snow Land Forest -SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_forest.jpg\http://www.wizards.com/global/images/magic/general/snow_covered_forest.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_forest.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_forest.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_forest.jpg Oracle:G SetInfo:ICE Land -SetInfo:CSP Common \ No newline at end of file +SetInfo:CSP Common diff --git a/res/cardsfolder/s/snow_covered_island.txt b/res/cardsfolder/s/snow_covered_island.txt index a88caaae8bd..e736ecba831 100644 --- a/res/cardsfolder/s/snow_covered_island.txt +++ b/res/cardsfolder/s/snow_covered_island.txt @@ -1,7 +1,7 @@ Name:Snow-Covered Island ManaCost:no cost Types:Basic Snow Land Island -SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_island.jpg\http://www.wizards.com/global/images/magic/general/snow_covered_island.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_island.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_island.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_island.jpg Oracle:U SetInfo:ICE Land -SetInfo:CSP Common \ No newline at end of file +SetInfo:CSP Common diff --git a/res/cardsfolder/s/snow_covered_mountain.txt b/res/cardsfolder/s/snow_covered_mountain.txt index 7fe59eca06c..3de20b2a7fc 100644 --- a/res/cardsfolder/s/snow_covered_mountain.txt +++ b/res/cardsfolder/s/snow_covered_mountain.txt @@ -1,7 +1,7 @@ Name:Snow-Covered Mountain ManaCost:no cost Types:Basic Snow Land Mountain -SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_mountain.jpg\http://www.wizards.com/global/images/magic/general/snow_covered_mountain.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_mountain.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_mountain.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_mountain.jpg Oracle:R SetInfo:ICE Land -SetInfo:CSP Common \ No newline at end of file +SetInfo:CSP Common diff --git a/res/cardsfolder/s/snow_covered_plains.txt b/res/cardsfolder/s/snow_covered_plains.txt index 4f6f0b23c56..1fbbd5bd44a 100644 --- a/res/cardsfolder/s/snow_covered_plains.txt +++ b/res/cardsfolder/s/snow_covered_plains.txt @@ -1,7 +1,7 @@ Name:Snow-Covered Plains ManaCost:no cost Types:Basic Snow Land Plains -SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_plains.jpg\http://www.wizards.com/global/images/magic/general/snow_covered_plains.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_plains.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_plains.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_plains.jpg Oracle:W SetInfo:ICE Land -SetInfo:CSP Common \ No newline at end of file +SetInfo:CSP Common diff --git a/res/cardsfolder/s/snow_covered_swamp.txt b/res/cardsfolder/s/snow_covered_swamp.txt index 0dc27dd4b56..38ddc434a7a 100644 --- a/res/cardsfolder/s/snow_covered_swamp.txt +++ b/res/cardsfolder/s/snow_covered_swamp.txt @@ -1,7 +1,7 @@ Name:Snow-Covered Swamp ManaCost:no cost Types:Basic Snow Land Swamp -SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_swamp.jpg\http://www.wizards.com/global/images/magic/general/snow_covered_swamp.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_swamp.jpg\http://www.magickartenmarkt.de/img/cards/Ice_Age/snow_covered_swamp.jpg +SVar:Picture:http://www.wizards.com/global/images/magic/general/snow_covered_swamp.jpg Oracle:B SetInfo:ICE Land -SetInfo:CSP Common \ No newline at end of file +SetInfo:CSP Common diff --git a/src/main/java/forge/gui/DialogMigrateProfile.java b/src/main/java/forge/gui/DialogMigrateProfile.java index a4444ee67cd..69794eebb2a 100644 --- a/src/main/java/forge/gui/DialogMigrateProfile.java +++ b/src/main/java/forge/gui/DialogMigrateProfile.java @@ -27,7 +27,7 @@ import java.io.IOException; import java.nio.channels.FileChannel; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; import javax.swing.JComboBox; import javax.swing.JPanel; @@ -70,7 +70,7 @@ public class DialogMigrateProfile { p.setBackgroundTexture(FSkin.getIcon(FSkin.Backgrounds.BG_TEXTURE)); // header - p.add(new FLabel.Builder().text("Migrate profile data (in progress: not yet functional)").fontSize(15).build(), "center"); + p.add(new FLabel.Builder().text("Migrate profile data (in progress: not fully functional)").fontSize(15).build(), "center"); if (showMigrationBlurb) { FPanel blurbPanel = new FPanel(new MigLayout("insets dialog, gap 10, center, wrap")); @@ -112,6 +112,7 @@ public class DialogMigrateProfile { File srcDirFile = new File(srcDir); txfSrc.setText(srcDirFile.getAbsolutePath()); } + // TODO: listen for new directory choice and reset analysis importSourcePanel.add(new FLabel.ButtonBuilder().text("Choose directory...").enabled(emptySrcDir).build(), "h pref+8!, w pref+12!"); p.add(importSourcePanel, "gaptop 20, growx"); @@ -186,6 +187,7 @@ public class DialogMigrateProfile { private final String _srcDir; private final JComboBox _unknownDeckCombo; private final FCheckBox _moveCheckbox; + private final FCheckBox _overwriteCheckbox; private final JTextArea _operationLog; private final JProgressBar _progressBar; @@ -245,12 +247,18 @@ public class DialogMigrateProfile { cbPanel.add(cachePanel, "aligny top"); _selectionPanel.add(cbPanel, "center"); - // add move/copy checkbox - _moveCheckbox = new FCheckBox("move files"); + // add move/copy and overwrite checkboxes + JPanel ioOptionPanel = new JPanel(new MigLayout("insets 0, gap 10")); + ioOptionPanel.setOpaque(false); + _moveCheckbox = new FCheckBox("Remove source file after copy"); _moveCheckbox.setSelected(true); _moveCheckbox.setEnabled(!forced); _moveCheckbox.addChangeListener(_stateChangedListener); - _selectionPanel.add(_moveCheckbox); + ioOptionPanel.add(_moveCheckbox); + _overwriteCheckbox = new FCheckBox("Overwrite existing files"); + _overwriteCheckbox.addChangeListener(_stateChangedListener); + ioOptionPanel.add(_overwriteCheckbox); + _selectionPanel.add(ioOptionPanel); // add operation summary textfield _operationLog = new JTextArea(); @@ -283,7 +291,9 @@ public class DialogMigrateProfile { cb.setSelected(true); cb.setEnabled(!forced); cb.addChangeListener(_stateChangedListener); - _selections.put(type, Pair.of(cb, new ConcurrentHashMap())); + + // use a skip list map instead of a regular hashmap so that the files are sorted alphabetically + _selections.put(type, Pair.of(cb, new ConcurrentSkipListMap())); parent.add(cb); } @@ -292,23 +302,14 @@ public class DialogMigrateProfile { // set operation summary StringBuilder log = new StringBuilder(); int totalOps = 0; - for (Pair> selection : _selections.values()) { - FCheckBox cb = selection.getLeft(); - int numOps = selection.getRight().size(); - - if (cb.isSelected()) { - totalOps += numOps; - } - - // update checkbox text with new totals - cb.setText(String.format("%s (%d)", cb.getName(), numOps)); - } - log.append(_moveCheckbox.isSelected() ? "Moving" : "Copying"); - log.append(" ").append(totalOps).append(" files\n\n"); for (Map.Entry>> entry : _selections.entrySet()) { Pair> selection = entry.getValue(); - if (selection.getLeft().isSelected()) { - for (Map.Entry op : selection.getRight().entrySet()) { + FCheckBox cb = selection.getLeft(); + Map ops = selection.getRight(); + int numOps = ops.size(); + if (cb.isSelected()) { + totalOps += numOps; + for (Map.Entry op : ops.entrySet()) { File dest = op.getValue(); if (OpType.UNKNOWN_DECK == entry.getKey()) { _UnknownDeckChoice choice = (_UnknownDeckChoice)_unknownDeckCombo.getSelectedItem(); @@ -318,7 +319,19 @@ public class DialogMigrateProfile { op.getKey().getAbsolutePath(), dest.getAbsolutePath())); } } + + // update checkbox text with new totals + cb.setText(String.format("%s (%d)", cb.getName(), numOps)); } + + if (0 < totalOps) { + log.append("\n"); + } + log.append(_moveCheckbox.isSelected() ? "Moving" : "Copying"); + log.append(" ").append(totalOps).append(" files\n"); + log.append(_overwriteCheckbox.isSelected() ? "O" : "Not o"); + log.append("verwriting existing files"); + _operationLog.setText(log.toString()); _uiUpdateAck = true; } @@ -394,6 +407,7 @@ public class DialogMigrateProfile { if (_cancel) { return; } _progressBar.setValue(_progressBar.getMaximum()); + _stateChangedListener.stateChanged(null); _progressBar.setString("Analysis complete"); _btnStart.addActionListener(new ActionListener() { @@ -404,7 +418,8 @@ public class DialogMigrateProfile { _disableAll(); _Importer importer = new _Importer( - _selections, _unknownDeckCombo, _operationLog, _progressBar, _moveCheckbox.isSelected()); + _selections, _unknownDeckCombo, _operationLog, _progressBar, + _moveCheckbox.isSelected(), _overwriteCheckbox.isSelected()); importer.execute(); } }); @@ -417,12 +432,14 @@ public class DialogMigrateProfile { private final JTextArea _operationLog; private final JProgressBar _progressBar; private final boolean _move; + private final boolean _overwrite; public _Importer(Map>> selections, JComboBox unknownDeckCombo, - JTextArea operationLog, JProgressBar progressBar, boolean move) { + JTextArea operationLog, JProgressBar progressBar, boolean move, boolean overwrite) { _operationLog = operationLog; _progressBar = progressBar; _move = move; + _overwrite = overwrite; int totalOps = 0; for (Pair> selection : selections.values()) { @@ -473,7 +490,9 @@ public class DialogMigrateProfile { File destFile = op.getValue(); try { - _copyFile(srcFile, destFile); + if (_overwrite || !destFile.exists()) { + _copyFile(srcFile, destFile); + } if (_move) { srcFile.delete(); diff --git a/src/main/java/forge/gui/MigrationSourceAnalyzer.java b/src/main/java/forge/gui/MigrationSourceAnalyzer.java index a3f71039bb2..743a12faeea 100644 --- a/src/main/java/forge/gui/MigrationSourceAnalyzer.java +++ b/src/main/java/forge/gui/MigrationSourceAnalyzer.java @@ -18,7 +18,16 @@ package forge.gui; import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; + +import forge.card.CardRules; +import forge.item.CardDb; +import forge.item.CardPrinted; import forge.properties.NewConstants; public class MigrationSourceAnalyzer { @@ -54,9 +63,7 @@ public class MigrationSourceAnalyzer { _source = new File(source); _cb = cb; - System.out.println("counting source files"); _numFilesToAnalyze = _countFiles(_source); - System.out.println("done counting source files: " + _numFilesToAnalyze); } public int getNumFilesToAnalyze() { return _numFilesToAnalyze; } @@ -80,31 +87,92 @@ public class MigrationSourceAnalyzer { // ignore other files if (file.isFile()) { ++_numFilesAnalyzed; - } - if (file.isDirectory()) { + } else if (file.isDirectory()) { _numFilesAnalyzed += _countFiles(file); } } } + private static String _oldCleanString(final String in) { + final StringBuffer out = new StringBuffer(); + char c; + for (int i = 0; i < in.length(); i++) { + c = in.charAt(i); + if ((c == ' ') || (c == '-')) { + out.append('_'); + } else if (Character.isLetterOrDigit(c) || (c == '_')) { + out.append(c); + } + } + return out.toString().toLowerCase(); + } + + private void _addDefaultPicNames(CardPrinted c, boolean backFace) { + CardRules cardRules = c.getRules(); + String urls = backFace ? cardRules.getPictureOtherSideUrl() : cardRules.getPictureUrl(); + if (StringUtils.isEmpty(urls)) { return; } + + int numPics = urls.split("\\\\").length; + for (int artIdx = 0; numPics > artIdx; ++artIdx) { + String filename = c.getImageFilename(backFace, artIdx, false) + ".jpg"; + _defaultPicNames.add(filename); + + String oldFilenameBase = _oldCleanString(filename.replace(".full.jpg", "")); + if (0 == artIdx) { + // remove trailing "1" from first art index + String oldFilename = oldFilenameBase.replaceAll("1$", "") + ".jpg"; + _defaultPicOldNameToCurrentName.put(oldFilename, filename); + } else { + // offset art indices by one + String oldFilename = oldFilenameBase.replaceAll("[0-9]+$", String.valueOf(artIdx)) + ".jpg"; + _defaultPicOldNameToCurrentName.put(oldFilename, filename); + } + } + } + + private Set _defaultPicNames; + private Map _defaultPicOldNameToCurrentName; private void _analyzePicsDir(File picsRoot) { - System.out.println("found pics dir: " + picsRoot); + if (null == _defaultPicNames) { + // build structures + _defaultPicNames = new HashSet(); + _defaultPicOldNameToCurrentName = new HashMap(); + + for (CardPrinted c : CardDb.instance().getUniqueCards()) { + _addDefaultPicNames(c, false); + _addDefaultPicNames(c, true); + } + + for (CardPrinted c : CardDb.variants().getUniqueCards()) { + _addDefaultPicNames(c, false); + _addDefaultPicNames(c, true); + } + } + for (File file : picsRoot.listFiles()) { if (_cb.checkCancel()) { return; } - System.out.println("analyzing dir entry: " + file.getAbsolutePath()); if (file.isFile()) { ++_numFilesAnalyzed; - // TODO: correct filename - _cb.addOp(OpType.DEFAULT_CARD_PIC, file, new File(NewConstants.CACHE_CARD_PICS_DIR, file.getName())); - } - if (file.isDirectory()) { - // skip set pics for now - _numFilesAnalyzed += _countFiles(file); + String fileName = file.getName(); + if (_defaultPicOldNameToCurrentName.containsKey(fileName)) { + fileName = _defaultPicOldNameToCurrentName.get(fileName); + } else if (!_defaultPicNames.contains(fileName)) { + System.out.println("skipping umappable pic file: " + file); + continue; + } + _cb.addOp(OpType.DEFAULT_CARD_PIC, file, new File(NewConstants.CACHE_CARD_PICS_DIR, fileName)); + } else if (file.isDirectory()) { + _analyzePicsSetDir(file); } } } + private void _analyzePicsSetDir(File setRoot) { + // if not a valid set name, skip + _numFilesAnalyzed += _countFiles(setRoot); + } + private int _countFiles(File directory) { int count = 0; for (File file : directory.listFiles()) { @@ -112,8 +180,7 @@ public class MigrationSourceAnalyzer { if (file.isFile()) { ++count; - } - if (file.isDirectory()) { + } else if (file.isDirectory()) { count += _countFiles(file); } } diff --git a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java index b4b9c5089cc..27558368950 100644 --- a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java @@ -40,11 +40,16 @@ public class GuiDownloadPicturesLQ extends GuiDownloader { ArrayList downloads = new ArrayList(); Set filenames = new HashSet(); - for (final CardPrinted c : CardDb.instance().getUniqueCards()) { + for (CardPrinted c : CardDb.instance().getUniqueCards()) { addDLObject(c, false, downloads, filenames); addDLObject(c, true, downloads, filenames); } + for (CardPrinted c : CardDb.variants().getUniqueCards()) { + addDLObject(c, false, downloads, filenames); + addDLObject(c, true, downloads, filenames); + } + // 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)) { if (!element.getDestination().exists()) { diff --git a/src/main/java/forge/item/CardPrinted.java b/src/main/java/forge/item/CardPrinted.java index 78ae6cdb767..e09e7be0dbb 100644 --- a/src/main/java/forge/item/CardPrinted.java +++ b/src/main/java/forge/item/CardPrinted.java @@ -24,6 +24,7 @@ import com.google.common.base.Function; import forge.Card; import forge.Singletons; +import forge.card.CardInSet; import forge.card.CardRarity; import forge.card.CardRules; import forge.card.CardSplitType; @@ -175,7 +176,20 @@ public final class CardPrinted implements Comparable, InventoryItemF s.append(toMWSFilename(nameToUse)); - int cntPictures = card.getEditionInfo(edition).getCopiesCount(); + final int cntPictures; + if (includeSet) { + cntPictures = card.getEditionInfo(edition).getCopiesCount(); + } else { + // raise the art index limit to the maximum of the sets this card was printed in + int maxCntPictures = 1; + for (String set : card.getSets()) { + CardInSet setInfo = card.getEditionInfo(set); + if (maxCntPictures < setInfo.getCopiesCount()) { + maxCntPictures = setInfo.getCopiesCount(); + } + } + cntPictures = maxCntPictures; + } if (cntPictures > 1 && cntPictures > artIdx) { s.append(artIdx + 1); }