From 59e1203b0c52091dd982ff77ff7b705d18ad8c4d Mon Sep 17 00:00:00 2001
From: leriomaggio
Date: Mon, 6 Sep 2021 01:45:17 +0100
Subject: [PATCH] Completely redesigned DeckImport with new panel for
statistics and full support for i18n
---
.../forge/screens/deckeditor/DeckImport.java | 440 +++++++++++++-----
forge-gui/res/languages/en-US.properties | 84 +++-
2 files changed, 394 insertions(+), 130 deletions(-)
diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java
index a9d97818409..532fa8d69a2 100644
--- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java
+++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/DeckImport.java
@@ -17,10 +17,13 @@
*/
package forge.screens.deckeditor;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.event.DocumentEvent;
@@ -28,6 +31,7 @@ import javax.swing.event.DocumentListener;
import forge.StaticData;
import forge.card.CardEdition;
+import forge.card.CardType;
import forge.deck.*;
import forge.deck.DeckRecognizer.TokenType;
import forge.game.GameFormat;
@@ -39,7 +43,6 @@ import forge.toolbox.FButton;
import forge.toolbox.FCheckBox;
import forge.toolbox.FComboBox;
import forge.toolbox.FHtmlViewer;
-import forge.toolbox.FLabel;
import forge.toolbox.FScrollPane;
import forge.toolbox.FSkin;
import forge.toolbox.FTextArea;
@@ -58,63 +61,105 @@ public class DeckImport ex
private final FTextArea txtInput = new FTextArea();
private static final String STYLESHEET = "";
// TODO: Add localisation support
- private static final String HTML_WELCOME_TEXT = ""
+ private static final String COLOUR_CODED_TAGS = String.format(
+ "" +
+ "- %s
" +
+ "- %s
" +
+ "- %s
" +
+ "- %s
" +
+ "-
",
+ Localizer.getInstance().getMessage("lblGuideKnownCard"),
+ Localizer.getInstance().getMessage("lblGuideUnknownCard"),
+ Localizer.getInstance().getMessage("lblGuideIllegalCard"),
+ Localizer.getInstance().getMessage("lblGuideInvalidCard"),
+ Localizer.getInstance().getMessage("lblGuideComment")
+ );
+ private static final String TIPS_LIST = String.format(
+ "",
+ Localizer.getInstance().getMessage("lblGuideTipsCount",
+ String.format("%s", Localizer.getInstance().getMessage("lblGuideTipsTitleCount")),
+ String.format("%s", "4 Power Sink"),
+ String.format("%s", "4x Power Sink")),
+ Localizer.getInstance().getMessage("lblGuideTipsSet",
+ String.format("%s", Localizer.getInstance().getMessage("lblGuideTipsTitleSet"))),
+ Localizer.getInstance().getMessage("lblGuideTipsCardType",
+ String.format("%s", Localizer.getInstance().getMessage("lblGuideTipsTitleCardType"))),
+ Localizer.getInstance().getMessage("lblGuideTipsDeckSection",
+ String.format("%s", Localizer.getInstance().getMessage("lblGuideTipsTitleDeckSections"))),
+ Localizer.getInstance().getMessage("lblGuideTipsDeckName",
+ String.format("%s", Localizer.getInstance().getMessage("lblGuideTipsTitleDeckName"))),
+ Localizer.getInstance().getMessage("lblGuideTipsDeckFormats",
+ String.format("%s", Localizer.getInstance().getMessage("lblGuideTipsTitleDeckFormat")))
+ );
+
+ private static final String EXAMPLES_LIST = String.format(
+// "" +
+// "%s
" +
+ "" +
+ "%s
" +
+ "" +
+ "%s
" +
+ "" +
+ "%s
" +
+ "" +
+ "%s
",
+// Localizer.getInstance().getMessage("lblExample1"),
+// Localizer.getInstance().getMessage("nlExample1"),
+ Localizer.getInstance().getMessage("lblExample2"),
+ Localizer.getInstance().getMessage("nlExample2"),
+ Localizer.getInstance().getMessage("lblExample3"),
+ Localizer.getInstance().getMessage("nlExample3"),
+ Localizer.getInstance().getMessage("lblExample4"),
+ Localizer.getInstance().getMessage("nlExample4"),
+ Localizer.getInstance().getMessage("lblExample5"),
+ Localizer.getInstance().getMessage("nlExample5")
+ );
+
+ private static final String HTML_WELCOME_TEXT = String.format(""
+ ""
+ DeckImport.STYLESHEET
+ ""
+ ""
- + "How to use the Deck Importer
" +
- "Quick Instructions:\n" +
- "Using the Deck Importer is very simple: " +
- "just type or paste the names of the cards you want (one per line in the Card List), " +
- "and the Importer will automatically create the Decklist with M:TG cards in Forge." +
- "You could also specify how many copies of each card you want (default: 1), " +
- "and their corresponding Edition.\nIf No Edition is specified, the card print will be " +
- "selected automatically according to the Card Art Preference option in Game Settings.\n\n" +
- "For example: \"4 Power Sink TMP\" will import:" +
- "
4 copies of Power Sink from Tempest.
" +
- "Each line in the list will be processed on-the-fly, and rendered in the Decklist with the following " +
- "color-codes:" +
- "" +
- "- Card Recognized: Successful match in the database.
" +
- "- Card Not Found, or Not Supported yet in Forge.
" +
- "-
" +
- "
" +
- "Additional Options:" +
- "
" +
- "- Deck Name: you can specify a name for your deck . Just type " +
- "
Name: <NAME OF YOUR DECK> in the Card List; " +
- "- Card types: you can organise your list by types, e.g. " +
- "
Creature, Instant, Land, Sorcery; " +
- "- Deck Section: Similarly, you can organise your list by Deck Sections, " +
- "e.g.
Main, Sideboard; " +
- "- Collector Number: You can identify a specific Card Print by including its CollNr., " +
- "e.g.
20 Island M21 265 " +
- "
" +
- "Deck Formats:" +
- "Card Lists in the following formats are supported : MTG Arena (.MTGA); " +
- "MTG Goldfish (.MTGO); TappedOut; DeckStats.net; .dec files.
"
+ + "%s
"
+ + "%s
"
+ + "%s
"
+ + "%s
"
+ + "%s
"
+ + "%s
"
+ ""
- + "";
+ + "",
+ Localizer.getInstance().getMessage("nlGuideTitle"),
+ Localizer.getInstance().getMessage("nlGuideQuickInstructions", COLOUR_CODED_TAGS),
+ Localizer.getInstance().getMessage("nlGuideTipsTitle"),
+ Localizer.getInstance().getMessage("nlGuideTipsText", TIPS_LIST),
+ Localizer.getInstance().getMessage("nlGuideExamplesTitle"),
+ Localizer.getInstance().getMessage("nlGuideExamplesText", EXAMPLES_LIST)
+ );
private final FHtmlViewer htmlOutput = new FHtmlViewer(DeckImport.HTML_WELCOME_TEXT);
+ private final FHtmlViewer decklistStats = new FHtmlViewer();
private final FScrollPane scrollInput = new FScrollPane(this.txtInput, false);
private final FScrollPane scrollOutput = new FScrollPane(this.htmlOutput, false);
- private final FLabel summaryMain = new FLabel.Builder().text(Localizer.getInstance().getMessage("lblImportedDeckSummay")).build();
- private final FLabel summarySide = new FLabel.Builder().text(Localizer.getInstance().getMessage("lblSideboardSummayLine")).build();
+ private final FScrollPane scrollStats = new FScrollPane(this.decklistStats, false);
+
private final FButton cmdCancel = new FButton(Localizer.getInstance().getMessage("lblCancel"));
private FButton cmdAccept; // Not initialised as label will be adaptive.
@@ -130,7 +175,6 @@ public class DeckImport ex
private final ACEditorBase host;
private final String IMPORT_CARDS_CMD_LABEL = Localizer.getInstance().getMessage("lblImportCardsCmd");
- private final String IMPORT_DECK_CMD_LABEL = Localizer.getInstance().getMessage("lblImportDeckCmd");
private final String REPLACE_CARDS_CMD_LABEL = Localizer.getInstance().getMessage("lblReplaceCardsCmd");
@@ -146,46 +190,53 @@ public class DeckImport ex
List allowedSetCodes = currentGameFormat.getAllowedSetCodes();
this.controller = new DeckImportController(dateTimeCheck, monthDropdown, yearDropdown,
currentDeckIsNotEmpty, allowedSetCodes, currentDeckFormat);
- String cmdAcceptLabel = currentDeckIsNotEmpty ? IMPORT_CARDS_CMD_LABEL : IMPORT_DECK_CMD_LABEL;
+ String import_deck_cmd_label = Localizer.getInstance().getMessage("lblImportDeckCmd");
+ String cmdAcceptLabel = currentDeckIsNotEmpty ? IMPORT_CARDS_CMD_LABEL : import_deck_cmd_label;
this.cmdAccept = new FButton(cmdAcceptLabel);
this.host = g;
- final int wWidth = 900;
- final int wHeight = 900;
+ initMainPanel(g, currentDeckIsNotEmpty, currentGameType);
+ }
- this.setPreferredSize(new java.awt.Dimension(wWidth, wHeight));
+ private void initMainPanel(ACEditorBase g, boolean currentDeckIsNotEmpty, GameType currentGameType) {
+ GraphicsDevice gd = this.getGraphicsConfiguration().getDevice();
+ final int wWidth = (int)(gd.getDisplayMode().getWidth() * 0.7);
+ final int wHeight = (int)(gd.getDisplayMode().getHeight() * 0.8);
+ this.setPreferredSize(new Dimension(wWidth, wHeight));
this.setSize(wWidth, wHeight);
- String gameTypeName = String.format(" %s", currentGameType.name());
+
+ String gameTypeName = String.format("For the Game %s", currentGameType.name());
this.setTitle(Localizer.getInstance().getMessage("lblDeckImporter") + gameTypeName);
txtInput.setFocusable(true);
txtInput.setEditable(true);
final FSkin.SkinColor foreColor = FSkin.getColor(FSkin.Colors.CLR_TEXT);
- this.scrollInput.setBorder(new FSkin.TitledSkinBorder(BorderFactory.createEtchedBorder(), Localizer.getInstance().getMessage("lblPasteTypeDecklist"), foreColor));
- this.scrollOutput.setBorder(new FSkin.TitledSkinBorder(BorderFactory.createEtchedBorder(), Localizer.getInstance().getMessage("lblExpectRecognizedLines"), foreColor));
+ this.scrollInput.setBorder(new FSkin.TitledSkinBorder(BorderFactory.createEtchedBorder(),
+ Localizer.getInstance().getMessage("lblPasteTypeDecklist"), foreColor));
this.scrollInput.setViewportBorder(BorderFactory.createLoweredBevelBorder());
+
+ this.scrollOutput.setBorder(new FSkin.TitledSkinBorder(BorderFactory.createEtchedBorder(),
+ Localizer.getInstance().getMessage("lblExpectRecognizedLines"), foreColor));
this.scrollOutput.setViewportBorder(BorderFactory.createLoweredBevelBorder());
- this.add(this.scrollInput, "cell 0 0, w 50%, growy, pushy");
- this.add(this.dateTimeCheck, "cell 0 2, w 50%, ax c");
-
- this.add(monthDropdown, "cell 0 3, w 20%, ax left, split 2, pad 0 4 0 0");
- this.add(yearDropdown, "w 15%");
+ this.scrollStats.setBorder(new FSkin.TitledSkinBorder(BorderFactory.createEtchedBorder(),
+ Localizer.getInstance().getMessage("lblSummaryStats"), foreColor));
+ this.scrollStats.setViewportBorder(BorderFactory.createLoweredBevelBorder());
+ this.add(this.scrollInput, "cell 0 0, w 45%, growy, pushy");
this.add(this.scrollOutput, "cell 1 0, w 50%, growy, pushy");
- this.add(this.summaryMain, "cell 1 1, label");
- this.add(this.summarySide, "cell 1 2, label");
+ this.add(this.scrollStats, "cell 2 0, w 50%, wrap, growy, pushy, pushx");
- if (currentDeckIsNotEmpty){
- // Disabled Default behaviour to replace current deck: bulk import cards into the existing deck!
- //this.replaceDeckCheckbox.setSelected(currentDeckIsNotEmpty);
- this.add(this.replaceDeckCheckbox, "cell 1 3, align r, ax r");
- }
+ this.add(this.dateTimeCheck, "cell 0 1, w 50%, ax c");
+ this.add(monthDropdown, "cell 0 2, w 20%, ax left, split 2, pad 0 4 0 0");
+ this.add(yearDropdown, "cell 0 2, w 20%, ax left, split 2, pad 0 4 0 0");
- this.add(this.cmdAccept, "cell 1 4, split 2, w 150, align r, h 26");
- this.add(this.cmdCancel, "w 150, h 26");
+ if (currentDeckIsNotEmpty)
+ this.add(this.replaceDeckCheckbox, "cell 2 1, w 50%, ax c");
+ this.add(this.cmdAccept, "cell 2 2, w 150, align r, h 26");
+ this.add(this.cmdCancel, "cell 2 2, w 150, align r, h 26");
this.cmdCancel.addActionListener(new ActionListener() {
@Override
@@ -206,7 +257,7 @@ public class DeckImport ex
// In this way, if this deck will replace the current one, the name will be kept the same!
if (!deck.hasName()){
if (currentDeckName.equals(""))
- deck.setName("New Deck"); // TODO: try to generate a deck name?
+ deck.setName(Localizer.getInstance().getMessage("lblNewDeckName")); // TODO: try to generate a deck name?
else
deck.setName(currentDeckName);
}
@@ -294,6 +345,7 @@ public class DeckImport ex
} else {
final StringBuilder sbOut = new StringBuilder("");
sbOut.append(DeckImport.STYLESHEET);
+ sbOut.append(String.format("%s
", Localizer.getInstance().getMessage("lblCurrentDecklist")));
for (final DeckRecognizer.Token t : tokens) {
sbOut.append(makeHtmlViewOfToken(t));
}
@@ -304,83 +356,225 @@ public class DeckImport ex
private boolean hasOnlyComment(final List tokens) {
for (DeckRecognizer.Token token : tokens) {
- if (token.getType() != TokenType.Comment && token.getType() != TokenType.UnknownText)
+ if (token.getType() != TokenType.COMMENT && token.getType() != TokenType.UNKNOWN_TEXT)
return false;
}
return true;
}
private void updateSummaries(final List tokens) {
- final int[] cardsOk = new int[2];
- final int[] cardsUnknown = new int[2];
- int idx = 0;
- for (final DeckRecognizer.Token t : tokens) {
- if (t.getType() == TokenType.KnownCard) {
- cardsOk[idx] += t.getNumber();
- }
- if (t.getType() == TokenType.UnknownCard) {
- cardsUnknown[idx] += t.getNumber();
- }
- if ((t.getType() == TokenType.DeckSectionName) && t.getText().toLowerCase().contains("side")) {
- idx = 1;
- }
+
+ String head = "";
+
+ int unknownCardsCount = 0;
+ int illegalCardsCount = 0;
+ int legalCardsCount = 0;
+ int invalidCardsCount = 0;
+
+ String summaryMsgTemplate = "%s%s
%s";
+ String deckListName = Localizer.getInstance().getMessage("lblDeckListDefaultName");
+
+ if (hasOnlyComment(tokens)) {
+ String statsSummaryList = String.format(
+ "",
+ Localizer.getInstance().getMessage("lblStatsSummaryCount"),
+ Localizer.getInstance().getMessage("lblStatsSummarySection"),
+ Localizer.getInstance().getMessage("lblStatsSummaryCardType"),
+ Localizer.getInstance().getMessage("lblStatsSummaryCardSet"));
+ this.decklistStats.setText(String.format(summaryMsgTemplate, head,
+ Localizer.getInstance().getMessage("lblSummaryHeadMsg", deckListName),
+ String.format("%s
",
+ Localizer.getInstance().getMessage("lblImportedDeckSummary", statsSummaryList))));
}
- summaryMain.setText(Localizer.getInstance().getMessage("lblDeckImporterSummaryOfMain", String.valueOf(cardsOk[0]), String.valueOf(cardsUnknown[0])));
- summarySide.setText(Localizer.getInstance().getMessage("lblDeckImporterSummaryOfSideboard", String.valueOf(cardsOk[1]), String.valueOf(cardsUnknown[1])));
- cmdAccept.setEnabled(cardsOk[0] > 0);
+ else {
+ Map deckSectionsStats = new HashMap<>();
+ deckSectionsStats.put(DeckSection.Main.name(), 0);
+ String currentKeySection = DeckSection.Main.name();
+ Map cardTypeStats = new HashMap<>();
+ Map editionsStats = new HashMap<>();
+
+ for (final DeckRecognizer.Token t : tokens) {
+ if (t.getType() == TokenType.UNKNOWN_CARD_REQUEST)
+ unknownCardsCount += t.getNumber();
+ else if (t.getType() == TokenType.ILLEGAL_CARD_REQUEST)
+ illegalCardsCount += t.getNumber();
+ else if (t.getType() == TokenType.INVALID_CARD_REQUEST)
+ invalidCardsCount += t.getNumber();
+ else if (t.getType() == TokenType.DECK_SECTION_NAME)
+ currentKeySection = t.getText();
+ else if (t.getType() == TokenType.DECK_NAME)
+ deckListName = String.format("\"%s\"", t.getText());
+ else if (t.getType() == TokenType.LEGAL_CARD_REQUEST) {
+ int tokenNumber = t.getNumber();
+ legalCardsCount += tokenNumber;
+
+ // update deck section stats
+ int sectionCount = deckSectionsStats.getOrDefault(currentKeySection, 0);
+ sectionCount += tokenNumber;
+ deckSectionsStats.put(currentKeySection, sectionCount);
+
+ // update card edition stats
+ String setCode = t.getCard().getEdition();
+ int setCount = editionsStats.getOrDefault(setCode, 0);
+ setCount += tokenNumber;
+ editionsStats.put(setCode, setCount);
+
+ // update card type stats
+ for (CardType.CoreType coreType : t.getCard().getRules().getType().getCoreTypes()) {
+ String coreTypeName = coreType.name();
+ int cTypeCount = cardTypeStats.getOrDefault(coreTypeName, 0);
+ cTypeCount += tokenNumber;
+ cardTypeStats.put(coreTypeName, cTypeCount);
+ }
+
+ }
+ }
+
+ String deckListSummaryHtml = createSummaryStats(unknownCardsCount, illegalCardsCount,
+ legalCardsCount, invalidCardsCount, deckSectionsStats, editionsStats,
+ cardTypeStats);
+ this.decklistStats.setText(String.format(summaryMsgTemplate, head,
+ Localizer.getInstance().getMessage("lblSummaryHeadMsg", deckListName),
+ deckListSummaryHtml));
+ }
+ cmdAccept.setEnabled(legalCardsCount > 0);
}
-// private static String makeHtmlViewOfToken(final DeckRecognizer.Token token) {
-// switch (token.getType()) {
-// case KnownCard:
-// return String.format("%s * %s [%s] %s
", token.getNumber(), token.getCard()
-// .getName(), token.getCard().getEdition(), token.getCard().isFoil() ? "foil" : "");
-// case UnknownCard:
-// return String.format("%s * %s
", token.getNumber(), token.getText());
-// case SectionName:
-// return String.format("%s
", token.getText());
-// case UnknownText:
-// case Comment:
-// return String.format("", token.getText());
-// default:
-// return "";
-// }
-// }
+ private String createSummaryStats(int unknownCardsCount, int illegalCardsCount,
+ int legalCardsCount, int invalidCardsCount,
+ Map deckSectionsStats,
+ Map editionsStats,
+ Map cardTypeStats) {
+ String cardStatsReport = createCardsStatsReport(unknownCardsCount, illegalCardsCount,
+ invalidCardsCount,
+ legalCardsCount, deckSectionsStats);
+ String editionsReport = createEditionsStatsReport(editionsStats);
+ String cardTypesReport = createCardTypeStatsReport(cardTypeStats);
+
+ return String.format("%s
%s" +
+ "%s
%s"+
+ "%s
%s",
+ Localizer.getInstance().getMessage("lblSummaryDeckStats"), cardStatsReport,
+ Localizer.getInstance().getMessage("lblSummaryCardTypeStats"), cardTypesReport,
+ Localizer.getInstance().getMessage("lblSummaryEditionStats"), editionsReport);
+ }
+
+ private String createEditionsStatsReport(Map editionsStats) {
+ StringBuilder editionsReport = new StringBuilder();
+ for (String setCode : editionsStats.keySet()){
+ CardEdition edition = StaticData.instance().getCardEdition(setCode);
+ if (edition == null)
+ edition = CardEdition.UNKNOWN;
+
+ String tag = String.format("[%s] %s : %d", setCode, edition.getName(),
+ editionsStats.get(setCode));
+ editionsReport.append(tag);
+ }
+ return editionsReport.toString();
+ }
+
+ private String createCardTypeStatsReport(Map
cardTypesStats) {
+ StringBuilder cardTypesReport = new StringBuilder("");
+ for (String typeLabel : cardTypesStats.keySet()){
+ String typeLocalLab = Localizer.getInstance().getMessage(String.format("lbl%s", typeLabel));
+ String tag = String.format("%s : %d
", typeLocalLab,
+ cardTypesStats.get(typeLabel));
+ cardTypesReport.append(tag);
+ }
+ return cardTypesReport.toString();
+ }
+
+ private String createCardsStatsReport(int unknownCardsCount, int illegalCardsCount, int invalidCardsCount,
+ int legalCardsCount, Map deckSectionsStats) {
+ StringBuilder sb = new StringBuilder();
+ if (legalCardsCount > 0){
+ sb.append(String.format("%s: %d
",
+ Localizer.getInstance().getMessage("lblLegalCardsCount"), legalCardsCount));
+ }
+ if (illegalCardsCount > 0){
+ sb.append(String.format("%s: %d
",
+ Localizer.getInstance().getMessage("lblIllegalCardsCount"), illegalCardsCount));
+ }
+ if (invalidCardsCount > 0){
+ sb.append(String.format("%s: %d
",
+ Localizer.getInstance().getMessage("lblInvalidCardsCount"), invalidCardsCount));
+ }
+ if (unknownCardsCount > 0){
+ sb.append(String.format("%s: %d
",
+ Localizer.getInstance().getMessage("lblUnknownCardsCount"), unknownCardsCount));
+ }
+ String cardStatsReport = sb.toString();
+ cardStatsReport += createDeckStatsReport(deckSectionsStats);
+ return cardStatsReport;
+ }
+
+ private String createDeckStatsReport(Map deckSectionsStats) {
+ StringBuilder deckSectionsReport = new StringBuilder("
");
+ for (String sectionName : deckSectionsStats.keySet()){
+ String sectionNameLabel = Localizer.getInstance().getMessage(String.format("lbl%s", sectionName));
+ String tag = String.format("%s : %d
",
+ Localizer.getInstance().getMessage("lblDeckSectionStats", sectionNameLabel),
+ deckSectionsStats.get(sectionName));
+ deckSectionsReport.append(tag);
+ }
+ return deckSectionsReport.toString();
+ }
private String makeHtmlViewOfToken(final DeckRecognizer.Token token) {
+ if (token == null)
+ return "";
+
switch (token.getType()) {
- case KnownCard:
- CardEdition edition = StaticData.instance().getEditions().get(token.getCard().getEdition());
- String editionName;
- if (edition == null)
- editionName = "Unknown Edition";
- else
- editionName = edition.getName();
+ case LEGAL_CARD_REQUEST:
// TODO: String Padding for alignment
- return String.format("%s x %s from %s (%s) %s
",
+ return String.format("%s x %s " +
+ "(%s) %s %s
",
token.getNumber(), token.getCard().getName(),
- editionName, token.getCard().getEdition(),
- token.getCard().isFoil() ? "foil" : "");
- case UnknownCard:
- return String.format("%s x %s (%s)
",
+ token.getCard().getEdition(),
+ token.getCard().getCollectorNumber(),
+ token.getCard().isFoil() ? "(FOIL)" : "");
+ case UNKNOWN_CARD_REQUEST:
+ return String.format("%s x %s (%s)
",
token.getNumber(), token.getText(),
- Localizer.getInstance().getMessage("lblUnknownCard"));
- case IllegalCard:
- return String.format("%s x %s (%s %s)
",
+ Localizer.getInstance().getMessage("lblUnknownCardMsg"));
+ case ILLEGAL_CARD_REQUEST:
+ return String.format("%s x %s (%s %s)
",
token.getNumber(), token.getText(),
- Localizer.getInstance().getMessage("lblIllegalCard"),
+ Localizer.getInstance().getMessage("lblIllegalCardMsg"),
this.deckFormat.name());
- case DeckSectionName:
- return String.format("%s
", token.getText());
- case CardType:
- return String.format("%s
", token.getText());
- case DeckName:
- return String.format("Deck Name: %s
", token.getText());
- case UnknownText:
- case Comment:
+ case INVALID_CARD_REQUEST:
+ return String.format("%s x %s (%s)
",
+ token.getNumber(), token.getText(),
+ Localizer.getInstance().getMessage("lblInvalidCardMsg"));
+ case DECK_SECTION_NAME:
+ return String.format("%s
", token.getText());
+ case CARD_TYPE:
+ return String.format("%s
", token.getText());
+ case DECK_NAME:
+ return String.format("%s: %s
",
+ Localizer.getInstance().getMessage("lblDeckName"),
+ token.getText());
+ case UNKNOWN_TEXT:
+ case COMMENT:
default:
return "";
- // return String.format("", token.getText());
+// return String.format("", token.getText());
}
}
}
diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties
index 7904747d980..e1be93022d6 100644
--- a/forge-gui/res/languages/en-US.properties
+++ b/forge-gui/res/languages/en-US.properties
@@ -2614,21 +2614,91 @@ lblTargetingArcsAlwaysOn=Targeting arcs: Always on
#ListCardArea.java
lblDone=Done
#DeckImport.java
-lblSideboardSummayLine=Line for sideboard summary
-lblImportedDeckSummay=Imported deck summary will appear here
+lblImportedDeckSummary=In this panel, the main Statistics about the Decklist will be automatically reported. These include: {0}.
+lblStatsSummaryCount=Statistics on recognized cards
+lblStatsSummarySection=The number of cards in each Deck Section (default: "Main")
+lblStatsSummaryCardType=The number of cards per (Core) Card Type
+lblStatsSummaryCardSet=Statistics on the number of cards per single M:TG Edition
lblDeckImporter=Deck Importer
lblPasteTypeDecklist=Paste or Type your Card List
-lblReplaceDeck=Replace current Deck
+lblReplaceDeck=Replace Current Deck
lblImportCardsCmd=Import Cards
lblImportDeckCmd=Import Deck
lblReplaceCardsCmd=Replace Deck
lblExpectRecognizedLines=Recognized Decklist
-lblDeckImporterSummaryOfMain=Main: {0} cards recognized, {1} unknown cards
-lblDeckImporterSummaryOfSideboard=Sideboard: {0} cards recognized, {1} unknown cards
-lblIllegalCard=Not Legal in Format
-lblUnknownCard=Not existing or Not Found
+lblSummaryStats=Decklist Summary
+lblSummaryHeadMsg=Summary Statistics for {0}
+lblSummaryDeckStats=Deck Statistics
+lblSummaryCardTypeStats=Card Types Statistics
+lblSummaryEditionStats=Card Editions Statistics
+lblDeckSectionStats=Cards in {0}
+lblLegalCardsCount=Matched Cards
+lblIllegalCardsCount=Illegal Cards
+lblUnknownCardsCount=Unknown Cards
+lblInvalidCardsCount=Invalid Cards
+lblIllegalCardMsg=Not Legal in Format
+lblInvalidCardMsg=Not Compliant with Date Restrictions
+lblUnknownCardMsg=Unknown Card or Unsupported in Forge
+lblNewDeckName=New Deck
+lblCurrentDecklist=Current Decklist
+lblDeckListDefaultName=Decklist
+lblDeckName=Deck Name
+lblArtifact=Artifact
+lblConspiracy=Conspiracy
+lblDungeon=Dungeon
+lblSorcery=Sorcery
+lblInstant=Instant
+lblEnchantment=Enchantment
+lblPhenomenon=Phenomenon
+lblScheme=Scheme
+lblTribal=Tribal
#CEditorTokenViewer.java
lblAllTokens=All Tokens
+# DeckImport Instructions
+nlGuideTitle=Instructions
+nlGuideQuickInstructions=Using the Deck Importer is very simple: just paste or type the names of the cards you \
+ want in the Card List (one per line), and the Importer will start creating the Decklist. \
+ Each line in the Decklist will be rendered according to the following color-codes: {0}
+lblGuideKnownCard=Card Found, and successfully added to the Decklist.
+lblGuideUnknownCard=Card Not Found, or Not Supported in Forge.
+lblGuideIllegalCard=Card Not Allowed in Current Deck Format, or Game Type.
+lblGuideInvalidCard=Invalid Card (from a Set not compliant with the selected release date, if any)
+lblGuideComment=Comment or general text. Ignored by the Importer.
+nlGuideTipsTitle=Quick Tips
+nlGuideTipsText=A few tips on the supported options to refine and organise your Decklist. {0}
+lblGuideTipsCount={0}: specify how many copies of each card to add (default: 1). \n{1} or {2} are both accepted entries.
+lblGuideTipsSet={0}: include the code of an M:TG Edition to select a specific Card Art. If necessary, also add in \
+ the Collector Number or an Art Index for the card (See examples below). \
+ If not specified, the Card Art will be chosen automatically according to the "Card Art Preference" in Game Settings.
+lblGuideTipsCardType={0}: organise your Card list by Card Type (e.g. "Land", "Creatures", "Artifacts"). These special \
+ lines will appear highlighted in the Decklist.
+lblGuideTipsDeckSection={0}: Similarly, the Card List can be organised by Deck Section (e.g. Main, Sideboard, Commander). \
+ The keywords will be highlighted in the Decklist, and cards then imported to the specified section (default: Main).
+lblGuideTipsDeckName={0}: Assign a name to your card list. Just type "Deck" or "Name", followed by the name you want. \
+ This will be used as (new) name for the Deck.
+lblGuideTipsDeckFormats={0}: The following Deck formats are supported for immediate import: MTG Arena; \
+ MTG Goldfish (all export); TappedOut (all export, but CSV); DeckStats.net; Deck format (.dec) files.
+lblGuideTipsTitleCount=Card Amount
+lblGuideTipsTitleSet=Card Art
+lblGuideTipsTitleCardType=Card Types
+lblGuideTipsTitleDeckSections=Deck Sections
+lblGuideTipsTitleDeckName=Deck Name
+lblGuideTipsTitleDeckFormat=Deck Formats
+nlGuideExamplesTitle=Examples
+nlGuideExamplesText=Please find below a few examples of some alternative valid entries in the Card List. {0}
+lblExample2=10x Islands+ MIR 2
+nlExample2=10 \"Island\" from Set \"Mirage\", 2nd Art, FOIL \n\ \
+ (the plus sign after card name indicates a Foil card).
+lblExample3=4 Darksteel Citadel (M15) 242
+nlExample3=4 \"Darksteel Citadel\" from \"M15\" with Collector Nr. \"242\"\n \
+ (MTGArena format as exported by TappedOut)
+lblExample4=18 Forest <254> [THB] (F)
+nlExample4=18 \"Forest\" FOIL from \"Theros Beyond Death\" with Collector Nr. \"254\"\n \
+ (MTGArena format as exported by MTGGoldfish). The last \"(F)\" is another way to specify foil.
+lblExample5=4x TMP|Counterspell
+nlExample5=4 copies of \"Counterspell\" from \"Tempest\". \
+ In this case, the Set code is specified before the card name using the (optional) pipe separator.\
+ Alternative valid separators for set codes are also braces, brackets, and parenthesis.
#StartRenderer.java
lblClickToAddTargetToFavorites=Click to add {0} to your favorites
lblClickToRemoveTargetToFavorites=Click to remove {0} from your favorites