Compare commits
9 commits
exercise-e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c58c8725e8 | |||
|
|
b3bdec1049 | ||
|
|
e1301f007b | ||
|
|
0b841e70a4 | ||
|
|
c552442029 | ||
|
|
e6dfbfbe03 | ||
|
|
8dca2f10c6 | ||
|
|
43bdb74698 | ||
|
|
c7629264b4 |
66 changed files with 4130 additions and 43 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1,2 +1,6 @@
|
||||||
target/
|
target/
|
||||||
.idea/
|
.idea/
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
|
|
||||||
31
README.md
Normal file
31
README.md
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
# JWS
|
||||||
|
|
||||||
|
> **Note** This is a school project, therefore it probably won't interest you if you are looking for something useful.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
JWS stands for Java Web Services and as its name doesn't suggest at all, it's basically a web server for a a pokemon-like game. It's written in Java and built onto Quarkus and Jakarta, providing a REST API with strict server-side rules like cooldowns and cheating prevention.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
> **Note** Source code is located inside the `yakamon` folder, both others are school requirements and aren't important
|
||||||
|
|
||||||
|
Each layer is strictly separated and can only communicate via to the one directly below or above it via converters.
|
||||||
|
|
||||||
|
### Presentation Layer (REST & DTOs)
|
||||||
|
* located at `yakamon/jws/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation`
|
||||||
|
* Handled by JAX-RS (Jakarta RESTful Web Services).
|
||||||
|
* Exposes standard HTTP endpoints (`/player`, `/move`, `/yakadex`, etc.). Full API specification can be found inside `yakamon/src/main/resources/openapi.yaml`
|
||||||
|
* Implements strict **Data Transfer Objects (DTOs)** for both Requests and Responses to ensure the internal database models are never exposed directly to the client.
|
||||||
|
|
||||||
|
### Business Logic Layer (Services)
|
||||||
|
* located at `yakamon/jws/yakamon/src/main/java/fr/epita/assistants/yakamon/domain`
|
||||||
|
* Acts as the brain of the application.
|
||||||
|
* Implements complex game rules: validating if a target tile is walkable based on the terrain type, calculating cooldowns between moves, and managing creature capture probabilities.
|
||||||
|
* **Converters** are used to translate Entities from the Data Layer into DTOs for the Presentation Layer.
|
||||||
|
|
||||||
|
### Data Access Layer (Hibernate ORM)
|
||||||
|
* located at `yakamon/jws/yakamon/src/main/java/fr/epita/assistants/yakamon/data`
|
||||||
|
* Manages persistence using **Hibernate ORM** with the Active Record / Repository pattern.
|
||||||
|
* Defines relational entities (Player, Game, Yakamon, Item) mapped to a PostgreSQL database.
|
||||||
|
|
||||||
|
|
@ -8,5 +8,5 @@ import java.util.List;
|
||||||
public class CourseModel {
|
public class CourseModel {
|
||||||
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected Long id;
|
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected Long id;
|
||||||
public String name;
|
public String name;
|
||||||
public @ElementCollection @CollectionTable(name = "course_model_tags") @JoinColumn(name="course_id") List<String> tag;
|
public @ElementCollection @CollectionTable(name = "course_model_tags", joinColumns = @JoinColumn(name = "course_id")) List<String> tag;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,30 @@
|
||||||
package fr.epita.assistants.presentation.rest;
|
package fr.epita.assistants.presentation.rest;
|
||||||
|
|
||||||
public class Endpoints {
|
import fr.epita.assistants.presentation.rest.request.ReverseRequest;
|
||||||
|
import fr.epita.assistants.presentation.rest.response.HelloResponse;
|
||||||
|
import fr.epita.assistants.presentation.rest.response.ReverseResponse;
|
||||||
|
import jakarta.ws.rs.*;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
|
||||||
|
@Path("/")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public class Endpoints {
|
||||||
|
String content;
|
||||||
|
@Path("/hello/{name}")
|
||||||
|
@GET
|
||||||
|
public Response greeting(@PathParam("name") String name) {
|
||||||
|
if (name == null || name.isEmpty()) {
|
||||||
|
return Response.status(400).build();
|
||||||
|
}
|
||||||
|
HelloResponse response = new HelloResponse("hello " + name);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Path("/reverse")
|
||||||
|
@POST
|
||||||
|
public Response reverse(ReverseRequest r) {
|
||||||
|
return Response.ok(new ReverseResponse(r.content)).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
package fr.epita.assistants.presentation.rest.request;
|
package fr.epita.assistants.presentation.rest.request;
|
||||||
|
|
||||||
public class ReverseRequest {
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ReverseRequest {
|
||||||
|
public String content;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,12 @@
|
||||||
package fr.epita.assistants.presentation.rest.response;
|
package fr.epita.assistants.presentation.rest.response;
|
||||||
|
|
||||||
import jakarta.ws.rs.Consumes;
|
import jakarta.ws.rs.*;
|
||||||
import jakarta.ws.rs.GET;
|
|
||||||
import jakarta.ws.rs.Path;
|
|
||||||
import jakarta.ws.rs.Produces;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
@Path("/hello")
|
@AllArgsConstructor
|
||||||
@Consumes(MediaType.TEXT_PLAIN)
|
|
||||||
@Produces(MediaType.TEXT_PLAIN)
|
|
||||||
public class HelloResponse {
|
public class HelloResponse {
|
||||||
@Path("/{name}")
|
public String content;
|
||||||
@GET
|
|
||||||
public String greeting(@PathParam("name") String name) {
|
|
||||||
String content
|
|
||||||
Response.accepted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
package fr.epita.assistants.presentation.rest.response;
|
package fr.epita.assistants.presentation.rest.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
public class ReverseResponse {
|
public class ReverseResponse {
|
||||||
|
public String original;
|
||||||
|
public String reverse;
|
||||||
|
|
||||||
|
public ReverseResponse(String original) {
|
||||||
|
this.original = original;
|
||||||
|
this.reverse = new StringBuilder(original).reverse().toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package fr.epita.assistants.yakamon.converter;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakadexEntryEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.request.StartGameRequest;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ElementType;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class DtoToEntityConverter {
|
||||||
|
|
||||||
|
public static YakamonEntity toYakamonEntity(YakamonAction dto) {
|
||||||
|
if (dto == null) return null;
|
||||||
|
|
||||||
|
YakamonEntity entity = new YakamonEntity();
|
||||||
|
if (dto.uuid != null) {
|
||||||
|
try {
|
||||||
|
entity.uuid = UUID.fromString(dto.uuid);
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
entity.uuid = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entity.uuid = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.nickname = dto.nickname;
|
||||||
|
entity.yakadexId = dto.yakadexId;
|
||||||
|
entity.energyPoints = dto.energyPoints;
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YakadexEntryEntity toYakadexEntryEntity(YakadexEntry dto) {
|
||||||
|
if (dto == null) return null;
|
||||||
|
|
||||||
|
YakadexEntryEntity e = new YakadexEntryEntity();
|
||||||
|
e.id = dto.id;
|
||||||
|
e.name = dto.name;
|
||||||
|
e.description = dto.description;
|
||||||
|
e.evolveThreshold = dto.evolveThreshold;
|
||||||
|
e.evolutionId = dto.evolutionId;
|
||||||
|
e.caught = dto.caught;
|
||||||
|
|
||||||
|
if (dto.firstType != null) {
|
||||||
|
try {
|
||||||
|
e.firstType = ElementType.valueOf(dto.firstType);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
e.firstType = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto.secondType != null) {
|
||||||
|
try {
|
||||||
|
e.secondType = ElementType.valueOf(dto.secondType);
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
e.secondType = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameEntity toGameEntity(StartGameRequest request) {
|
||||||
|
if (request == null) return null;
|
||||||
|
GameEntity g = new GameEntity();
|
||||||
|
g.mapPath = request.mapPath;
|
||||||
|
g.start(LocalDateTime.now());
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package fr.epita.assistants.yakamon.converter;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakadexEntryEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class EntityToDtoConverter {
|
||||||
|
|
||||||
|
public static YakamonAction toYakamonAction(YakamonEntity e) {
|
||||||
|
if (e == null) return null;
|
||||||
|
String uuid = null;
|
||||||
|
if (e.uuid != null) {
|
||||||
|
uuid = e.uuid.toString();
|
||||||
|
}
|
||||||
|
return new YakamonAction(uuid, e.nickname, e.yakadexId, e.energyPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YakadexEntry toYakadexEntry(YakadexEntryEntity e) {
|
||||||
|
if (e == null) return null;
|
||||||
|
|
||||||
|
String firstType = null;
|
||||||
|
if (e.firstType != null) {
|
||||||
|
firstType = e.firstType.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
String secondType = null;
|
||||||
|
if (e.secondType != null) {
|
||||||
|
secondType = e.secondType.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer evolutionId = e.evolutionId;
|
||||||
|
|
||||||
|
return new YakadexEntry(
|
||||||
|
e.id,
|
||||||
|
e.name,
|
||||||
|
firstType,
|
||||||
|
secondType,
|
||||||
|
e.evolveThreshold,
|
||||||
|
evolutionId,
|
||||||
|
e.caught,
|
||||||
|
e.description
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<YakadexEntry> toYakadexEntries(
|
||||||
|
List<YakadexEntryEntity> entries
|
||||||
|
) {
|
||||||
|
List<YakadexEntry> out = new ArrayList<>();
|
||||||
|
if (entries == null || entries.isEmpty()) return out;
|
||||||
|
for (YakadexEntryEntity e : entries) {
|
||||||
|
YakadexEntry dto = toYakadexEntry(e);
|
||||||
|
if (dto != null) out.add(dto);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<YakamonAction> toYakamonActions(
|
||||||
|
List<YakamonEntity> yakamons
|
||||||
|
) {
|
||||||
|
List<YakamonAction> out = new ArrayList<>();
|
||||||
|
if (yakamons == null || yakamons.isEmpty()) return out;
|
||||||
|
for (YakamonEntity y : yakamons) {
|
||||||
|
YakamonAction a = toYakamonAction(y);
|
||||||
|
if (a != null) out.add(a);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package fr.epita.assistants.yakamon.converter;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.GameModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.PlayerModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakadexEntryModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakamonModel;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.PlayerEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakadexEntryEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
|
||||||
|
public final class EntityToModelConverter {
|
||||||
|
|
||||||
|
public static GameModel toGameModel(GameEntity e) {
|
||||||
|
if (e == null) return null;
|
||||||
|
GameModel m = new GameModel();
|
||||||
|
m.map = e.mapPath;
|
||||||
|
m.started = e.started;
|
||||||
|
m.startTime = e.startTime;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlayerModel toPlayerModel(PlayerEntity e) {
|
||||||
|
if (e == null) return null;
|
||||||
|
PlayerModel m = new PlayerModel();
|
||||||
|
m.name = e.name;
|
||||||
|
m.posX = e.posX;
|
||||||
|
m.posY = e.posY;
|
||||||
|
m.lastMove = e.lastMove;
|
||||||
|
m.lastCatch = e.lastCatch;
|
||||||
|
m.lastCollect = e.lastCollect;
|
||||||
|
m.lastFeed = e.lastFeed;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YakamonModel toYakamonModel(YakamonEntity e) {
|
||||||
|
if (e == null) return null;
|
||||||
|
YakamonModel m = new YakamonModel();
|
||||||
|
m.nickname = e.nickname;
|
||||||
|
m.energy_points = e.energyPoints;
|
||||||
|
if (e.yakadexId != null) {
|
||||||
|
YakadexEntryModel yakadex = new YakadexEntryModel();
|
||||||
|
m.yakadex_entry_id = yakadex;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YakadexEntryModel toYakadexEntryModel(YakadexEntryEntity e) {
|
||||||
|
if (e == null) return null;
|
||||||
|
YakadexEntryModel m = new YakadexEntryModel();
|
||||||
|
m.name = e.name;
|
||||||
|
m.caught = e.caught;
|
||||||
|
m.first_type = e.firstType != null ? e.firstType.name() : null;
|
||||||
|
m.second_type = e.secondType != null ? e.secondType.name() : null;
|
||||||
|
m.description = e.description;
|
||||||
|
m.evolve_threshold = e.evolveThreshold;
|
||||||
|
m.evolution_id = null;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "game")
|
||||||
|
public class GameModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
public Long id;
|
||||||
|
|
||||||
|
public String map;
|
||||||
|
public boolean started;
|
||||||
|
public LocalDateTime startTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.model;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.ItemType;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "item")
|
||||||
|
public class ItemModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Enumerated
|
||||||
|
private ItemType type;
|
||||||
|
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(ItemType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getQuantity() {
|
||||||
|
return quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQuantity(Integer quantity) {
|
||||||
|
this.quantity = quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "player")
|
||||||
|
public class PlayerModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
public UUID id;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
public Integer posX;
|
||||||
|
public Integer posY;
|
||||||
|
public LocalDateTime lastMove;
|
||||||
|
public LocalDateTime lastCatch;
|
||||||
|
public LocalDateTime lastCollect;
|
||||||
|
public LocalDateTime lastFeed;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "yakadex_entry")
|
||||||
|
public class YakadexEntryModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
public Integer id;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
public Boolean caught;
|
||||||
|
|
||||||
|
// Changed to string otherwise it doesn't work
|
||||||
|
public String first_type;
|
||||||
|
public String second_type;
|
||||||
|
|
||||||
|
public String description;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@JoinColumn(name = "evolution_id")
|
||||||
|
public YakadexEntryModel evolution_id;
|
||||||
|
|
||||||
|
public Integer evolve_threshold;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "yakamon")
|
||||||
|
public class YakamonModel {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.UUID)
|
||||||
|
public UUID id;
|
||||||
|
|
||||||
|
public String nickname;
|
||||||
|
public Integer energy_points;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "yakadex_id")
|
||||||
|
public YakadexEntryModel yakadex_entry_id;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.repository;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.GameModel;
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class GameRepository implements PanacheRepository<GameModel> {}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.repository;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.ItemModel;
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ItemRepository implements PanacheRepository<ItemModel> {}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.repository;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.PlayerModel;
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class PlayerRepository implements PanacheRepository<PlayerModel> {}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.repository;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakadexEntryModel;
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class YakadexRepository
|
||||||
|
implements PanacheRepository<YakadexEntryModel> {}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package fr.epita.assistants.yakamon.data.repository;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakamonModel;
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class YakamonRepository implements PanacheRepository<YakamonModel> {}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public class GameEntity {
|
||||||
|
|
||||||
|
public static GameEntity INSTANCE = null;
|
||||||
|
public String mapPath;
|
||||||
|
public boolean started;
|
||||||
|
public LocalDateTime startTime;
|
||||||
|
public TileEntity[][] map;
|
||||||
|
|
||||||
|
public GameEntity() {
|
||||||
|
this.start(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameEntity(String mapPath) {
|
||||||
|
this.start(null);
|
||||||
|
this.mapPath = mapPath;
|
||||||
|
GameEntity.INSTANCE = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameEntity start(LocalDateTime startTime) {
|
||||||
|
if (started || INSTANCE != null) {
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
startTime = startTime == null ? LocalDateTime.now() : startTime;
|
||||||
|
this.startTime = startTime;
|
||||||
|
this.started = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameEntity stop() {
|
||||||
|
GameEntity.INSTANCE = null;
|
||||||
|
this.started = false;
|
||||||
|
this.startTime = null;
|
||||||
|
this.map = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.entity;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.ItemType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ItemEntity {
|
||||||
|
|
||||||
|
public Integer id;
|
||||||
|
public ItemType type;
|
||||||
|
public Integer quantity;
|
||||||
|
|
||||||
|
// public ItemEntity(Integer id, ItemType type, Integer quantity) {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public ItemEntity addQuantity(int amount) {
|
||||||
|
// int current = this.quantity != null ? this.quantity : 0;
|
||||||
|
// this.quantity = current + amount;
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.entity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PlayerEntity {
|
||||||
|
|
||||||
|
public UUID uuid;
|
||||||
|
public String name;
|
||||||
|
public Integer posX;
|
||||||
|
public Integer posY;
|
||||||
|
public LocalDateTime lastMove;
|
||||||
|
public LocalDateTime lastCatch;
|
||||||
|
public LocalDateTime lastCollect;
|
||||||
|
public LocalDateTime lastFeed;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.entity;
|
||||||
|
|
||||||
|
public class TileEntity {
|
||||||
|
|
||||||
|
public Character terrain;
|
||||||
|
public Character collectible;
|
||||||
|
|
||||||
|
public TileEntity(Character terrain, Character collectible) {
|
||||||
|
this.terrain = terrain;
|
||||||
|
this.collectible = collectible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWalkable() {
|
||||||
|
return terrain == 'G' || terrain == 'R' || terrain == 'S';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.entity;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.utils.ElementType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class YakadexEntryEntity {
|
||||||
|
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
public ElementType firstType;
|
||||||
|
public ElementType secondType;
|
||||||
|
public Integer evolveThreshold;
|
||||||
|
public Integer evolutionId;
|
||||||
|
public Boolean caught;
|
||||||
|
public String description;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.entity;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class YakamonEntity {
|
||||||
|
|
||||||
|
public UUID uuid;
|
||||||
|
public String nickname;
|
||||||
|
public Integer yakadexId;
|
||||||
|
public Integer energyPoints;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.service;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.converter.EntityToModelConverter;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.GameModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.ItemModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.PlayerModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.GameRepository;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.ItemRepository;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.PlayerRepository;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.TileEntity;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ErrorCode;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.ItemType;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class GameService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
GameRepository gameRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PlayerRepository playerRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ItemRepository itemRepository;
|
||||||
|
|
||||||
|
public static GameEntity game;
|
||||||
|
|
||||||
|
public GameEntity startGame(String mapPath, String playerName) {
|
||||||
|
if (mapPath == null) {
|
||||||
|
ErrorCode.INVALID_MAP.throwException("Map is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Game with mapPath
|
||||||
|
game = new GameEntity(mapPath);
|
||||||
|
GameModel gameModel = EntityToModelConverter.toGameModel(game);
|
||||||
|
|
||||||
|
// Parse map and store in GameEntity
|
||||||
|
TileEntity[][] parsedMap = parseMapFile(mapPath);
|
||||||
|
game.map = parsedMap;
|
||||||
|
|
||||||
|
// Initialize player
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
PlayerModel player = new PlayerModel();
|
||||||
|
player.name = playerName;
|
||||||
|
player.posX = 0;
|
||||||
|
player.posY = 0;
|
||||||
|
player.lastCatch = now;
|
||||||
|
player.lastCollect = now;
|
||||||
|
player.lastFeed = now;
|
||||||
|
player.lastMove = now;
|
||||||
|
|
||||||
|
// Initialize player inventory
|
||||||
|
ItemModel yakaballs = new ItemModel();
|
||||||
|
yakaballs.setType(ItemType.YAKABALL);
|
||||||
|
yakaballs.setQuantity(5);
|
||||||
|
|
||||||
|
// Store
|
||||||
|
playerRepository.persist(player);
|
||||||
|
itemRepository.persist(yakaballs);
|
||||||
|
gameRepository.persist(gameModel);
|
||||||
|
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStarted() {
|
||||||
|
return game != null && game.started;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopGame() {
|
||||||
|
if (game == null) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
game.stop();
|
||||||
|
gameRepository.deleteAll();
|
||||||
|
playerRepository.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TileEntity[][] parseMapFile(String mapPath) {
|
||||||
|
try {
|
||||||
|
String resourcePath = "maps/" + mapPath + ".epimap";
|
||||||
|
BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
GameService.class.getClassLoader().getResourceAsStream(
|
||||||
|
resourcePath
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<List<TileEntity>> mapList = new ArrayList<>();
|
||||||
|
String line;
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
line = line.trim();
|
||||||
|
if (!line.isEmpty()) {
|
||||||
|
List<TileEntity> row = parseLine(line);
|
||||||
|
mapList.add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
if (mapList.isEmpty()) {
|
||||||
|
ErrorCode.INVALID_MAP.throwException("Map file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
TileEntity[][] map = new TileEntity[mapList.size()][];
|
||||||
|
for (int i = 0; i < mapList.size(); i++) {
|
||||||
|
List<TileEntity> row = mapList.get(i);
|
||||||
|
map[i] = row.toArray(new TileEntity[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
} catch (Exception e) {
|
||||||
|
ErrorCode.INVALID_MAP.throwException("Failed to load map");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TileEntity> parseLine(String line) {
|
||||||
|
List<TileEntity> row = new ArrayList<>();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < line.length()) {
|
||||||
|
// Parse count
|
||||||
|
int count = Character.getNumericValue(line.charAt(i));
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Parse terrain character
|
||||||
|
if (i >= line.length()) break;
|
||||||
|
char terrain = line.charAt(i);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Parse collectible character
|
||||||
|
if (i >= line.length()) break;
|
||||||
|
char collectible = line.charAt(i);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Add tiles
|
||||||
|
for (int j = 0; j < count; j++) {
|
||||||
|
row.add(new TileEntity(terrain, collectible));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.service;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.ItemModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.ItemRepository;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ErrorCode;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class InventoryService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ItemRepository itemRepository;
|
||||||
|
|
||||||
|
public List<ItemModel> getInventory() {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemRepository.listAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,365 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.service;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.ItemModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.PlayerModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakadexEntryModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakamonModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.ItemRepository;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.PlayerRepository;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.YakadexRepository;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.YakamonRepository;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.PlayerEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.TileEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.utils.Direction;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ErrorCode;
|
||||||
|
import fr.epita.assistants.yakamon.utils.Point;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.Collectible;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.CollectibleUtils;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.ItemType;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.TerrainType;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.YakamonInfo;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.YakamonType;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import jakarta.ws.rs.WebApplicationException;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class PlayerService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PlayerRepository playerRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
YakamonRepository yakamonRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
YakadexRepository yakadexRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ItemRepository itemRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Point move(Direction direction) {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerModel player = playerRepository.findAll().firstResult();
|
||||||
|
if (player == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Player not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMovementDelay(player);
|
||||||
|
|
||||||
|
if (direction == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Invalid direction");
|
||||||
|
}
|
||||||
|
|
||||||
|
TileEntity[][] map = GameEntity.INSTANCE.map;
|
||||||
|
if (map == null) {
|
||||||
|
ErrorCode.INVALID_MAP.throwException("Map not loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
Point directionOffset = direction.getPoint();
|
||||||
|
int newX = player.posX + directionOffset.getPosX();
|
||||||
|
int newY = player.posY + directionOffset.getPosY();
|
||||||
|
|
||||||
|
if (
|
||||||
|
newY < 0 ||
|
||||||
|
newY >= map.length ||
|
||||||
|
newX < 0 ||
|
||||||
|
newX >= map[newY].length
|
||||||
|
) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException(
|
||||||
|
"Cannot move outside map boundaries"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TileEntity tile = map[newY][newX];
|
||||||
|
if (tile == null || !tile.isWalkable()) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Tile is not walkable");
|
||||||
|
}
|
||||||
|
|
||||||
|
player.posX = newX;
|
||||||
|
player.posY = newY;
|
||||||
|
player.lastMove = LocalDateTime.now();
|
||||||
|
|
||||||
|
return new Point(newX, newY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public YakamonEntity catchYakamon() {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerModel player = playerRepository.findAll().firstResult();
|
||||||
|
if (player == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Player not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCatchDelay(player);
|
||||||
|
|
||||||
|
TileEntity[][] map = GameEntity.INSTANCE.map;
|
||||||
|
if (map == null) {
|
||||||
|
ErrorCode.INVALID_MAP.throwException("Map not loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = player.posX;
|
||||||
|
int y = player.posY;
|
||||||
|
|
||||||
|
if (y < 0 || y >= map.length || x < 0 || x >= map[y].length) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Invalid position");
|
||||||
|
}
|
||||||
|
|
||||||
|
TileEntity tile = map[y][x];
|
||||||
|
if (
|
||||||
|
tile == null || tile.collectible == null || tile.collectible == 'N'
|
||||||
|
) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
Response.status(400)
|
||||||
|
.entity("No yakamon at this position")
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collectible collectible = CollectibleUtils.getCollectible(
|
||||||
|
tile.collectible
|
||||||
|
);
|
||||||
|
if (!(collectible instanceof YakamonType)) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
Response.status(400)
|
||||||
|
.entity("No yakamon at this position")
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemModel yakaballItem = itemRepository
|
||||||
|
.find("type", ItemType.YAKABALL)
|
||||||
|
.firstResult();
|
||||||
|
if (yakaballItem == null || yakaballItem.getQuantity() < 1) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
Response.status(400).entity("Not enough Yakaballs").build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
long teamSize = yakamonRepository.count();
|
||||||
|
if (teamSize >= 3) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
Response.status(400).entity("Team is full").build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
YakamonType yakamonType = (YakamonType) collectible;
|
||||||
|
YakamonInfo yakamonInfo =
|
||||||
|
(YakamonInfo) yakamonType.getCollectibleInfo();
|
||||||
|
Integer yakadexId = yakamonInfo.getYakadexId();
|
||||||
|
|
||||||
|
YakadexEntryModel yakadex = yakadexRepository
|
||||||
|
.find("id", yakadexId)
|
||||||
|
.firstResult();
|
||||||
|
if (yakadex == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Yakamon species not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
yakaballItem.setQuantity(yakaballItem.getQuantity() - 1);
|
||||||
|
itemRepository.persist(yakaballItem);
|
||||||
|
|
||||||
|
YakamonModel newYakamon = new YakamonModel();
|
||||||
|
newYakamon.nickname = yakamonType.name();
|
||||||
|
newYakamon.energy_points = 0;
|
||||||
|
newYakamon.yakadex_entry_id = yakadex;
|
||||||
|
yakamonRepository.persist(newYakamon);
|
||||||
|
|
||||||
|
yakadex.caught = true;
|
||||||
|
yakadexRepository.persist(yakadex);
|
||||||
|
|
||||||
|
tile.collectible = 'N';
|
||||||
|
|
||||||
|
player.lastCatch = LocalDateTime.now();
|
||||||
|
playerRepository.persist(player);
|
||||||
|
|
||||||
|
return new YakamonEntity(
|
||||||
|
newYakamon.id,
|
||||||
|
newYakamon.nickname,
|
||||||
|
newYakamon.yakadex_entry_id.id,
|
||||||
|
newYakamon.energy_points
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkMovementDelay(PlayerModel player) {
|
||||||
|
String tickDurationStr = System.getenv("JWS_TICK_DURATION");
|
||||||
|
String movementDelayStr = System.getenv("JWS_MOVEMENT_DELAY");
|
||||||
|
|
||||||
|
if (tickDurationStr == null || movementDelayStr == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
long tickDuration = Long.parseLong(tickDurationStr);
|
||||||
|
long movementDelay = Long.parseLong(movementDelayStr);
|
||||||
|
long requiredDelay = tickDuration * movementDelay;
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
long elapsed = ChronoUnit.MILLIS.between(player.lastMove, now);
|
||||||
|
|
||||||
|
if (elapsed < requiredDelay) {
|
||||||
|
throw new WebApplicationException(Response.status(429).build());
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException(
|
||||||
|
"Invalid environment variables"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCatchDelay(PlayerModel player) {
|
||||||
|
String tickDurationStr = System.getenv("JWS_TICK_DURATION");
|
||||||
|
String catchDelayStr = System.getenv("JWS_CATCH_DELAY");
|
||||||
|
|
||||||
|
if (tickDurationStr == null || catchDelayStr == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
long tickDuration = Long.parseLong(tickDurationStr);
|
||||||
|
long catchDelay = Long.parseLong(catchDelayStr);
|
||||||
|
long requiredDelay = tickDuration * catchDelay;
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
long elapsed = ChronoUnit.MILLIS.between(player.lastCatch, now);
|
||||||
|
|
||||||
|
if (elapsed < requiredDelay) {
|
||||||
|
throw new WebApplicationException(Response.status(429).build());
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException(
|
||||||
|
"Invalid environment variables"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCollectDelay(PlayerModel player) {
|
||||||
|
String tickDurationStr = System.getenv("JWS_TICK_DURATION");
|
||||||
|
String collectDelayStr = System.getenv("JWS_COLLECT_DELAY");
|
||||||
|
|
||||||
|
if (tickDurationStr == null || collectDelayStr == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
long tickDuration = Long.parseLong(tickDurationStr);
|
||||||
|
long collectDelay = Long.parseLong(collectDelayStr);
|
||||||
|
long requiredDelay = tickDuration * collectDelay;
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
long elapsed = ChronoUnit.MILLIS.between(player.lastCollect, now);
|
||||||
|
|
||||||
|
if (elapsed < requiredDelay) {
|
||||||
|
throw new WebApplicationException(Response.status(429).build());
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException(
|
||||||
|
"Invalid environment variables"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public PlayerEntity getPlayerInfo() {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerModel player = playerRepository.findAll().firstResult();
|
||||||
|
if (player == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Player not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PlayerEntity(
|
||||||
|
player.id,
|
||||||
|
player.name,
|
||||||
|
player.posX,
|
||||||
|
player.posY,
|
||||||
|
player.lastMove,
|
||||||
|
player.lastCatch,
|
||||||
|
player.lastCollect,
|
||||||
|
player.lastFeed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Map<String, Object> collect() {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerModel player = playerRepository.findAll().firstResult();
|
||||||
|
if (player == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Player not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCollectDelay(player);
|
||||||
|
|
||||||
|
TileEntity[][] map = GameEntity.INSTANCE.map;
|
||||||
|
if (map == null) {
|
||||||
|
ErrorCode.INVALID_MAP.throwException("Map not loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = player.posX;
|
||||||
|
int y = player.posY;
|
||||||
|
|
||||||
|
if (y < 0 || y >= map.length || x < 0 || x >= map[y].length) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Invalid position");
|
||||||
|
}
|
||||||
|
|
||||||
|
TileEntity tile = map[y][x];
|
||||||
|
if (
|
||||||
|
tile == null || tile.collectible == null || tile.collectible == 'N'
|
||||||
|
) {
|
||||||
|
throw new WebApplicationException(
|
||||||
|
Response.status(400)
|
||||||
|
.entity("No collectible at this position")
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collectible collectible = CollectibleUtils.getCollectible(
|
||||||
|
tile.collectible
|
||||||
|
);
|
||||||
|
if (collectible instanceof ItemType) {
|
||||||
|
ItemType itemType = (ItemType) collectible;
|
||||||
|
ItemModel item = itemRepository
|
||||||
|
.find("type", itemType)
|
||||||
|
.firstResult();
|
||||||
|
if (item == null) {
|
||||||
|
item = new ItemModel();
|
||||||
|
item.setType(itemType);
|
||||||
|
item.setQuantity(1);
|
||||||
|
itemRepository.persist(item);
|
||||||
|
} else {
|
||||||
|
item.setQuantity(item.getQuantity() + 1);
|
||||||
|
itemRepository.persist(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tile.collectible = 'N';
|
||||||
|
player.lastCollect = LocalDateTime.now();
|
||||||
|
playerRepository.persist(player);
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
Map<String, Object> tileData = new HashMap<>();
|
||||||
|
tileData.put("terrainType", TerrainType.getTerrain(tile.terrain));
|
||||||
|
tileData.put("collectible", collectible);
|
||||||
|
response.put("tileType", tileData);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.service;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakadexEntryModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakamonModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.YakadexRepository;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.YakamonRepository;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ErrorCode;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class TeamService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
YakamonRepository yakamonRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
YakadexRepository yakadexRepository;
|
||||||
|
|
||||||
|
public List<YakamonEntity> getTeam() {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<YakamonModel> models = yakamonRepository.listAll();
|
||||||
|
List<YakamonEntity> entities = new ArrayList<>();
|
||||||
|
|
||||||
|
for (YakamonModel model : models) {
|
||||||
|
entities.add(
|
||||||
|
new YakamonEntity(
|
||||||
|
model.id,
|
||||||
|
model.nickname,
|
||||||
|
model.yakadex_entry_id.id,
|
||||||
|
model.energy_points
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public YakamonEntity evolve(UUID uuid) {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
YakamonModel yakamon = yakamonRepository.find("id", uuid).firstResult();
|
||||||
|
if (yakamon == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Yakamon not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
YakadexEntryModel entry = yakamon.yakadex_entry_id;
|
||||||
|
if (entry.evolution_id == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("This yakamon cannot evolve");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yakamon.energy_points < entry.evolve_threshold) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException(
|
||||||
|
"Not enough energy points to evolve"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
YakadexEntryModel evolution = yakadexRepository
|
||||||
|
.find("id", entry.evolution_id.id)
|
||||||
|
.firstResult();
|
||||||
|
yakamon.yakadex_entry_id = evolution;
|
||||||
|
yakamonRepository.persist(yakamon);
|
||||||
|
|
||||||
|
return new YakamonEntity(
|
||||||
|
yakamon.id,
|
||||||
|
yakamon.nickname,
|
||||||
|
yakamon.yakadex_entry_id.id,
|
||||||
|
yakamon.energy_points
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public YakamonEntity feed(UUID uuid, Integer quantity) {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quantity == null || quantity <= 0) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Invalid quantity");
|
||||||
|
}
|
||||||
|
|
||||||
|
YakamonModel yakamon = yakamonRepository.find("id", uuid).firstResult();
|
||||||
|
if (yakamon == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Yakamon not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
yakamon.energy_points += quantity;
|
||||||
|
yakamonRepository.persist(yakamon);
|
||||||
|
|
||||||
|
return new YakamonEntity(
|
||||||
|
yakamon.id,
|
||||||
|
yakamon.nickname,
|
||||||
|
yakamon.yakadex_entry_id.id,
|
||||||
|
yakamon.energy_points
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void release(UUID uuid) {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
YakamonModel yakamon = yakamonRepository.find("id", uuid).firstResult();
|
||||||
|
if (yakamon == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Yakamon not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
yakamonRepository.delete(yakamon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public YakamonEntity rename(UUID uuid, String newName) {
|
||||||
|
if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) {
|
||||||
|
ErrorCode.GAME_NOT_STARTED.throwException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newName == null || newName.isBlank()) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Invalid name");
|
||||||
|
}
|
||||||
|
|
||||||
|
YakamonModel yakamon = yakamonRepository.find("id", uuid).firstResult();
|
||||||
|
if (yakamon == null) {
|
||||||
|
ErrorCode.BAD_REQUEST.throwException("Yakamon not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
yakamon.nickname = newName;
|
||||||
|
yakamonRepository.persist(yakamon);
|
||||||
|
|
||||||
|
return new YakamonEntity(
|
||||||
|
yakamon.id,
|
||||||
|
yakamon.nickname,
|
||||||
|
yakamon.yakadex_entry_id.id,
|
||||||
|
yakamon.energy_points
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package fr.epita.assistants.yakamon.domain.service;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.YakadexEntryModel;
|
||||||
|
import fr.epita.assistants.yakamon.data.repository.YakadexRepository;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakadexEntryEntity;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ElementType;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class YakadexService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
YakadexRepository yakadexRepository;
|
||||||
|
|
||||||
|
public List<YakadexEntryEntity> getAllEntries(Boolean onlyMissing) {
|
||||||
|
List<YakadexEntryModel> entries;
|
||||||
|
|
||||||
|
if (onlyMissing != null && onlyMissing) {
|
||||||
|
entries = yakadexRepository.find("caught = false").list();
|
||||||
|
} else {
|
||||||
|
entries = yakadexRepository.listAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<YakadexEntryEntity> entities = new ArrayList<>();
|
||||||
|
for (YakadexEntryModel entry : entries) {
|
||||||
|
YakadexEntryEntity entity = new YakadexEntryEntity(
|
||||||
|
entry.id,
|
||||||
|
entry.name,
|
||||||
|
entry.first_type != null
|
||||||
|
? ElementType.valueOf(entry.first_type)
|
||||||
|
: null,
|
||||||
|
entry.second_type != null
|
||||||
|
? ElementType.valueOf(entry.second_type)
|
||||||
|
: null,
|
||||||
|
entry.evolve_threshold,
|
||||||
|
null,
|
||||||
|
entry.caught,
|
||||||
|
entry.description
|
||||||
|
);
|
||||||
|
entities.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YakadexEntryEntity getEntryById(Integer id) {
|
||||||
|
YakadexEntryModel entry = yakadexRepository
|
||||||
|
.find("id = ?1", id)
|
||||||
|
.firstResult();
|
||||||
|
|
||||||
|
if (entry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new YakadexEntryEntity(
|
||||||
|
entry.id,
|
||||||
|
entry.name,
|
||||||
|
entry.first_type != null
|
||||||
|
? ElementType.valueOf(entry.first_type)
|
||||||
|
: null,
|
||||||
|
entry.second_type != null
|
||||||
|
? ElementType.valueOf(entry.second_type)
|
||||||
|
: null,
|
||||||
|
entry.evolve_threshold,
|
||||||
|
null,
|
||||||
|
entry.caught,
|
||||||
|
entry.description
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class YakadexEntry {
|
||||||
|
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
public String firstType;
|
||||||
|
public String secondType;
|
||||||
|
public Integer evolveThreshold;
|
||||||
|
public Integer evolutionId;
|
||||||
|
public Boolean caught;
|
||||||
|
public String description;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class YakamonAction {
|
||||||
|
|
||||||
|
public String uuid;
|
||||||
|
public String nickname;
|
||||||
|
public Integer yakadexId;
|
||||||
|
public Integer energyPoints;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.request;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.utils.Direction;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PlayerMoveRequest {
|
||||||
|
|
||||||
|
public Direction direction;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.request;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class StartGameRequest {
|
||||||
|
|
||||||
|
public String mapPath;
|
||||||
|
public String playerName;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.request;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeamFeedRequest {
|
||||||
|
|
||||||
|
public Integer quantity;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.request;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeamRenameRequest {
|
||||||
|
|
||||||
|
public String newNickname;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ErrorResponse {
|
||||||
|
|
||||||
|
public String message;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class GetInventoryResponse {
|
||||||
|
|
||||||
|
public class ItemType {
|
||||||
|
|
||||||
|
public String type;
|
||||||
|
public String value;
|
||||||
|
|
||||||
|
public ItemType() {}
|
||||||
|
|
||||||
|
public ItemType(String type, String value) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Items {
|
||||||
|
|
||||||
|
public ItemType itemType;
|
||||||
|
public Integer quantity;
|
||||||
|
|
||||||
|
public Items() {}
|
||||||
|
|
||||||
|
public Items(ItemType itemType, Integer quantity) {
|
||||||
|
this.itemType = itemType;
|
||||||
|
this.quantity = quantity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Items> items;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PlayerCatchResponse extends YakamonAction {
|
||||||
|
|
||||||
|
public PlayerCatchResponse(
|
||||||
|
String uuid,
|
||||||
|
String nickname,
|
||||||
|
Integer yakadexId,
|
||||||
|
Integer energyPoints
|
||||||
|
) {
|
||||||
|
super(uuid, nickname, yakadexId, energyPoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.ItemType;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.TerrainType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class PlayerCollectResponse {
|
||||||
|
|
||||||
|
public class TileType {
|
||||||
|
|
||||||
|
public class Collectible {
|
||||||
|
|
||||||
|
public ItemType type;
|
||||||
|
public String value;
|
||||||
|
|
||||||
|
public Collectible() {}
|
||||||
|
|
||||||
|
public Collectible(ItemType type, String value) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerrainType terrainType;
|
||||||
|
public Collectible collectible;
|
||||||
|
|
||||||
|
public TileType() {}
|
||||||
|
|
||||||
|
public TileType(TerrainType terrainType, Collectible collectible) {
|
||||||
|
this.terrainType = terrainType;
|
||||||
|
this.collectible = collectible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileType tileType;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PlayerInfosResponse {
|
||||||
|
|
||||||
|
public String uuid;
|
||||||
|
public String name;
|
||||||
|
public Integer posX;
|
||||||
|
public Integer posY;
|
||||||
|
public String lastMove;
|
||||||
|
public String lastCollect;
|
||||||
|
public String lastCatch;
|
||||||
|
public String lastFeed;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PlayerMoveResponse {
|
||||||
|
|
||||||
|
public Integer posX;
|
||||||
|
public Integer posY;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class StartGameResponse {
|
||||||
|
|
||||||
|
public class Collectible {
|
||||||
|
|
||||||
|
public String item;
|
||||||
|
public String value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Tile {
|
||||||
|
|
||||||
|
String terrainType;
|
||||||
|
Collectible collectible;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tile[][] tiles;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeamEvolveResponse extends YakamonAction {
|
||||||
|
|
||||||
|
public TeamEvolveResponse(
|
||||||
|
String uuid,
|
||||||
|
String nickname,
|
||||||
|
Integer yakadexId,
|
||||||
|
Integer energyPoints
|
||||||
|
) {
|
||||||
|
super(uuid, nickname, yakadexId, energyPoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeamFeedResponse extends YakamonAction {
|
||||||
|
|
||||||
|
public TeamFeedResponse(
|
||||||
|
String uuid,
|
||||||
|
String nickname,
|
||||||
|
Integer yakadexId,
|
||||||
|
Integer energyPoints
|
||||||
|
) {
|
||||||
|
super(uuid, nickname, yakadexId, energyPoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeamInfosResponse {
|
||||||
|
|
||||||
|
public YakamonAction[] yakamons;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TeamRenameResponse extends YakamonAction {
|
||||||
|
|
||||||
|
public TeamRenameResponse(
|
||||||
|
String uuid,
|
||||||
|
String nickname,
|
||||||
|
Integer yakadexId,
|
||||||
|
Integer energyPoints
|
||||||
|
) {
|
||||||
|
super(uuid, nickname, yakadexId, energyPoints);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class YakadexAllInfosResponse {
|
||||||
|
|
||||||
|
public YakadexEntry[] entries;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.api.response;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
|
||||||
|
|
||||||
|
public class YakadexInfosResponse extends YakadexEntry {
|
||||||
|
|
||||||
|
public YakadexInfosResponse(
|
||||||
|
Integer id,
|
||||||
|
String name,
|
||||||
|
String firstType,
|
||||||
|
String secondType,
|
||||||
|
Integer evolveThreshold,
|
||||||
|
Integer evolutionId,
|
||||||
|
Boolean caught,
|
||||||
|
String description
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
firstType,
|
||||||
|
secondType,
|
||||||
|
evolveThreshold,
|
||||||
|
evolutionId,
|
||||||
|
caught,
|
||||||
|
description
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.rest;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.TileEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.GameService;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.request.StartGameRequest;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.Collectible;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.CollectibleUtils;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.ItemType;
|
||||||
|
import fr.epita.assistants.yakamon.utils.tile.YakamonType;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.Consumes;
|
||||||
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@Path("/start")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class GameResource {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(
|
||||||
|
GameResource.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private GameService gameService;
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/")
|
||||||
|
public Response start(StartGameRequest request) {
|
||||||
|
if (
|
||||||
|
request == null ||
|
||||||
|
request.mapPath == null ||
|
||||||
|
request.mapPath.isBlank() ||
|
||||||
|
request.playerName == null ||
|
||||||
|
request.playerName.isBlank()
|
||||||
|
) {
|
||||||
|
LOGGER.warning(
|
||||||
|
"Invalid start request: missing mapPath or playerName"
|
||||||
|
);
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid mapPath or playerName")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info(
|
||||||
|
"Starting game for player '" +
|
||||||
|
request.playerName +
|
||||||
|
"' with map '" +
|
||||||
|
request.mapPath +
|
||||||
|
"'"
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
gameService.startGame(request.mapPath, request.playerName);
|
||||||
|
LOGGER.info("Game started successfully");
|
||||||
|
|
||||||
|
TileEntity[][] map = GameEntity.INSTANCE.map;
|
||||||
|
Map<String, Object>[][] tiles = new Map[map.length][];
|
||||||
|
|
||||||
|
for (int y = 0; y < map.length; y++) {
|
||||||
|
tiles[y] = new Map[map[y].length];
|
||||||
|
for (int x = 0; x < map[y].length; x++) {
|
||||||
|
TileEntity tile = map[y][x];
|
||||||
|
Map<String, Object> tileData = new HashMap<>();
|
||||||
|
tileData.put("terrainType", getTerrainType(tile.terrain));
|
||||||
|
|
||||||
|
Map<String, Object> collectibleData = new HashMap<>();
|
||||||
|
String collectibleType = getCollectibleType(
|
||||||
|
tile.collectible
|
||||||
|
);
|
||||||
|
String collectibleValue = getCollectibleValue(
|
||||||
|
tile.collectible
|
||||||
|
);
|
||||||
|
|
||||||
|
if (collectibleType != null) {
|
||||||
|
collectibleData.put("type", collectibleType);
|
||||||
|
collectibleData.put("value", collectibleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
tileData.put("collectible", collectibleData);
|
||||||
|
tiles[y][x] = tileData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
response.put("tiles", tiles);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.severe("Failed to start game: " + e.getMessage());
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid path or invalid name provided.")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTerrainType(Character terrain) {
|
||||||
|
return switch (terrain) {
|
||||||
|
case 'G' -> "GRASS";
|
||||||
|
case 'M' -> "MOUNTAIN";
|
||||||
|
case 'R' -> "ROCK";
|
||||||
|
case 'S' -> "SAND";
|
||||||
|
case 'W' -> "WATER";
|
||||||
|
case 'L' -> "LAVA";
|
||||||
|
default -> "GRASS";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCollectibleType(Character collectible) {
|
||||||
|
if (collectible == 'N') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collectible c = CollectibleUtils.getCollectible(collectible);
|
||||||
|
if (c instanceof ItemType) {
|
||||||
|
return "ITEM";
|
||||||
|
} else if (c instanceof YakamonType) {
|
||||||
|
return "YAKAMON";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCollectibleValue(Character collectible) {
|
||||||
|
if (collectible == 'N') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collectible c = CollectibleUtils.getCollectible(collectible);
|
||||||
|
if (c instanceof ItemType) {
|
||||||
|
return ((ItemType) c).name();
|
||||||
|
} else if (c instanceof YakamonType) {
|
||||||
|
return ((YakamonType) c).name();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package fr.epita.assistants.yakamon.presentation.rest;
|
|
||||||
|
|
||||||
import jakarta.ws.rs.*;
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
@Path("/hello")
|
|
||||||
@Produces(MediaType.TEXT_PLAIN)
|
|
||||||
@Consumes(MediaType.TEXT_PLAIN)
|
|
||||||
public class HelloWorldResource {
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/")
|
|
||||||
public String helloWorld() {
|
|
||||||
return "Hello, world!";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{name}")
|
|
||||||
public String helloWorld(@PathParam("name") String name) {
|
|
||||||
return "Hello " + name + "!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.rest;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.data.model.ItemModel;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.GameService;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.InventoryService;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.GetInventoryResponse;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.Consumes;
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Path("/inventory")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class InventoryResource {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private GameService gameService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private InventoryService inventoryService;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getInventory() {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<ItemModel> items = inventoryService.getInventory();
|
||||||
|
List<GetInventoryResponse.Items> responseItems = new ArrayList<>();
|
||||||
|
GetInventoryResponse temp = new GetInventoryResponse(responseItems);
|
||||||
|
|
||||||
|
for (ItemModel item : items) {
|
||||||
|
GetInventoryResponse.Items responseItem = temp.new Items();
|
||||||
|
GetInventoryResponse.ItemType itemType = temp.new ItemType();
|
||||||
|
itemType.type = item.getType().name();
|
||||||
|
itemType.value = item.getType().name();
|
||||||
|
responseItem.itemType = itemType;
|
||||||
|
responseItem.quantity = item.getQuantity();
|
||||||
|
responseItems.add(responseItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetInventoryResponse response = new GetInventoryResponse(
|
||||||
|
responseItems
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.rest;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.GameService;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.PlayerService;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.request.PlayerMoveRequest;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.PlayerCatchResponse;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.PlayerInfosResponse;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.PlayerMoveResponse;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.*;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@Path("/")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public class PlayerResource {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private GameService gameService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private PlayerService playerService;
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/catch")
|
||||||
|
public Response catchYakamon() {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
YakamonEntity yakamon = playerService.catchYakamon();
|
||||||
|
var response = new PlayerCatchResponse(
|
||||||
|
yakamon.uuid.toString(),
|
||||||
|
yakamon.nickname,
|
||||||
|
yakamon.yakadexId,
|
||||||
|
yakamon.energyPoints
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (jakarta.ws.rs.WebApplicationException e) {
|
||||||
|
return e.getResponse();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/collect")
|
||||||
|
public Response collect() {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var tileData = playerService.collect();
|
||||||
|
return Response.ok(tileData).build();
|
||||||
|
} catch (jakarta.ws.rs.WebApplicationException e) {
|
||||||
|
return e.getResponse();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/move")
|
||||||
|
public Response move(PlayerMoveRequest request) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request == null || request.direction == null) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid direction")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fr.epita.assistants.yakamon.utils.Point newPos = playerService.move(
|
||||||
|
request.direction
|
||||||
|
);
|
||||||
|
return Response.ok(
|
||||||
|
new PlayerMoveResponse(newPos.getPosX(), newPos.getPosY())
|
||||||
|
).build();
|
||||||
|
} catch (jakarta.ws.rs.WebApplicationException e) {
|
||||||
|
return e.getResponse();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/player")
|
||||||
|
public Response getPlayerInfos() {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var player = playerService.getPlayerInfo();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||||
|
var response = new PlayerInfosResponse(
|
||||||
|
player.uuid.toString(),
|
||||||
|
player.name,
|
||||||
|
player.posX,
|
||||||
|
player.posY,
|
||||||
|
player.lastMove != null
|
||||||
|
? player.lastMove.format(formatter)
|
||||||
|
: null,
|
||||||
|
player.lastCollect != null
|
||||||
|
? player.lastCollect.format(formatter)
|
||||||
|
: null,
|
||||||
|
player.lastCatch != null
|
||||||
|
? player.lastCatch.format(formatter)
|
||||||
|
: null,
|
||||||
|
player.lastFeed != null
|
||||||
|
? player.lastFeed.format(formatter)
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (jakarta.ws.rs.WebApplicationException e) {
|
||||||
|
return e.getResponse();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.rest;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.converter.EntityToDtoConverter;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.GameService;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.TeamService;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.request.TeamFeedRequest;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.request.TeamRenameRequest;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.TeamEvolveResponse;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.TeamFeedResponse;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.TeamInfosResponse;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.TeamRenameResponse;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.*;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Path("/team")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public class TeamResource {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private GameService gameService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TeamService teamService;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getTeam() {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<YakamonEntity> team = teamService.getTeam();
|
||||||
|
var actions = EntityToDtoConverter.toYakamonActions(team);
|
||||||
|
TeamInfosResponse response = new TeamInfosResponse(
|
||||||
|
actions.toArray(
|
||||||
|
new fr.epita.assistants.yakamon.presentation.api.YakamonAction[0]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{uuid}/evolve")
|
||||||
|
public Response evolve(@PathParam("uuid") String uuid) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (uuid == null || uuid.isBlank()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Missing or invalid uuid")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID yakemonId = UUID.fromString(uuid);
|
||||||
|
YakamonEntity evolved = teamService.evolve(yakemonId);
|
||||||
|
var action = EntityToDtoConverter.toYakamonAction(evolved);
|
||||||
|
TeamEvolveResponse response = new TeamEvolveResponse(
|
||||||
|
action.uuid,
|
||||||
|
action.nickname,
|
||||||
|
action.yakadexId,
|
||||||
|
action.energyPoints
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid uuid format")
|
||||||
|
.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/{uuid}/feed")
|
||||||
|
public Response feed(
|
||||||
|
@PathParam("uuid") String uuid,
|
||||||
|
TeamFeedRequest request
|
||||||
|
) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (uuid == null || uuid.isBlank()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Missing or invalid uuid")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
request == null || request.quantity == null || request.quantity <= 0
|
||||||
|
) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid quantity")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID yakemonId = UUID.fromString(uuid);
|
||||||
|
YakamonEntity fed = teamService.feed(yakemonId, request.quantity);
|
||||||
|
var action = EntityToDtoConverter.toYakamonAction(fed);
|
||||||
|
TeamFeedResponse response = new TeamFeedResponse(
|
||||||
|
action.uuid,
|
||||||
|
action.nickname,
|
||||||
|
action.yakadexId,
|
||||||
|
action.energyPoints
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid uuid format")
|
||||||
|
.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("/{uuid}/release")
|
||||||
|
public Response release(@PathParam("uuid") String uuid) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (uuid == null || uuid.isBlank()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Missing or invalid uuid")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID yakemonId = UUID.fromString(uuid);
|
||||||
|
teamService.release(yakemonId);
|
||||||
|
return Response.noContent().build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid uuid format")
|
||||||
|
.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("/{uuid}/rename")
|
||||||
|
public Response rename(
|
||||||
|
@PathParam("uuid") String uuid,
|
||||||
|
TeamRenameRequest request
|
||||||
|
) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game not started")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (uuid == null || uuid.isBlank()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Missing or invalid uuid")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
request == null ||
|
||||||
|
request.newNickname == null ||
|
||||||
|
request.newNickname.isBlank()
|
||||||
|
) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Missing or invalid name")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UUID yakemonId = UUID.fromString(uuid);
|
||||||
|
YakamonEntity renamed = teamService.rename(
|
||||||
|
yakemonId,
|
||||||
|
request.newNickname
|
||||||
|
);
|
||||||
|
var action = EntityToDtoConverter.toYakamonAction(renamed);
|
||||||
|
TeamRenameResponse response = new TeamRenameResponse(
|
||||||
|
action.uuid,
|
||||||
|
action.nickname,
|
||||||
|
action.yakadexId,
|
||||||
|
action.energyPoints
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Invalid uuid format")
|
||||||
|
.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(e.getMessage())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package fr.epita.assistants.yakamon.presentation.rest;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.converter.EntityToDtoConverter;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakadexEntryEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.GameService;
|
||||||
|
import fr.epita.assistants.yakamon.domain.service.YakadexService;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.response.YakadexAllInfosResponse;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.*;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Path("/yakadex")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class YakadexResource {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private GameService gameService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private YakadexService yakadexService;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getYakadex(
|
||||||
|
@QueryParam("only_missing") Boolean onlyMissing
|
||||||
|
) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game is not running")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<YakadexEntryEntity> entries = yakadexService.getAllEntries(
|
||||||
|
onlyMissing
|
||||||
|
);
|
||||||
|
List<YakadexEntry> dtos = EntityToDtoConverter.toYakadexEntries(
|
||||||
|
entries
|
||||||
|
);
|
||||||
|
YakadexAllInfosResponse response = new YakadexAllInfosResponse(
|
||||||
|
dtos.toArray(new YakadexEntry[0])
|
||||||
|
);
|
||||||
|
return Response.ok(response).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{id}")
|
||||||
|
public Response getYakadexById(@PathParam("id") Integer id) {
|
||||||
|
if (!gameService.isStarted()) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Game is not running")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
YakadexEntryEntity entry = yakadexService.getEntryById(id);
|
||||||
|
|
||||||
|
if (entry == null) {
|
||||||
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
YakadexEntry dto = EntityToDtoConverter.toYakadexEntry(entry);
|
||||||
|
return Response.ok(dto).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,23 +1,31 @@
|
||||||
package fr.epita.assistants.yakamon.utils;
|
package fr.epita.assistants.yakamon.utils;
|
||||||
|
|
||||||
|
import static jakarta.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import jakarta.ws.rs.WebApplicationException;
|
import jakarta.ws.rs.WebApplicationException;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import static jakarta.ws.rs.core.Response.Status;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public enum ErrorCode {
|
public enum ErrorCode {
|
||||||
EXAMPLE_ERROR(Status.INTERNAL_SERVER_ERROR, "This is an error example");
|
EXAMPLE_ERROR(Status.INTERNAL_SERVER_ERROR, "This is an error example"),
|
||||||
|
BAD_REQUEST(Status.BAD_REQUEST, "Bad request"),
|
||||||
|
INVALID_MAP(Status.BAD_REQUEST, "Given map is invalid"),
|
||||||
|
GAME_NOT_STARTED(Status.CONFLICT, "Game has not been started"),
|
||||||
|
GAME_ALREADY_STARTED(Status.FORBIDDEN, "Game is already started");
|
||||||
|
|
||||||
private final Response.Status errorCode;
|
private final Response.Status errorCode;
|
||||||
|
|
||||||
private final String errorMessage;
|
private final String errorMessage;
|
||||||
|
|
||||||
public WebApplicationException getException() {
|
public WebApplicationException getException() {
|
||||||
return new WebApplicationException(Response.status(errorCode).entity(new ErrorInfo(errorMessage)).build());
|
return new WebApplicationException(
|
||||||
|
Response.status(errorCode)
|
||||||
|
.entity(new ErrorInfo(errorMessage))
|
||||||
|
.build()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void throwException() {
|
public void throwException() {
|
||||||
|
|
@ -25,6 +33,10 @@ public enum ErrorCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void throwException(String prefix) {
|
public void throwException(String prefix) {
|
||||||
throw new WebApplicationException(Response.status(errorCode).entity(new ErrorInfo(prefix + ": " + errorMessage)).build());
|
throw new WebApplicationException(
|
||||||
|
Response.status(errorCode)
|
||||||
|
.entity(new ErrorInfo(prefix + ": " + errorMessage))
|
||||||
|
.build()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,239 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.converter.DtoToEntityConverter;
|
||||||
|
import fr.epita.assistants.yakamon.converter.EntityToDtoConverter;
|
||||||
|
import fr.epita.assistants.yakamon.converter.EntityToModelConverter;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakadexEntryEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.YakamonEntity;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
|
||||||
|
import fr.epita.assistants.yakamon.presentation.api.request.StartGameRequest;
|
||||||
|
import fr.epita.assistants.yakamon.utils.ElementType;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@DisplayName("ConverterTests")
|
||||||
|
public class ConverterTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ModelToYakamon: null returns null")
|
||||||
|
public void testNullYakamonToModel() {
|
||||||
|
assertNull(EntityToModelConverter.toYakamonModel(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ModelToYakamon: valid conversion")
|
||||||
|
public void testYakamonToModel() {
|
||||||
|
YakamonEntity yakamon = new YakamonEntity();
|
||||||
|
yakamon.uuid = UUID.randomUUID();
|
||||||
|
yakamon.nickname = "Bastiedon";
|
||||||
|
yakamon.yakadexId = 6;
|
||||||
|
yakamon.energyPoints = 50;
|
||||||
|
|
||||||
|
var model = EntityToModelConverter.toYakamonModel(yakamon);
|
||||||
|
|
||||||
|
assertNotNull(model);
|
||||||
|
assertEquals("Bastiedon", model.nickname);
|
||||||
|
assertEquals(50, model.energy_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ModelToYakadex: null returns null")
|
||||||
|
public void testNullYakadexToModel() {
|
||||||
|
assertNull(EntityToModelConverter.toYakadexEntryModel(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ModelToYakadex: single type")
|
||||||
|
public void testYakadexSingleType() {
|
||||||
|
YakadexEntryEntity yakadex = new YakadexEntryEntity();
|
||||||
|
yakadex.id = 1;
|
||||||
|
yakadex.name = "Yakimon";
|
||||||
|
yakadex.firstType = ElementType.NORMAL;
|
||||||
|
yakadex.secondType = null;
|
||||||
|
yakadex.caught = true;
|
||||||
|
|
||||||
|
var model = EntityToModelConverter.toYakadexEntryModel(yakadex);
|
||||||
|
|
||||||
|
assertNotNull(model);
|
||||||
|
assertEquals("NORMAL", model.first_type);
|
||||||
|
assertNull(model.second_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ModelToYakadex: dual types")
|
||||||
|
public void testYakadexDualTypes() {
|
||||||
|
YakadexEntryEntity yakadex = new YakadexEntryEntity();
|
||||||
|
yakadex.id = 25;
|
||||||
|
yakadex.name = "Pikachu";
|
||||||
|
yakadex.firstType = ElementType.ELECTRIC;
|
||||||
|
yakadex.secondType = ElementType.FLYING;
|
||||||
|
yakadex.caught = false;
|
||||||
|
|
||||||
|
var model = EntityToModelConverter.toYakadexEntryModel(yakadex);
|
||||||
|
|
||||||
|
assertNotNull(model);
|
||||||
|
assertEquals("ELECTRIC", model.first_type);
|
||||||
|
assertEquals("FLYING", model.second_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToYakamon: null returns null")
|
||||||
|
public void testNullYakamonAction() {
|
||||||
|
assertNull(DtoToEntityConverter.toYakamonEntity(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToYakamon: valid conversion")
|
||||||
|
public void testYakamonActionValid() {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
YakamonAction action = new YakamonAction(
|
||||||
|
uuid.toString(),
|
||||||
|
"Bastiedon",
|
||||||
|
6,
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
|
YakamonEntity entity = DtoToEntityConverter.toYakamonEntity(action);
|
||||||
|
|
||||||
|
assertNotNull(entity);
|
||||||
|
assertEquals(uuid, entity.uuid);
|
||||||
|
assertEquals("Bastiedon", entity.nickname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToYakamon: invalid uuid handled")
|
||||||
|
public void testYakamonInvalidUuid() {
|
||||||
|
YakamonAction action = new YakamonAction("not-a-uuid", "Test", 1, 0);
|
||||||
|
YakamonEntity entity = DtoToEntityConverter.toYakamonEntity(action);
|
||||||
|
|
||||||
|
assertNotNull(entity);
|
||||||
|
assertNull(entity.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToYakadex: null returns null")
|
||||||
|
public void testNullYakadexEntry() {
|
||||||
|
assertNull(DtoToEntityConverter.toYakadexEntryEntity(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToYakadex: valid types")
|
||||||
|
public void testYakadexTypesConvert() {
|
||||||
|
YakadexEntry dto = new YakadexEntry(
|
||||||
|
1,
|
||||||
|
"Yakimon",
|
||||||
|
"NORMAL",
|
||||||
|
"FLYING",
|
||||||
|
10,
|
||||||
|
2,
|
||||||
|
true,
|
||||||
|
"A creature"
|
||||||
|
);
|
||||||
|
YakadexEntryEntity entity = DtoToEntityConverter.toYakadexEntryEntity(
|
||||||
|
dto
|
||||||
|
);
|
||||||
|
|
||||||
|
assertNotNull(entity);
|
||||||
|
assertEquals(ElementType.NORMAL, entity.firstType);
|
||||||
|
assertEquals(ElementType.FLYING, entity.secondType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToYakadex: invalid enum handled")
|
||||||
|
public void testYakadexInvalidEnum() {
|
||||||
|
YakadexEntry dto = new YakadexEntry(
|
||||||
|
1,
|
||||||
|
"Test",
|
||||||
|
"INVALID",
|
||||||
|
null,
|
||||||
|
10,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
"Test"
|
||||||
|
);
|
||||||
|
YakadexEntryEntity entity = DtoToEntityConverter.toYakadexEntryEntity(
|
||||||
|
dto
|
||||||
|
);
|
||||||
|
|
||||||
|
assertNotNull(entity);
|
||||||
|
assertNull(entity.firstType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DtoToGame: converts correctly")
|
||||||
|
public void testGameDtoConvert() {
|
||||||
|
StartGameRequest request = new StartGameRequest("test_map", "Player");
|
||||||
|
GameEntity entity = DtoToEntityConverter.toGameEntity(request);
|
||||||
|
|
||||||
|
assertNotNull(entity);
|
||||||
|
assertEquals("test_map", entity.mapPath);
|
||||||
|
assertTrue(entity.started);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EntityToYakamon: null returns null")
|
||||||
|
public void testNullYakamonDto() {
|
||||||
|
assertNull(EntityToDtoConverter.toYakamonAction(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EntityToYakamon: valid conversion")
|
||||||
|
public void testYakamonDto() {
|
||||||
|
YakamonEntity yakamon = new YakamonEntity();
|
||||||
|
yakamon.uuid = UUID.randomUUID();
|
||||||
|
yakamon.nickname = "Bastiedon";
|
||||||
|
yakamon.yakadexId = 6;
|
||||||
|
yakamon.energyPoints = 75;
|
||||||
|
|
||||||
|
YakamonAction action = EntityToDtoConverter.toYakamonAction(yakamon);
|
||||||
|
|
||||||
|
assertNotNull(action);
|
||||||
|
assertEquals("Bastiedon", action.nickname);
|
||||||
|
assertEquals(6, action.yakadexId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EntityToYakadex: null returns null")
|
||||||
|
public void testNullYakadexDto() {
|
||||||
|
assertNull(EntityToDtoConverter.toYakadexEntry(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EntityToYakadex: conversion")
|
||||||
|
public void testYakadexDto() {
|
||||||
|
YakadexEntryEntity yakadex = new YakadexEntryEntity();
|
||||||
|
yakadex.id = 1;
|
||||||
|
yakadex.name = "Yakimon";
|
||||||
|
yakadex.firstType = ElementType.NORMAL;
|
||||||
|
yakadex.secondType = null;
|
||||||
|
yakadex.caught = true;
|
||||||
|
|
||||||
|
YakadexEntry entry = EntityToDtoConverter.toYakadexEntry(yakadex);
|
||||||
|
|
||||||
|
assertNotNull(entry);
|
||||||
|
assertEquals("NORMAL", entry.firstType);
|
||||||
|
assertNull(entry.secondType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EntityToYakamon: list conversion")
|
||||||
|
public void testYakamonListDto() {
|
||||||
|
YakamonEntity y1 = new YakamonEntity();
|
||||||
|
y1.uuid = UUID.randomUUID();
|
||||||
|
y1.nickname = "Yak1";
|
||||||
|
y1.yakadexId = 1;
|
||||||
|
y1.energyPoints = 0;
|
||||||
|
|
||||||
|
var result = EntityToDtoConverter.toYakamonActions(
|
||||||
|
java.util.List.of(y1)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertEquals(1, result.size());
|
||||||
|
assertEquals("Yak1", result.get(0).nickname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("GameResourceTest")
|
||||||
|
public class GameResourceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ with valid request")
|
||||||
|
public void testStartGameWithValidRequest() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"Alice\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start without trailing slash")
|
||||||
|
public void testStartGameWithoutTrailingSlash() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"Alice\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ missing mapPath returns 400")
|
||||||
|
public void testStartGameWithoutMapPath() {
|
||||||
|
String requestBody = "{\"playerName\": \"Alice\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ missing playerName returns 400")
|
||||||
|
public void testStartGameWithoutPlayerName() {
|
||||||
|
String requestBody = "{\"mapPath\": \"map1.txt\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ blank mapPath returns 400")
|
||||||
|
public void testStartGameWithBlankMapPath() {
|
||||||
|
String requestBody = "{\"mapPath\": \"\", \"playerName\": \"Alice\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ blank playerName returns 400")
|
||||||
|
public void testStartGameWithBlankPlayerName() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ both fields blank returns 400")
|
||||||
|
public void testStartGameWithBothBlank() {
|
||||||
|
String requestBody = "{\"mapPath\": \"\", \"playerName\": \"\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ whitespace mapPath returns 400")
|
||||||
|
public void testStartGameWithWhitespaceMapPath() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \" \", \"playerName\": \"Alice\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ whitespace playerName returns 400")
|
||||||
|
public void testStartGameWithWhitespacePlayerName() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \" \"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ with special characters in name")
|
||||||
|
public void testStartGameWithSpecialCharacterName() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"Alice-Smith_123\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ with complex map path")
|
||||||
|
public void testStartGameWithComplexMapPath() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"maps/world/level1/forest.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /start/ returns JSON")
|
||||||
|
public void testStartGameContentType() {
|
||||||
|
String requestBody =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"Alice\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/start/")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("HelloWorldResourceTest")
|
||||||
|
public class HelloWorldResourceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /hello/")
|
||||||
|
public void testHelloWorldWithoutName() {
|
||||||
|
given()
|
||||||
|
.when()
|
||||||
|
.get("/hello/")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /hello without trailing slash")
|
||||||
|
public void testHelloWorldWithoutTrailingSlash() {
|
||||||
|
given()
|
||||||
|
.when()
|
||||||
|
.get("/hello")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /hello/{name}")
|
||||||
|
public void testHelloWorldWithName() {
|
||||||
|
given()
|
||||||
|
.when()
|
||||||
|
.get("/hello/Alice")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /hello/{name} with different name")
|
||||||
|
public void testHelloWorldWithDifferentName() {
|
||||||
|
given()
|
||||||
|
.when()
|
||||||
|
.get("/hello/Bob")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /hello/{name} with special characters")
|
||||||
|
public void testHelloWorldWithSpecialCharacters() {
|
||||||
|
given()
|
||||||
|
.when()
|
||||||
|
.get("/hello/John-Doe")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /hello/{name} with numeric name")
|
||||||
|
public void testHelloWorldWithNumericName() {
|
||||||
|
given()
|
||||||
|
.when()
|
||||||
|
.get("/hello/123")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.TEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("InventoryResourceTest")
|
||||||
|
public class InventoryResourceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory returns 200")
|
||||||
|
public void testGetInventorySuccess() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory returns JSON")
|
||||||
|
public void testGetInventoryContentType() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory without trailing slash")
|
||||||
|
public void testGetInventoryWithoutTrailingSlash() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory multiple requests")
|
||||||
|
public void testGetInventoryMultipleCalls() {
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory with accept header")
|
||||||
|
public void testGetInventoryWithAcceptHeader() {
|
||||||
|
given()
|
||||||
|
.accept(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory without body")
|
||||||
|
public void testGetInventoryNoBody() {
|
||||||
|
given().when().get("/inventory").then().statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory with query params")
|
||||||
|
public void testGetInventoryWithQueryParams() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.queryParam("filter", "all")
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory rapid consecutive requests")
|
||||||
|
public void testGetInventoryRapidRequests() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
// import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
// import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MainTests {}
|
||||||
|
|
@ -0,0 +1,210 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("PlayerResourceTest")
|
||||||
|
public class PlayerResourceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /catch without game returns 400")
|
||||||
|
public void testCatchYakamonWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/catch")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /collect without game returns 400")
|
||||||
|
public void testCollectWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/collect")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory without game returns 400")
|
||||||
|
public void testGetInventoryWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move without game returns 400")
|
||||||
|
public void testMoveWithoutGameStarted() {
|
||||||
|
String requestBody = "{\"direction\": \"UP\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move without body returns 400")
|
||||||
|
public void testMoveWithoutRequestBody() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /player without game returns 400")
|
||||||
|
public void testGetPlayerInfosWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/player")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /inventory returns JSON")
|
||||||
|
public void testGetInventoryContentType() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/inventory")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move returns JSON")
|
||||||
|
public void testMoveContentType() {
|
||||||
|
String requestBody = "{\"direction\": \"UP\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /player returns JSON")
|
||||||
|
public void testGetPlayerContentType() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/player")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /catch returns JSON")
|
||||||
|
public void testCatchContentType() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/catch")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /collect returns JSON")
|
||||||
|
public void testCollectContentType() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/collect")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move with UP direction")
|
||||||
|
public void testMoveWithUpDirection() {
|
||||||
|
String requestBody = "{\"direction\": \"UP\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move with DOWN direction")
|
||||||
|
public void testMoveWithDownDirection() {
|
||||||
|
String requestBody = "{\"direction\": \"DOWN\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move with LEFT direction")
|
||||||
|
public void testMoveWithLeftDirection() {
|
||||||
|
String requestBody = "{\"direction\": \"LEFT\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move with RIGHT direction")
|
||||||
|
public void testMoveWithRightDirection() {
|
||||||
|
String requestBody = "{\"direction\": \"RIGHT\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /move with invalid direction")
|
||||||
|
public void testMoveWithInvalidDirection() {
|
||||||
|
String requestBody = "{\"direction\": \"INVALID\"}";
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/move")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.GameEntity;
|
||||||
|
import fr.epita.assistants.yakamon.domain.entity.TileEntity;
|
||||||
|
import fr.epita.assistants.yakamon.utils.Direction;
|
||||||
|
import fr.epita.assistants.yakamon.utils.Point;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@DisplayName("ServiceLayerTests")
|
||||||
|
public class ServiceLayerTests {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
GameEntity.INSTANCE = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GameStart")
|
||||||
|
public void testGameStart() {
|
||||||
|
GameEntity game = new GameEntity("test_map");
|
||||||
|
assertTrue(game.started);
|
||||||
|
assertEquals("test_map", game.mapPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GameStop")
|
||||||
|
public void testGameStop() {
|
||||||
|
GameEntity game = new GameEntity("map");
|
||||||
|
game.stop();
|
||||||
|
assertFalse(game.started);
|
||||||
|
assertNull(GameEntity.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GameSetMap")
|
||||||
|
public void testGameSetMap() {
|
||||||
|
GameEntity game = new GameEntity("map");
|
||||||
|
TileEntity[][] map = new TileEntity[2][2];
|
||||||
|
game.map = map;
|
||||||
|
assertNotNull(game.map);
|
||||||
|
assertEquals(2, game.map.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileGrassWalkable")
|
||||||
|
public void testGrassWalkable() {
|
||||||
|
TileEntity tile = new TileEntity('G', 'N');
|
||||||
|
assertTrue(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileSandWalkable")
|
||||||
|
public void testSandWalkable() {
|
||||||
|
TileEntity tile = new TileEntity('S', 'N');
|
||||||
|
assertTrue(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileRockWalkable")
|
||||||
|
public void testRockWalkable() {
|
||||||
|
TileEntity tile = new TileEntity('R', 'N');
|
||||||
|
assertTrue(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileWaterNotWalkable")
|
||||||
|
public void testWaterNotWalkable() {
|
||||||
|
TileEntity tile = new TileEntity('W', 'N');
|
||||||
|
assertFalse(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileMountainNotWalkable")
|
||||||
|
public void testMountainNotWalkable() {
|
||||||
|
TileEntity tile = new TileEntity('M', 'N');
|
||||||
|
assertFalse(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileLavaNotWalkable")
|
||||||
|
public void testLavaNotWalkable() {
|
||||||
|
TileEntity tile = new TileEntity('L', 'N');
|
||||||
|
assertFalse(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("TileCollectible")
|
||||||
|
public void testTileCollectible() {
|
||||||
|
TileEntity tile = new TileEntity('G', 'Y');
|
||||||
|
assertEquals('Y', tile.collectible);
|
||||||
|
assertEquals('G', tile.terrain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DirectionUp")
|
||||||
|
public void testDirectionUp() {
|
||||||
|
Point p = Direction.UP.getPoint();
|
||||||
|
assertEquals(0, p.getPosX());
|
||||||
|
assertEquals(-1, p.getPosY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DirectionDown")
|
||||||
|
public void testDirectionDown() {
|
||||||
|
Point p = Direction.DOWN.getPoint();
|
||||||
|
assertEquals(0, p.getPosX());
|
||||||
|
assertEquals(1, p.getPosY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DirectionLeft")
|
||||||
|
public void testDirectionLeft() {
|
||||||
|
Point p = Direction.LEFT.getPoint();
|
||||||
|
assertEquals(-1, p.getPosX());
|
||||||
|
assertEquals(0, p.getPosY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DirectionRight")
|
||||||
|
public void testDirectionRight() {
|
||||||
|
Point p = Direction.RIGHT.getPoint();
|
||||||
|
assertEquals(1, p.getPosX());
|
||||||
|
assertEquals(0, p.getPosY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PointCreation")
|
||||||
|
public void testPointCreation() {
|
||||||
|
Point p = new Point(5, 10);
|
||||||
|
assertEquals(5, p.getPosX());
|
||||||
|
assertEquals(10, p.getPosY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GameInstance")
|
||||||
|
public void testGameInstance() {
|
||||||
|
GameEntity g1 = new GameEntity("map1");
|
||||||
|
assertSame(GameEntity.INSTANCE, g1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("MapGrid")
|
||||||
|
public void testMapGrid() {
|
||||||
|
TileEntity[][] map = new TileEntity[3][3];
|
||||||
|
map[0][0] = new TileEntity('G', 'N');
|
||||||
|
map[1][1] = new TileEntity('W', 'N');
|
||||||
|
map[2][2] = new TileEntity('R', 'Y');
|
||||||
|
|
||||||
|
assertTrue(map[0][0].isWalkable());
|
||||||
|
assertFalse(map[1][1].isWalkable());
|
||||||
|
assertTrue(map[2][2].isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("YakamonTile")
|
||||||
|
public void testYakamonTile() {
|
||||||
|
TileEntity tile = new TileEntity('G', 'b');
|
||||||
|
assertEquals('b', tile.collectible);
|
||||||
|
assertTrue(tile.isWalkable());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ItemTile")
|
||||||
|
public void testItemTile() {
|
||||||
|
TileEntity tile = new TileEntity('S', 'S');
|
||||||
|
assertEquals('S', tile.collectible);
|
||||||
|
assertTrue(tile.isWalkable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,457 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("TeamResourceTest")
|
||||||
|
public class TeamResourceTest {
|
||||||
|
|
||||||
|
private static final String VALID_UUID =
|
||||||
|
"550e8400-e29b-41d4-a716-446655440000";
|
||||||
|
private static final String ANOTHER_UUID =
|
||||||
|
"6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /team without game returns 400")
|
||||||
|
public void testGetTeamWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/team")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /team returns JSON")
|
||||||
|
public void testGetTeamContentType() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/team")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/evolve without game returns 400")
|
||||||
|
public void testEvolveWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/evolve")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/evolve with blank uuid returns 400")
|
||||||
|
public void testEvolveWithBlankUuid() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/team//evolve")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/evolve with valid uuid returns 200")
|
||||||
|
public void testEvolveWithValidUuid() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/evolve")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/evolve returns JSON")
|
||||||
|
public void testEvolveContentType() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/evolve")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed without game returns 400")
|
||||||
|
public void testFeedWithoutGameStarted() {
|
||||||
|
String requestBody = "{\"quantity\": 10}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed with blank uuid returns 400")
|
||||||
|
public void testFeedWithBlankUuid() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"quantity\": 10}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team//feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed with null quantity returns 400")
|
||||||
|
public void testFeedWithNullQuantity() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"quantity\": null}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed with zero quantity returns 400")
|
||||||
|
public void testFeedWithZeroQuantity() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"quantity\": 0}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed with negative quantity returns 400")
|
||||||
|
public void testFeedWithNegativeQuantity() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"quantity\": -5}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed with valid quantity returns 200")
|
||||||
|
public void testFeedWithValidQuantity() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"quantity\": 10}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed without body returns 400")
|
||||||
|
public void testFeedWithMissingRequestBody() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("POST /team/{uuid}/feed returns JSON")
|
||||||
|
public void testFeedContentType() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"quantity\": 10}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/team/" + VALID_UUID + "/feed")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DELETE /team/{uuid}/release without game returns 400")
|
||||||
|
public void testReleaseWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.delete("/team/" + VALID_UUID + "/release")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DELETE /team/{uuid}/release with blank uuid returns 400")
|
||||||
|
public void testReleaseWithBlankUuid() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.delete("/team//release")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DELETE /team/{uuid}/release with valid uuid returns 204")
|
||||||
|
public void testReleaseWithValidUuid() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.delete("/team/" + VALID_UUID + "/release")
|
||||||
|
.then()
|
||||||
|
.statusCode(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("DELETE /team/{uuid}/release multiple times")
|
||||||
|
public void testReleaseWithMultipleUuids() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.delete("/team/" + VALID_UUID + "/release")
|
||||||
|
.then()
|
||||||
|
.statusCode(204);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.delete("/team/" + ANOTHER_UUID + "/release")
|
||||||
|
.then()
|
||||||
|
.statusCode(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PATCH /team/{uuid}/rename without game returns 400")
|
||||||
|
public void testRenameWithoutGameStarted() {
|
||||||
|
String requestBody = "{\"newNickname\": \"NewName\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.patch("/team/" + VALID_UUID + "/rename")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PATCH /team/{uuid}/rename with blank uuid returns 400")
|
||||||
|
public void testRenameWithBlankUuid() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"newNickname\": \"NewName\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.patch("/team//rename")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PATCH /team/{uuid}/rename without body returns 400")
|
||||||
|
public void testRenameWithMissingRequestBody() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.patch("/team/" + VALID_UUID + "/rename")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PATCH /team/{uuid}/rename with valid request returns 200")
|
||||||
|
public void testRenameWithValidRequest() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"newNickname\": \"NewName\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.patch("/team/" + VALID_UUID + "/rename")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PATCH /team/{uuid}/rename returns JSON")
|
||||||
|
public void testRenameContentType() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"newNickname\": \"NewName\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.patch("/team/" + VALID_UUID + "/rename")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("PATCH /team/{uuid}/rename with special characters")
|
||||||
|
public void testRenameWithSpecialCharacters() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
String requestBody = "{\"newNickname\": \"New-Name_123\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.patch("/team/" + VALID_UUID + "/rename")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,328 @@
|
||||||
|
package fr.epita.assistants.yakamon_testsuite;
|
||||||
|
|
||||||
|
import static io.restassured.RestAssured.given;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@QuarkusTest
|
||||||
|
@DisplayName("YakadexResourceTest")
|
||||||
|
public class YakadexResourceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex without game returns 400")
|
||||||
|
public void testGetYakadexWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex returns 200 when game started")
|
||||||
|
public void testGetYakadexWithGameStarted() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex with only_missing=true")
|
||||||
|
public void testGetYakadexWithOnlyMissingTrue() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.queryParam("only_missing", true)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex with only_missing=false")
|
||||||
|
public void testGetYakadexWithOnlyMissingFalse() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.queryParam("only_missing", false)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex with only_missing=TRUE uppercase")
|
||||||
|
public void testGetYakadexWithOnlyMissingUppercase() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.queryParam("only_missing", "TRUE")
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex returns JSON")
|
||||||
|
public void testGetYakadexContentType() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} without game returns 400")
|
||||||
|
public void testGetYakadexByIdWithoutGameStarted() {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/1")
|
||||||
|
.then()
|
||||||
|
.statusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} with valid id")
|
||||||
|
public void testGetYakadexByIdWithGameStarted() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/1")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} with id=0")
|
||||||
|
public void testGetYakadexByIdWithZero() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/0")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} with negative id returns 404")
|
||||||
|
public void testGetYakadexByIdWithNegativeId() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/-1")
|
||||||
|
.then()
|
||||||
|
.statusCode(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} with large id")
|
||||||
|
public void testGetYakadexByIdWithLargeId() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/999999")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} returns JSON")
|
||||||
|
public void testGetYakadexByIdContentType() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/1")
|
||||||
|
.then()
|
||||||
|
.contentType(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} multiple different ids")
|
||||||
|
public void testGetYakadexByIdMultipleIds() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
int[] ids = { 1, 2, 5, 10, 42, 100 };
|
||||||
|
for (int id : ids) {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/" + id)
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} with id=-2 returns 404")
|
||||||
|
public void testGetYakadexByIdWithAnotherNegativeId() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/-2")
|
||||||
|
.then()
|
||||||
|
.statusCode(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex/{id} with id=-100 returns 404")
|
||||||
|
public void testGetYakadexByIdWithLargeNegativeId() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex/-100")
|
||||||
|
.then()
|
||||||
|
.statusCode(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex without query params")
|
||||||
|
public void testGetYakadexWithoutQueryParams() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GET /yakadex multiple calls")
|
||||||
|
public void testGetYakadexMultipleCalls() {
|
||||||
|
String startRequest =
|
||||||
|
"{\"mapPath\": \"map1.txt\", \"playerName\": \"TestPlayer\"}";
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(startRequest)
|
||||||
|
.when()
|
||||||
|
.post("/start/");
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.when()
|
||||||
|
.get("/yakadex")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue