mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
DeckImport - wip
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
package forge.deck;
|
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;
|
import forge.item.CardPrinted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,9 +61,63 @@ public class DeckRecognizer {
|
|||||||
public int getNumber() { return number; }
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package forge.gui.deckeditor;
|
|||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.WindowAdapter;
|
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -12,7 +11,7 @@ import javax.swing.BorderFactory;
|
|||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JEditorPane;
|
import javax.swing.JEditorPane;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
@@ -28,6 +27,7 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckRecognizer;
|
import forge.deck.DeckRecognizer;
|
||||||
|
import forge.deck.DeckRecognizer.TokenType;
|
||||||
import forge.gui.GuiUtils;
|
import forge.gui.GuiUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,9 +38,30 @@ public class DeckImport extends JDialog {
|
|||||||
private static final long serialVersionUID = -5837776824284093004L;
|
private static final long serialVersionUID = -5837776824284093004L;
|
||||||
|
|
||||||
private JTextArea txtInput = new JTextArea();
|
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 scrollInput = new JScrollPane(txtInput);
|
||||||
private JScrollPane scrollOutput = new JScrollPane(htmlOutput);
|
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 cmdAccept = new JButton("Import Deck");
|
||||||
private JButton cmdCancel = new JButton("Cancel");
|
private JButton cmdCancel = new JButton("Cancel");
|
||||||
|
|
||||||
@@ -78,10 +99,14 @@ public class DeckImport extends JDialog {
|
|||||||
scrollOutput.setViewportBorder(BorderFactory.createLoweredBevelBorder());
|
scrollOutput.setViewportBorder(BorderFactory.createLoweredBevelBorder());
|
||||||
|
|
||||||
getContentPane().setLayout(new MigLayout("fill"));
|
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(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() {
|
cmdCancel.addActionListener(new ActionListener() {
|
||||||
@Override public void actionPerformed(ActionEvent e) {
|
@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>");
|
StringBuilder sbOut = new StringBuilder("<html>");
|
||||||
sbOut.append(stylesheet);
|
sbOut.append(stylesheet);
|
||||||
for (DeckRecognizer.Token t : tokens) {
|
for (DeckRecognizer.Token t : tokens) {
|
||||||
@@ -134,13 +150,25 @@ public class DeckImport extends JDialog {
|
|||||||
htmlOutput.setText(sbOut.toString());
|
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();
|
return new Deck();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class OnChangeTextUpdate implements DocumentListener {
|
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 insertUpdate(DocumentEvent e) { onChange(); }
|
||||||
@Override public void removeUpdate(DocumentEvent e) { onChange(); }
|
@Override public void removeUpdate(DocumentEvent e) { onChange(); }
|
||||||
@Override public void changedUpdate(DocumentEvent e) { } // Happend only on ENTER pressed
|
@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) {
|
private String makeHtmlViewOfToken(DeckRecognizer.Token token) {
|
||||||
switch(token.getType())
|
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:
|
case Unknown:
|
||||||
return String.format("<div class='unknown'>%s</div>", token.getText());
|
case Comment:
|
||||||
default:
|
return String.format("<div class='comment'>%s</div>", token.getText());
|
||||||
return String.format("<div class='%s'>%s</div>", token.getType(), token.getText());
|
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.Map.Entry;
|
|||||||
import net.slightlymagic.braids.util.lambda.Lambda1;
|
import net.slightlymagic.braids.util.lambda.Lambda1;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.card.CardInSet;
|
import forge.card.CardInSet;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
@@ -102,24 +102,42 @@ public final class CardDb {
|
|||||||
uniqueCards.put(cardName, lastAdded);
|
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
|
// Single fetch
|
||||||
public CardPrinted getCard(final String name) {
|
public CardPrinted getCard(final String name) {
|
||||||
// Sometimes they read from decks things like "CardName|Set" - but we can handle it
|
// Sometimes they read from decks things like "CardName|Set" - but we can handle it
|
||||||
int pipePos = name.indexOf('|');
|
ImmutablePair<String, String> nameWithSet = splitCardName(name);
|
||||||
String cardName = name;
|
if (nameWithSet.right != null) { return getCard(nameWithSet.left, nameWithSet.right); }
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// OK, plain name here
|
// OK, plain name here
|
||||||
CardPrinted card = uniqueCards.get(cardName.toLowerCase());
|
CardPrinted card = uniqueCards.get(nameWithSet.left.toLowerCase());
|
||||||
if (card != null) { return card; }
|
if (card != null) { return card; }
|
||||||
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
|
throw new NoSuchElementException(String.format("Card '%s' not found in our database.", name));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user