diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb23564 --- /dev/null +++ b/README.md @@ -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. + diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/ItemModel.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/ItemModel.java index ff1a256..e71d104 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/ItemModel.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/ItemModel.java @@ -9,10 +9,34 @@ public class ItemModel { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - protected Integer id; + private Integer id; @Enumerated - public ItemType type; + private ItemType type; - public Integer quantity; + 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; + } } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/YakadexEntryModel.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/YakadexEntryModel.java index 7d165b5..ddc3919 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/YakadexEntryModel.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/data/model/YakadexEntryModel.java @@ -1,6 +1,5 @@ package fr.epita.assistants.yakamon.data.model; -import fr.epita.assistants.yakamon.utils.ElementType; import jakarta.persistence.*; @Entity diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/ItemEntity.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/ItemEntity.java index 97f8f22..3395967 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/ItemEntity.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/ItemEntity.java @@ -1,7 +1,6 @@ package fr.epita.assistants.yakamon.domain.entity; import fr.epita.assistants.yakamon.utils.tile.ItemType; -import java.util.Objects; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/PlayerEntity.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/PlayerEntity.java index 7788d6d..012bbe0 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/PlayerEntity.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/entity/PlayerEntity.java @@ -1,9 +1,15 @@ 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; diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/GameService.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/GameService.java index 0d4fd1c..29abf6e 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/GameService.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/GameService.java @@ -59,8 +59,8 @@ public class GameService { // Initialize player inventory ItemModel yakaballs = new ItemModel(); - yakaballs.type = ItemType.YAKABALL; - yakaballs.quantity = 5; + yakaballs.setType(ItemType.YAKABALL); + yakaballs.setQuantity(5); // Store playerRepository.persist(player); diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/InventoryService.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/InventoryService.java new file mode 100644 index 0000000..f9a4993 --- /dev/null +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/InventoryService.java @@ -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 getInventory() { + if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) { + ErrorCode.GAME_NOT_STARTED.throwException(); + } + + return itemRepository.listAll(); + } +} diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/PlayerService.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/PlayerService.java index edc7d3e..954eea4 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/PlayerService.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/PlayerService.java @@ -9,13 +9,16 @@ 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; @@ -25,7 +28,8 @@ import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Response; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; -import java.util.UUID; +import java.util.HashMap; +import java.util.Map; @ApplicationScoped public class PlayerService { @@ -92,7 +96,7 @@ public class PlayerService { } @Transactional - public YakamonModel catchYakamon() { + public YakamonEntity catchYakamon() { if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) { ErrorCode.GAME_NOT_STARTED.throwException(); } @@ -141,7 +145,7 @@ public class PlayerService { ItemModel yakaballItem = itemRepository .find("type", ItemType.YAKABALL) .firstResult(); - if (yakaballItem == null || yakaballItem.quantity < 1) { + if (yakaballItem == null || yakaballItem.getQuantity() < 1) { throw new WebApplicationException( Response.status(400).entity("Not enough Yakaballs").build() ); @@ -166,7 +170,7 @@ public class PlayerService { ErrorCode.BAD_REQUEST.throwException("Yakamon species not found"); } - yakaballItem.quantity -= 1; + yakaballItem.setQuantity(yakaballItem.getQuantity() - 1); itemRepository.persist(yakaballItem); YakamonModel newYakamon = new YakamonModel(); @@ -183,7 +187,12 @@ public class PlayerService { player.lastCatch = LocalDateTime.now(); playerRepository.persist(player); - return newYakamon; + return new YakamonEntity( + newYakamon.id, + newYakamon.nickname, + newYakamon.yakadex_entry_id.id, + newYakamon.energy_points + ); } private void checkMovementDelay(PlayerModel player) { @@ -237,4 +246,120 @@ public class PlayerService { ); } } + + 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 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 response = new HashMap<>(); + Map tileData = new HashMap<>(); + tileData.put("terrainType", TerrainType.getTerrain(tile.terrain)); + tileData.put("collectible", collectible); + response.put("tileType", tileData); + return response; + } } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/TeamService.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/TeamService.java index 3f12a02..60ea6c7 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/TeamService.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/TeamService.java @@ -1,3 +1,149 @@ package fr.epita.assistants.yakamon.domain.service; -public class TeamService {} +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 getTeam() { + if (GameEntity.INSTANCE == null || !GameEntity.INSTANCE.started) { + ErrorCode.GAME_NOT_STARTED.throwException(); + } + + List models = yakamonRepository.listAll(); + List 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 + ); + } +} diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/YakadexService.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/YakadexService.java index 42285af..2476b00 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/YakadexService.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/domain/service/YakadexService.java @@ -2,9 +2,8 @@ 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.presentation.api.YakadexEntry; -import fr.epita.assistants.yakamon.presentation.api.response.YakadexAllInfosResponse; -import fr.epita.assistants.yakamon.presentation.api.response.YakadexInfosResponse; +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; @@ -16,7 +15,7 @@ public class YakadexService { @Inject YakadexRepository yakadexRepository; - public YakadexAllInfosResponse getAllEntries(Boolean onlyMissing) { + public List getAllEntries(Boolean onlyMissing) { List entries; if (onlyMissing != null && onlyMissing) { @@ -25,25 +24,29 @@ public class YakadexService { entries = yakadexRepository.listAll(); } - List dtos = new ArrayList<>(); + List entities = new ArrayList<>(); for (YakadexEntryModel entry : entries) { - YakadexEntry dto = new YakadexInfosResponse( + YakadexEntryEntity entity = new YakadexEntryEntity( entry.id, entry.name, - entry.first_type, - entry.second_type, + 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 ); - dtos.add(dto); + entities.add(entity); } - return new YakadexAllInfosResponse(dtos.toArray(new YakadexEntry[0])); + return entities; } - public YakadexInfosResponse getEntryById(Integer id) { + public YakadexEntryEntity getEntryById(Integer id) { YakadexEntryModel entry = yakadexRepository .find("id = ?1", id) .firstResult(); @@ -52,11 +55,15 @@ public class YakadexService { return null; } - return new YakadexInfosResponse( + return new YakadexEntryEntity( entry.id, entry.name, - entry.first_type, - entry.second_type, + 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, diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/YakamonAction.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/YakamonAction.java index 5b307d3..6faef97 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/YakamonAction.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/YakamonAction.java @@ -1,7 +1,9 @@ package fr.epita.assistants.yakamon.presentation.api; import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +@NoArgsConstructor @AllArgsConstructor public class YakamonAction { diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/StartGameRequest.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/StartGameRequest.java index 97461d1..885e164 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/StartGameRequest.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/StartGameRequest.java @@ -1,7 +1,9 @@ package fr.epita.assistants.yakamon.presentation.api.request; import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +@NoArgsConstructor @AllArgsConstructor public class StartGameRequest { diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamFeedRequest.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamFeedRequest.java index 8d094b0..5c9fbfa 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamFeedRequest.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamFeedRequest.java @@ -1,8 +1,10 @@ package fr.epita.assistants.yakamon.presentation.api.request; import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; @AllArgsConstructor +@NoArgsConstructor public class TeamFeedRequest { public Integer quantity; diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamRenameRequest.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamRenameRequest.java index bceb7e2..db76322 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamRenameRequest.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/request/TeamRenameRequest.java @@ -1,8 +1,10 @@ package fr.epita.assistants.yakamon.presentation.api.request; import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; @AllArgsConstructor +@NoArgsConstructor public class TeamRenameRequest { public String newNickname; diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/GetInventoryResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/GetInventoryResponse.java index 8b4a708..3a1cf7e 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/GetInventoryResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/GetInventoryResponse.java @@ -2,21 +2,37 @@ 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; + } } - List items; + public List items; } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCatchResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCatchResponse.java index 499002b..9ca2b4d 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCatchResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCatchResponse.java @@ -1,7 +1,9 @@ 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( diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCollectResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCollectResponse.java index 1ac932c..200336f 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCollectResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerCollectResponse.java @@ -3,20 +3,36 @@ 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 { - ItemType type; - String value; + public ItemType type; + public String value; + + public Collectible() {} + + public Collectible(ItemType type, String value) { + this.type = type; + this.value = value; + } } - TerrainType terrainType; - Collectible collectible; + public TerrainType terrainType; + public Collectible collectible; + + public TileType() {} + + public TileType(TerrainType terrainType, Collectible collectible) { + this.terrainType = terrainType; + this.collectible = collectible; + } } public TileType tileType; diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerInfosResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerInfosResponse.java index 7773e89..c4fa464 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerInfosResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/PlayerInfosResponse.java @@ -1,7 +1,9 @@ package fr.epita.assistants.yakamon.presentation.api.response; import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +@NoArgsConstructor @AllArgsConstructor public class PlayerInfosResponse { @@ -10,7 +12,7 @@ public class PlayerInfosResponse { public Integer posX; public Integer posY; public String lastMove; - public String lastCatch; public String lastCollect; + public String lastCatch; public String lastFeed; } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamEvolveResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamEvolveResponse.java index 5347429..7b97656 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamEvolveResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamEvolveResponse.java @@ -1,7 +1,9 @@ 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( diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamFeedResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamFeedResponse.java index d13d43b..d8b024b 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamFeedResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamFeedResponse.java @@ -1,7 +1,9 @@ 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( diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamInfosResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamInfosResponse.java index e2444ea..cc56a45 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamInfosResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamInfosResponse.java @@ -2,9 +2,11 @@ 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 { - YakamonAction[] yakamons; + public YakamonAction[] yakamons; } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamRenameResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamRenameResponse.java index a1b7f28..2c46caf 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamRenameResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/TeamRenameResponse.java @@ -1,7 +1,9 @@ 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( diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/YakadexAllInfosResponse.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/YakadexAllInfosResponse.java index 0302209..5409a5e 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/YakadexAllInfosResponse.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/api/response/YakadexAllInfosResponse.java @@ -2,9 +2,11 @@ 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 { - YakadexEntry[] entries; + public YakadexEntry[] entries; } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/GameResource.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/GameResource.java index dd8218c..e6d167e 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/GameResource.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/GameResource.java @@ -1,15 +1,22 @@ 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.presentation.api.response.StartGameResponse; +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") @@ -21,6 +28,9 @@ public class GameResource { GameResource.class.getName() ); + @Inject + private GameService gameService; + @POST @Path("/") public Response start(StartGameRequest request) { @@ -48,24 +58,87 @@ public class GameResource { ); try { - GameService gameService = new GameService(); - GameEntity startedGame = gameService.startGame( - request.mapPath, - request.playerName - ); - LOGGER.info( - "Game started at: " + - (startedGame != null ? startedGame.startTime : "unknown") - ); + gameService.startGame(request.mapPath, request.playerName); + LOGGER.info("Game started successfully"); - // StartGameResponse response = new StartGameResponse(); - // return Response.ok(response).build(); - return Response.ok().build(); + TileEntity[][] map = GameEntity.INSTANCE.map; + Map[][] 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 tileData = new HashMap<>(); + tileData.put("terrainType", getTerrainType(tile.terrain)); + + Map 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 response = new HashMap<>(); + response.put("tiles", tiles); + return Response.ok(response).build(); } catch (Exception e) { - return Response.status( - 400, - "Invalid path or invalid name provided." - ).build(); + 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; + } } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/HelloWorldResource.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/HelloWorldResource.java deleted file mode 100644 index fb62d4b..0000000 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/HelloWorldResource.java +++ /dev/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 + "!"; - } -} diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/InventoryResource.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/InventoryResource.java index 757b215..c8af0e9 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/InventoryResource.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/InventoryResource.java @@ -1,20 +1,29 @@ 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 { - private final GameService gameService = new GameService(); + @Inject + private GameService gameService; + + @Inject + private InventoryService inventoryService; @GET public Response getInventory() { @@ -23,9 +32,30 @@ public class InventoryResource { .entity("Game not started") .build(); } - // TODO service - // GetInventoryResponse response = inventoryService.getInventory(); - // return Response.ok(response).build(); - return Response.status(Response.Status.NOT_IMPLEMENTED).build(); + + try { + List items = inventoryService.getInventory(); + List 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(); + } } } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/PlayerResource.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/PlayerResource.java index 2ac486c..174f90e 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/PlayerResource.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/PlayerResource.java @@ -1,17 +1,17 @@ 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.GetInventoryResponse; import fr.epita.assistants.yakamon.presentation.api.response.PlayerCatchResponse; -import fr.epita.assistants.yakamon.presentation.api.response.PlayerCollectResponse; 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) @@ -34,12 +34,12 @@ public class PlayerResource { } try { - var yakamon = playerService.catchYakamon(); + YakamonEntity yakamon = playerService.catchYakamon(); var response = new PlayerCatchResponse( - yakamon.id.toString(), + yakamon.uuid.toString(), yakamon.nickname, - yakamon.yakadex_entry_id.id, - yakamon.energy_points + yakamon.yakadexId, + yakamon.energyPoints ); return Response.ok(response).build(); } catch (jakarta.ws.rs.WebApplicationException e) { @@ -59,8 +59,17 @@ public class PlayerResource { .entity("Game not started") .build(); } - // TODO service - return Response.status(Response.Status.NOT_IMPLEMENTED).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 @@ -103,9 +112,34 @@ public class PlayerResource { .build(); } - // TODO service - // PlayerInfosResponse response = playerService.getInfos(...); - // return Response.ok(response).build(); - return Response.status(Response.Status.NOT_IMPLEMENTED).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(); + } } } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/TeamResource.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/TeamResource.java index 9f429b5..c52b5f9 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/TeamResource.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/TeamResource.java @@ -1,22 +1,32 @@ 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 { - private final GameService gameService = new GameService(); + @Inject + private GameService gameService; + + @Inject + private TeamService teamService; @GET public Response getTeam() { @@ -25,10 +35,21 @@ public class TeamResource { .entity("Game not started") .build(); } - // TODO service - // TeamInfosResponse response = new TeamInfosResponse(); - // return Response.ok(response).build(); - return Response.ok().build(); + + try { + List 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 @@ -45,10 +66,26 @@ public class TeamResource { .build(); } - // TODO service - // TeamEvolveResponse response = new TeamEvolveResponse(); - // return Response.ok(response).build(); - return Response.ok().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 @@ -75,10 +112,26 @@ public class TeamResource { .build(); } - // TODO service - // TeamFeedResponse response = new TeamFeedResponse(); - // return Response.ok(response).build(); - return Response.ok().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 @@ -95,9 +148,19 @@ public class TeamResource { .build(); } - // TODO service - // return 204 (No Content) to match the subject - return Response.noContent().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 @@ -116,15 +179,38 @@ public class TeamResource { .entity("Missing or invalid uuid") .build(); } - if (request == null) { + if ( + request == null || + request.newNickname == null || + request.newNickname.isBlank() + ) { return Response.status(Response.Status.BAD_REQUEST) - .entity("Missing request body") + .entity("Missing or invalid name") .build(); } - // TODO service - // TeamRenameResponse response = new TeamRenameResponse(); - // return Response.ok(response).build(); - return Response.ok().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(); + } } } diff --git a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/YakadexResource.java b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/YakadexResource.java index 54c7102..dd3f0bc 100644 --- a/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/YakadexResource.java +++ b/yakamon/src/main/java/fr/epita/assistants/yakamon/presentation/rest/YakadexResource.java @@ -1,13 +1,16 @@ 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 fr.epita.assistants.yakamon.presentation.api.response.YakadexInfosResponse; 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) @@ -30,9 +33,15 @@ public class YakadexResource { .build(); } - YakadexAllInfosResponse response = yakadexService.getAllEntries( + List entries = yakadexService.getAllEntries( onlyMissing ); + List dtos = EntityToDtoConverter.toYakadexEntries( + entries + ); + YakadexAllInfosResponse response = new YakadexAllInfosResponse( + dtos.toArray(new YakadexEntry[0]) + ); return Response.ok(response).build(); } @@ -45,12 +54,13 @@ public class YakadexResource { .build(); } - YakadexInfosResponse response = yakadexService.getEntryById(id); + YakadexEntryEntity entry = yakadexService.getEntryById(id); - if (response == null) { + if (entry == null) { return Response.status(Response.Status.NOT_FOUND).build(); } - return Response.ok(response).build(); + YakadexEntry dto = EntityToDtoConverter.toYakadexEntry(entry); + return Response.ok(dto).build(); } }