From a6337fd28a89d7ea7df02fe3d783597dd8c5cc3e Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 4 Apr 2023 22:05:22 +0400 Subject: [PATCH] Cheats: improved cheat and test commands to use same set_code-card_name notation, added additional tests (related to #10139, cheat command example: battlefield:Human:XLN-Island:1) --- .../java/mage/server/util/SystemUtil.java | 38 ++++++++++----- .../mage/test/serverside/TokenImagesTest.java | 2 +- .../base/impl/CardTestPlayerAPIImpl.java | 10 ++-- .../org/mage/test/testapi/AddCardApiTest.java | 46 +++++++++++++++++-- .../java/mage/verify/VerifyCardDataTest.java | 13 ++++-- Mage/src/main/java/mage/util/CardUtil.java | 3 +- 6 files changed, 84 insertions(+), 28 deletions(-) diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 95f4d8dc1d..28b3b39fe0 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -87,7 +87,10 @@ public final class SystemUtil { private static final Pattern patternGroup = Pattern.compile("\\[(.+)\\]"); // [test new card] private static final Pattern patternCommand = Pattern.compile("([\\w]+):([\\S ]+?):([\\S ]+):([\\d]+)"); // battlefield:Human:Island:10 - private static final Pattern patternCardInfo = Pattern.compile("([\\S ]+):([\\S ]+)"); // Island:XLN + private static final Pattern patternCardInfo = Pattern.compile("(^[\\dA-Z]{2,7})@([\\S ]+)" // XLN-Island + .replace("7", String.valueOf(CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH)) + .replace("@", CardUtil.TESTS_SET_CODE_DELIMETER) + ); // show ext info for special commands private static final String PARAM_COLOR_COST = "color cost"; @@ -220,17 +223,10 @@ public final class SystemUtil { } // card name can be with set - String cardInfo = matchCommand.group(3); - Matcher matchInfo = patternCardInfo.matcher(cardInfo); - if (matchInfo.matches()) { - // name with set - com.cardName = matchInfo.group(1); - com.cardSet = matchInfo.group(2); - } else { - // name only - com.cardName = cardInfo; - com.cardSet = ""; - } + // example: XLN-Island + List cardInfo = parseSetAndCardNameCommand(matchCommand.group(3)); + com.cardSet = cardInfo.get(0); + com.cardName = cardInfo.get(1); if (com.cardName.isEmpty()) { com.Error = "Card name is empty"; @@ -729,4 +725,22 @@ public final class SystemUtil { long diffInMillies = date2.getTime() - date1.getTime(); return timeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS); } + + /** + * Parse set code and card name from command line + * + * @param info format example: XLN-Mountain (set code must be upper case) + * @return + */ + public static List parseSetAndCardNameCommand(String info) { + Matcher matchInfo = patternCardInfo.matcher(info); + String cardSet = ""; + String cardName = info; + if (matchInfo.matches()) { + // set with card + cardSet = matchInfo.group(1); + cardName = matchInfo.group(2); + } + return Arrays.asList(cardSet, cardName); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/TokenImagesTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/TokenImagesTest.java index 57faeb431c..d02bcb3394 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/TokenImagesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/TokenImagesTest.java @@ -15,7 +15,7 @@ public class TokenImagesTest extends CardTestPlayerBase { @Test public void test_TokenMustGetSameSetCodeAsSourceCard() { //{3}{W}, {T}, Sacrifice Memorial to Glory: Create two 1/1 white Soldier creature tokens. - addCard(Zone.BATTLEFIELD, playerA, "40K:Memorial to Glory"); + addCard(Zone.BATTLEFIELD, playerA, "40K-Memorial to Glory"); addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{W}, {T}, Sacrifice"); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index afdfc0396a..adcfd7ed9d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -600,7 +600,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement * @param gameZone {@link mage.constants.Zone} to add cards to. * @param player {@link Player} to add cards for. Use either playerA or * playerB. - * @param cardName Card name or set:card + * @param cardName Card name or set-card * @param count Amount of cards to be added. * @param tapped In case gameZone is Battlefield, determines whether * permanent should be tapped. In case gameZone is other @@ -624,11 +624,9 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement // set code for card String setCode = ""; - String setLookup = CardUtil.substring(cardName, CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH); - if (setLookup.contains(":")) { - setCode = setLookup.substring(0, setLookup.indexOf(":")); - cardName = cardName.substring(setCode.length() + 1); - } + List cardCommand = SystemUtil.parseSetAndCardNameCommand(cardName); + setCode = cardCommand.get(0); + cardName = cardCommand.get(1); CardInfo cardInfo; if (setCode.isEmpty()) { diff --git a/Mage.Tests/src/test/java/org/mage/test/testapi/AddCardApiTest.java b/Mage.Tests/src/test/java/org/mage/test/testapi/AddCardApiTest.java index ff78a37a06..42147d4fc8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/testapi/AddCardApiTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/testapi/AddCardApiTest.java @@ -2,15 +2,55 @@ package org.mage.test.testapi; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.server.util.SystemUtil; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import java.util.List; + /** * @author JayDi85 */ public class AddCardApiTest extends CardTestPlayerBase { + @Test + public void test_CardParsing() { + List info; + + info = SystemUtil.parseSetAndCardNameCommand(""); + Assert.assertEquals(2, info.size()); + Assert.assertEquals("", info.get(0)); + Assert.assertEquals("", info.get(1)); + + info = SystemUtil.parseSetAndCardNameCommand("single name"); + Assert.assertEquals(2, info.size()); + Assert.assertEquals("", info.get(0)); + Assert.assertEquals("single name", info.get(1)); + + info = SystemUtil.parseSetAndCardNameCommand("SET-name"); + Assert.assertEquals(2, info.size()); + Assert.assertEquals("SET", info.get(0)); + Assert.assertEquals("name", info.get(1)); + + // only upper case set codes can be used + info = SystemUtil.parseSetAndCardNameCommand("non-set-code-name"); + Assert.assertEquals(2, info.size()); + Assert.assertEquals("", info.get(0)); + Assert.assertEquals("non-set-code-name", info.get(1)); + + info = SystemUtil.parseSetAndCardNameCommand("SET-card-name"); + Assert.assertEquals(2, info.size()); + Assert.assertEquals("SET", info.get(0)); + Assert.assertEquals("card-name", info.get(1)); + + // must find first symbols before delimeter, e.g. TOO + info = SystemUtil.parseSetAndCardNameCommand("TOO-LONG-SET-card-name"); + Assert.assertEquals(2, info.size()); + Assert.assertEquals("TOO", info.get(0)); + Assert.assertEquals("LONG-SET-card-name", info.get(1)); + } + @Test public void test_CardName_Normal() { addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); @@ -30,8 +70,8 @@ public class AddCardApiTest extends CardTestPlayerBase { @Test public void test_CardNameWithSetCode_Normal() { - addCard(Zone.BATTLEFIELD, playerA, "40K:Memorial to Glory", 2); - addCard(Zone.BATTLEFIELD, playerA, "PANA:Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, "40K-Memorial to Glory", 2); + addCard(Zone.BATTLEFIELD, playerA, "PANA-Plains", 2); setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); @@ -50,6 +90,6 @@ public class AddCardApiTest extends CardTestPlayerBase { @Test(expected = org.junit.ComparisonFailure.class) public void test_CardNameWithSetCode_RaiseErrorOnUnknownSet() { - addCard(Zone.BATTLEFIELD, playerA, "SS4:Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "SS4-Plains", 1); } } diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 7716504726..28aec1baac 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -29,6 +29,7 @@ import mage.game.draft.DraftCube; import mage.game.draft.RateCard; import mage.game.permanent.token.Token; import mage.game.permanent.token.TokenImpl; +import mage.server.util.SystemUtil; import mage.sets.TherosBeyondDeath; import mage.util.CardUtil; import mage.verify.mtgjson.MtgJsonCard; @@ -964,7 +965,7 @@ public class VerifyCardDataTest { cardNames.add(cardInfo.getName()); } - // CHECK: set code must be compatible with tests commands format + // CHECK: set code must be compatible with tests commands format like "SET-card" // how-to fix: increase lookup lenth if (set.getCode().length() + 1 > CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH) { errorsList.add("Error: set code too big for test commads lookup: " + set.getCode() + ", lookup length: " + CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH); @@ -995,10 +996,12 @@ public class VerifyCardDataTest { errorsList.add("Error: card name or number contains non-ascii symbols: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); } - // CHECK: card name must not contain : symbol due set:name commands format in test engine - // (if it exists then decrease TESTS_SET_CODE_LOOKUP_LENGTH) - if (CardUtil.substring(card.getName(), CardUtil.TESTS_SET_CODE_LOOKUP_LENGTH).contains(":")) { - errorsList.add("Error: card name can't contain : symbol: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); + // CHECK: set code and card name must be parseable for test and cheat commands XLN-Mountain + List cardCommand = SystemUtil.parseSetAndCardNameCommand(set.getCode() + CardUtil.TESTS_SET_CODE_DELIMETER + card.getName()); + if (!Objects.equals(set.getCode(), cardCommand.get(0)) + || !Objects.equals(card.getName(), cardCommand.get(1))) { + // if you catch it then parser logic must be changed to support problem set-card combination + errorsList.add("Error: card name can't be used in tests and cheats with set code: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); } // CHECK: card number must start with 09-aZ symbols (wrong symbol example: *123) diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 3039e5fd19..f9bdc931fe 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -77,7 +77,8 @@ public final class CardUtil { "put", "return", "exile", "discard", "sacrifice", "remove", "tap", "reveal", "pay" ); - public static final int TESTS_SET_CODE_LOOKUP_LENGTH = 10; // search set code in commands like "set:card_name" + public static final int TESTS_SET_CODE_LOOKUP_LENGTH = 6; // search set code in commands like "set_code-card_name" + public static final String TESTS_SET_CODE_DELIMETER = "-"; // delimeter for cheats and tests command "set_code-card_name" /** * Increase spell or ability cost to be paid.