forked from External/mage
* added power level info in deck validation panel; * added detail calculation info (hint with cards and their power levels); * fixed that deck's edh power level ignore individual card's levels and used only commanders; * removed outdated deck restrictions by commander colors; * now players can really limit allowed decks by edh power level;
This commit is contained in:
parent
11dcc18049
commit
f3ba897536
9 changed files with 235 additions and 76 deletions
|
|
@ -0,0 +1,76 @@
|
|||
package mage.client.components;
|
||||
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.client.util.GUISizeHelper;
|
||||
import mage.client.util.gui.GuiDisplayUtil;
|
||||
import mage.deck.Commander;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Inject power level info inside validation panel
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class EdhPowerLevelLegalityLabel extends LegalityLabel {
|
||||
|
||||
private final Commander commanderDeckType = new Commander();
|
||||
private final List<String> foundPowerCards = new ArrayList<>();
|
||||
|
||||
public EdhPowerLevelLegalityLabel() {
|
||||
super("EDH Power Level: ?", null);
|
||||
setPreferredSize(DIM_PREFERRED_X3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> selectCards() {
|
||||
// choose cards with power level
|
||||
return this.foundPowerCards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateDeck(Deck deck) {
|
||||
// find and save power level and card hints
|
||||
|
||||
List<String> foundInfo = new ArrayList<>();
|
||||
int level = this.commanderDeckType.getEdhPowerLevel(deck, foundPowerCards, foundInfo);
|
||||
this.setText(String.format("EDH Power Level: %d", level));
|
||||
|
||||
// sort by score "+5 from xxx"
|
||||
Pattern pattern = Pattern.compile("\\+(\\d+)");
|
||||
foundInfo.sort((o1, o2) -> {
|
||||
Matcher matcher = pattern.matcher(o1);
|
||||
int score1 = matcher.find() ? Integer.parseInt(matcher.group(1)) : 0;
|
||||
matcher = pattern.matcher(o2);
|
||||
int score2 = matcher.find() ? Integer.parseInt(matcher.group(1)) : 0;
|
||||
if (score1 != score2) {
|
||||
return Integer.compare(score2, score1);
|
||||
}
|
||||
return o1.compareTo(o2);
|
||||
});
|
||||
|
||||
showStateInfo(formatCardsInfoTooltip(level, foundInfo));
|
||||
}
|
||||
|
||||
private String formatCardsInfoTooltip(int level, List<String> foundInfo) {
|
||||
// use 60% font for better and compatible list
|
||||
int infoFontSize = Math.round(GUISizeHelper.cardTooltipFont.getSize() * 0.6f);
|
||||
int maxLimit = 25;
|
||||
String extraInfo = this.foundPowerCards.size() <= maxLimit ? "" : String.format("<li style=\"margin-bottom: 2px;\">and %d more cards</li>", maxLimit - this.foundPowerCards.size());
|
||||
return foundInfo.stream()
|
||||
.limit(maxLimit)
|
||||
.reduce("<html><body>"
|
||||
+ "<p>EDH Power Level: <span style='color:#b8860b;font-weight:bold;'>" + level + "</span></p>"
|
||||
+ "<br>"
|
||||
+ "<u>Found <span style='font-weight:bold;'>" + this.foundPowerCards.size() + "</span> cards with power levels (click to select it)</u>"
|
||||
+ "<br>"
|
||||
+ "<ul style=\"font-size: " + infoFontSize + "px; width: " + TOOLTIP_TABLE_WIDTH + "px; padding-left: 10px; margin: 0;\">",
|
||||
(str, info) -> str + String.format("<li style=\"margin-bottom: 2px;\">%s</li>", info), String::concat)
|
||||
+ extraInfo
|
||||
+ "</ul>"
|
||||
+ "</body></html>";
|
||||
}
|
||||
}
|
||||
|
|
@ -3,17 +3,18 @@ package mage.client.components;
|
|||
import mage.cards.decks.Deck;
|
||||
import mage.cards.decks.DeckValidator;
|
||||
import mage.cards.decks.DeckValidatorError;
|
||||
import mage.cards.decks.importer.DeckImporter;
|
||||
import org.unbescape.html.HtmlEscape;
|
||||
import org.unbescape.html.HtmlEscapeLevel;
|
||||
import org.unbescape.html.HtmlEscapeType;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Elandril
|
||||
* @author Elandril, JayDi85
|
||||
*/
|
||||
public class LegalityLabel extends JLabel {
|
||||
|
||||
|
|
@ -25,8 +26,10 @@ public class LegalityLabel extends JLabel {
|
|||
protected static final Dimension DIM_MINIMUM = new Dimension(75, 25);
|
||||
protected static final Dimension DIM_MAXIMUM = new Dimension(150, 75);
|
||||
protected static final Dimension DIM_PREFERRED = new Dimension(75, 25);
|
||||
protected static final Dimension DIM_PREFERRED_X2 = new Dimension(DIM_PREFERRED.width * 2 + 5, 25);
|
||||
protected static final Dimension DIM_PREFERRED_X3 = new Dimension(DIM_PREFERRED.width * 3 + 5 + 5, 25);
|
||||
|
||||
protected static final int TOOLTIP_TABLE_WIDTH = 300; // size of the label's tooltip
|
||||
protected static final int TOOLTIP_TABLE_WIDTH = 400; // size of the label's tooltip
|
||||
protected static final int TOOLTIP_MAX_ERRORS = 20; // max errors to show in tooltip
|
||||
|
||||
protected Deck currentDeck;
|
||||
|
|
@ -92,19 +95,6 @@ public class LegalityLabel extends JLabel {
|
|||
return button;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public DeckValidator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
public void setValidator(DeckValidator validator) {
|
||||
this.validator = validator;
|
||||
revalidateDeck();
|
||||
}
|
||||
|
||||
protected String escapeHtml(String string) {
|
||||
return HtmlEscape.escapeHtml(string, HtmlEscapeType.HTML4_NAMED_REFERENCES_DEFAULT_TO_HEXA, HtmlEscapeLevel.LEVEL_0_ONLY_MARKUP_SIGNIFICANT_EXCEPT_APOS);
|
||||
}
|
||||
|
|
@ -146,25 +136,33 @@ public class LegalityLabel extends JLabel {
|
|||
setBackground(color);
|
||||
}
|
||||
|
||||
public void showState(Color color, String tooltip) {
|
||||
public void showState(Color color, String tooltip, boolean useErrors) {
|
||||
setBackground(color);
|
||||
setToolTipText(appendErrorMessage(tooltip));
|
||||
if (useErrors) {
|
||||
setToolTipText(appendErrorMessage(tooltip));
|
||||
} else {
|
||||
setToolTipText(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
public void showStateInfo(String tooltip) {
|
||||
showState(COLOR_LEGAL, tooltip, false);
|
||||
}
|
||||
|
||||
public void showStateUnknown(String tooltip) {
|
||||
showState(COLOR_UNKNOWN, tooltip);
|
||||
showState(COLOR_UNKNOWN, tooltip, true);
|
||||
}
|
||||
|
||||
public void showStateLegal(String tooltip) {
|
||||
showState(COLOR_LEGAL, tooltip);
|
||||
showState(COLOR_LEGAL, tooltip, true);
|
||||
}
|
||||
|
||||
public void showStatePartlyLegal(String tooltip) {
|
||||
showState(COLOR_PARTLY_LEGAL, tooltip);
|
||||
showState(COLOR_PARTLY_LEGAL, tooltip, true);
|
||||
}
|
||||
|
||||
public void showStateNotLegal(String tooltip) {
|
||||
showState(COLOR_NOT_LEGAL, tooltip);
|
||||
showState(COLOR_NOT_LEGAL, tooltip, true);
|
||||
}
|
||||
|
||||
public void validateDeck(Deck deck) {
|
||||
|
|
@ -191,28 +189,13 @@ public class LegalityLabel extends JLabel {
|
|||
}
|
||||
}
|
||||
|
||||
public void validateDeck(File deckFile) {
|
||||
deckFile = deckFile.getAbsoluteFile();
|
||||
if (!deckFile.exists()) {
|
||||
errorMessage = String.format("Deck file '%s' does not exist.", deckFile.getAbsolutePath());
|
||||
showStateUnknown("<html><body><b>No Deck loaded!</b></body></html>");
|
||||
return;
|
||||
public java.util.List<String> selectCards() {
|
||||
if (this.validator == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
StringBuilder errorMessages = new StringBuilder();
|
||||
Deck deck = Deck.load(DeckImporter.importDeckFromFile(deckFile.getAbsolutePath(), errorMessages, false), true, true);
|
||||
errorMessage = errorMessages.toString();
|
||||
validateDeck(deck);
|
||||
} catch (Exception ex) {
|
||||
errorMessage = String.format("Error importing deck from file '%s'!", deckFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public void revalidateDeck() {
|
||||
validateDeck(currentDeck);
|
||||
}
|
||||
|
||||
public void validateDeck(String deckFile) {
|
||||
validateDeck(new File(deckFile));
|
||||
return this.validator.getErrorsList().stream()
|
||||
.map(DeckValidatorError::getCardName)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -533,10 +533,10 @@
|
|||
<Component class="mage.client.deckeditor.DeckLegalityPanel" name="deckLegalityDisplay">
|
||||
<Properties>
|
||||
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[245, 155]"/>
|
||||
<Dimension value="[245, 255]"/>
|
||||
</Property>
|
||||
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||
<Dimension value="[85, 155]"/>
|
||||
<Dimension value="[85, 255]"/>
|
||||
</Property>
|
||||
<Property name="opaque" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
|
|
|
|||
|
|
@ -121,12 +121,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
if (!SwingUtilities.isLeftMouseButton(e)) {
|
||||
return;
|
||||
}
|
||||
List<String> cardNames = new ArrayList<>();
|
||||
LegalityLabel label = (LegalityLabel) e.getComponent();
|
||||
label.getValidator().getErrorsList().stream()
|
||||
.map(DeckValidatorError::getCardName)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(cardNames::add);
|
||||
List<String> cardNames = new ArrayList<>(label.selectCards());
|
||||
deckArea.getDeckList().deselectAll();
|
||||
deckArea.getDeckList().selectByName(cardNames);
|
||||
deckArea.getSideboardList().deselectAll();
|
||||
|
|
@ -1290,8 +1286,8 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
|
||||
panelInfo.setOpaque(false);
|
||||
|
||||
deckLegalityDisplay.setMaximumSize(new java.awt.Dimension(245, 155));
|
||||
deckLegalityDisplay.setMinimumSize(new java.awt.Dimension(85, 155));
|
||||
deckLegalityDisplay.setMaximumSize(new java.awt.Dimension(245, 255));
|
||||
deckLegalityDisplay.setMinimumSize(new java.awt.Dimension(85, 255));
|
||||
deckLegalityDisplay.setOpaque(false);
|
||||
deckLegalityDisplay.setVisible(false);
|
||||
|
||||
|
|
@ -1313,7 +1309,7 @@ public class DeckEditorPanel extends javax.swing.JPanel {
|
|||
panelInfoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(panelInfoLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(deckLegalityDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 155, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(deckLegalityDisplay, javax.swing.GroupLayout.PREFERRED_SIZE, 255, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.cards.decks.Deck;
|
|||
import mage.cards.decks.DeckValidator;
|
||||
import mage.cards.mock.MockCard;
|
||||
import mage.cards.mock.MockSplitCard;
|
||||
import mage.client.components.EdhPowerLevelLegalityLabel;
|
||||
import mage.client.components.LegalityLabel;
|
||||
import mage.deck.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
|
@ -15,7 +16,7 @@ import java.util.stream.Stream;
|
|||
|
||||
|
||||
/**
|
||||
* @author Elandril
|
||||
* @author Elandril, JayDi85
|
||||
*/
|
||||
public class DeckLegalityPanel extends javax.swing.JPanel {
|
||||
|
||||
|
|
@ -101,6 +102,10 @@ public class DeckLegalityPanel extends javax.swing.JPanel {
|
|||
new Frontier(), new HistoricalType2(), new PennyDreadfulCommander(), new EuropeanHighlander(), new CanadianHighlander()
|
||||
// not used: new Eternal(), new Momir(), new TinyLeaders()
|
||||
).forEach(this::addLegalityLabel);
|
||||
|
||||
// extra buttons like score
|
||||
this.add(new EdhPowerLevelLegalityLabel());
|
||||
|
||||
addHidePanelButton();
|
||||
|
||||
revalidate();
|
||||
|
|
@ -147,5 +152,4 @@ public class DeckLegalityPanel extends javax.swing.JPanel {
|
|||
.map(LegalityLabel.class::cast)
|
||||
.forEach(label -> label.validateDeck(deckToValidate));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ public class CardViewEDHPowerLevelComparator implements CardViewComparator {
|
|||
return "EDH: " + getPowerLevel(sample);
|
||||
}
|
||||
|
||||
// TODO: it's outdated code, must migrate to shared code from AbstractCommander
|
||||
private int getPowerLevel(CardView card) {
|
||||
|
||||
int thisMaxPower = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue