diff --git a/forge-core/src/main/java/forge/card/CardDb.java b/forge-core/src/main/java/forge/card/CardDb.java index 63fc5566505..7e65256a4a8 100644 --- a/forge-core/src/main/java/forge/card/CardDb.java +++ b/forge-core/src/main/java/forge/card/CardDb.java @@ -353,6 +353,27 @@ public final class CardDb implements ICardDatabase { return false; } } + + public StringBuilder appendCardToStringBuilder(PaperCard card, StringBuilder sb) { + final boolean hasBadSetInfo = "???".equals(card.getEdition()) || StringUtils.isBlank(card.getEdition()); + sb.append(card.getName()); + + if (!hasBadSetInfo) { + int artCount = getArtCount(card.getName(), card.getEdition()); + sb.append(CardDb.NameSetSeparator).append(card.getEdition()); + if (artCount > 1) { + sb.append(CardDb.NameSetSeparator).append(card.getArtIndex()); // indexes start at 1 to match image file name conventions + } + } + if(card.isFoil()) { + sb.append(CardDb.foilSuffix); + } + return sb; + } + + public String cardToString(PaperCard pc) { + return appendCardToStringBuilder(pc, new StringBuilder()).toString(); + } private final Editor editor = new Editor(); public Editor getEditor() { return editor; } diff --git a/forge-core/src/main/java/forge/deck/CardPool.java b/forge-core/src/main/java/forge/deck/CardPool.java index 367d3f1a444..0496d38250f 100644 --- a/forge-core/src/main/java/forge/deck/CardPool.java +++ b/forge-core/src/main/java/forge/deck/CardPool.java @@ -17,16 +17,21 @@ */ package forge.deck; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; +import com.google.common.collect.Lists; + import forge.StaticData; import forge.card.CardDb; import forge.item.PaperCard; import forge.util.ItemPool; +import forge.util.ItemPoolSorter; import forge.util.MyRandom; /** @@ -92,6 +97,8 @@ public class CardPool extends ItemPool { } } } + + /** * Add all from a List of CardPrinted. @@ -163,4 +170,28 @@ public class CardPool extends ItemPool { } return pool; } + + public String toCardList(String separator) { + List> main2sort = Lists.newArrayList(this); + Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET); + final CardDb commonDb = StaticData.instance().getCommonCards(); + StringBuilder sb = new StringBuilder(); + + boolean isFirst = true; + + for (final Entry e : main2sort) { + if(!isFirst) + sb.append(separator); + else + isFirst = false; + + CardDb db = e.getKey().getRules().isVariant() ? commonDb : StaticData.instance().getVariantCards(); + sb.append(e.getValue()).append(" "); + db.appendCardToStringBuilder(e.getKey(), sb); + + } + return sb.toString(); + } + + } diff --git a/forge-core/src/main/java/forge/deck/Deck.java b/forge-core/src/main/java/forge/deck/Deck.java index f4018c51668..c1721b8a15d 100644 --- a/forge-core/src/main/java/forge/deck/Deck.java +++ b/forge-core/src/main/java/forge/deck/Deck.java @@ -17,37 +17,21 @@ */ package forge.deck; -import java.io.File; -import java.util.ArrayList; import java.util.Calendar; -import java.util.Collections; import java.util.Date; import java.util.EnumMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; -import org.apache.commons.lang3.StringUtils; - import com.google.common.base.Function; -import com.google.common.collect.Lists; - import forge.StaticData; -import forge.card.CardDb; import forge.card.CardEdition; import forge.card.CardDb.SetPreference; -import forge.deck.io.DeckFileHeader; -import forge.deck.io.DeckSerializer; import forge.item.PaperCard; -import forge.item.IPaperCard; -import forge.util.FileSection; -import forge.util.FileUtil; -import forge.util.ItemPool; -import forge.util.ItemPoolSorter; @@ -125,6 +109,10 @@ public class Deck extends DeckBase implements Iterable> sections) { - return Deck.fromSections(sections, false); - } - - /** - * From sections. - * - * @param sections the sections - * @param canThrowExtendedErrors the can throw extended errors - * @return the deck - */ - public static Deck fromSections(final Map> sections, final boolean canThrowExtendedErrors) { - if (sections == null || sections.isEmpty()) { - return null; - } - - final DeckFileHeader dh = DeckSerializer.readDeckMetadata(sections, canThrowExtendedErrors); - if (dh == null) { - return null; - } - - final Deck d = new Deck(dh.getName()); - d.setComment(dh.getComment()); - d.tags.addAll(dh.getTags()); - - boolean hasExplicitlySpecifiedSet = false; - - for (Entry> s : sections.entrySet()) { - DeckSection sec = DeckSection.smartValueOf(s.getKey()); - if (sec == null) { - continue; - } - - for(String k : s.getValue()) - if ( k.indexOf(CardDb.NameSetSeparator) > 0 ) - hasExplicitlySpecifiedSet = true; - - CardPool pool = CardPool.fromCardList(s.getValue()); - // I used to store planes and schemes under sideboard header, so this will assign them to a correct section - IPaperCard sample = pool.get(0); - if (sample != null && ( sample.getRules().getType().isPlane() || sample.getRules().getType().isPhenomenon())) { - sec = DeckSection.Planes; - } - if (sample != null && sample.getRules().getType().isScheme()) { - sec = DeckSection.Schemes; - } - - d.parts.put(sec, pool); - } - - if (!hasExplicitlySpecifiedSet) { - d.convertByXitaxMethod(); - } - - return d; - } public void convertByXitaxMethod() { CardEdition earliestSet = StaticData.instance().getEditions().getEarliestEditionWithAllCards(getAllCardsInASinglePool()); @@ -259,63 +176,6 @@ public class Deck extends DeckBase implements Iterable writeCardPool(final ItemPool pool) { - List> main2sort = Lists.newArrayList(pool); - Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET); - final List out = new ArrayList(); - for (final Entry e : main2sort) { - out.add(serializeSingleCard(e.getKey(), e.getValue())); - } - return out; - } - - private static String serializeSingleCard(PaperCard card, Integer n) { - final boolean hasBadSetInfo = "???".equals(card.getEdition()) || StringUtils.isBlank(card.getEdition()); - StringBuilder sb = new StringBuilder(); - sb.append(n).append(" ").append(card.getName()); - - if (!hasBadSetInfo) { - int artCount = StaticData.instance().getCommonCards().getArtCount(card.getName(), card.getEdition()); - - sb.append("|").append(card.getEdition()); - - if (artCount > 1) { - sb.append("|").append(card.getArtIndex()); // indexes start at 1 to match image file name conventions - } - } - if(card.isFoil()) { - sb.append(CardDb.foilSuffix); - } - return sb.toString(); - } - - /** - *

- * writeDeck. - *

- * - * @return the list - */ - public List save() { - final List out = new ArrayList(); - out.add(String.format("[metadata]")); - - out.add(String.format("%s=%s", DeckFileHeader.NAME, this.getName().replaceAll("\n", ""))); - // these are optional - if (this.getComment() != null) { - out.add(String.format("%s=%s", DeckFileHeader.COMMENT, this.getComment().replaceAll("\n", ""))); - } - if (!this.getTags().isEmpty()) { - out.add(String.format("%s=%s", DeckFileHeader.TAGS, StringUtils.join(getTags(), DeckFileHeader.TAGS_SEPARATOR))); - } - - for(Entry s : parts.entrySet()) { - out.add(String.format("[%s]", s.getKey().toString())); - out.addAll(Deck.writeCardPool(s.getValue())); - } - return out; - } - public static final Function FN_NAME_SELECTOR = new Function() { @Override public String apply(Deck arg1) { diff --git a/forge-core/src/main/java/forge/deck/io/DeckSerializer.java b/forge-core/src/main/java/forge/deck/io/DeckSerializer.java index 6349005ccdd..1943c25ec7c 100644 --- a/forge-core/src/main/java/forge/deck/io/DeckSerializer.java +++ b/forge-core/src/main/java/forge/deck/io/DeckSerializer.java @@ -19,13 +19,19 @@ package forge.deck.io; import java.io.File; import java.io.FilenameFilter; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; +import forge.card.CardDb; +import forge.deck.CardPool; import forge.deck.Deck; +import forge.deck.DeckSection; +import forge.item.IPaperCard; import forge.util.FileSection; import forge.util.FileSectionManual; import forge.util.FileUtil; @@ -56,15 +62,93 @@ public class DeckSerializer extends StorageReaderFolder implements IItemSe return name.endsWith(FILE_EXTENSION); } }; -public static void writeDeck(final Deck d, final File f) { - FileUtil.writeFile(f, d.save()); + + public static void writeDeck(final Deck d, final File f) { + FileUtil.writeFile(f, serializeDeck(d)); } @Override public void save(final Deck unit) { - FileUtil.writeFile(this.makeFileFor(unit), unit.save()); + writeDeck(unit, this.makeFileFor(unit)); + } + + private static List serializeDeck(Deck d) { + final List out = new ArrayList(); + out.add(String.format("[metadata]")); + + out.add(String.format("%s=%s", DeckFileHeader.NAME, d.getName().replaceAll("\n", ""))); + // these are optional + if (d.getComment() != null) { + out.add(String.format("%s=%s", DeckFileHeader.COMMENT, d.getComment().replaceAll("\n", ""))); + } + if (!d.getTags().isEmpty()) { + out.add(String.format("%s=%s", DeckFileHeader.TAGS, StringUtils.join(d.getTags(), DeckFileHeader.TAGS_SEPARATOR))); + } + + for(Entry s : d) { + out.add(String.format("[%s]", s.getKey().toString())); + out.add(s.getValue().toCardList(System.getProperty("line.separator"))); + } + return out; } + + public static Deck fromFile(final File deckFile) { + return fromSections(FileSection.parseSections(FileUtil.readFile(deckFile)), false); + } + + + public static Deck fromSections(final Map> sections) { + return fromSections(sections, false); + } + + + private static Deck fromSections(final Map> sections, final boolean canThrowExtendedErrors) { + if (sections == null || sections.isEmpty()) { + return null; + } + + final DeckFileHeader dh = DeckSerializer.readDeckMetadata(sections, canThrowExtendedErrors); + if (dh == null) { + return null; + } + + final Deck d = new Deck(dh.getName()); + d.setComment(dh.getComment()); + d.getTags().addAll(dh.getTags()); + + boolean hasExplicitlySpecifiedSet = false; + + for (Entry> s : sections.entrySet()) { + DeckSection sec = DeckSection.smartValueOf(s.getKey()); + if (sec == null) { + continue; + } + + for(String k : s.getValue()) + if ( k.indexOf(CardDb.NameSetSeparator) > 0 ) + hasExplicitlySpecifiedSet = true; + + CardPool pool = CardPool.fromCardList(s.getValue()); + // I used to store planes and schemes under sideboard header, so this will assign them to a correct section + IPaperCard sample = pool.get(0); + if (sample != null && ( sample.getRules().getType().isPlane() || sample.getRules().getType().isPhenomenon())) { + sec = DeckSection.Planes; + } + if (sample != null && sample.getRules().getType().isScheme()) { + sec = DeckSection.Schemes; + } + + d.putSection(sec, pool); + } + + if (!hasExplicitlySpecifiedSet) { + d.convertByXitaxMethod(); + } + + return d; + } + @Override public void erase(final Deck unit) { this.makeFileFor(unit).delete(); @@ -77,7 +161,7 @@ public static void writeDeck(final Deck d, final File f) { @Override protected Deck read(final File file) { final Map> sections = FileSection.parseSections(FileUtil.readFile(file)); - Deck result = Deck.fromSections(sections, true); + Deck result = fromSections(sections, true); if (moveWronglyNamedDecks) { adjustFileLocation(file, result); diff --git a/forge-core/src/main/java/forge/item/PreconDeck.java b/forge-core/src/main/java/forge/item/PreconDeck.java index d39ccb4b51d..29d71fedeb3 100644 --- a/forge-core/src/main/java/forge/item/PreconDeck.java +++ b/forge-core/src/main/java/forge/item/PreconDeck.java @@ -134,7 +134,7 @@ public class PreconDeck implements InventoryItemFromSet { String description = kv.get("Description"); String deckEdition = kv.get("set"); String set = deckEdition == null || StaticData.instance().getEditions().get(deckEdition.toUpperCase()) == null ? "n/a" : deckEdition; - PreconDeck result = new PreconDeck(Deck.fromSections(sections), set, description); + PreconDeck result = new PreconDeck(DeckSerializer.fromSections(sections), set, description); result.imageFilename = imageFilename; return result; } diff --git a/forge-gui/src/main/java/forge/deck/io/DeckGroupSerializer.java b/forge-gui/src/main/java/forge/deck/io/DeckGroupSerializer.java index 96a9a47a7d0..b2c0d21eec8 100644 --- a/forge-gui/src/main/java/forge/deck/io/DeckGroupSerializer.java +++ b/forge-gui/src/main/java/forge/deck/io/DeckGroupSerializer.java @@ -27,7 +27,6 @@ import com.google.common.collect.ImmutableList; import forge.deck.Deck; import forge.deck.DeckGroup; -import forge.util.FileUtil; import forge.util.IItemSerializer; import forge.util.storage.StorageReaderFolder; @@ -59,10 +58,10 @@ public class DeckGroupSerializer extends StorageReaderFolder implemen public void save(final DeckGroup unit) { final File f = this.makeFileFor(unit); f.mkdir(); - FileUtil.writeFile(new File(f, this.humanDeckFile), unit.getHumanDeck().save()); + DeckSerializer.writeDeck(unit.getHumanDeck(), new File(f, this.humanDeckFile)); final List aiDecks = unit.getAiDecks(); for (int i = 1; i <= aiDecks.size(); i++) { - FileUtil.writeFile(new File(f, "ai-" + i + ".dck"), aiDecks.get(i - 1).save()); + DeckSerializer.writeDeck(aiDecks.get(i - 1), new File(f, "ai-" + i + ".dck")); } } @@ -72,7 +71,7 @@ public class DeckGroupSerializer extends StorageReaderFolder implemen @Override protected final DeckGroup read(final File file) { - final Deck human = Deck.fromFile(new File(file, this.humanDeckFile)); + final Deck human = DeckSerializer.fromFile(new File(file, this.humanDeckFile)); if (null == human) { return null; } @@ -85,7 +84,7 @@ public class DeckGroupSerializer extends StorageReaderFolder implemen break; } - d.addAiDeck(Deck.fromFile(theFile)); + d.addAiDeck(DeckSerializer.fromFile(theFile)); } return d; } diff --git a/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java b/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java index 207662c6033..3d2e79216b8 100644 --- a/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java +++ b/forge-gui/src/main/java/forge/deck/io/OldDeckParser.java @@ -130,12 +130,12 @@ public class OldDeckParser { private void convertDrafts() { for (final File f : this.deckDir.listFiles(OldDeckParser.BDK_FILE_FILTER)) { boolean gotError = false; - final Deck human = Deck.fromFile(new File(f, "0.dck")); + final Deck human = DeckSerializer.fromFile(new File(f, "0.dck")); final DeckGroup d = new DeckGroup(human.getName()); d.setHumanDeck(human); for (int i = 1; i < DeckGroupSerializer.MAX_DRAFT_PLAYERS; i++) { - final Deck nextAi = Deck.fromFile(new File(f, i + ".dck")); + final Deck nextAi = DeckSerializer.fromFile(new File(f, i + ".dck")); if (nextAi == null) { gotError = true; break; @@ -176,7 +176,7 @@ public class OldDeckParser { if (dh.isCustomPool()) { try { - this.cube.add(Deck.fromSections(sections)); + this.cube.add(DeckSerializer.fromSections(sections)); importedOk = true; } catch (final NoSuchElementException ex) { @@ -196,7 +196,7 @@ public class OldDeckParser { switch (dh.getDeckType()) { case Constructed: try { - this.constructed.add(Deck.fromSections(sections)); + this.constructed.add(DeckSerializer.fromSections(sections)); importedOk = true; } catch (final NoSuchElementException ex) { if (!allowDeleteUnsupportedConstructed) { @@ -219,7 +219,7 @@ public class OldDeckParser { stored = ImmutablePair.of(new DeckGroup(name), MutablePair.of((File) null, (File) null)); } - final Deck deck = Deck.fromSections(sections); + final Deck deck = DeckSerializer.fromSections(sections); if (dh.isIntendedForAi()) { stored.getLeft().addAiDeck(deck); stored.getRight().setRight(f); diff --git a/forge-gui/src/main/java/forge/gui/deckchooser/FDeckChooser.java b/forge-gui/src/main/java/forge/gui/deckchooser/FDeckChooser.java index 1a3d8f35032..4f21c127ce4 100644 --- a/forge-gui/src/main/java/forge/gui/deckchooser/FDeckChooser.java +++ b/forge-gui/src/main/java/forge/gui/deckchooser/FDeckChooser.java @@ -12,7 +12,6 @@ import org.apache.commons.lang3.StringUtils; import forge.Command; import forge.Singletons; -import forge.card.ColorSet; import forge.deck.Deck; import forge.game.GameType; import forge.game.player.RegisteredPlayer; diff --git a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java index 12ff091a5f0..e176bdde6ee 100644 --- a/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java +++ b/forge-gui/src/main/java/forge/gui/deckeditor/controllers/CCurrentDeck.java @@ -172,7 +172,7 @@ public enum CCurrentDeck implements ICDoc { try { ((DeckController) CDeckEditorUI.SINGLETON_INSTANCE .getCurrentEditorController().getDeckController()) - .setModel(Deck.fromFile(file)); + .setModel(DeckSerializer.fromFile(file)); } catch (final Exception ex) { BugReporter.reportException(ex); diff --git a/forge-gui/src/main/java/forge/net/FServer.java b/forge-gui/src/main/java/forge/net/FServer.java index 5e6364186db..550f98a2b83 100644 --- a/forge-gui/src/main/java/forge/net/FServer.java +++ b/forge-gui/src/main/java/forge/net/FServer.java @@ -10,6 +10,7 @@ import com.google.common.base.Supplier; import forge.Singletons; import forge.deck.Deck; +import forge.deck.io.DeckSerializer; import forge.game.Game; import forge.game.GameLogEntry; import forge.game.GameRules; @@ -120,7 +121,7 @@ public enum FServer { private Deck deckFromCommandLineParameter(String deckname) { int dotpos = deckname.lastIndexOf('.'); if(dotpos > 0 && dotpos == deckname.length()-4) - return Deck.fromFile(new File(deckname)); + return DeckSerializer.fromFile(new File(deckname)); return Singletons.getModel().getDecks().getConstructed().get(deckname); } /** diff --git a/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java b/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java index 7e9133315aa..0823b248bf4 100644 --- a/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java +++ b/forge-gui/src/main/java/forge/quest/io/QuestChallengeReader.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; import forge.ImageKeys; -import forge.deck.Deck; import forge.deck.io.DeckSerializer; import forge.properties.NewConstants; import forge.quest.QuestEventChallenge; @@ -50,7 +49,7 @@ public class QuestChallengeReader extends StorageReaderFolder { qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon")); // Deck - qc.setEventDeck(Deck.fromSections(contents)); + qc.setEventDeck(DeckSerializer.fromSections(contents)); return qc; }