fight unit tests

~1.25h work
This commit is contained in:
Benedikt Galbavy 2024-01-21 14:02:55 +01:00
parent 37d9f84787
commit 69cb4417fd
3 changed files with 138 additions and 12 deletions

View File

@ -15,4 +15,13 @@ public class Pair<T, U> {
public T left() { return this.left; }; public T left() { return this.left; };
public U right() { return this.right; }; public U right() { return this.right; };
@Override
public boolean equals(Object o) {
if (o instanceof Pair<?,?>) {
return left.equals(((Pair<?, ?>) o).left) && right.equals(((Pair<?, ?>) o).right);
}
return super.equals(o);
}
} }

View File

@ -12,15 +12,15 @@ import java.util.List;
public class Battle { public class Battle {
@RequiredArgsConstructor @RequiredArgsConstructor
private enum ElementMod { enum ElementMod {
HALF(0.5), HALF(0.5),
NONE(1), NONE(1),
DOUBLE(2); DOUBLE(2);
public final double percentMod; public final double percentMod;
} }
private record FightDTO(Combatant player, Card card) {}; record FightDTO(Combatant player, Card card) {};
private record RoundResult(FightDTO winner, FightDTO loser, boolean draw, ElementMod winnerMod, ElementMod loserMod) {}; record RoundResult(FightDTO winner, FightDTO loser, boolean draw, ElementMod winnerMod, ElementMod loserMod) {};
private Pair<Combatant, Combatant> combatants; private Pair<Combatant, Combatant> combatants;
@Getter @Getter
private volatile List<String> log = new ArrayList<>(); private volatile List<String> log = new ArrayList<>();
@ -50,7 +50,7 @@ public class Battle {
this.combatants.right().updateStats(!leftWins); this.combatants.right().updateStats(!leftWins);
} }
private void playRound(int round) { void playRound(int round) {
RoundResult result = this.fight( RoundResult result = this.fight(
new FightDTO( new FightDTO(
this.combatants.left(), this.combatants.left(),
@ -74,7 +74,7 @@ public class Battle {
result.loser().card()); result.loser().card());
} }
private boolean isImmune(Card defend, Card attack) { static boolean isImmune(Card defend, Card attack) {
if (defend.name().equals("Dragon") && attack.name().endsWith("Goblin")) return true; if (defend.name().equals("Dragon") && attack.name().endsWith("Goblin")) return true;
if (defend.name().equals("Wizzard") && attack.name().equals("Ork")) return true; if (defend.name().equals("Wizzard") && attack.name().equals("Ork")) return true;
if (defend.name().equals("WaterSpell") && attack.name().equals("Knight")) return true; if (defend.name().equals("WaterSpell") && attack.name().equals("Knight")) return true;
@ -84,7 +84,7 @@ public class Battle {
return false; return false;
} }
private enum Element { enum Element {
NORMAL, NORMAL,
FIRE, FIRE,
WATER; WATER;
@ -105,7 +105,7 @@ public class Battle {
} }
} }
private Pair<ElementMod, ElementMod> getElementMod(Card left, Card right) { static Pair<ElementMod, ElementMod> getElementMod(Card left, Card right) {
Pair<ElementMod, ElementMod> returnMods = new Pair<>(ElementMod.NONE, ElementMod.NONE); Pair<ElementMod, ElementMod> returnMods = new Pair<>(ElementMod.NONE, ElementMod.NONE);
if (!left.name().endsWith("Spell") && !right.name().endsWith("Spell")) return returnMods; if (!left.name().endsWith("Spell") && !right.name().endsWith("Spell")) return returnMods;
@ -130,13 +130,13 @@ public class Battle {
return returnMods; return returnMods;
} }
private RoundResult fight(FightDTO left, FightDTO right) { static RoundResult fight(FightDTO left, FightDTO right) {
if (this.isImmune(left.card(), right.card())) return new RoundResult(left, right, false, ElementMod.NONE, ElementMod.NONE); if (isImmune(left.card(), right.card())) return new RoundResult(left, right, false, ElementMod.NONE, ElementMod.NONE);
if (this.isImmune(right.card(), left.card())) return new RoundResult(right, left, false, ElementMod.NONE, ElementMod.NONE); if (isImmune(right.card(), left.card())) return new RoundResult(right, left, false, ElementMod.NONE, ElementMod.NONE);
Pair<ElementMod, ElementMod> dmgMods = getElementMod(left.card(), right.card()); Pair<ElementMod, ElementMod> dmgMods = getElementMod(left.card(), right.card());
boolean leftWins = left.card().damage()*dmgMods.left().percentMod > right.card().damage()*dmgMods.right().percentMod; boolean leftWins = left.card().damage()*dmgMods.left().percentMod >= right.card().damage()*dmgMods.right().percentMod;
return new RoundResult( return new RoundResult(
leftWins ? left : right, leftWins ? left : right,
leftWins ? right : left, leftWins ? right : left,
@ -145,7 +145,7 @@ public class Battle {
leftWins ? dmgMods.right() : dmgMods.left()); leftWins ? dmgMods.right() : dmgMods.left());
} }
private String createCombatString(int round, RoundResult result) { static String createCombatString(int round, RoundResult result) {
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
stringBuilder stringBuilder
.append(round) .append(round)

View File

@ -0,0 +1,117 @@
package at.nanopenguin.mtcg.application;
import at.nanopenguin.mtcg.Pair;
import at.nanopenguin.mtcg.application.service.schemas.Card;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Mockito;
public class BattleTest {
private static Card cardWithName(String name) {
Card cardMock = Mockito.mock(Card.class);
Mockito.when(cardMock.name()).thenReturn(name);
return cardMock;
}
private static Card cardWithNameAndDmg(String name, float dmg) {
Card cardMock = Mockito.mock(Card.class);
Mockito.when(cardMock.name()).thenReturn(name);
Mockito.when(cardMock.damage()).thenReturn(dmg);
return cardMock;
}
@ParameterizedTest
@CsvSource({
"WaterGoblin, FireSpell, DOUBLE, HALF", // generic
"FireGoblin, NormalSpell, DOUBLE, HALF",
"NormalGoblin, WaterSpell, DOUBLE, HALF",
"FireGoblin, WaterSpell, HALF, DOUBLE", // generic reverse
"NormalGoblin, FireSpell, HALF, DOUBLE",
"WaterGoblin, NormalSpell, HALF, DOUBLE",
"WaterGoblin, FireTroll, NONE, NONE", // no spell
"WaterSpell, FireSpell, DOUBLE, HALF", // two spells
"FireGoblin, FireSpell, NONE, NONE", // same element
"FireSpell, Dragon, DOUBLE, HALF" // non elemental
})
void elementMods(String name1, String name2, Battle.ElementMod expectedMod1, Battle.ElementMod expectedMod2){
Card card1 = cardWithName(name1);
Card card2 = cardWithName(name2);
Assertions.assertEquals(new Pair<>(expectedMod1, expectedMod2), Battle.getElementMod(card1, card2));
}
@ParameterizedTest
@CsvSource({
"Dragon, FireGoblin, true",
"Dragon, WaterGoblin, true",
"Dragon, NormalGoblin, true",
"WaterGoblin, Dragon, false",
"Wizzard, Ork, true",
"Ork, Wizzard, false",
"WaterSpell, Knight, true",
"FireSpell, Knight, false",
"Knight, WaterSpell, false",
"Kraken, WaterSpell, true",
"Kraken, FireSpell, true",
"FireElf, Dragon, true",
"NormalElf, Dragon, false"
})
void immunityTest(String name1, String name2, boolean expected) {
Card card1 = cardWithName(name1);
Card card2 = cardWithName(name2);
Assertions.assertEquals(expected, Battle.isImmune(card1, card2));
}
private static Battle.FightDTO getFightDTO(String cardName, float dmg) {
Battle.FightDTO fightDTOmock = Mockito.mock(Battle.FightDTO.class);
Card cardMock = cardWithNameAndDmg(cardName, dmg);
Mockito.when(fightDTOmock.card()).thenReturn(cardMock);
return fightDTOmock;
}
enum fightOutcome {
LEFT_WINS,
DRAW,
RIGHT_WINS
}
@ParameterizedTest
@CsvSource({
"WaterGoblin, 10, FireTroll, 15, RIGHT_WINS, NONE, NONE",
"FireTroll, 15, WaterGoblin, 10, LEFT_WINS, NONE, NONE",
"FireSpell, 10, WaterSpell, 20, RIGHT_WINS, DOUBLE, HALF",
"FireSpell, 20, WaterSpell, 5, DRAW, HALF, DOUBLE",
"FireSpell, 90, WaterSpell, 5, LEFT_WINS, HALF, DOUBLE",
"FireSpell, 10, WaterGoblin, 10, RIGHT_WINS, DOUBLE, HALF",
"WaterSpell, 10, WaterGoblin, 10, DRAW, NONE, NONE",
"RegularSpell, 10, WaterGoblin, 10, LEFT_WINS, DOUBLE, HALF",
"RegularSpell, 10, Knight, 15, RIGHT_WINS, NONE, NONE",
})
void fightTest(String card1, float dmg1, String card2, float dmg2, fightOutcome outcome, Battle.ElementMod expectedMod1, Battle.ElementMod expectedMod2) {
Battle.FightDTO fightDTO1 = getFightDTO(card1, dmg1);
Battle.FightDTO fightDTO2 = getFightDTO(card2, dmg2);
Battle.RoundResult result = Battle.fight(fightDTO1, fightDTO2);
switch (outcome) {
case LEFT_WINS -> {
Assertions.assertEquals(fightDTO1, result.winner());
Assertions.assertFalse(result.draw());
}
case DRAW -> {
Assertions.assertTrue(result.draw());
}
case RIGHT_WINS -> {
Assertions.assertEquals(fightDTO2, result.winner());
Assertions.assertFalse(result.draw());
}
}
Assertions.assertEquals(expectedMod1, result.winnerMod());
Assertions.assertEquals(expectedMod2, result.loserMod());
}
}