re-arranged deck serialization code to make it more "symmetric": the what is serialized somewhere tends to be de-serialized in the same class

This commit is contained in:
Maxmtg
2014-02-02 08:39:12 +00:00
parent 86edf9fd66
commit cec3d26493
12 changed files with 160 additions and 167 deletions

View File

@@ -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; }

View File

@@ -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<PaperCard> {
}
}
}
/**
* Add all from a List of CardPrinted.
@@ -163,4 +170,28 @@ public class CardPool extends ItemPool<PaperCard> {
}
return pool;
}
public String toCardList(String separator) {
List<Entry<PaperCard, Integer>> 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<PaperCard, Integer> 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();
}
}

View File

@@ -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<Entry<DeckSection, CardPo
this.parts.put(deckSection, p);
return p;
}
public void putSection(DeckSection section, CardPool pool) {
this.parts.put(section, pool);
}
/* (non-Javadoc)
* @see forge.deck.DeckBase#cloneFieldsTo(forge.deck.DeckBase)
@@ -150,78 +138,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
return new Deck(name0);
}
/**
* From file.
*
* @param deckFile the deck file
* @return the deck
*/
public static Deck fromFile(final File deckFile) {
return Deck.fromSections(FileSection.parseSections(FileUtil.readFile(deckFile)));
}
/**
* From sections.
*
* @param sections the sections
* @return the deck
*/
public static Deck fromSections(final Map<String, List<String>> 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<String, List<String>> 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<String, List<String>> 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<Entry<DeckSection, CardPo
}
private static List<String> writeCardPool(final ItemPool<PaperCard> pool) {
List<Entry<PaperCard, Integer>> main2sort = Lists.newArrayList(pool);
Collections.sort(main2sort, ItemPoolSorter.BY_NAME_THEN_SET);
final List<String> out = new ArrayList<String>();
for (final Entry<PaperCard, Integer> 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();
}
/**
* <p>
* writeDeck.
* </p>
*
* @return the list
*/
public List<String> save() {
final List<String> out = new ArrayList<String>();
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<DeckSection, CardPool> s : parts.entrySet()) {
out.add(String.format("[%s]", s.getKey().toString()));
out.addAll(Deck.writeCardPool(s.getValue()));
}
return out;
}
public static final Function<Deck, String> FN_NAME_SELECTOR = new Function<Deck, String>() {
@Override
public String apply(Deck arg1) {

View File

@@ -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<Deck> 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<String> serializeDeck(Deck d) {
final List<String> out = new ArrayList<String>();
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<DeckSection, CardPool> 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<String, List<String>> sections) {
return fromSections(sections, false);
}
private static Deck fromSections(final Map<String, List<String>> 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<String, List<String>> 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<String, List<String>> sections = FileSection.parseSections(FileUtil.readFile(file));
Deck result = Deck.fromSections(sections, true);
Deck result = fromSections(sections, true);
if (moveWronglyNamedDecks) {
adjustFileLocation(file, result);

View File

@@ -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;
}