Tests: improved performance in game tests;

This commit is contained in:
Oleg Agafonov 2021-09-18 14:03:54 +04:00
parent 2fa76fc7be
commit 2cf005f971
6 changed files with 123 additions and 34 deletions

View file

@ -102,21 +102,25 @@ public abstract class MageTestBase {
@BeforeClass
public static void init() {
Logger.getRootLogger().setLevel(Level.DEBUG);
deleteSavedGames();
ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml"));
config.getGameTypes().forEach((gameType) -> {
GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType));
});
config.getTournamentTypes().forEach((tournamentType) -> {
TournamentFactory.instance.addTournamentType(tournamentType.getName(), loadTournamentType(tournamentType), loadPlugin(tournamentType));
});
config.getPlayerTypes().forEach((playerType) -> {
PlayerFactory.instance.addPlayerType(playerType.getName(), loadPlugin(playerType));
});
// one time init for all tests
if (GameFactory.instance.getGameTypes().isEmpty()) {
deleteSavedGames();
ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml"));
config.getGameTypes().forEach((gameType) -> {
GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType));
});
config.getTournamentTypes().forEach((tournamentType) -> {
TournamentFactory.instance.addTournamentType(tournamentType.getName(), loadTournamentType(tournamentType), loadPlugin(tournamentType));
});
config.getPlayerTypes().forEach((playerType) -> {
PlayerFactory.instance.addPlayerType(playerType.getName(), loadPlugin(playerType));
});
// for (Plugin plugin : config.getDeckTypes()) {
// DeckValidatorFactory.getInstance().addDeckType(plugin.getName(), loadPlugin(plugin));
// }
Copier.setLoader(classLoader);
Copier.setLoader(classLoader);
}
}
@SuppressWarnings("UseSpecificCatch")

View file

@ -81,7 +81,8 @@ public abstract class MageTestPlayerBase {
protected Map<TestPlayer, Map<Zone, String>> commands = new HashMap<>();
protected static Map<String, DeckCardLists> loadedDeckCardLists = new HashMap<>(); // test decks buffer
protected static Map<String, DeckCardLists> loadedDecks = new HashMap<>(); // deck's cache
protected static Map<String, CardInfo> loadedCardInfo = new HashMap<>(); // db card's cache
protected TestPlayer playerA;
protected TestPlayer playerB;
@ -131,12 +132,15 @@ public abstract class MageTestPlayerBase {
logger.debug("Logging level: " + logger.getLevel());
logger.debug("Default charset: " + Charset.defaultCharset());
deleteSavedGames();
ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml"));
for (GamePlugin plugin : config.getGameTypes()) {
GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
// one time init for all tests
if (GameFactory.instance.getGameTypes().isEmpty()) {
deleteSavedGames();
ConfigSettings config = new ConfigWrapper(ConfigFactory.loadFromFile("config/config.xml"));
for (GamePlugin plugin : config.getGameTypes()) {
GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
}
Copier.setLoader(classLoader);
}
Copier.setLoader(classLoader);
}
private static Class<?> loadPlugin(Plugin plugin) {

View file

@ -259,13 +259,13 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
logger.debug("Loading deck...");
DeckCardLists list;
if (loadedDeckCardLists.containsKey(deckName)) {
list = loadedDeckCardLists.get(deckName);
if (loadedDecks.containsKey(deckName)) {
list = loadedDecks.get(deckName);
} else {
list = DeckImporter.importDeckFromFile(deckName, true);
loadedDeckCardLists.put(deckName, list);
loadedDecks.put(deckName, list);
}
Deck deck = Deck.load(list, false, false);
Deck deck = Deck.load(list, false, false, loadedCardInfo);
logger.debug("Done!");
if (deck.getCards().size() < 40) {
throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getCards().size());

View file

@ -4,13 +4,17 @@ import mage.cards.Card;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.game.GameException;
import mage.util.Copyable;
import mage.util.DeckUtil;
import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
public class Deck implements Serializable {
public class Deck implements Serializable, Copyable<Deck> {
static final int MAX_CARDS_PER_DECK = 1000;
private String name;
private final Set<Card> cards = new LinkedHashSet<>();
@ -20,6 +24,20 @@ public class Deck implements Serializable {
private long deckHashCode = 0;
private long deckCompleteHashCode = 0;
public Deck() {
super();
}
public Deck(final Deck deck) {
this.name = deck.name;
this.cards.addAll(deck.cards.stream().map(Card::copy).collect(Collectors.toList()));
this.sideboard.addAll(deck.sideboard.stream().map(Card::copy).collect(Collectors.toList()));
this.cardsLayout = deck.cardsLayout == null ? null : deck.cardsLayout.copy();
this.sideboardLayout = deck.sideboardLayout == null ? null : deck.sideboardLayout.copy();
this.deckHashCode = deck.deckHashCode;
this.deckCompleteHashCode = deck.deckCompleteHashCode;
}
public static Deck load(DeckCardLists deckCardLists) throws GameException {
return Deck.load(deckCardLists, false);
}
@ -51,6 +69,10 @@ public class Deck implements Serializable {
return currentDeck;
}
public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors, boolean mockCards) throws GameException {
return load(deckCardLists, ignoreErrors, mockCards, null);
}
/**
* Warning, AI can't play Mock cards, so call it with extra params in real games or tests
*
@ -60,17 +82,17 @@ public class Deck implements Serializable {
* @return
* @throws GameException
*/
public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors, boolean mockCards) throws GameException {
public static Deck load(DeckCardLists deckCardLists, boolean ignoreErrors, boolean mockCards, Map<String, CardInfo> cardInfoCache) throws GameException {
Deck deck = new Deck();
deck.setName(deckCardLists.getName());
deck.cardsLayout = deckCardLists.getCardLayout();
deck.sideboardLayout = deckCardLists.getSideboardLayout();
deck.cardsLayout = deckCardLists.getCardLayout() == null ? null : deckCardLists.getCardLayout().copy();
deck.sideboardLayout = deckCardLists.getSideboardLayout() == null ? null : deckCardLists.getSideboardLayout().copy();
List<String> deckCardNames = new ArrayList<>();
int totalCards = 0;
for (DeckCardInfo deckCardInfo : deckCardLists.getCards()) {
Card card = createCard(deckCardInfo, mockCards);
Card card = createCard(deckCardInfo, mockCards, cardInfoCache);
if (card != null) {
if (totalCards > 1000) {
if (totalCards > MAX_CARDS_PER_DECK) {
break;
}
deck.cards.add(card);
@ -83,9 +105,9 @@ public class Deck implements Serializable {
}
List<String> sbCardNames = new ArrayList<>();
for (DeckCardInfo deckCardInfo : deckCardLists.getSideboard()) {
Card card = createCard(deckCardInfo, mockCards);
Card card = createCard(deckCardInfo, mockCards, cardInfoCache);
if (card != null) {
if (totalCards > 1000) {
if (totalCards > MAX_CARDS_PER_DECK) {
break;
}
deck.sideboard.add(card);
@ -127,8 +149,21 @@ public class Deck implements Serializable {
}
private static Card createCard(DeckCardInfo deckCardInfo, boolean mockCards) {
CardInfo cardInfo = CardRepository.instance.findCard(deckCardInfo.getSetCode(), deckCardInfo.getCardNum());
private static Card createCard(DeckCardInfo deckCardInfo, boolean mockCards, Map<String, CardInfo> cardInfoCache) {
CardInfo cardInfo;
if (cardInfoCache != null) {
// from cache
String key = String.format("%s_%s", deckCardInfo.getSetCode(), deckCardInfo.getCardNum());
cardInfo = cardInfoCache.getOrDefault(key, null);
if (cardInfo == null) {
cardInfo = CardRepository.instance.findCard(deckCardInfo.getSetCode(), deckCardInfo.getCardNum());
cardInfoCache.put(key, cardInfo);
}
} else {
// from db
cardInfo = CardRepository.instance.findCard(deckCardInfo.getSetCode(), deckCardInfo.getCardNum());
}
if (cardInfo == null) {
return null;
}
@ -226,4 +261,8 @@ public class Deck implements Serializable {
this.sideboardLayout = null;
}
@Override
public Deck copy() {
return new Deck(this);
}
}

View file

@ -2,19 +2,32 @@
package mage.cards.decks;
import mage.util.Copyable;
import java.io.Serializable;
/**
*
* @author LevelX2
*/
public class DeckCardInfo implements Serializable {
public class DeckCardInfo implements Serializable, Copyable<DeckCardInfo> {
private String cardName;
private String setCode;
private String cardNum;
private int quantity;
public DeckCardInfo() {
super();
}
public DeckCardInfo(final DeckCardInfo info) {
this.cardName = info.cardName;
this.setCode = info.setCode;
this.cardNum = info.cardNum;
this.quantity = info.quantity;
}
public DeckCardInfo(String cardName, String cardNum, String setCode) {
this(cardName, cardNum, setCode, 1);
}
@ -51,4 +64,8 @@ public class DeckCardInfo implements Serializable {
return setCode + cardNum;
}
@Override
public DeckCardInfo copy() {
return new DeckCardInfo(this);
}
}

View file

@ -1,15 +1,35 @@
package mage.cards.decks;
import mage.util.Copyable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by stravant@gmail.com on 2016-10-03.
*/
public class DeckCardLayout {
public class DeckCardLayout implements Copyable<DeckCardLayout> {
private final List<List<List<DeckCardInfo>>> cards;
private final String settings;
public DeckCardLayout(final DeckCardLayout layout) {
this.cards = new ArrayList<>();
for (int i1 = 0; i1 < layout.cards.size(); i1++) {
List<List<DeckCardInfo>> list1 = new ArrayList<>();
this.cards.add(list1);
for (int i2 = 0; i2 < layout.cards.get(i1).size(); i2++) {
List<DeckCardInfo> list2 = new ArrayList<>();
list1.add(list2);
for (int i3 = 0; i3 < layout.cards.get(i1).get(i2).size(); i3++) {
DeckCardInfo info = layout.cards.get(i1).get(i2).get(i3);
list2.add(info.copy());
}
}
}
this.settings = layout.settings;
}
public DeckCardLayout(List<List<List<DeckCardInfo>>> cards, String settings) {
this.cards = cards;
this.settings = settings;
@ -22,4 +42,9 @@ public class DeckCardLayout {
public String getSettings() {
return settings;
}
@Override
public DeckCardLayout copy() {
return new DeckCardLayout(this);
}
}