deck: fixed that clipboard import can choose wrong promo card (close #7666)

This commit is contained in:
Oleg Agafonov 2025-08-10 23:59:19 +04:00
parent 2e6f26e589
commit b06682797c
14 changed files with 69 additions and 75 deletions

View file

@ -785,7 +785,7 @@ public final class SystemUtil {
* @return added cards list
*/
private static Set<Card> addNewCardsToGame(Game game, String cardName, String setCode, int amount, Player owner) {
CardInfo cardInfo = CardLookup.instance.lookupCardInfo(cardName, setCode).orElse(null);
CardInfo cardInfo = CardLookup.instance.lookupCardInfo(cardName, setCode, null);
if (cardInfo == null || amount <= 0) {
return null;
}

View file

@ -3,9 +3,10 @@ package mage.cards.decks.importer;
import mage.cards.repository.CardCriteria;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.util.CardUtil;
import java.util.List;
import java.util.Optional;
import java.util.Objects;
/**
* Deck import: helper class to mock cards repository
@ -14,49 +15,40 @@ public class CardLookup {
public static final CardLookup instance = new CardLookup();
public Optional<CardInfo> lookupCardInfo(String name) {
return Optional.ofNullable(CardRepository.instance.findPreferredCoreExpansionCard(name));
public CardInfo lookupCardInfo(String name) {
return CardRepository.instance.findPreferredCoreExpansionCard(name);
}
public List<CardInfo> lookupCardInfo(CardCriteria criteria) {
// can be override to make fake lookup, e.g. for tests
return CardRepository.instance.findCards(criteria);
}
public Optional<CardInfo> lookupCardInfo(String name, String set) {
if (set == null) {
return lookupCardInfo(name);
public CardInfo lookupCardInfo(String name, String set, String cardNumber) {
CardCriteria cardCriteria = new CardCriteria();
cardCriteria.name(name);
if (set != null) {
cardCriteria.setCodes(set);
}
if (cardNumber != null) {
int intCardNumber = CardUtil.parseCardNumberAsInt(cardNumber);
cardCriteria.minCardNumber(intCardNumber);
cardCriteria.maxCardNumber(intCardNumber);
}
List<CardInfo> foundCards = lookupCardInfo(cardCriteria);
CardInfo res = null;
// if possible then use strict card number
if (cardNumber != null) {
res = foundCards.stream().filter(c -> Objects.equals(c.getCardNumber(), cardNumber)).findAny().orElse(null);
}
Optional<CardInfo> result = lookupCardInfo(new CardCriteria().name(name).setCodes(set))
.stream()
.findAny();
if (result.isPresent()) {
return result;
if (res == null) {
res = foundCards.stream().findAny().orElse(null);
}
return lookupCardInfo(name);
}
public Optional<CardInfo> lookupCardInfo(String name, String set, String cardNumber) {
Optional<CardInfo> result;
try {
int intCardNumber = Integer.parseInt(cardNumber);
result = lookupCardInfo(
new CardCriteria()
.name(name)
.setCodes(set)
.minCardNumber(intCardNumber)
.maxCardNumber(intCardNumber))
.stream()
.findAny();
if (result.isPresent()) {
return result;
}
} catch (NumberFormatException ignore) {
/* ignored */
}
return lookupCardInfo(name, set);
return res;
}
}

View file

@ -66,14 +66,13 @@ public class CodDeckImporter extends XmlDeckImporter {
private static Function<Node, Stream<DeckCardInfo>> toDeckCardInfo(CardLookup lookup, StringBuilder errors) {
return node -> {
String name = node.getAttributes().getNamedItem("name").getNodeValue().trim();
Optional<CardInfo> cardInfo = lookup.lookupCardInfo(name);
if (cardInfo.isPresent()) {
CardInfo info = cardInfo.get();
CardInfo cardInfo = lookup.lookupCardInfo(name);
if (cardInfo != null) {
int amount = getQuantityFromNode(node);
DeckCardInfo.makeSureCardAmountFine(amount, info.getName());
DeckCardInfo.makeSureCardAmountFine(amount, cardInfo.getName());
return Collections.nCopies(
amount,
new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())
new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode())
).stream();
} else {
errors.append("Could not find card: '").append(name).append("'\n");

View file

@ -33,11 +33,10 @@ public class DecDeckImporter extends PlainTextDeckImporter {
String lineName = line.substring(delim).trim();
try {
int num = Integer.parseInt(lineNum);
Optional<CardInfo> cardLookup = getCardLookup().lookupCardInfo(lineName);
if (!cardLookup.isPresent()) {
CardInfo cardInfo = getCardLookup().lookupCardInfo(lineName);
if (cardInfo == null) {
sbMessage.append("Could not find card: '").append(lineName).append("' at line ").append(lineCount).append('\n');
} else {
CardInfo cardInfo = cardLookup.get();
DeckCardInfo.makeSureCardAmountFine(num, cardInfo.getName());
DeckCardInfo deckCardInfo = new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode());
for (int i = 0; i < num; i++) {

View file

@ -32,7 +32,7 @@ public class DekDeckImporter extends PlainTextDeckImporter {
}
boolean isSideboard = "true".equals(extractAttribute(line, "Sideboard"));
CardInfo cardInfo = getCardLookup().lookupCardInfo(cardName).orElse(null);
CardInfo cardInfo = getCardLookup().lookupCardInfo(cardName);
if (cardInfo == null) {
sbMessage.append("Could not find card: '").append(cardName).append("' at line ").append(lineCount).append('\n');
} else {

View file

@ -29,9 +29,9 @@ public class DraftLogImporter extends PlainTextDeckImporter {
Matcher pickMatcher = PICK_PATTERN.matcher(line);
if (pickMatcher.matches()) {
String name = pickMatcher.group(1);
CardInfo card = getCardLookup().lookupCardInfo(name, currentSet).orElse(null);
if (card != null) {
deckList.getCards().add(new DeckCardInfo(card.getName(), card.getCardNumber(), card.getSetCode()));
CardInfo cardInfo = getCardLookup().lookupCardInfo(name, currentSet, null);
if (cardInfo != null) {
deckList.getCards().add(new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode()));
} else {
sbMessage.append("couldn't find: \"").append(name).append("\"\n");
}

View file

@ -36,9 +36,9 @@ public class MWSDeckImporter extends PlainTextDeckImporter {
int num = Integer.parseInt(lineNum);
CardInfo cardInfo = null;
if (setCode.isEmpty()) {
cardInfo = getCardLookup().lookupCardInfo(lineName, setCode).orElse(null);
cardInfo = getCardLookup().lookupCardInfo(lineName, setCode, null);
} else {
cardInfo = getCardLookup().lookupCardInfo(lineName).orElse(null);
cardInfo = getCardLookup().lookupCardInfo(lineName);
}
if (cardInfo == null) {

View file

@ -65,12 +65,12 @@ public class MtgaImporter extends PlainTextDeckImporter {
CardInfo found;
int count = Integer.parseInt(pattern.group(1));
String name = pattern.group(2);
if (pattern.group(3) != null && pattern.group(4) != null) {
if (pattern.group(3) != null) {
String set = SET_REMAPPING.getOrDefault(pattern.group(3), pattern.group(3));
String cardNumber = pattern.group(4);
found = lookup.lookupCardInfo(name, set, cardNumber).orElse(null);
String cardNumber = pattern.groupCount() >= 4 ? pattern.group(4) : null;
found = lookup.lookupCardInfo(name, set, cardNumber);
} else {
found = lookup.lookupCardInfo(name).orElse(null);
found = lookup.lookupCardInfo(name, null, null);
}
if (found == null) {
@ -110,9 +110,8 @@ public class MtgaImporter extends PlainTextDeckImporter {
// by card marks
Matcher pattern = MtgaImporter.MTGA_PATTERN.matcher(CardNameUtil.normalizeCardName(firstLine));
return pattern.matches()
&& pattern.groupCount() >= 4
&& pattern.group(3) != null
&& pattern.group(4) != null;
&& pattern.groupCount() >= 3
&& pattern.group(3) != null;
}
}

View file

@ -63,11 +63,10 @@ public class MtgjsonDeckImporter extends JsonDeckImporter {
}
int num = JsonUtil.getAsInt(card, "count");
Optional<CardInfo> cardLookup = getCardLookup().lookupCardInfo(name, setCode);
if (!cardLookup.isPresent()) {
CardInfo cardInfo = getCardLookup().lookupCardInfo(name, setCode, null);
if (cardInfo == null) {
sbMessage.append("Could not find card: '").append(name).append("'\n");
} else {
CardInfo cardInfo = cardLookup.get();
for (int i = 0; i < num; i++) {
list.add(new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode()));
}

View file

@ -63,12 +63,11 @@ public class O8dDeckImporter extends XmlDeckImporter {
private static Function<Node, Stream<DeckCardInfo>> toDeckCardInfo(CardLookup lookup, StringBuilder errors) {
return node -> {
String name = node.getTextContent();
Optional<CardInfo> cardInfo = lookup.lookupCardInfo(name);
if (cardInfo.isPresent()) {
CardInfo info = cardInfo.get();
CardInfo cardInfo = lookup.lookupCardInfo(name);
if (cardInfo != null) {
return Collections.nCopies(
getQuantityFromNode(node),
new DeckCardInfo(info.getName(), info.getCardNumber(), info.getSetCode())).stream();
new DeckCardInfo(cardInfo.getName(), cardInfo.getCardNumber(), cardInfo.getSetCode())).stream();
} else {
errors.append("Could not find card: '").append(name).append("'\n");
return Stream.empty();

View file

@ -29,11 +29,11 @@ public final class EmblemOfCard extends Emblem {
String setCode,
String infoTypeForError
) {
int cardNumberInt = CardUtil.parseCardNumberAsInt(cardNumber);
int intCardNumber = CardUtil.parseCardNumberAsInt(cardNumber);
List<CardInfo> found = CardRepository.instance.findCards(new CardCriteria()
.name(cardName)
.minCardNumber(cardNumberInt)
.maxCardNumber(cardNumberInt)
.minCardNumber(intCardNumber)
.maxCardNumber(intCardNumber)
.setCodes(setCode));
return found.stream()
.filter(ci -> ci.getCardNumber().equals(cardNumber))

View file

@ -5,6 +5,9 @@
1 Expansion // Explosion (GRN) 224
1 Forest (XLN) 277
1 Teferi, Hero of Dominaria (DAR) 207
1 Benalish Marshal (PDOM) 6p
1 Benalish Marshal (PDOM) 6s
1 Benalish Marshal
3 Unmoored Ego (GRN) 212
1 Beacon Bolt (GRN) 154

View file

@ -29,26 +29,29 @@ public class FakeCardLookup extends CardLookup {
return this;
}
public Optional<CardInfo> lookupCardInfo(String cardName) {
public CardInfo lookupCardInfo(String cardName) {
CardInfo card = lookup.get(cardName);
if (card != null) {
return Optional.of(card);
return card;
}
if (alwaysMatches) {
return Optional.of(new CardInfo() {{
return new CardInfo() {{
name = cardName;
}});
}};
}
return Optional.empty();
return null;
}
@Override
public List<CardInfo> lookupCardInfo(CardCriteria criteria) {
return lookupCardInfo(criteria.getName())
.map(Collections::singletonList)
.orElse(Collections.emptyList());
CardInfo found = lookupCardInfo(criteria.getName());
if (found != null) {
return new ArrayList<>(Collections.singletonList(found));
} else {
return Collections.emptyList();
}
}
}

View file

@ -36,11 +36,12 @@ public class MtgaImporterTest {
.addMain("Expansion // Explosion", 1)
.addMain("Forest", 1)
.addMain("Teferi, Hero of Dominaria", 1)
.addMain("Benalish Marshal", 3)
.addSide("Unmoored Ego", 3)
.addSide("Beacon Bolt", 1)
.verify(deck, 8, 4);
.verify(deck, 11, 4);
}
}