package com.cardshifter.modapi.base;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.junit.Before;
import com.cardshifter.modapi.actions.ActionComponent;
import com.cardshifter.modapi.actions.ECSAction;
import com.cardshifter.modapi.actions.TargetSet;
import com.cardshifter.modapi.cards.BattlefieldComponent;
import com.cardshifter.modapi.cards.CardComponent;
import com.cardshifter.modapi.cards.DeckComponent;
import com.cardshifter.modapi.cards.HandComponent;
import com.cardshifter.modapi.phase.PhaseController;
import com.cardshifter.modapi.resources.ECSResource;
import com.cardshifter.modapi.resources.ECSResourceData;
import com.cardshifter.modapi.resources.ResourceRetriever;
public abstract class GameTest {
private static final Logger logger = LogManager.getLogger(GameTest.class);
protected ECSGame game;
@Retriever protected ComponentRetriever<ActionComponent> actions;
@Retriever protected ComponentRetriever<CardComponent> card;
@Retriever protected ComponentRetriever<DeckComponent> deck;
@Retriever protected ComponentRetriever<HandComponent> hand;
@Retriever protected ComponentRetriever<BattlefieldComponent> field;
@Retriever protected ComponentRetriever<CreatureTypeComponent> ctype;
@RetrieverSingleton protected PhaseController phase;
@Before
public void before() {
game = new ECSGame();
game.setRandomSeed(42);
setupGame(game);
Retrievers.inject(this, game);
game.startGame();
onAfterGameStart();
}
protected abstract void onAfterGameStart();
protected abstract void setupGame(ECSGame ecsGame);
protected Entity getOpponent() {
List<Entity> list = game.getEntitiesWithComponent(PlayerComponent.class).stream()
.filter(entity -> entity != phase.getCurrentEntity())
.collect(Collectors.toList());
assertEquals("Found more than one opponent", 1, list.size());
return list.get(0);
}
protected Predicate<Entity> isCreatureType(String creatureType) {
return entity -> entity.hasComponent(CreatureTypeComponent.class) &&
entity.getComponent(CreatureTypeComponent.class).hasCreatureType(creatureType);
}
protected void assertResource(Entity entity, ECSResource resource, int expected) {
ResourceRetriever retriever = ResourceRetriever.forResource(resource);
ECSResourceData res = retriever.resFor(entity);
assertEquals("Unexpected resource " + resource + " for " + entity, expected, res.get());
}
protected void useActionWithFailedTarget(Entity source, String actionName, Entity target) {
ECSAction action = getAction(source, actionName);
Objects.requireNonNull(action, source + " does not have action " + actionName);
assertTrue(action.isAllowed(phase.getCurrentEntity()));
assertEquals(1, action.getTargetSets().size());
TargetSet targets = action.getTargetSets().get(0);
assertFalse("Did not expect target to be allowed", targets.addTarget(target));
assertFalse("Did not expect action to be performed", action.perform(phase.getCurrentEntity()));
}
protected List<Entity> findPossibleTargets(Entity entity, String actionName) {
ECSAction action = getAction(entity, actionName);
assertTrue(action.isAllowed(phase.getCurrentEntity()));
assertEquals(1, action.getTargetSets().size());
TargetSet targets = action.getTargetSets().get(0);
return targets.findPossibleTargets();
}
protected void useActionWithTarget(Entity entity, String actionName, Entity target) {
ECSAction action = getAction(entity, actionName);
assertTrue(action.isAllowed(phase.getCurrentEntity()));
assertEquals("Unexpected numbet of TargetSets.", 1, action.getTargetSets().size());
TargetSet targets = action.getTargetSets().get(0);
assertTrue("Target could not be added: " + target + " to action " + action, targets.addTarget(target));
assertTrue(action + " could not be performed", action.perform(phase.getCurrentEntity()));
}
protected void useFail(Entity entity, String actionName) {
useFail(entity, actionName, phase.getCurrentEntity());
}
protected void useFail(Entity entity, String actionName, Entity performer) {
ECSAction action = getAction(entity, actionName);
assertFalse("Did not expect action " + actionName + " to be allowed on " + entity + " by " + performer, action.isAllowed(performer));
}
protected Entity findCardInDeck(Predicate<Entity> condition) {
return deck.get(phase.getCurrentEntity()).stream().filter(condition).findAny().get();
}
protected Entity cardToHand(Predicate<Entity> condition) {
Entity player = phase.getCurrentEntity();
HandComponent myHand = hand.get(player);
Optional<Entity> inHand = myHand.stream().filter(condition).findAny();
if (!inHand.isPresent()) {
int previousHand = myHand.size();
Entity inDeck = findCardInDeck(condition);
card.get(inDeck).moveToBottom(myHand);
card.get(myHand.getTopCard()).moveToBottom(deck.get(player));
assertEquals(previousHand, myHand.size());
return inDeck;
}
return inHand.get();
}
protected void nextPhase() {
useAction(phase.getCurrentEntity(), "End Turn");
logger.info("Next phase, current entity is now " + phase.getCurrentEntity() + " phase is " + phase.getCurrentPhase());
}
protected void useAction(Entity entity, String actionName) {
ECSAction action = getAction(entity, actionName);
assertTrue("Action " + actionName + " is not allowed for " + entity, action.isAllowed(phase.getCurrentEntity()));
action.perform(phase.getCurrentEntity());
}
protected ECSAction getAction(Entity entity, String actionName) {
if (actions == null) {
throw new AssertionError("actions is null");
}
ActionComponent available = Objects.requireNonNull(actions.get(entity), "Entity does not have any action component");
return available.getAction(actionName);
}
protected Entity currentPlayer() {
return phase.getCurrentEntity();
}
}