DeckImport - wip

This commit is contained in:
Maxmtg
2011-09-21 04:00:53 +00:00
parent 33ce88cb56
commit b270e744ef
3 changed files with 149 additions and 40 deletions

View File

@@ -1,7 +1,10 @@
package forge.deck;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import forge.item.CardDb;
import forge.item.CardPrinted;
/**
@@ -58,9 +61,63 @@ public class DeckRecognizer {
public int getNumber() { return number; }
}
public static Token recognizeLine(String line)
// Let's think about it numbers in the back later
// private static final Pattern searchNumbersInBack = Pattern.compile("(.*)[^A-Za-wyz]*\\s+([\\d]{1,2})");
private static final Pattern searchNumbersInFront = Pattern.compile("([\\d]{1,2})[^A-Za-wyz]*\\s+(.*)");
public static Token recognizeLine(String raw_line)
{
return new Token(TokenType.Unknown, 0, line);
if (StringUtils.isBlank(raw_line)) { return new Token(TokenType.Comment, 0, raw_line); }
String line = raw_line.trim();
Token result = null;
Matcher foundNumbersInFront = searchNumbersInFront.matcher(line);
// Matcher foundNumbersInBack = searchNumbersInBack.matcher(line);
if (foundNumbersInFront.matches()) {
String cardName = foundNumbersInFront.group(2);
int amount = Integer.parseInt(foundNumbersInFront.group(1));
result = recognizePossibleNameAndNumber(cardName, amount);
} /* else if (foundNumbersInBack.matches()) {
String cardName = foundNumbersInBack.group(1);
int amount = Integer.parseInt(foundNumbersInBack.group(2));
return new Token(cardName, amount);
} */else {
if ( CardDb.instance().isCardSupported(line)) {
return new Token( CardDb.instance().getCard(line), 1);
}
result = recognizeNonCard(line, 1);
}
return result != null ? result : new Token(TokenType.Unknown, 0, line);
}
private static Token recognizePossibleNameAndNumber(String name, int n) {
if ( CardDb.instance().isCardSupported(name))
return new Token( CardDb.instance().getCard(name), n);
Token known = recognizeNonCard(name, n);
return null == known ? new Token(name, n) : known;
}
private static Token recognizeNonCard(String text, int n) {
if (isDecoration(text)) { return new Token(TokenType.Comment, n, text); }
if (isSectionName(text)) { return new Token(TokenType.SectionName, n, text); }
return null;
}
private final static String[] knownComments = new String[] {
"lands", "creatures", "creature", "spells", "enchancements", "other spells", "artifacts", "cards" };
private static boolean isDecoration(String line) {
for (String s : knownComments) {
if (line.equalsIgnoreCase(s)) { return true; }
}
return false;
}
private static boolean isSectionName(String line) {
if (line.equalsIgnoreCase("sideboard")) { return true; }
if (line.equalsIgnoreCase("MAIN BOARD")) { return true; }
if (line.equalsIgnoreCase("MAIN")) { return true; }
return false;
}
}

View File

@@ -3,7 +3,6 @@ package forge.gui.deckeditor;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
@@ -12,7 +11,7 @@ import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
@@ -28,6 +27,7 @@ import net.miginfocom.swing.MigLayout;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckRecognizer;
import forge.deck.DeckRecognizer.TokenType;
import forge.gui.GuiUtils;
/**
@@ -38,9 +38,30 @@ public class DeckImport extends JDialog {
private static final long serialVersionUID = -5837776824284093004L;
private JTextArea txtInput = new JTextArea();
private JEditorPane htmlOutput = new JEditorPane("text/html", "<html><style>.rose { color:#ebaeba; }</style><h3 class=\"rose\">Expect result here</h3></html>");
private static final String stylesheet = "<style>" +
"body, h1, h2, h3, h4, h5, h6, table, tr, td, p {margin: 1px; padding: 0; font-weight: normal; font-style: normal; text-decoration: none; font-family: Arial; font-size: 10px;} " +
//"h1 {border-bottom: solid 1px black; color: blue; font-size: 12px; margin: 3px 0 9px 0; } " +
".comment {color: #666666;} " +
".knowncard {color: #009900;} " +
".unknowncard {color: #990000;} " +
".section {font-weight: bold; margin: 6px 0; text-decoration: underline; } " +
"</style>";
private static final String htmlWelcomeText = "<html>"+stylesheet+"<h3>You'll see recognized cards here</h3>" +
"<div class='section'>Legend</div>" +
"<ul>" +
"<li class='knowncard'>Recognized cards will be shown in green. These cards will be auto-imported into a new deck<BR></li>" +
"<li class='unknowncard'>Lines which seem to see cards but could not be recognized, are shown in red<BR></li>" +
"<li class='comment'>Lines that appear unsignificant will be shown in gray<BR><BR></li>" +
"</ul>" +
"<div class='comment'>Submit feedback to Max mtg on slightlymagic.net forum</div>" +
"<div class='comment'>Post bug-reports to http://cardforge.org/bugz/</div>" +
"</html>";
private JEditorPane htmlOutput = new JEditorPane("text/html", htmlWelcomeText);
private JScrollPane scrollInput = new JScrollPane(txtInput);
private JScrollPane scrollOutput = new JScrollPane(htmlOutput);
private JLabel summaryMain = new JLabel("Imported deck summary will appear here");
private JLabel summarySide = new JLabel("This is second line");
private JButton cmdAccept = new JButton("Import Deck");
private JButton cmdCancel = new JButton("Cancel");
@@ -78,10 +99,14 @@ public class DeckImport extends JDialog {
scrollOutput.setViewportBorder(BorderFactory.createLoweredBevelBorder());
getContentPane().setLayout(new MigLayout("fill"));
getContentPane().add(scrollInput, "cell 0 0, w 50%, growy, pushy");
getContentPane().add(scrollInput, "cell 0 0, w 50%, sy 4, growy, pushy");
getContentPane().add(scrollOutput, "cell 1 0, w 50%, growy, pushy");
getContentPane().add(cmdAccept, "cell 0 1, w 100, align r");
getContentPane().add(cmdCancel, "cell 1 1, w 100, align l");
getContentPane().add(summaryMain, "cell 1 1, label");
getContentPane().add(summarySide, "cell 1 2, label");
getContentPane().add(cmdAccept, "cell 1 3, split 2, w 100, align c");
getContentPane().add(cmdCancel, "w 100");
cmdCancel.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
@@ -113,18 +138,9 @@ public class DeckImport extends JDialog {
}
}
private static String stylesheet = "<style>" +
"body, h1, h2, h3, h4, h5, h6, table, tr, td, p {margin: 0; padding: 0; font-weight: normal; font-style: normal; text-decoration: none; font-family: Arial; font-size: 10px;} " +
//"h1 {border-bottom: solid 1px black; color: blue; font-size: 12px; margin: 3px 0 9px 0; } " +
".unknown {color: #660000;} " +
".comment {color: #006666;} " +
".KnownCardWithNumber {color: #009900;} " +
".UnknownCardWithNumber {color: #000099;} " +
".SectionName {font-weight: bold;} " +
"</style>";
private void displayTokens()
{
private void displayTokens() {
StringBuilder sbOut = new StringBuilder("<html>");
sbOut.append(stylesheet);
for (DeckRecognizer.Token t : tokens) {
@@ -134,13 +150,25 @@ public class DeckImport extends JDialog {
htmlOutput.setText(sbOut.toString());
}
private Deck buildDeck()
{
private void updateSummaries() {
int[] cardsOk = new int[2];
int[] cardsUnknown = new int[2];
int idx = 0;
for (DeckRecognizer.Token t : tokens) {
if (t.getType() == TokenType.KnownCardWithNumber) { cardsOk[idx] += t.getNumber(); }
if (t.getType() == TokenType.UnknownCardWithNumber) { cardsUnknown[idx] += t.getNumber(); }
if (t.getType() == TokenType.SectionName && t.getText().toLowerCase().contains("side") ) { idx = 1; }
}
summaryMain.setText(String.format("Main: %d cards recognized, %d unknown cards", cardsOk[0], cardsUnknown[0]));
summarySide.setText(String.format("Sideboard: %d cards recognized, %d unknown cards", cardsOk[1], cardsUnknown[1]));
}
private Deck buildDeck(){
return new Deck();
}
protected class OnChangeTextUpdate implements DocumentListener {
private void onChange() { readInput(); displayTokens(); }
private void onChange() { readInput(); displayTokens(); updateSummaries(); }
@Override public void insertUpdate(DocumentEvent e) { onChange(); }
@Override public void removeUpdate(DocumentEvent e) { onChange(); }
@Override public void changedUpdate(DocumentEvent e) { } // Happend only on ENTER pressed
@@ -149,11 +177,17 @@ public class DeckImport extends JDialog {
private String makeHtmlViewOfToken(DeckRecognizer.Token token) {
switch(token.getType())
{
case KnownCardWithNumber:
return String.format("<div class='knowncard'>%s * %s [%s]</div>", token.getNumber(), token.getCard().getName(), token.getCard().getSet());
case UnknownCardWithNumber:
return String.format("<div class='unknowncard'>%s * %s</div>", token.getNumber(), token.getText());
case SectionName:
return String.format("<div class='section'>%s</div>", token.getText());
case Unknown:
return String.format("<div class='unknown'>%s</div>", token.getText());
default:
return String.format("<div class='%s'>%s</div>", token.getType(), token.getText());
case Comment:
return String.format("<div class='comment'>%s</div>", token.getText());
}
return "";
}
}

View File

@@ -11,7 +11,7 @@ import java.util.Map.Entry;
import net.slightlymagic.braids.util.lambda.Lambda1;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import forge.Card;
import forge.card.CardInSet;
import forge.card.CardRules;
@@ -102,24 +102,42 @@ public final class CardDb {
uniqueCards.put(cardName, lastAdded);
}
public boolean isCardSupported(final String cardName) { return uniqueCards.containsKey(cardName.toLowerCase()); }
public boolean isCardSupported(final String cardName) {
ImmutablePair<String, String> nameWithSet = splitCardName(cardName);
if ( nameWithSet.right == null ) { return uniqueCards.containsKey(nameWithSet.left.toLowerCase()); }
// Set exists?
Map<String, CardPrinted[]> cardsFromset = allCardsBySet.get(nameWithSet.right.toUpperCase());
if (cardsFromset == null) return false;
// Card exists?
CardPrinted[] cardCopies = cardsFromset.get(nameWithSet.left.toLowerCase());
return cardCopies != null && cardCopies.length > 0;
}
/**
* Splits cardname into Name and set whenever deck line reads as name|set
*/
private static ImmutablePair<String, String> splitCardName(final String name) {
String cardName = name; // .trim() ?
int pipePos = cardName.indexOf('|');
if (pipePos >= 0) {
String setName = cardName.substring(pipePos + 1).trim();
cardName = cardName.substring(0, pipePos);
// only if set is not blank try to load it
if (StringUtils.isNotBlank(setName) && !"???".equals(setName)) {
return new ImmutablePair<String, String>(cardName, setName);
}
}
return new ImmutablePair<String, String>(cardName, null);
}
// Single fetch
public CardPrinted getCard(final String name) {
// Sometimes they read from decks things like "CardName|Set" - but we can handle it
int pipePos = name.indexOf('|');
String cardName = name;
if (pipePos >= 0) {
cardName = name.substring(0, pipePos);
String setName = name.substring(pipePos + 1).trim();
// only if set is not blank try to load it
if (StringUtils.isNotBlank(setName) && !"???".equals(setName)) {
return getCard(cardName, setName);
}
}
ImmutablePair<String, String> nameWithSet = splitCardName(name);
if (nameWithSet.right != null) { return getCard(nameWithSet.left, nameWithSet.right); }
// OK, plain name here
CardPrinted card = uniqueCards.get(cardName.toLowerCase());
CardPrinted card = uniqueCards.get(nameWithSet.left.toLowerCase());
if (card != null) { return card; }
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
}