Deck and DeckManager restored?

This commit is contained in:
Doublestrike
2011-09-03 12:13:39 +00:00
parent 8310c076ab
commit 51c52609c3
3 changed files with 905 additions and 0 deletions

View File

@@ -0,0 +1,390 @@
package forge.deck;
import forge.Constant;
import forge.card.CardDb;
import forge.card.CardPool;
import forge.card.CardPoolView;
import forge.card.CardPrinted;
import java.io.Serializable;
import java.util.*;
/**
* <p>Deck class.</p>
*
* @author Forge
* @version $Id: Deck.java 10183 2011-09-02 22:51:47Z Max mtg $
*/
public final class Deck implements Comparable<Deck>, Serializable {
/**
*
*/
private static final long serialVersionUID = -7478025567887481994L;
//gameType is from Constant.GameType, like Constant.GameType.Regular
private Map<String, String> metadata = new HashMap<String, String>();
private CardPool main;
private CardPool sideboard;
private CardPool humanExtraCards;
private CardPool aiExtraCards;
/** Constant <code>NAME="Name"</code> */
public static final String NAME = "Name";
/** Constant <code>DECK_TYPE="Deck Type"</code> */
public static final String DECK_TYPE = "Deck Type";
/** Constant <code>COMMENT="Comment"</code> */
public static final String COMMENT = "Comment";
/** Constant <code>DESCRIPTION="Description"</code> */
public static final String DESCRIPTION = "Description";
/** Constant <code>DIFFICULTY="Difficulty"</code> */
public static final String DIFFICULTY = "Difficulty";
//gameType is from Constant.GameType, like Constant.GameType.Regular
/**
* <p>Constructor for Deck.</p>
*/
public Deck() {
main = new CardPool();
sideboard = new CardPool();
}
/**
* <p>Constructor for Deck.</p>
*
* @param deckType a {@link java.lang.String} object.
* @param main a {@link java.util.List} object.
* @param sideboard a {@link java.util.List} object.
* @param name a {@link java.lang.String} object.
*/
public Deck(String deckType, List<String> main, List<String> sideboard, String name) {
setDeckType(deckType);
setName(name);
this.main = new CardPool(main);
this.sideboard = new CardPool(sideboard);
}
/**
* <p>Constructor for Deck.</p>
*
* @param type a {@link java.lang.String} object.
*/
public Deck(final String type) {
this();
setDeckType(type);
}
/**
* <p>Getter for the field <code>main</code>.</p>
*
* @return a {@link java.util.List} object.
*/
public CardPoolView getMain() {
return main.getView();
}
/**
* <p>Getter for the field <code>sideboard</code>.</p>
*
* @return a {@link java.util.List} object.
*/
public CardPoolView getSideboard() {
return sideboard.getView();
}
/**
* <p>Getter for the field <code>humanExtraCards</code>.</p>
*
* @return a {@link java.util.List} object.
*/
public CardPoolView getHumanExtraCards() {
return humanExtraCards.getView();
}
/**
* <p>Getter for the field <code>aiExtraCards</code>.</p>
*
* @return a {@link java.util.List} object.
*/
public CardPoolView getAIExtraCards() {
return aiExtraCards.getView();
}
/**
* <p>getDeckType.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getDeckType() {
return metadata.get(DECK_TYPE);
}
//can only call this method ONCE
/**
* <p>setDeckType.</p>
*
* @param deckType a {@link java.lang.String} object.
*/
void setDeckType(String deckType) {
if (this.getDeckType() != null) {
throw new IllegalStateException(
"Deck : setDeckType() error, deck type has already been set");
}
if (!Constant.GameType.GameTypes.contains(deckType)) {
throw new RuntimeException(
"Deck : setDeckType() error, invalid deck type - " + deckType);
}
metadata.put(DECK_TYPE, deckType);
}
/**
* <p>setName.</p>
*
* @param s a {@link java.lang.String} object.
*/
public void setName(String s) {
metadata.put(NAME, s);
}
/**
* <p>getName.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getName() {
return metadata.get(NAME);
}
/**
* <p>setComment.</p>
*
* @param comment a {@link java.lang.String} object.
*/
public void setComment(String comment) {
metadata.put(COMMENT, comment);
}
/**
* <p>getComment.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getComment() {
return metadata.get(COMMENT);
}
/**
* <p>addMain.</p>
*
* @param cardName a {@link java.lang.String} object.
*/
public void addMain(final String cardName) { addMain(CardDb.instance().getCard(cardName)); }
public void addMain(final CardPrinted card) { main.add(card); }
public void addMain(final CardPoolView list) { main.addAll(list); }
public void removeMain(final CardPrinted card) { main.remove(card); }
public void removeMain(final CardPrinted card, final int amount) { main.remove(card, amount); }
public int countMain() { return main.countAll(); }
/**
* <p>addSideboard.</p>
*
* @param cardName a {@link java.lang.String} object.
*/
public final void addSideboard(final String cardName) { addSideboard(CardDb.instance().getCard(cardName)); }
public final void addSideboard(final CardPrinted card) { sideboard.add(card); }
public final void addSideboard(final CardPrinted card, final int amount) { sideboard.add(card, amount); }
public final void addSideboard(final CardPoolView cards) { sideboard.addAll(cards); }
/**
* <p>countSideboard.</p>
*
* @return a int.
*/
public int countSideboard() {
return sideboard.countAll();
}
/**
* <p>removeSideboard.</p>
*
* @param index a int.
* @return a {@link java.lang.String} object.
*/
public void removeFromSideboard(CardPrinted card) {
sideboard.remove(card);
}
/**
* <p>addHumanExtraCards.</p>
*
* @param cardName a {@link java.lang.String} object.
*/
public void addHumanExtraCards(final String cardName) { addHumanExtraCards(CardDb.instance().getCard(cardName)); }
public void addHumanExtraCards(final CardPrinted card) { humanExtraCards.add(card); }
public void addHumanExtraCards(final CardPoolView list) { humanExtraCards.addAll(list); }
public void removeHumanExtraCards(final CardPrinted card) { humanExtraCards.remove(card); }
public void removeHumanExtraCards(final CardPrinted card, final int amount) { humanExtraCards.remove(card, amount); }
public int countHumanExtraCards() { return main.countAll(); }
/**
* <p>addAIExtraCards.</p>
*
* @param cardName a {@link java.lang.String} object.
*/
public void addAIExtraCards(final String cardName) { addHumanExtraCards(CardDb.instance().getCard(cardName)); }
public void addAIExtraCards(final CardPrinted card) { aiExtraCards.add(card); }
public void addAIExtraCards(final CardPoolView list) { aiExtraCards.addAll(list); }
public void removeAIExtraCards(final CardPrinted card) { aiExtraCards.remove(card); }
public void removeAIExtraCards(final CardPrinted card, final int amount) { aiExtraCards.remove(card, amount); }
public int countAIExtraCards() { return aiExtraCards.countAll(); }
/**
* <p>isDraft.</p>
*
* @return a boolean.
*/
public boolean isDraft() {
return getDeckType().equals(Constant.GameType.Draft);
}
/**
* <p>isSealed.</p>
*
* @return a boolean.
*/
public boolean isSealed() {
return getDeckType().equals(Constant.GameType.Sealed);
}
/**
* <p>isRegular.</p>
*
* @return a boolean.
*/
public boolean isRegular() {
return getDeckType().equals(Constant.GameType.Constructed);
}
/**
* <p>hashCode.</p>
*
* @return a int.
*/
public int hashCode() {
return getName().hashCode();
}
/** {@inheritDoc} */
@Override
public String toString() {
return getName();
}
// The setters and getters below are for Quest decks
/**
* <p>setDifficulty.</p>
*
* @param s a {@link java.lang.String} object.
*/
public void setDifficulty(String s) {
metadata.put(DIFFICULTY, s);
}
/**
* <p>getDifficulty.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getDifficulty() {
return metadata.get(DIFFICULTY);
}
/**
* <p>setDescription.</p>
*
* @param s a {@link java.lang.String} object.
*/
public void setDescription(String s) {
metadata.put(DESCRIPTION, s);
}
/**
* <p>getDescription.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getDescription() {
return metadata.get(DESCRIPTION);
}
/**
* <p>compareTo.</p>
*
* @param d a {@link forge.deck.Deck} object.
* @return a int.
*/
public int compareTo(Deck d) {
return getName().compareTo(d.getName());
}
/** {@inheritDoc} */
public boolean equals(Object o) {
if (o instanceof Deck) {
Deck d = (Deck) o;
return getName().equals(d.getName());
}
return false;
}
/**
* <p>Getter for the field <code>metadata</code>.</p>
*
* @return a {@link java.util.Set} object.
*/
public Set<Map.Entry<String, String>> getMetadata() {
return metadata.entrySet();
}
/**
* <p>Getter for the field <code>metadata</code>.</p>
*
* @param key a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
* @since 1.0.15
*/
public String getMetadata(String key) {
if (metadata.containsKey(key))
return metadata.get(key);
System.err.println("In forge.deck/Deck.java, getMetadata() failed "+
"for property '"+key+"' in deck '"+getName()+"'.");
return "";
}
/**
* <p>addMetaData.</p>
*
* @param key a {@link java.lang.String} object.
* @param value a {@link java.lang.String} object.
*/
public void addMetaData(String key, String value) {
metadata.put(key, value);
}
public void clearSideboard() {
sideboard.clear();
}
public void clearMain() {
main.clear();
}
}

View File

@@ -0,0 +1,513 @@
package forge.deck;
import forge.Constant;
import forge.card.CardPrinted;
import forge.error.ErrorViewer;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import static java.lang.Integer.parseInt;
import static java.lang.String.format;
import static java.util.Arrays.asList;
//reads and writeDeck Deck objects
/**
* <p>DeckManager class.</p>
*
* @author Forge
* @version $Id: DeckManager.java 10146 2011-09-01 18:11:00Z Max mtg $
*/
public class DeckManager {
/** Constant <code>BDKFileFilter</code> */
private static FilenameFilter BDKFileFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".bdk");
}
};
/** Constant <code>DCKFileFilter</code> */
private static FilenameFilter DCKFileFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".dck");
}
};
private File deckDir;
Map<String, Deck> deckMap;
Map<String, Deck[]> draftMap;
/**
* <p>Constructor for DeckManager.</p>
*
* @param deckDir a {@link java.io.File} object.
*/
public DeckManager(File deckDir) {
if (deckDir == null) {
throw new IllegalArgumentException("No deck directory specified");
}
try {
this.deckDir = deckDir;
if (deckDir.isFile()) {
throw new IOException("Not a directory");
} else {
deckDir.mkdirs();
if (!deckDir.isDirectory()) {
throw new IOException("Directory can't be created");
}
this.deckMap = new HashMap<String, Deck>();
this.draftMap = new HashMap<String, Deck[]>();
readAllDecks();
}
} catch (IOException ex) {
ErrorViewer.showError(ex);
throw new RuntimeException("DeckManager : writeDeck() error, " + ex.getMessage());
}
}
/**
* <p>isUnique.</p>
*
* @param deckName a {@link java.lang.String} object.
* @return a boolean.
*/
public boolean isUnique(String deckName) {
return !deckMap.containsKey(deckName);
}
/**
* <p>isUniqueDraft.</p>
*
* @param deckName a {@link java.lang.String} object.
* @return a boolean.
*/
public boolean isUniqueDraft(String deckName) {
return !draftMap.keySet().contains(deckName);
}
/**
* <p>getDeck.</p>
*
* @param deckName a {@link java.lang.String} object.
* @return a {@link forge.deck.Deck} object.
*/
public Deck getDeck(String deckName) {
return deckMap.get(deckName);
}
/**
* <p>addDeck.</p>
*
* @param deck a {@link forge.deck.Deck} object.
*/
public void addDeck(Deck deck) {
if (deck.getDeckType().equals(Constant.GameType.Draft)) {
throw new RuntimeException(
"DeckManager : addDeck() error, deck type is Draft");
}
deckMap.put(deck.getName(), deck);
}
/**
* <p>deleteDeck.</p>
*
* @param deckName a {@link java.lang.String} object.
*/
public void deleteDeck(String deckName) {
deckMap.remove(deckName);
}
/**
* <p>getDraftDeck.</p>
*
* @param deckName a {@link java.lang.String} object.
* @return an array of {@link forge.deck.Deck} objects.
*/
public Deck[] getDraftDeck(String deckName) {
if (!draftMap.containsKey(deckName)) {
throw new RuntimeException(
"DeckManager : getDraftDeck() error, deck name not found - " + deckName);
}
return draftMap.get(deckName);
}
/**
* <p>addDraftDeck.</p>
*
* @param deck an array of {@link forge.deck.Deck} objects.
*/
public void addDraftDeck(Deck[] deck) {
checkDraftDeck(deck);
draftMap.put(deck[0].toString(), deck);
}
/**
* <p>deleteDraftDeck.</p>
*
* @param deckName a {@link java.lang.String} object.
*/
public void deleteDraftDeck(String deckName) {
if (!draftMap.containsKey(deckName)) {
throw new RuntimeException(
"DeckManager : deleteDraftDeck() error, deck name not found - " + deckName);
}
draftMap.remove(deckName);
}
/**
* <p>checkDraftDeck.</p>
*
* @param deck an array of {@link forge.deck.Deck} objects.
*/
private void checkDraftDeck(Deck[] deck) {
if (deck == null || deck.length != 8 || deck[0].getName().equals("")
|| (!deck[0].getDeckType().equals(Constant.GameType.Draft))) {
throw new RuntimeException("DeckManager : checkDraftDeck() error, invalid deck");
}
}
/**
* <p>getDecks.</p>
*
* @return a {@link java.util.Collection} object.
*/
public Collection<Deck> getDecks() {
return deckMap.values();
}
/**
* <p>getDraftDecks.</p>
*
* @return a {@link java.util.Map} object.
*/
public Map<String, Deck[]> getDraftDecks() {
return new HashMap<String, Deck[]>(draftMap);
}
/**
* <p>close.</p>
*/
public void close() {
writeAllDecks();
}
/**
* <p>readAllDecks.</p>
*/
public void readAllDecks() {
deckMap.clear();
draftMap.clear();
File[] files;
files = deckDir.listFiles(DCKFileFilter);
for (File file : files) {
Deck newDeck = readDeck(file);
deckMap.put(newDeck.getName(), newDeck);
}
files = deckDir.listFiles(BDKFileFilter);
for (File file : files) {
Deck[] d = new Deck[8];
for (int i = 0; i < d.length; i++) {
d[i] = readDeck(new File(file, i + ".dck"));
}
draftMap.put(d[0].getName(), d);
}
}
/**
* <p>readDeck.</p>
*
* @param deckFile a {@link java.io.File} object.
* @return a {@link forge.deck.Deck} object.
*/
public static Deck readDeck(File deckFile) {
List<String> lines = new LinkedList<String>();
try {
BufferedReader r = new BufferedReader(new FileReader(deckFile));
String line;
while ((line = r.readLine()) != null) {
lines.add(line);
}
r.close();
} catch (IOException e) {
e.printStackTrace();
}
ListIterator<String> lineIterator = lines.listIterator();
String line = lineIterator.next();
//Old text-based format
if (!line.equals("[metadata]")) {
lineIterator.previous();
return readDeckOld(lineIterator);
}
Deck d = new Deck();
//read metadata
while (!(line = lineIterator.next()).equals("[main]")) {
String[] linedata = line.split("=", 2);
d.addMetaData(linedata[0], linedata[1]);
}
addCardList(lineIterator, d);
return d;
}
/**
* <p>readDeckOld.</p>
*
* @param iterator a {@link java.util.ListIterator} object.
* @return a {@link forge.deck.Deck} object.
*/
private static Deck readDeckOld(ListIterator<String> iterator) {
String line;
//readDeck name
String name = iterator.next();
//readDeck comments
String comment = null;
while ((line = iterator.next()) != null && !line.equals("[general]")) {
if (comment == null) {
comment = line;
} else {
comment += "\n" + line;
}
}
//readDeck deck type
String deckType = iterator.next();
Deck d = new Deck();
d.setName(name);
d.setComment(comment);
d.setDeckType(deckType);
//go to [main]
while ((line = iterator.next()) != null && !line.equals("[main]")) {
System.err.println("unexpected line: " + line);
}
addCardList(iterator, d);
return d;
}
/**
* <p>addCardList.</p>
*
* @param lineIterator a {@link java.util.ListIterator} object.
* @param d a {@link forge.deck.Deck} object.
*/
private static void addCardList(ListIterator<String> lineIterator, Deck d) {
String line;
Pattern p = Pattern.compile("\\s*((\\d+)\\s+)?(.*?)\\s*");
//readDeck main deck
while (lineIterator.hasNext() && !(line = lineIterator.next()).equals("[sideboard]")) {
Matcher m = p.matcher(line);
m.matches();
String s = m.group(2);
int count = s == null ? 1 : parseInt(s);
for (int i = 0; i < count; i++) {
d.addMain(m.group(3));
}
}
//readDeck sideboard
while (lineIterator.hasNext() && !(line = lineIterator.next()).equals("[human_extra_cards]")) {
Matcher m = p.matcher(line);
m.matches();
String s = m.group(2);
String cardName = m.group(3);
if (StringUtils.isBlank(cardName)) { continue; }
int count = s == null ? 1 : parseInt(s);
for (int i = 0; i < count; i++) {
d.addSideboard(cardName);
}
}
while (lineIterator.hasNext() && !(line = lineIterator.next()).equals("[ai_extra_cards]")) {
Matcher m = p.matcher(line);
m.matches();
String s = m.group(2);
String cardName = m.group(3);
if (StringUtils.isBlank(cardName)) { continue; }
int count = s == null ? 1 : parseInt(s);
for (int i = 0; i < count; i++) {
d.addHumanExtraCards(cardName);
}
}
while (lineIterator.hasNext()) {
line = lineIterator.next();
Matcher m = p.matcher(line);
m.matches();
String s = m.group(2);
String cardName = m.group(3);
if (StringUtils.isBlank(cardName)) { continue; }
int count = s == null ? 1 : parseInt(s);
for (int i = 0; i < count; i++) {
d.addAIExtraCards(cardName);
}
}
}
/**
* <p>deriveFileName.</p>
*
* @param deckName a {@link java.lang.String} object.
* @return a {@link java.lang.String} object.
*/
private String deriveFileName(String deckName) {
//skips all but the listed characters
return deckName.replaceAll("[^-_$#@.{[()]} a-zA-Z0-9]", "");
}
/**
* <p>writeAllDecks.</p>
*/
public void writeAllDecks() {
try {
//store the files that do exist
List<File> files = new ArrayList<File>();
files.addAll(asList(deckDir.listFiles(DCKFileFilter)));
//save the files and remove them from the list
for (Deck deck : deckMap.values()) {
File f = new File(deckDir, deriveFileName(deck.getName()) + ".dck");
files.remove(f);
BufferedWriter out = new BufferedWriter(new FileWriter(f));
writeDeck(deck, out);
out.close();
}
//delete the files that were not written out: the decks that were deleted
for (File file : files) {
file.delete();
}
//store the files that do exist
files.clear();
files.addAll(asList(deckDir.listFiles(BDKFileFilter)));
//save the files and remove them from the list
for (Entry<String, Deck[]> e : draftMap.entrySet()) {
File f = new File(deckDir, deriveFileName(e.getValue()[0].getName()) + ".bdk");
f.mkdir();
for (int i = 0; i < e.getValue().length; i++) {
BufferedWriter out = new BufferedWriter(new FileWriter(new File(f, i + ".dck")));
writeDeck(e.getValue()[i], out);
out.close();
}
}
/*
//delete the files that were not written out: the decks that were deleted
for(File file:files) {
for(int i = 0; i < 8; i++)
new File(file, i + ".dck").delete();
file.delete();
}
*/
} catch (IOException ex) {
ErrorViewer.showError(ex);
throw new RuntimeException("DeckManager : writeDeck() error, " + ex.getMessage());
}
}
/**
* <p>writeDeck.</p>
*
* @param d a {@link forge.deck.Deck} object.
* @param out a {@link java.io.BufferedWriter} object.
* @throws java.io.IOException if any.
*/
private static void writeDeck(Deck d, BufferedWriter out) throws IOException {
out.write("[metadata]\n");
for (Entry<String, String> entry : d.getMetadata()) {
if (entry.getValue() != null)
out.write(format("%s=%s%n", entry.getKey(), entry.getValue().replaceAll("\n", "")));
}
out.write(format("%s%n", "[main]"));
for (Entry<CardPrinted, Integer> e : d.getMain()) {
out.write(format("%d %s%n", e.getValue(), e.getKey().getName()));
}
out.write(format("%s%n", "[sideboard]"));
for (Entry<CardPrinted, Integer> e : d.getSideboard()) {
out.write(format("%d %s%n", e.getValue(), e.getKey().getName()));
}
}
/**
* <p>count.</p>
*
* @param src a {@link java.util.List} object.
* @return a {@link java.util.Map} object.
*/
private static Map<String, Integer> count(List<String> src) {
Map<String, Integer> result = new HashMap<String, Integer>();
for (String s : src) {
Integer dstValue = result.get(s);
if (dstValue == null) {
result.put(s, 1);
} else {
result.put(s, dstValue + 1);
}
}
return result;
}
/**
* <p>writeDeck.</p>
*
* @param d a {@link forge.deck.Deck} object.
* @param f a {@link java.io.File} object.
*/
public static void writeDeck(Deck d, File f) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(f));
writeDeck(d, writer);
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}