Compare commits

..

No commits in common. "master" and "friday_04-03_reload-yakamon-2" have entirely different histories.

19 changed files with 24 additions and 133 deletions

View file

@ -1,31 +0,0 @@
# 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.

View file

@ -9,34 +9,10 @@ public class ItemModel {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; protected Integer id;
@Enumerated @Enumerated
private ItemType type; public ItemType type;
private Integer quantity; public 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;
}
} }

View file

@ -59,8 +59,8 @@ public class GameService {
// Initialize player inventory // Initialize player inventory
ItemModel yakaballs = new ItemModel(); ItemModel yakaballs = new ItemModel();
yakaballs.setType(ItemType.YAKABALL); yakaballs.type = ItemType.YAKABALL;
yakaballs.setQuantity(5); yakaballs.quantity = 5;
// Store // Store
playerRepository.persist(player); playerRepository.persist(player);

View file

@ -145,7 +145,7 @@ public class PlayerService {
ItemModel yakaballItem = itemRepository ItemModel yakaballItem = itemRepository
.find("type", ItemType.YAKABALL) .find("type", ItemType.YAKABALL)
.firstResult(); .firstResult();
if (yakaballItem == null || yakaballItem.getQuantity() < 1) { if (yakaballItem == null || yakaballItem.quantity < 1) {
throw new WebApplicationException( throw new WebApplicationException(
Response.status(400).entity("Not enough Yakaballs").build() Response.status(400).entity("Not enough Yakaballs").build()
); );
@ -170,7 +170,7 @@ public class PlayerService {
ErrorCode.BAD_REQUEST.throwException("Yakamon species not found"); ErrorCode.BAD_REQUEST.throwException("Yakamon species not found");
} }
yakaballItem.setQuantity(yakaballItem.getQuantity() - 1); yakaballItem.quantity -= 1;
itemRepository.persist(yakaballItem); itemRepository.persist(yakaballItem);
YakamonModel newYakamon = new YakamonModel(); YakamonModel newYakamon = new YakamonModel();
@ -342,11 +342,11 @@ public class PlayerService {
.firstResult(); .firstResult();
if (item == null) { if (item == null) {
item = new ItemModel(); item = new ItemModel();
item.setType(itemType); item.type = itemType;
item.setQuantity(1); item.quantity = 1;
itemRepository.persist(item); itemRepository.persist(item);
} else { } else {
item.setQuantity(item.getQuantity() + 1); item.quantity += 1;
itemRepository.persist(item); itemRepository.persist(item);
} }
} }

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api; package fr.epita.assistants.yakamon.presentation.api;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class YakamonAction { public class YakamonAction {

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api.request; package fr.epita.assistants.yakamon.presentation.api.request;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class StartGameRequest { public class StartGameRequest {

View file

@ -1,10 +1,8 @@
package fr.epita.assistants.yakamon.presentation.api.request; package fr.epita.assistants.yakamon.presentation.api.request;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class TeamFeedRequest { public class TeamFeedRequest {
public Integer quantity; public Integer quantity;

View file

@ -1,10 +1,8 @@
package fr.epita.assistants.yakamon.presentation.api.request; package fr.epita.assistants.yakamon.presentation.api.request;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class TeamRenameRequest { public class TeamRenameRequest {
public String newNickname; public String newNickname;

View file

@ -2,37 +2,21 @@ package fr.epita.assistants.yakamon.presentation.api.response;
import java.util.List; import java.util.List;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class GetInventoryResponse { public class GetInventoryResponse {
public class ItemType { public class ItemType {
public String type; public String type;
public String value; public String value;
public ItemType() {}
public ItemType(String type, String value) {
this.type = type;
this.value = value;
}
} }
public class Items { public class Items {
public ItemType itemType; public ItemType itemType;
public Integer quantity; public Integer quantity;
public Items() {}
public Items(ItemType itemType, Integer quantity) {
this.itemType = itemType;
this.quantity = quantity;
}
} }
public List<Items> items; List<Items> items;
} }

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api.response; package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.presentation.api.YakamonAction; import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class PlayerCatchResponse extends YakamonAction { public class PlayerCatchResponse extends YakamonAction {
public PlayerCatchResponse( public PlayerCatchResponse(

View file

@ -3,36 +3,20 @@ package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.utils.tile.ItemType; import fr.epita.assistants.yakamon.utils.tile.ItemType;
import fr.epita.assistants.yakamon.utils.tile.TerrainType; import fr.epita.assistants.yakamon.utils.tile.TerrainType;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class PlayerCollectResponse { public class PlayerCollectResponse {
public class TileType { public class TileType {
public class Collectible { public class Collectible {
public ItemType type; ItemType type;
public String value; String value;
public Collectible() {}
public Collectible(ItemType type, String value) {
this.type = type;
this.value = value;
}
} }
public TerrainType terrainType; TerrainType terrainType;
public Collectible collectible; Collectible collectible;
public TileType() {}
public TileType(TerrainType terrainType, Collectible collectible) {
this.terrainType = terrainType;
this.collectible = collectible;
}
} }
public TileType tileType; public TileType tileType;

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api.response; package fr.epita.assistants.yakamon.presentation.api.response;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class PlayerInfosResponse { public class PlayerInfosResponse {
@ -12,7 +10,7 @@ public class PlayerInfosResponse {
public Integer posX; public Integer posX;
public Integer posY; public Integer posY;
public String lastMove; public String lastMove;
public String lastCollect;
public String lastCatch; public String lastCatch;
public String lastCollect;
public String lastFeed; public String lastFeed;
} }

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api.response; package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.presentation.api.YakamonAction; import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class TeamEvolveResponse extends YakamonAction { public class TeamEvolveResponse extends YakamonAction {
public TeamEvolveResponse( public TeamEvolveResponse(

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api.response; package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.presentation.api.YakamonAction; import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class TeamFeedResponse extends YakamonAction { public class TeamFeedResponse extends YakamonAction {
public TeamFeedResponse( public TeamFeedResponse(

View file

@ -2,11 +2,9 @@ package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.presentation.api.YakamonAction; import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class TeamInfosResponse { public class TeamInfosResponse {
public YakamonAction[] yakamons; YakamonAction[] yakamons;
} }

View file

@ -1,9 +1,7 @@
package fr.epita.assistants.yakamon.presentation.api.response; package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.presentation.api.YakamonAction; import fr.epita.assistants.yakamon.presentation.api.YakamonAction;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class TeamRenameResponse extends YakamonAction { public class TeamRenameResponse extends YakamonAction {
public TeamRenameResponse( public TeamRenameResponse(

View file

@ -2,11 +2,9 @@ package fr.epita.assistants.yakamon.presentation.api.response;
import fr.epita.assistants.yakamon.presentation.api.YakadexEntry; import fr.epita.assistants.yakamon.presentation.api.YakadexEntry;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor
public class YakadexAllInfosResponse { public class YakadexAllInfosResponse {
public YakadexEntry[] entries; YakadexEntry[] entries;
} }

View file

@ -41,10 +41,10 @@ public class InventoryResource {
for (ItemModel item : items) { for (ItemModel item : items) {
GetInventoryResponse.Items responseItem = temp.new Items(); GetInventoryResponse.Items responseItem = temp.new Items();
GetInventoryResponse.ItemType itemType = temp.new ItemType(); GetInventoryResponse.ItemType itemType = temp.new ItemType();
itemType.type = item.getType().name(); itemType.type = item.type.name();
itemType.value = item.getType().name(); itemType.value = item.type.name();
responseItem.itemType = itemType; responseItem.itemType = itemType;
responseItem.quantity = item.getQuantity(); responseItem.quantity = item.quantity;
responseItems.add(responseItem); responseItems.add(responseItem);
} }

View file

@ -123,12 +123,12 @@ public class PlayerResource {
player.lastMove != null player.lastMove != null
? player.lastMove.format(formatter) ? player.lastMove.format(formatter)
: null, : null,
player.lastCollect != null
? player.lastCollect.format(formatter)
: null,
player.lastCatch != null player.lastCatch != null
? player.lastCatch.format(formatter) ? player.lastCatch.format(formatter)
: null, : null,
player.lastCollect != null
? player.lastCollect.format(formatter)
: null,
player.lastFeed != null player.lastFeed != null
? player.lastFeed.format(formatter) ? player.lastFeed.format(formatter)
: null : null