Compare commits
3 commits
friday_04-
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| c58c8725e8 | |||
|
|
b3bdec1049 | ||
|
|
e1301f007b |
19 changed files with 133 additions and 24 deletions
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.
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -145,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()
|
||||
);
|
||||
|
|
@ -170,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();
|
||||
|
|
@ -342,11 +342,11 @@ public class PlayerService {
|
|||
.firstResult();
|
||||
if (item == null) {
|
||||
item = new ItemModel();
|
||||
item.type = itemType;
|
||||
item.quantity = 1;
|
||||
item.setType(itemType);
|
||||
item.setQuantity(1);
|
||||
itemRepository.persist(item);
|
||||
} else {
|
||||
item.quantity += 1;
|
||||
item.setQuantity(item.getQuantity() + 1);
|
||||
itemRepository.persist(item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package fr.epita.assistants.yakamon.presentation.api;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class YakamonAction {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package fr.epita.assistants.yakamon.presentation.api.request;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class StartGameRequest {
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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> items;
|
||||
public List<Items> items;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ public class InventoryResource {
|
|||
for (ItemModel item : items) {
|
||||
GetInventoryResponse.Items responseItem = temp.new Items();
|
||||
GetInventoryResponse.ItemType itemType = temp.new ItemType();
|
||||
itemType.type = item.type.name();
|
||||
itemType.value = item.type.name();
|
||||
itemType.type = item.getType().name();
|
||||
itemType.value = item.getType().name();
|
||||
responseItem.itemType = itemType;
|
||||
responseItem.quantity = item.quantity;
|
||||
responseItem.quantity = item.getQuantity();
|
||||
responseItems.add(responseItem);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,12 +123,12 @@ public class PlayerResource {
|
|||
player.lastMove != null
|
||||
? player.lastMove.format(formatter)
|
||||
: null,
|
||||
player.lastCatch != null
|
||||
? player.lastCatch.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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue