Completely redesigned DeckImport with new panel for statistics and full support for i18n

This commit is contained in:
leriomaggio
2021-09-06 01:45:17 +01:00
parent 71793fb747
commit 59e1203b0c
2 changed files with 394 additions and 130 deletions

View File

@@ -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<TItem extends InventoryItem, TModel extends DeckBase> ex
private final FTextArea txtInput = new FTextArea();
private static final String STYLESHEET = "<style>"
+ "body, h1, h2, h3, h4, h5, h6, table, tr, td, p {padding: 0; font-weight: normal; "
+ "body, h1, h2, h3, h4, h5, h6, table, tr, td {font-weight: normal; line-height: 1.4; "
+ "text-decoration: none; font-family: Arial; font-size: 10px; color: #000000; background-color: white;} "
+ " h3 {font-size: 12px; margin: 2px 0; padding: 0px 5px; } "
+ " h4 {font-size: 11px; } "
+ " h3 {font-size: 13px; margin: 2px 0; padding: 0px 5px; } "
+ " h4 {font-size: 11px; margin: 2px 0; padding: 0px 5px; } "
+ " h5 {font-size: 11px; margin: 2px 0; padding: 0px 5px; } "
+ " code {font-size: 10px; color: #000000; background-color: white; } "
+ "ul, ol, ul li, ol li {padding: 1px; margin 0; } "
+ "p {padding: 2px 5px; margin: 2px 0; font-weight: 400 !important; color: #000000; text-align: justify } "
+ ".unknowncard {color: #666666;} " + ".knowncard {color: #009900;} " + ".illegalcard {color: #990000;} "
+ " ul li {padding: 5px 1px 1px 1px !important; margin: 0 1px !important} "
+ " p {margin: 2px; text-align: justify; padding: 2px 5px;} "
+ " p.example {margin: 0 2px !important; padding: 0 5px !important;} "
+ ".unknowncard {color: #666666;} " + ".knowncard {color: #009900;} "
+ ".illegalcard {color: #990000;} " + ".invalidcard {color: #000099;} "
+ ".comment {font-style: italic} "
+ ".section {padding: 2px 5px; margin: 2px 0; font-weight: 700; background-color: #DDDDDD; color: #000000 } "
+ ".editioncode {font-weight: 700; color: #5a8276 !important;} "
+ ".cardtype {padding: 2px 20px; margin: 3px 0; font-weight: 400; background-color: #FFCC66; color: #000000 } "
+ ".deckname {padding: 2px 20px; margin: 3px 0; font-weight: 400; background-color: #332200; color: #FFFFFF }"
+ "</style>";
// TODO: Add localisation support
private static final String HTML_WELCOME_TEXT = "<html>"
private static final String COLOUR_CODED_TAGS = String.format(
"<ul>" +
"<li> <span class=\"knowncard\">%s</span></li>" +
"<li> <span class=\"unknowncard\">%s</span></li>" +
"<li> <span class=\"illegalcard\">%s</span></li>" +
"<li> <span class=\"invalidcard\">%s</span></li>" +
"<li> <span class=\"comment\">%s</span></li></ul>",
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(
"<ul><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li></ul>",
Localizer.getInstance().getMessage("lblGuideTipsCount",
String.format("<b>%s</b>", Localizer.getInstance().getMessage("lblGuideTipsTitleCount")),
String.format("<code>%s</code>", "4 Power Sink"),
String.format("<code>%s</code>", "4x Power Sink")),
Localizer.getInstance().getMessage("lblGuideTipsSet",
String.format("<b>%s</b>", Localizer.getInstance().getMessage("lblGuideTipsTitleSet"))),
Localizer.getInstance().getMessage("lblGuideTipsCardType",
String.format("<b>%s</b>", Localizer.getInstance().getMessage("lblGuideTipsTitleCardType"))),
Localizer.getInstance().getMessage("lblGuideTipsDeckSection",
String.format("<b>%s</b>", Localizer.getInstance().getMessage("lblGuideTipsTitleDeckSections"))),
Localizer.getInstance().getMessage("lblGuideTipsDeckName",
String.format("<b>%s</b>", Localizer.getInstance().getMessage("lblGuideTipsTitleDeckName"))),
Localizer.getInstance().getMessage("lblGuideTipsDeckFormats",
String.format("<b>%s</b>", Localizer.getInstance().getMessage("lblGuideTipsTitleDeckFormat")))
);
private static final String EXAMPLES_LIST = String.format(
// "<ul><li><code>%s</code></li></ul>" +
// "<p class=\"example\">%s</p>" +
"<ul><li><code>%s</code></li></ul>" +
"<p class=\"example\">%s</p>" +
"<ul><li><code>%s</code></li></ul>" +
"<p class=\"example\">%s</p>" +
"<ul><li><code>%s</code></li></ul>" +
"<p class=\"example\">%s</p>" +
"<ul><li><code>%s</code></li></ul>" +
"<p class=\"example\">%s</p>",
// 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("<html>"
+ "<head>"
+ DeckImport.STYLESHEET
+ "</head>"
+ "<body>"
+ "<h3 id='how-to-use-the-deck-importer'>How to use the Deck Importer</h3>" +
"<p><strong>Quick Instructions</strong>:\n" +
"Using the Deck Importer is <strong>very simple</strong>: " +
"just type or paste the names of the cards you want (one per line in the <em>Card List</em>), " +
"and the Importer will automatically create the <em>Decklist</em> with M:TG cards in Forge." +
"You could also specify how many copies of each card you want (default: <code>1</code>), " +
"and their corresponding Edition.\nIf No Edition is specified, the card print will be " +
"selected automatically according to the <em>Card Art Preference</em> option in Game Settings.\n\n" +
"For example: <code>\"4 Power Sink TMP\"</code> will import:" +
"<ul><li><code>4</code> copies of <code>Power Sink</code> from <code>Tempest</code>.</li></ul>" +
"Each line in the list will be processed on-the-fly, and rendered in the Decklist with the following " +
"color-codes:" +
"<ul>" +
"<li> <span class=\"knowncard\">Card Recognized: Successful match in the database.</span></li>" +
"<li> <span class=\"unknowncard\">Card Not Found, or Not Supported yet in Forge.</span></li>" +
"<li> <span class=\"comment\">General text or Comment: Simply ignored by the Importer.</span></li>" +
"</ul></p>" +
"<p><b>Additional Options</b>:" +
"<ol>" +
"<li><strong>Deck Name</strong>: you can specify a name for your deck . Just type " +
"<code>Name: &lt;NAME OF YOUR DECK&gt;</code> in the Card List;</li>" +
"<li><strong>Card types</strong>: you can organise your list by types, e.g. " +
"<code>Creature</code>, <code>Instant</code>, <code>Land</code>, <code>Sorcery</code>;</li>" +
"<li><strong>Deck Section</strong>: Similarly, you can organise your list by Deck Sections, " +
"e.g. <code>Main</code>, <code>Sideboard</code>;</li>" +
"<li><strong>Collector Number</strong>: You can identify a specific Card Print by including its CollNr., " +
"e.g. <code>20 Island M21 265</code></li>" +
"</ol></p>" +
"<p><strong>Deck Formats</strong>:" +
"Card Lists in the following formats are supported : MTG Arena (<code>.MTGA</code>); " +
"MTG Goldfish (<code>.MTGO</code>); TappedOut; DeckStats.net; <code>.dec</code> files.</p>"
+ "<h3 id='how-to-use-the-deck-importer'>%s</h3>"
+ "<p>%s</p> "
+ "<h4>%s</h4> "
+ "<p>%s</p> "
+ "<h4>%s</h4> "
+ "<p>%s</p> "
+ "</body>"
+ "</html>";
+ "</html>",
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<TItem extends InventoryItem, TModel extends DeckBase> ex
private final ACEditorBase<TItem, TModel> 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<TItem extends InventoryItem, TModel extends DeckBase> ex
List<String> 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<TItem, TModel> 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<TItem extends InventoryItem, TModel extends DeckBase> 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<TItem extends InventoryItem, TModel extends DeckBase> ex
} else {
final StringBuilder sbOut = new StringBuilder("<html>");
sbOut.append(DeckImport.STYLESHEET);
sbOut.append(String.format("<h3>%s</h3>", Localizer.getInstance().getMessage("lblCurrentDecklist")));
for (final DeckRecognizer.Token t : tokens) {
sbOut.append(makeHtmlViewOfToken(t));
}
@@ -304,83 +356,225 @@ public class DeckImport<TItem extends InventoryItem, TModel extends DeckBase> ex
private boolean hasOnlyComment(final List<DeckRecognizer.Token> 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<DeckRecognizer.Token> 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 = "<style>"
+ "body, h1, h2, h3, h4, h5, h6, table, tr, td, p {padding: 0; font-weight: normal; "
+ "text-decoration: none; font-family: Arial; font-size: 10px; "
+ "color: white; background-color: #ffffff; color: #000000;} "
+ " h3 {font-size: 13px; margin: 2px 0; padding: 0px 5px; } "
+ " h5 {font-size: 11px; padding: 2px 20px; margin: 3px 0;} "
+ " span {display: block !important; } "
+ " div {margin: 0 !important; text-align: justify; padding 2px 10px; } "
+ " p {margin: 2px; text-align: justify; padding: 2px 5px;} "
+ ".unknowncard {color: #666666;} " + ".knowncard {color: #009900;} "
+ ".illegalcard {color: #990000;} " + ".invalidcard {color: #000099;} "
+ ".section {font-weight: 700; background-color: #DDDDDD; color: #000000 } "
+ ".edition {font-weight: 700; background-color: #5a8276; color: #ffffff } "
+ ".editioncode {font-weight: 700; color: #5a8276;} "
+ ".cardtype {font-weight: 700; background-color: #FFCC66; color: #000000} "
+ " ul li {padding: 5px 1px 1px 1px !important; margin: 0 1px !important} "
+ "</style>";
int unknownCardsCount = 0;
int illegalCardsCount = 0;
int legalCardsCount = 0;
int invalidCardsCount = 0;
String summaryMsgTemplate = "<html><head>%s</head><body><h3>%s</h3>%s</body></html>";
String deckListName = Localizer.getInstance().getMessage("lblDeckListDefaultName");
if (hasOnlyComment(tokens)) {
String statsSummaryList = String.format(
"<ul><li>%s</li><li>%s</li><li>%s</li><li>%s</li></ul>",
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("<p>%s</p>",
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<String, Integer> deckSectionsStats = new HashMap<>();
deckSectionsStats.put(DeckSection.Main.name(), 0);
String currentKeySection = DeckSection.Main.name();
Map<String, Integer> cardTypeStats = new HashMap<>();
Map<String, Integer> 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("<div class='knowncard'>%s * %s [%s] %s</div>", token.getNumber(), token.getCard()
// .getName(), token.getCard().getEdition(), token.getCard().isFoil() ? "<i>foil</i>" : "");
// case UnknownCard:
// 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 UnknownText:
// case Comment:
// return String.format("<div class='comment'>%s</div>", token.getText());
// default:
// return "";
// }
// }
private String createSummaryStats(int unknownCardsCount, int illegalCardsCount,
int legalCardsCount, int invalidCardsCount,
Map<String, Integer> deckSectionsStats,
Map<String, Integer> editionsStats,
Map<String, Integer> cardTypeStats) {
String cardStatsReport = createCardsStatsReport(unknownCardsCount, illegalCardsCount,
invalidCardsCount,
legalCardsCount, deckSectionsStats);
String editionsReport = createEditionsStatsReport(editionsStats);
String cardTypesReport = createCardTypeStatsReport(cardTypeStats);
return String.format("<h5 class=\"section\">%s</h5>%s" +
"<h5 class=\"cardtype\">%s</h5>%s"+
"<h5 class=\"edition\">%s</h5>%s",
Localizer.getInstance().getMessage("lblSummaryDeckStats"), cardStatsReport,
Localizer.getInstance().getMessage("lblSummaryCardTypeStats"), cardTypesReport,
Localizer.getInstance().getMessage("lblSummaryEditionStats"), editionsReport);
}
private String createEditionsStatsReport(Map<String, Integer> 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("<div><span class=\"editioncode\">[%s]</span> %s : %d", setCode, edition.getName(),
editionsStats.get(setCode));
editionsReport.append(tag);
}
return editionsReport.toString();
}
private String createCardTypeStatsReport(Map<String, Integer> cardTypesStats) {
StringBuilder cardTypesReport = new StringBuilder("");
for (String typeLabel : cardTypesStats.keySet()){
String typeLocalLab = Localizer.getInstance().getMessage(String.format("lbl%s", typeLabel));
String tag = String.format("<div>%s : %d</div>", typeLocalLab,
cardTypesStats.get(typeLabel));
cardTypesReport.append(tag);
}
return cardTypesReport.toString();
}
private String createCardsStatsReport(int unknownCardsCount, int illegalCardsCount, int invalidCardsCount,
int legalCardsCount, Map<String, Integer> deckSectionsStats) {
StringBuilder sb = new StringBuilder();
if (legalCardsCount > 0){
sb.append(String.format("<div class=\"knowncard\">%s: %d</div>",
Localizer.getInstance().getMessage("lblLegalCardsCount"), legalCardsCount));
}
if (illegalCardsCount > 0){
sb.append(String.format("<div class=\"illegalcard\">%s: %d</div>",
Localizer.getInstance().getMessage("lblIllegalCardsCount"), illegalCardsCount));
}
if (invalidCardsCount > 0){
sb.append(String.format("<div class=\"invalidcard\">%s: %d</div>",
Localizer.getInstance().getMessage("lblInvalidCardsCount"), invalidCardsCount));
}
if (unknownCardsCount > 0){
sb.append(String.format("<div class=\"unknowncard\">%s: %d</div>",
Localizer.getInstance().getMessage("lblUnknownCardsCount"), unknownCardsCount));
}
String cardStatsReport = sb.toString();
cardStatsReport += createDeckStatsReport(deckSectionsStats);
return cardStatsReport;
}
private String createDeckStatsReport(Map<String, Integer> deckSectionsStats) {
StringBuilder deckSectionsReport = new StringBuilder("<br />");
for (String sectionName : deckSectionsStats.keySet()){
String sectionNameLabel = Localizer.getInstance().getMessage(String.format("lbl%s", sectionName));
String tag = String.format("<div>%s : %d</div>",
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("<div class='knowncard'>%s x %s from %s (%s) %s</div>",
return String.format("<div class=\"knowncard\">%s x %s " +
"<span class=\"editioncode\">(%s)</span> %s %s</div>",
token.getNumber(), token.getCard().getName(),
editionName, token.getCard().getEdition(),
token.getCard().isFoil() ? "<i>foil</i>" : "");
case UnknownCard:
return String.format("<div class='unknowncard'>%s x %s (%s)</div>",
token.getCard().getEdition(),
token.getCard().getCollectorNumber(),
token.getCard().isFoil() ? "<i>(FOIL)</i>" : "");
case UNKNOWN_CARD_REQUEST:
return String.format("<div class=\"unknowncard\">%s x %s (%s)</div>",
token.getNumber(), token.getText(),
Localizer.getInstance().getMessage("lblUnknownCard"));
case IllegalCard:
return String.format("<div class='illegalcard'>%s x %s (%s %s)</div>",
Localizer.getInstance().getMessage("lblUnknownCardMsg"));
case ILLEGAL_CARD_REQUEST:
return String.format("<div class=\"illegalcard\">%s x %s (%s %s)</div>",
token.getNumber(), token.getText(),
Localizer.getInstance().getMessage("lblIllegalCard"),
Localizer.getInstance().getMessage("lblIllegalCardMsg"),
this.deckFormat.name());
case DeckSectionName:
return String.format("<div class='section'>%s</div>", token.getText());
case CardType:
return String.format("<div class='cardtype'>%s</div>", token.getText());
case DeckName:
return String.format("<div class='deckname'>Deck Name: %s</div>", token.getText());
case UnknownText:
case Comment:
case INVALID_CARD_REQUEST:
return String.format("<div class=\"invalidcard\">%s x %s (%s)</div>",
token.getNumber(), token.getText(),
Localizer.getInstance().getMessage("lblInvalidCardMsg"));
case DECK_SECTION_NAME:
return String.format("<div class=\"section\">%s</div>", token.getText());
case CARD_TYPE:
return String.format("<div class=\"cardtype\">%s</div>", token.getText());
case DECK_NAME:
return String.format("<div class=\"deckname\">%s: %s</div>",
Localizer.getInstance().getMessage("lblDeckName"),
token.getText());
case UNKNOWN_TEXT:
case COMMENT:
default:
return "";
// return String.format("<div class='comment'>%s</div>", token.getText());
// return String.format("<div class=\"comment\">%s</div>", token.getText());
}
}
}