Custom printsheets implemented

CardPool deserialization moved to cardpool as factory method.
This commit is contained in:
Maxmtg
2013-04-25 13:42:12 +00:00
parent edec0d0eca
commit c6c4fa5b17
10 changed files with 254 additions and 60 deletions

2
.gitattributes vendored
View File

@@ -15,6 +15,7 @@ res/blockdata/blocks.txt svneol=native#text/plain
res/blockdata/fantasyblocks.txt -text
res/blockdata/fatpacks.txt -text
res/blockdata/formats.txt -text
res/blockdata/printsheets.txt -text
res/blockdata/setdata.txt svneol=native#text/plain
res/blockdata/starters.txt -text
res/cardsfolder/a/a_display_of_my_dark_power.txt -text
@@ -14418,6 +14419,7 @@ src/main/java/forge/util/storage/IStorage.java -text
src/main/java/forge/util/storage/IStorageView.java -text
src/main/java/forge/util/storage/StorageImmediatelySerialized.java svneol=native#text/plain
src/main/java/forge/util/storage/StorageReaderFile.java -text
src/main/java/forge/util/storage/StorageReaderFileSections.java -text
src/main/java/forge/util/storage/StorageReaderFolder.java -text
src/main/java/forge/util/storage/StorageView.java -text
src/main/java/forge/util/storage/package-info.java -text

View File

@@ -20,7 +20,7 @@ CFX: 3 covers, 10 Common, 3 Uncommon, 1 Rare, 1 BasicLand ALA
CHK: 5 covers, 11 Common, 3 Uncommon, 1 Rare
CHR: 1 covers, 9 Common, 3 UncommonRare
CSP: 3 covers, 11 Common, 3 Uncommon, 1 Rare
DGM: 3 covers, 10 Common, 3 Uncommon, 1 Rare:!name("Maze's End"), 1 MazeLand
DGM: 3 covers, 10 Common, 3 Uncommon, 1 Rare:!name("Maze's End"), 1 Custom("Dragon's Maze Lands")
DIS: 3 covers, 11 Common, 3 Uncommon, 1 Rare
DKA: 3 covers, 9 Common:!dfc, 3 Uncommon:!dfc, 1 Rare:!dfc, 1 Any:dfc, 1 BasicLand ISD
DRK: 1 covers, 6 Common, 2 UncommonRare

View File

@@ -0,0 +1,23 @@
[Dragon's Maze Lands]
# Uncomment all after DGM set is added to setdata.txt
#10 Azorius Guildgate|DGM
#10 Boros Guildgate|DGM
#10 Dimir Guildgate|DGM
#10 Golgari Guildgate|DGM
#10 Gruul Guildgate|DGM
#10 Izzet Guildgate|DGM
#10 Orzhov Guildgate|DGM
#10 Rakdos Guildgate|DGM
#10 Selesnya Guildgate|DGM
#10 Simic Guildgate|DGM
2 Blood Crypt|RTR
2 Hallowed Fountain|RTR
2 Overgrown Tomb|RTR
2 Steam Vents|RTR
2 Temple Garden|RTR
2 Breeding Pool|GTC
2 Godless Shrine|GTC
2 Sacred Foundry|GTC
2 Stomping Ground|GTC
2 Watery Grave|GTC
#1 Maze's End|DGM

View File

@@ -31,10 +31,12 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.item.CardDb;
import forge.item.CardPrinted;
import forge.item.IPaperCard;
import forge.item.PrintSheet;
import forge.model.FModel;
import forge.util.TextUtil;
/**
@@ -86,7 +88,7 @@ public class BoosterGenerator {
@SuppressWarnings("unchecked")
private static final PrintSheet makeSheet(String sheetKey, Iterable<CardPrinted> src) {
PrintSheet ps = new PrintSheet();
PrintSheet ps = new PrintSheet(sheetKey);
String[] sKey = TextUtil.splitWithParenthesis(sheetKey, ' ', '(', ')', 2);
String[] operators = TextUtil.splitWithParenthesis(sKey[0], ':', '(', ')');
@@ -148,8 +150,9 @@ public class BoosterGenerator {
Predicate<CardPrinted> predicate = Predicates.and( setPred, IPaperCard.Predicates.Presets.IS_SPECIAL, extraPred );
ps.addAll(Iterables.filter(src, predicate));
} else if ( mainCode.equalsIgnoreCase("mazeland") ) {
} else if ( mainCode.equalsIgnoreCase("custom(") ) {
String sheetName = StringUtils.strip(mainCode.substring(6), "()\" ");
return Singletons.getModel().getPrintSheets().get(sheetName);
}
return ps;
}

View File

@@ -17,10 +17,15 @@
*/
package forge.deck;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.NoSuchElementException;
import org.apache.commons.lang3.StringUtils;
import forge.Card;
import forge.item.CardDb;
import forge.item.CardPrinted;
@@ -49,19 +54,6 @@ public class CardPool extends ItemPool<CardPrinted> {
this.addAll(cards);
}
/**
* Sets the.
*
* @param cardNames
* the card names
*/
public void set(final Iterable<String> cardNames) {
this.clear();
for (final String name : cardNames) {
this.add(name);
}
}
/**
* Adds the.
*
@@ -131,13 +123,13 @@ public class CardPool extends ItemPool<CardPrinted> {
*
* @param cardName the card name
*/
public void add(final String cardName) {
public void add(final String cardName, int cnt) {
CardPrinted cp = CardDb.instance().tryGetCard(cardName);
if ( cp == null )
cp = CardDb.variants().tryGetCard(cardName);
if ( cp != null)
this.add(cp);
this.add(cp, cnt);
else
throw new NoSuchElementException(String.format("Card %s is not supported by Forge, as it's neither a known common card nor one of casual variants' card.", cardName));
}
@@ -171,4 +163,32 @@ public class CardPool extends ItemPool<CardPrinted> {
}
return sb.append(']').toString();
}
public static CardPool fromCardList(final Iterable<String> lines) {
CardPool pool = new CardPool();
final Pattern p = Pattern.compile("((\\d+)\\s+)?(.*?)");
if (lines == null) {
return pool;
}
final Iterator<String> lineIterator = lines.iterator();
while (lineIterator.hasNext()) {
final String line = lineIterator.next();
if (line.startsWith(";") || line.startsWith("#")) { continue; } // that is a comment or not-yet-supported card
final Matcher m = p.matcher(line.trim());
m.matches();
final String sCnt = m.group(2);
final String cardName = m.group(3);
if (StringUtils.isBlank(cardName)) {
continue;
}
final int count = sCnt == null ? 1 : Integer.parseInt(sCnt);
pool.add(cardName, count);
}
return pool;
}
}

View File

@@ -27,9 +27,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
@@ -185,9 +182,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
if ( null == sec )
continue;
CardPool pool = new CardPool();
pool.set(Deck.readCardList(s.getValue()));
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() ) )
@@ -200,34 +195,7 @@ public class Deck extends DeckBase implements Iterable<Entry<DeckSection, CardPo
return d;
}
private static List<String> readCardList(final List<String> lines) {
final List<String> result = new ArrayList<String>();
final Pattern p = Pattern.compile("((\\d+)\\s+)?(.*?)");
if (lines == null) {
return result;
}
final Iterator<String> lineIterator = lines.iterator();
while (lineIterator.hasNext()) {
final String line = lineIterator.next();
if (line.startsWith(";") || line.startsWith("#")) { continue; } // that is a comment or not-yet-supported card
final Matcher m = p.matcher(line.trim());
m.matches();
final String sCnt = m.group(2);
final String cardName = m.group(3);
if (StringUtils.isBlank(cardName)) {
continue;
}
final int count = sCnt == null ? 1 : Integer.parseInt(sCnt);
for (int i = 0; i < count; i++) {
result.add(cardName);
}
}
return result;
}
private static List<String> writeCardPool(final ItemPoolView<CardPrinted> pool) {
final List<Entry<CardPrinted, Integer>> main2sort = pool.getOrderedList();

View File

@@ -84,12 +84,12 @@ public enum CDeckgen implements ICDoc {
Iterable<CardPrinted> source = Iterables.filter(CardDb.instance().getUniqueCards(), notBasicLand);
randomDeck.getMain().addAllFlat(Aggregates.random(source, 15 * 5));
randomDeck.getMain().add("Plains");
randomDeck.getMain().add("Island");
randomDeck.getMain().add("Swamp");
randomDeck.getMain().add("Mountain");
randomDeck.getMain().add("Forest");
randomDeck.getMain().add("Terramorphic Expanse");
randomDeck.getMain().add("Plains", 1);
randomDeck.getMain().add("Island", 1);
randomDeck.getMain().add("Swamp", 1);
randomDeck.getMain().add("Mountain", 1);
randomDeck.getMain().add("Forest", 1);
randomDeck.getMain().add("Terramorphic Expanse", 1);
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>)
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();

View File

@@ -1,10 +1,16 @@
package forge.item;
import java.io.File;
import java.util.List;
import java.util.Map.Entry;
import java.util.ArrayList;
import java.util.Collection;
import com.google.common.base.Function;
import forge.deck.CardPool;
import forge.util.MyRandom;
import forge.util.storage.StorageReaderFileSections;
/**
@@ -12,9 +18,24 @@ import forge.util.MyRandom;
*
*/
public class PrintSheet {
private final ItemPool<CardPrinted> cardsWithWeights = new ItemPool<CardPrinted>(CardPrinted.class);
public static final Function<PrintSheet, String> FN_GET_KEY = new Function<PrintSheet, String>() {
@Override public final String apply(PrintSheet sheet) { return sheet.name; }
};
private final ItemPool<CardPrinted> cardsWithWeights;
private final String name;
public PrintSheet(String name0) {
this(name0, null);
}
private PrintSheet(String name0, ItemPool<CardPrinted> pool) {
name = name0;
cardsWithWeights = pool != null ? pool : new ItemPool<CardPrinted>(CardPrinted.class);
}
public void add(CardPrinted card) {
add(card,1);
}
@@ -67,5 +88,16 @@ public class PrintSheet {
return result;
}
public static class Reader extends StorageReaderFileSections<PrintSheet> {
public Reader(String fileName) {
super(fileName, PrintSheet.FN_GET_KEY);
}
@Override
protected PrintSheet read(String title, Iterable<String> body, int idx) {
return new PrintSheet(title, CardPool.fromCardList(body));
}
}
}

View File

@@ -42,6 +42,7 @@ import forge.game.MatchController;
import forge.game.limited.GauntletMini;
import forge.gauntlet.GauntletData;
import forge.item.CardDb;
import forge.item.PrintSheet;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
import forge.properties.NewConstants;
@@ -89,6 +90,7 @@ public enum FModel {
private final IStorageView<CardBlock> blocks;
private final IStorageView<CardBlock> fantasyBlocks;
private final IStorageView<QuestWorld> worlds;
private final IStorageView<PrintSheet> printSheets;
/**
* Constructor.
@@ -170,6 +172,8 @@ public enum FModel {
this.decks = new CardCollections();
this.quest = new QuestController();
this.printSheets = new StorageView<PrintSheet>(new PrintSheet.Reader("res/blockdata/printsheets.txt"));
}
public final QuestController getQuest() {
@@ -373,6 +377,10 @@ public enum FModel {
return boosters;
}
public IStorageView<PrintSheet> getPrintSheets() {
return printSheets;
}
/**
* TODO: Write javadoc for this method.
* @param data0 {@link forge.gauntlet.GauntletData}
@@ -392,4 +400,6 @@ public enum FModel {
}
return gauntlet;
}
}

View File

@@ -0,0 +1,136 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Nate
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.util.storage;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JOptionPane;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Function;
import forge.util.FileUtil;
import forge.util.IItemReader;
/**
* This class treats every line of a given file as a source for a named object.
*
* @param <T>
* the generic type
*/
public abstract class StorageReaderFileSections<T> implements IItemReader<T> {
private final File file;
private final Function<? super T, String> keySelector;
public StorageReaderFileSections(final String pathname, final Function<? super T, String> keySelector0) {
this(new File(pathname), keySelector0);
}
public StorageReaderFileSections(final File file0, final Function<? super T, String> keySelector0) {
this.file = file0;
this.keySelector = keySelector0;
}
/* (non-Javadoc)
* @see forge.util.IItemReader#readAll()
*/
@Override
public Map<String, T> readAll() {
final Map<String, T> result = new TreeMap<String, T>();
int idx = 0;
Iterable<String> file = FileUtil.readFile(this.file);
List<String> accumulator = new ArrayList<String>();
String header = null;
for (final String s : file) {
if (!this.lineContainsObject(s)) {
continue;
}
if(s.charAt(0) == '[') {
if( header != null ) {
// read previously collected item
T item = readItem(header, accumulator, idx);
if( item != null ) {
result.put(this.keySelector.apply(item), item);
idx++;
}
}
header = StringUtils.strip(s, "[] ");
accumulator.clear();
} else
accumulator.add(s);
}
// store the last item
if ( !accumulator.isEmpty() ) {
T item = readItem(header, accumulator, idx);
if( item != null ) {
result.put(this.keySelector.apply(item), item);
}
}
return result;
}
private final T readItem(String header, Iterable<String> accumulator, int idx) {
final T item = this.read(header, accumulator, idx);
if (null != item) return item;
final String msg = "An object stored in " + this.file.getPath() + " failed to load.\nPlease submit this as a bug with the mentioned file attached.";
JOptionPane.showMessageDialog(null, msg);
return null;
}
/**
* TODO: Write javadoc for this method.
*
* @param line
* the line
* @return the t
*/
protected abstract T read(String title, Iterable<String> body, int idx);
/**
* Line contains object.
*
* @param line
* the line
* @return true, if successful
*/
protected boolean lineContainsObject(final String line) {
return !StringUtils.isBlank(line) && !line.trim().startsWith("#");
}
/* (non-Javadoc)
* @see forge.util.IItemReader#getItemKey(java.lang.Object)
*/
@Override
public String getItemKey(final T item) {
return this.keySelector.apply(item);
}
}