Merge branch 'gamelib' of https://gitlab.informatik.uni-ulm.de/sopra/ws20-marvelous-mashup/teams/team25 into gamelib
This commit is contained in:
@ -2,19 +2,27 @@ package uulm.teamname.marvelous.gamelibrary.json;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.jqwik.api.*;
|
||||
import net.jqwik.api.lifecycle.BeforeContainer;
|
||||
import net.jqwik.api.lifecycle.BeforeProperty;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.EntityID;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.Rock;
|
||||
import uulm.teamname.marvelous.gamelibrary.events.Event;
|
||||
import uulm.teamname.marvelous.gamelibrary.events.EventBuilder;
|
||||
import uulm.teamname.marvelous.gamelibrary.events.EventType;
|
||||
import uulm.teamname.marvelous.gamelibrary.json.basic.EventMessage;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.*;
|
||||
|
||||
class JSONTest {
|
||||
|
||||
@ -29,11 +37,11 @@ class JSONTest {
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
messageStructureStart = """
|
||||
{
|
||||
"messages":[
|
||||
""";
|
||||
messageStructureEnd = new String[] {
|
||||
"""
|
||||
{
|
||||
"messages":[
|
||||
""";
|
||||
messageStructureEnd = new String[]{
|
||||
"""
|
||||
],
|
||||
"messageType": "REQUESTS",
|
||||
"customContentType": "TestCustomContent",
|
||||
@ -43,7 +51,7 @@ class JSONTest {
|
||||
"customProperty" = true
|
||||
}
|
||||
""",
|
||||
"""
|
||||
"""
|
||||
],
|
||||
"messageType": "EVENTS",
|
||||
"customContentType": "TestCustomContent",
|
||||
@ -75,9 +83,9 @@ class JSONTest {
|
||||
};
|
||||
|
||||
String eventRepresentation = """
|
||||
{"eventType": "Ack"},
|
||||
{"eventType": "Nack"}
|
||||
""";
|
||||
{"eventType": "Ack"},
|
||||
{"eventType": "Nack"}
|
||||
""";
|
||||
String completeMessageStructure = messageStructureStart + eventRepresentation + messageStructureEnd[1];
|
||||
|
||||
target.messageType = MessageType.EVENTS;
|
||||
@ -90,19 +98,19 @@ class JSONTest {
|
||||
@Test
|
||||
void parseMoreComplicatedEvents() {
|
||||
String eventRepresentation = """
|
||||
{
|
||||
"eventType": "GamestateEvent",
|
||||
"activeCharacter": {"entityID": "P2", "ID": 4},
|
||||
"turnOrder": [
|
||||
{"entityID": "P2", "ID": 4},
|
||||
{"entityID": "P2", "ID": 2},
|
||||
{"entityID": "P1", "ID": 3},
|
||||
{"entityID": "NPC", "ID": 1},
|
||||
{"entityID": "InfinityStones", "ID": 5},
|
||||
{"entityID": "Rocks", "ID": 0}
|
||||
]
|
||||
}
|
||||
""";
|
||||
{
|
||||
"eventType": "GamestateEvent",
|
||||
"activeCharacter": {"entityID": "P2", "ID": 4},
|
||||
"turnOrder": [
|
||||
{"entityID": "P2", "ID": 4},
|
||||
{"entityID": "P2", "ID": 2},
|
||||
{"entityID": "P1", "ID": 3},
|
||||
{"entityID": "NPC", "ID": 1},
|
||||
{"entityID": "InfinityStones", "ID": 5},
|
||||
{"entityID": "Rocks", "ID": 0}
|
||||
]
|
||||
}
|
||||
""";
|
||||
String completeMessageStructure = messageStructureStart + eventRepresentation + messageStructureEnd[1];
|
||||
|
||||
System.out.println(JSON.parse(completeMessageStructure));
|
||||
@ -112,11 +120,11 @@ class JSONTest {
|
||||
@Disabled
|
||||
void simpleInDevTest() throws JsonProcessingException {
|
||||
String simpleEntity = """
|
||||
{
|
||||
"entityID": "P2",
|
||||
"ID": 4
|
||||
}
|
||||
""";
|
||||
{
|
||||
"entityID": "P2",
|
||||
"ID": 4
|
||||
}
|
||||
""";
|
||||
System.out.println(new ObjectMapper().readValue(simpleEntity, EntityID.class));
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.json.ingame;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.jqwik.api.*;
|
||||
import net.jqwik.api.lifecycle.BeforeProperty;
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class IntVector2SerializerTest {
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@BeforeProperty
|
||||
void setup() {
|
||||
mapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Property
|
||||
void vectorsGetProperlyDeserialized(@ForAll @From("positions") IntVector2 vector) throws JsonProcessingException {
|
||||
var jsonRepresentingVector = String.format("[%d,%d]", vector.getX(), vector.getY());
|
||||
assertThat(mapper.writeValueAsString(vector))
|
||||
.isEqualTo(jsonRepresentingVector);
|
||||
|
||||
}
|
||||
|
||||
@Provide("positions")
|
||||
Arbitrary<IntVector2> positions() {
|
||||
return Arbitraries.integers()
|
||||
.tuple2()
|
||||
.map(pos -> new IntVector2(pos.get1(), pos.get2()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
package uulm.teamname.marvelous.gamelibrary.json.ingame;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.jqwik.api.*;
|
||||
import net.jqwik.api.lifecycle.BeforeProperty;
|
||||
import uulm.teamname.marvelous.gamelibrary.IntVector2;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.EntityID;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.EntityType;
|
||||
import uulm.teamname.marvelous.gamelibrary.entities.StoneType;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.CharacterRequest;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.GameRequest;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.RequestBuilder;
|
||||
import uulm.teamname.marvelous.gamelibrary.requests.RequestType;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class RequestSerializerTest {
|
||||
|
||||
private ObjectMapper mapper;
|
||||
@BeforeProperty
|
||||
void setup() {
|
||||
mapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Property
|
||||
void gameRequestsGetSerializedProperly(
|
||||
@ForAll @From("gameRequests") GameRequest request)
|
||||
throws JsonProcessingException {
|
||||
var jsonRepresentingRequest = String.format(
|
||||
"{\"requestType\":\"%s\"}",
|
||||
request.type);
|
||||
|
||||
assertThat(mapper.writeValueAsString(request))
|
||||
.isEqualTo(jsonRepresentingRequest);
|
||||
}
|
||||
|
||||
@Property
|
||||
void characterRequestsGetSerializedProperly(
|
||||
@ForAll @From("characterRequests") CharacterRequest request)
|
||||
throws JsonProcessingException {
|
||||
|
||||
var jsonRepresentingValue = request.type == RequestType.MeleeAttackRequest ||
|
||||
request.type == RequestType.RangedAttackRequest ?
|
||||
String.format("\"value\":%d", request.value) : "";
|
||||
|
||||
var jsonRepresentingTargetEntity = request.type == RequestType.MeleeAttackRequest ||
|
||||
request.type == RequestType.RangedAttackRequest ||
|
||||
request.type == RequestType.ExchangeInfinityStoneRequest ?
|
||||
String.format(
|
||||
"\"targetEntity\":{\"entityID\":\"%s\",\"ID\":%d},",
|
||||
request.targetEntity.type,
|
||||
request.targetEntity.id) : "";
|
||||
|
||||
var jsonRepresentingStoneType = request.type == RequestType.UseInfinityStoneRequest ||
|
||||
request.type == RequestType.ExchangeInfinityStoneRequest ?
|
||||
String.format(
|
||||
"\"stoneType\":{\"entityID\":\"%s\",\"ID\":%d}",
|
||||
EntityType.InfinityStones,
|
||||
request.stoneType.getID()) : "";
|
||||
|
||||
var jsonRepresentingRequest = String.format(
|
||||
"""
|
||||
{
|
||||
"requestType":"%s",
|
||||
"originEntity":{"entityID":"%s","ID":%d},
|
||||
%s
|
||||
"originField":[%d,%d],
|
||||
"targetField":[%d,%d]%s
|
||||
%s%s
|
||||
%s
|
||||
}
|
||||
""",
|
||||
request.type,
|
||||
request.originEntity.type,
|
||||
request.originEntity.id,
|
||||
jsonRepresentingTargetEntity,
|
||||
request.originField.getX(),
|
||||
request.originField.getY(),
|
||||
request.targetField.getX(),
|
||||
request.targetField.getY(),
|
||||
jsonRepresentingStoneType.length() != 0 ? "," : "",
|
||||
jsonRepresentingStoneType,
|
||||
jsonRepresentingValue.length() != 0 ? "," : "",
|
||||
jsonRepresentingValue
|
||||
).replace("\n", "");
|
||||
|
||||
assertThat(mapper.writeValueAsString(request))
|
||||
.isEqualTo(jsonRepresentingRequest);
|
||||
}
|
||||
|
||||
// Note that everything that follows could be extracted into another class,
|
||||
// but that's complicated, so I won't do it
|
||||
|
||||
static Set<RequestType> characterRequestTypes;
|
||||
static Set<RequestType> gameRequestTypes;
|
||||
|
||||
static {
|
||||
characterRequestTypes = new HashSet<>();
|
||||
characterRequestTypes.add(RequestType.MeleeAttackRequest);
|
||||
characterRequestTypes.add(RequestType.RangedAttackRequest);
|
||||
characterRequestTypes.add(RequestType.MoveRequest);
|
||||
characterRequestTypes.add(RequestType.ExchangeInfinityStoneRequest);
|
||||
characterRequestTypes.add(RequestType.UseInfinityStoneRequest);
|
||||
|
||||
gameRequestTypes = new HashSet<>();
|
||||
gameRequestTypes.add(RequestType.PauseStopRequest);
|
||||
gameRequestTypes.add(RequestType.PauseStartRequest);
|
||||
gameRequestTypes.add(RequestType.EndRoundRequest);
|
||||
gameRequestTypes.add(RequestType.DisconnectRequest);
|
||||
gameRequestTypes.add(RequestType.Req);
|
||||
}
|
||||
|
||||
@Provide("gameRequests")
|
||||
public static Arbitrary<GameRequest> gameRequests() {
|
||||
return requestBuilders()
|
||||
.map(RequestBuilder::buildGameRequest)
|
||||
.filter(request -> gameRequestTypes.contains(request.type));
|
||||
}
|
||||
|
||||
@Provide("characterRequests")
|
||||
public static Arbitrary<CharacterRequest> characterRequests() {
|
||||
return requestBuilders()
|
||||
.map(RequestBuilder::buildCharacterRequest)
|
||||
.filter(request -> characterRequestTypes.contains(request.type));
|
||||
}
|
||||
|
||||
|
||||
@Provide("filledRequestBuilders")
|
||||
public static Arbitrary<RequestBuilder> requestBuilders() {
|
||||
var emptyBuilders = Arbitraries.of(RequestType.class)
|
||||
.map(RequestBuilder::new);
|
||||
|
||||
var buildersWithEntitiesAndValue = Combinators.combine(
|
||||
emptyBuilders,
|
||||
entityIDs().filter(x -> x.type == EntityType.P1 || x.type == EntityType.P2).tuple2(),
|
||||
entityIDs().filter(x -> x.type == EntityType.Rocks),
|
||||
Arbitraries.integers())
|
||||
.as((builder, characterIDs, rockID, value) -> builder
|
||||
.withOriginEntity(characterIDs.get1())
|
||||
.withTargetEntity(value % 7 == 0 ? characterIDs.get2() : rockID)
|
||||
.withValue(value)
|
||||
);
|
||||
|
||||
var buildersWithStoneTypes = Combinators.combine(
|
||||
buildersWithEntitiesAndValue,
|
||||
Arbitraries.of(StoneType.class))
|
||||
.as(RequestBuilder::withStoneType);
|
||||
|
||||
return Combinators.combine(
|
||||
buildersWithStoneTypes,
|
||||
randomPositions(),
|
||||
directions(),
|
||||
attackPositions())
|
||||
.as((builder, position, direction, attackPos) -> {
|
||||
var type = builder.buildGameRequest().type; // hacky but whatever
|
||||
Tuple.Tuple2<IntVector2, IntVector2> originAndTargetPosition;
|
||||
if (type == RequestType.RangedAttackRequest) {
|
||||
originAndTargetPosition = attackPos;
|
||||
} else {
|
||||
originAndTargetPosition = Tuple.of(position, position.copy().add(direction));
|
||||
}
|
||||
return builder.withOriginField(originAndTargetPosition.get1())
|
||||
.withTargetField(originAndTargetPosition.get2());
|
||||
});
|
||||
}
|
||||
|
||||
@Provide("entityIDs")
|
||||
public static Arbitrary<EntityID> entityIDs() {
|
||||
var entityTypes = Arbitraries.of(EntityType.class);
|
||||
return Combinators.combine(entityTypes, Arbitraries.integers().greaterOrEqual(0))
|
||||
.as((type, id) -> {
|
||||
int actualID;
|
||||
if (type == EntityType.P1 || type == EntityType.P2 || type == EntityType.InfinityStones) {
|
||||
actualID = id % 6;
|
||||
} else if (type == EntityType.NPC) {
|
||||
actualID = id % 3;
|
||||
} else {
|
||||
actualID = id;
|
||||
}
|
||||
return new EntityID(type, id);
|
||||
});
|
||||
}
|
||||
|
||||
@Provide("randomPositions")
|
||||
public static Arbitrary<IntVector2> randomPositions() {
|
||||
return Arbitraries.integers()
|
||||
.greaterOrEqual(0)
|
||||
.tuple2()
|
||||
.map((pos) -> new IntVector2(pos.get1(), pos.get2()));
|
||||
}
|
||||
|
||||
@Provide("directions")
|
||||
public static Arbitrary<IntVector2> directions() {
|
||||
return Arbitraries.integers()
|
||||
.between(-1, 1)
|
||||
.tuple2()
|
||||
.filter(pos -> pos.get1() != 0 && pos.get2() != 0) // eliminate zero vectors
|
||||
.map(pos -> new IntVector2(pos.get1(), pos.get2()));
|
||||
}
|
||||
|
||||
@Provide("attackPositions")
|
||||
/** Returns tuples of origin vectors (of an attack), and the vector pointing to the attack dir */
|
||||
public static Arbitrary<Tuple.Tuple2<IntVector2, IntVector2>> attackPositions() {
|
||||
return Combinators.combine(randomPositions(), directions().tuple5())
|
||||
.as((origin, dir) -> {
|
||||
var attackField = origin.copy()
|
||||
.add(dir.get1().scale(3))
|
||||
.add(dir.get2().scale(3))
|
||||
.add(dir.get3().scale(3))
|
||||
.add(dir.get4().scale(3));
|
||||
if (attackField.length() == 0) {
|
||||
attackField.add(dir.get5().scale(3));
|
||||
}
|
||||
return Tuple.<IntVector2, IntVector2>of(origin, attackField);
|
||||
});
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user