summaryrefslogtreecommitdiff
path: root/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer
diff options
context:
space:
mode:
Diffstat (limited to 'jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer')
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/converter/ItemProducerConverter.java126
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/GameModel.java19
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/ItemModel.java28
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/PlayerModel.java37
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/GameRepository.java59
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/ItemRepository.java50
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/PlayerRepository.java62
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/GameEntity.java4
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemEntity.java13
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemsEntity.java13
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/MoveEntity.java11
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/PlayerEntity.java18
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/StartEntity.java11
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/UpgradeCostEntity.java12
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ErwenService.java4
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ItemProducerService.java199
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/HelloWorldResource.java19
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/ItemProducerResource.java154
-rw-r--r--jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/subscriber/AggregateSubscriber.java47
19 files changed, 886 insertions, 0 deletions
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/converter/ItemProducerConverter.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/converter/ItemProducerConverter.java
new file mode 100644
index 0000000..cb81247
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/converter/ItemProducerConverter.java
@@ -0,0 +1,126 @@
+package fr.epita.assistants.item_producer.converter;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import fr.epita.assistants.common.aggregate.ResetInventoryAggregate;
+import fr.epita.assistants.common.api.request.StartRequest;
+import fr.epita.assistants.common.api.response.*;
+import fr.epita.assistants.item_producer.data.model.PlayerModel;
+import fr.epita.assistants.item_producer.domain.entity.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ItemProducerConverter {
+ public static StartEntity Start(StartRequest r) {
+ if (r.getMapPath() == null || r.getMapPath().isEmpty())
+ return null;
+ return new StartEntity(r.getMapPath(), null);
+ }
+
+ public static Map<ItemAggregate.ResourceType, Float> DeleteItems(ResetInventoryAggregate items) {
+ Map<ItemAggregate.ResourceType, Float> map = new HashMap<>();
+ for (ItemAggregate i : items.getItems()) {
+ map.merge(i.getType(), i.getQuantity(), Float::sum);
+ }
+ return map;
+ }
+
+ public static MoveEntity Move(PlayerModel playerMove) {
+ return new MoveEntity(playerMove.getPosX(), playerMove.getPosY());
+ }
+
+ public static List<List<String>> RLEtoMap(String rle) {
+ List<String> lines = List.of(rle.split(";"));
+ List<List<String>> map = new ArrayList<>();
+ for (int k = 0; k < lines.size(); k++) {
+ map.add(new ArrayList<>());
+ for (int i = 0; i < lines.get(k).length(); i++) {
+ for (int j = 0; j < lines.get(k).charAt(i) - '0'; j++) {
+ String type = ItemAggregate.ResourceType.getResource(lines.get(k).charAt(i + 1)).toString();
+ map.get(k).add(type);
+ }
+ i++;
+ }
+ }
+ return map;
+ }
+
+ public static String MapToRLE(List<List<String>> map) {
+ List<String> rows = new ArrayList<>();
+ for (List<String> resourceRow : map) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < resourceRow.size(); i++) {
+ int j;
+ // count sequence of this resource type
+ String s = resourceRow.get(i);
+ for (j = i; j < resourceRow.size() && s.equals(resourceRow.get(j)); j++) {
+ continue;
+ }
+ int tmp = j;
+ j -= i;
+ i = tmp - 1;
+ while (j > 9) {
+ sb.append('9');
+ sb.append(ItemAggregate.ResourceType.valueOf(s).getItemInfo().getValue());
+ j -= 9;
+ }
+ if (j > 0) {
+ sb.append(j);
+ sb.append(ItemAggregate.ResourceType.valueOf(s).getItemInfo().getValue());
+ }
+ }
+ rows.add(sb.toString());
+ }
+ return String.join(";", rows);
+ }
+
+ public static StartEntity Collect(String resource) {
+ List<List<String>> map = new ArrayList<>();
+ map.add(new ArrayList<>());
+ map.getFirst().add(resource);
+ return new StartEntity(null, MapToRLE(map));
+ }
+
+ public static PlayerEntity ResponseToEntity(PlayerResponse r) {
+ return new PlayerEntity(r.getPosX(), r.getPosY(), r.getLastMove(), r.getLastCollect(),
+ r.getMoveSpeedMultiplier(), r.getStaminaMultiplier(), r.getCollectRateMultiplier());
+ }
+
+ public static StartEntity ResponseToEntity(StartResponse r) {
+ return new StartEntity(null, MapToRLE(r.getMap()));
+ }
+
+ public static StartResponse EntityToResponse(StartEntity e) {
+ if (e == null)
+ return null;
+ return new StartResponse(RLEtoMap(e.getRle()));
+ }
+ public static ItemResponse EntityToResponse(ItemEntity e) {
+ return new ItemResponse(e.getId(), e.getQuantity(), e.getType());
+ }
+
+ public static ItemsResponse EntityToResponse(ItemsEntity e) {
+ if (e == null)
+ return null;
+ return new ItemsResponse(e.getItems().stream().map(ItemProducerConverter::EntityToResponse).toList());
+ }
+
+ public static PlayerResponse EntityToResponse(PlayerEntity e) {
+ if (e == null)
+ return null;
+ return new PlayerResponse(e.getPosX(), e.getPosY(), e.getLastMove(), e.getLastCollect(),
+ e.getMoveSpeedMultiplier(), e.getStaminaMultiplier(), e.getCollectRateMultiplier());
+ }
+
+ public static MoveResponse EntityToResponse(MoveEntity e) {
+ if (e == null)
+ return null;
+ return new MoveResponse(e.getPosX(), e.getPosY());
+ }
+
+ public static UpgradeCostResponse EntityToResponse(UpgradeCostEntity e) {
+ return null;
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/GameModel.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/GameModel.java
new file mode 100644
index 0000000..7cca88c
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/GameModel.java
@@ -0,0 +1,19 @@
+package fr.epita.assistants.item_producer.data.model;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Setter
+@Table(name = "game")
+public class GameModel {
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ Long id;
+ String map;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/ItemModel.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/ItemModel.java
new file mode 100644
index 0000000..68d765a
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/ItemModel.java
@@ -0,0 +1,28 @@
+package fr.epita.assistants.item_producer.data.model;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Setter
+@Table(name = "item")
+public class ItemModel {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ Long id;
+ @Enumerated(value = EnumType.STRING)
+ ItemAggregate.ResourceType type;
+ Float quantity;
+
+ public ItemModel(float quantity, ItemAggregate.ResourceType type) {
+ this.quantity = quantity;
+ this.type = type;
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/PlayerModel.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/PlayerModel.java
new file mode 100644
index 0000000..943b5a3
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/model/PlayerModel.java
@@ -0,0 +1,37 @@
+package fr.epita.assistants.item_producer.data.model;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+@Table(name = "player")
+public class PlayerModel {
+ Float collectRateMultiplier;
+ Float moveSpeedMultiplier;
+ Integer posX;
+ Integer posY;
+ Float staminaMultiplier;
+ LocalDateTime lastCollect;
+ LocalDateTime lastMove;
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ Long id;
+
+ public PlayerModel(float collectRateMultiplier, float moveSpeedMultiplier, int posX, int posY, float staminaMultiplier, LocalDateTime lastCollect, LocalDateTime lastMove) {
+ this.collectRateMultiplier = collectRateMultiplier;
+ this.moveSpeedMultiplier = moveSpeedMultiplier;
+ this.posX = posX;
+ this.posY = posY;
+ this.staminaMultiplier = staminaMultiplier;
+ this.lastCollect = lastCollect;
+ this.lastMove = lastMove;
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/GameRepository.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/GameRepository.java
new file mode 100644
index 0000000..e48f844
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/GameRepository.java
@@ -0,0 +1,59 @@
+package fr.epita.assistants.item_producer.data.repository;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import fr.epita.assistants.item_producer.converter.ItemProducerConverter;
+import fr.epita.assistants.item_producer.data.model.GameModel;
+import io.quarkus.hibernate.orm.panache.PanacheRepository;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.transaction.Transactional;
+
+import java.util.List;
+
+@ApplicationScoped
+public class GameRepository implements PanacheRepository<GameModel> {
+ @Transactional
+ public String getMap() {
+ return getGame().getMap();
+ }
+
+ private GameModel getGame() {
+ return findAll().firstResult();
+ }
+
+ @Transactional
+ public boolean isEmpty() {
+ return count() == 0;
+ }
+
+ @Transactional
+ public void clearDB() {
+ deleteAll();
+ }
+
+ @Transactional
+ public void addEntry(String rle) {
+ GameModel game = new GameModel();
+ game.setMap(rle);
+ persist(game);
+ }
+
+ @Transactional
+ public boolean isValidCollect(int x, int y) {
+ List<List<String>> map = ItemProducerConverter.RLEtoMap(getMap());
+ return ItemAggregate.ResourceType.valueOf(map.get(y).get(x)).getItemInfo().isCollectable();
+ }
+
+ @Transactional
+ public void setToGround(int x, int y) {
+ List<List<String>> map = ItemProducerConverter.RLEtoMap(getMap());
+ map.get(y).set(x, ItemAggregate.ResourceType.GROUND.toString());
+ String rle = ItemProducerConverter.MapToRLE(map);
+ update("map = ?1 where id = ?2", rle, getGame().getId());
+ }
+
+ @Transactional
+ public String collectResource(int posX, int posY) {
+ List<List<String>> map = ItemProducerConverter.RLEtoMap(getMap());
+ return map.get(posY).get(posX);
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/ItemRepository.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/ItemRepository.java
new file mode 100644
index 0000000..b46311f
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/ItemRepository.java
@@ -0,0 +1,50 @@
+package fr.epita.assistants.item_producer.data.repository;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import fr.epita.assistants.item_producer.data.model.ItemModel;
+import io.quarkus.hibernate.orm.panache.PanacheRepository;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.transaction.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@ApplicationScoped
+public class ItemRepository implements PanacheRepository<ItemModel> {
+ @Transactional
+ public void deleteItems(Map<ItemAggregate.ResourceType, Float> toDelete) {
+ for (ItemAggregate.ResourceType type : toDelete.keySet()) {
+ ItemModel item = find("type = ?1", type).firstResult();
+ if (item != null)
+ update("quantity = ?1 where type = ?2", item.getQuantity() - toDelete.get(type), type);
+ }
+ }
+
+ @Transactional
+ public List<ItemModel> getItems() {
+ return find("where quantity > 0").stream().toList();
+ }
+
+ @Transactional
+ public Optional<ItemModel> exists(ItemAggregate.ResourceType type) {
+ return find("type = ?1", type).firstResultOptional();
+ }
+
+ @Transactional
+ public void addItem(ItemAggregate.ResourceType type, Float amount) {
+ ItemModel res = new ItemModel(amount, type);
+ persist(res);
+ }
+
+ // amount should already be the updated amount
+ @Transactional
+ public void fillInventory(ItemAggregate.ResourceType type, Float amount) {
+ update("quantity = ?1 where type = ?2", amount, type);
+ }
+
+ @Transactional
+ public List<ItemModel> getMoney() {
+ return find("where type = ?1", ItemAggregate.ResourceType.MONEY).stream().toList();
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/PlayerRepository.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/PlayerRepository.java
new file mode 100644
index 0000000..b5bcde7
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/data/repository/PlayerRepository.java
@@ -0,0 +1,62 @@
+package fr.epita.assistants.item_producer.data.repository;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import fr.epita.assistants.common.utils.Direction;
+import fr.epita.assistants.item_producer.converter.ItemProducerConverter;
+import fr.epita.assistants.item_producer.data.model.PlayerModel;
+import io.quarkus.hibernate.orm.panache.PanacheRepository;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.transaction.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@ApplicationScoped
+public class PlayerRepository implements PanacheRepository<PlayerModel> {
+ @Transactional
+ public void clearDB() {
+ deleteAll();
+ }
+
+ @Transactional
+ public void addEntry() {
+ PlayerModel player = new PlayerModel(1, 1, 0, 0, 1, null, null);
+ persist(player);
+ }
+
+ @Transactional
+ public PlayerModel getFirstPlayer() {
+ return findAll().firstResult();
+ }
+
+ @Transactional
+ public boolean isValidMove(Direction direction, String rle) {
+ PlayerModel playerModel = getFirstPlayer();
+ int x = playerModel.getPosX() + direction.getPoint().getPosX();
+ int y = playerModel.getPosY() + direction.getPoint().getPosY();
+ List<List<String>> map = ItemProducerConverter.RLEtoMap(rle);
+ return y >= 0 && x >= 0 && x < map.getFirst().size() && y < map.getFirst().size() && ItemAggregate.ResourceType.valueOf(map.get(y).get(x)).getItemInfo().isWalkable();
+ }
+
+ @Transactional
+ public void movePlayer(Direction direction) {
+ PlayerModel player = getFirstPlayer();
+ update("posX = ?1, posY = ?2, lastMove = ?3 where id = ?4", player.getPosX() + direction.getPoint().getPosX()
+ , player.getPosY() + direction.getPoint().getPosY(), LocalDateTime.now(), player.getId());
+ }
+
+ public void updateMoveSpeed(Float newSpeed) {
+ PlayerModel player = getFirstPlayer();
+ update("moveSpeedMultiplier = ?1 where id = ?2", newSpeed, player.getId());
+ }
+
+ public void updateCollectRate(Float newRate) {
+ PlayerModel player = getFirstPlayer();
+ update("collectRateMultiplier = ?1 where id = ?2", newRate, player.getId());
+ }
+
+ public void updateStamina(Float newStamina) {
+ PlayerModel player = getFirstPlayer();
+ update("staminaMultiplier = ?1 where id = ?2", newStamina, player.getId());
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/GameEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/GameEntity.java
new file mode 100644
index 0000000..e248cb5
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/GameEntity.java
@@ -0,0 +1,4 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+public class GameEntity {
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemEntity.java
new file mode 100644
index 0000000..a8b666d
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemEntity.java
@@ -0,0 +1,13 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class ItemEntity {
+ long id;
+ float quantity;
+ ItemAggregate.ResourceType type;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemsEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemsEntity.java
new file mode 100644
index 0000000..b03b373
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/ItemsEntity.java
@@ -0,0 +1,13 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+import fr.epita.assistants.common.api.response.ItemResponse;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.List;
+
+@Getter
+@AllArgsConstructor
+public class ItemsEntity {
+ List<ItemEntity> items;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/MoveEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/MoveEntity.java
new file mode 100644
index 0000000..72ea511
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/MoveEntity.java
@@ -0,0 +1,11 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class MoveEntity {
+ int posX;
+ int posY;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/PlayerEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/PlayerEntity.java
new file mode 100644
index 0000000..0913c3f
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/PlayerEntity.java
@@ -0,0 +1,18 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.time.LocalDateTime;
+
+@AllArgsConstructor
+@Getter
+public class PlayerEntity {
+ int posX;
+ int posY;
+ LocalDateTime lastMove;
+ LocalDateTime lastCollect;
+ float moveSpeedMultiplier;
+ float staminaMultiplier;
+ float collectRateMultiplier;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/StartEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/StartEntity.java
new file mode 100644
index 0000000..44a4961
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/StartEntity.java
@@ -0,0 +1,11 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class StartEntity {
+ String mapPath;
+ String rle;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/UpgradeCostEntity.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/UpgradeCostEntity.java
new file mode 100644
index 0000000..fac79e0
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/entity/UpgradeCostEntity.java
@@ -0,0 +1,12 @@
+package fr.epita.assistants.item_producer.domain.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class UpgradeCostEntity {
+ float upgradeCollectCost;
+ float upgradeMoveCost;
+ float upgradeStaminaCost;
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ErwenService.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ErwenService.java
new file mode 100644
index 0000000..fb3a507
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ErwenService.java
@@ -0,0 +1,4 @@
+package fr.epita.assistants.item_producer.domain.service;
+
+public class ErwenService {
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ItemProducerService.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ItemProducerService.java
new file mode 100644
index 0000000..2a224c7
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/domain/service/ItemProducerService.java
@@ -0,0 +1,199 @@
+package fr.epita.assistants.item_producer.domain.service;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import fr.epita.assistants.common.aggregate.ResetInventoryAggregate;
+import fr.epita.assistants.common.api.response.*;
+import fr.epita.assistants.common.command.*;
+import fr.epita.assistants.common.utils.Direction;
+import fr.epita.assistants.item_producer.converter.ItemProducerConverter;
+import fr.epita.assistants.item_producer.data.model.ItemModel;
+import fr.epita.assistants.item_producer.data.model.PlayerModel;
+import fr.epita.assistants.item_producer.data.repository.GameRepository;
+import fr.epita.assistants.item_producer.data.repository.ItemRepository;
+import fr.epita.assistants.item_producer.data.repository.PlayerRepository;
+import fr.epita.assistants.item_producer.domain.entity.*;
+import io.smallrye.reactive.messaging.annotations.Broadcast;
+import jakarta.enterprise.context.ApplicationScoped;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import org.eclipse.microprofile.reactive.messaging.Channel;
+import org.eclipse.microprofile.reactive.messaging.Emitter;
+
+import jakarta.inject.Inject;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@ApplicationScoped
+public class ItemProducerService {
+ @ConfigProperty(name = "JWS_TICK_DURATION")
+ String tps;
+ @ConfigProperty(name = "JWS_DELAY_MOVEMENT")
+ String movementDelay;
+ @ConfigProperty(name = "JWS_DELAY_COLLECT")
+ String collectDelay;
+ @ConfigProperty(name = "JWS_UPGRADE_COLLECT_COST")
+ String upgradeCollectCost;
+ @ConfigProperty(name = "JWS_UPGRADE_MOVE_COST")
+ String upgradeMoveCost;
+ @ConfigProperty(name = "JWS_UPGRADE_STAMINA_COST")
+ String upgradeStaminaCost;
+ @ConfigProperty(name = "JWS_UPGRADE_MULTIPLIER")
+ String upgradeMultiplier;
+ @Inject
+ PlayerRepository playerRepository;
+ @Inject
+ GameRepository gameRepository;
+ @Inject
+ ItemRepository itemRepository;
+
+ @Inject
+ @Channel("reset-inventory-command")
+ @Broadcast
+ Emitter<ResetInventoryCommand> resetInventoryCommandEmitter;
+ @Inject
+ @Channel("collect-item-command")
+ @Broadcast
+ Emitter<CollectItemCommand> collectItemCommandEmitter;
+ @Inject
+ @Channel("upgrade-movement-speed-command")
+ @Broadcast
+ Emitter<UpgradeMovementSpeedCommand> upgradeMovementSpeedCommandEmitter;
+ @Inject
+ @Channel("upgrade-stamina-command")
+ @Broadcast
+ Emitter<UpgradeStaminaCommand> upgradeStaminaCommandEmitter;
+ @Inject
+ @Channel("upgrade-collect-rate-command")
+ @Broadcast
+ Emitter<UpgradeCollectRateCommand> upgradeCollectRateCommandEmitter;
+
+ public StartEntity startGame(StartEntity startEntity) {
+ if (startEntity == null)
+ return null;
+ gameRepository.clearDB();
+ playerRepository.clearDB();
+ try (Stream<String> stream = Files.lines(Paths.get(startEntity.getMapPath()))) {
+ if (new File(startEntity.getMapPath()).isDirectory())
+ return null;
+ String rle = stream.collect(Collectors.joining(";"));
+ gameRepository.addEntry(rle);
+ playerRepository.addEntry();
+ resetInventoryCommandEmitter.send(new ResetInventoryCommand());
+ return new StartEntity(null, rle);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ public void clearItems(ResetInventoryAggregate items) {
+ itemRepository.deleteItems(ItemProducerConverter.DeleteItems(items));
+ }
+
+ public ItemsEntity getAllItems() {
+ return new ItemsEntity(itemRepository.getItems().stream().map(m -> new ItemEntity(m.getId(),
+ m.getQuantity(), m.getType())).toList());
+ }
+
+ public boolean isGameRunning() {
+ return !gameRepository.isEmpty();
+ }
+
+ public boolean canMove() {
+ long tickRate = Long.parseLong(tps);
+ long moveDelay = Long.parseLong(movementDelay);
+ PlayerEntity player = getCurrentPlayer();
+ return player.getLastMove() == null || player.getLastMove().plus((long) (moveDelay * tickRate * player.getMoveSpeedMultiplier()),
+ ChronoUnit.MILLIS).isBefore(LocalDateTime.now());
+ }
+
+ public boolean canCollect() {
+ long tickRate = Long.parseLong(tps);
+ long collectDelayLong = Long.parseLong(collectDelay);
+ PlayerEntity player = getCurrentPlayer();
+ return player.getLastCollect() == null || player.getLastCollect().plus((long) (collectDelayLong * tickRate * player.getMoveSpeedMultiplier()),
+ ChronoUnit.MILLIS).isBefore(LocalDateTime.now());
+ }
+
+ public PlayerEntity getCurrentPlayer() {
+ PlayerModel p = playerRepository.getFirstPlayer();
+ return new PlayerEntity(p.getPosX(), p.getPosY(), p.getLastMove(), p.getLastCollect(),
+ p.getMoveSpeedMultiplier(), p.getStaminaMultiplier(), p.getCollectRateMultiplier());
+ }
+
+ public UpgradeCostEntity getUpgradeCosts() {
+ return new UpgradeCostEntity(Float.parseFloat(upgradeCollectCost),
+ Float.parseFloat(upgradeMoveCost), Float.parseFloat(upgradeStaminaCost));
+ }
+
+ public MoveEntity move(Direction direction) {
+ if (direction == null)
+ return null;
+ if (!playerRepository.isValidMove(direction, gameRepository.getMap()))
+ return null;
+ playerRepository.movePlayer(direction);
+ return ItemProducerConverter.Move(playerRepository.getFirstPlayer());
+ }
+
+ public StartEntity collect() {
+ PlayerEntity player = getCurrentPlayer();
+ if (!gameRepository.isValidCollect(player.getPosX(), player.getPosY()))
+ return null;
+ String item = gameRepository.collectResource(player.getPosX(), player.getPosY());
+ gameRepository.setToGround(player.getPosX(), player.getPosY());
+ collectItemCommandEmitter.send(new CollectItemCommand(ItemAggregate.ResourceType.valueOf(item),
+ player.getCollectRateMultiplier()));
+ return ItemProducerConverter.Collect(item);
+ }
+
+ public void collectItem(ItemAggregate agr) {
+ Optional<ItemModel> item = itemRepository.exists(agr.getType());
+ if (item.isPresent()) {
+ itemRepository.fillInventory(agr.getType(), agr.getQuantity());
+ } else {
+ itemRepository.addItem(agr.getType(), agr.getQuantity());
+ }
+ }
+
+ public Double getMoney() {
+ List<ItemModel> entries = itemRepository.getMoney();
+ if (entries.isEmpty())
+ return null;
+ return entries.stream().mapToDouble(m -> m.getQuantity().doubleValue()).sum();
+ }
+
+ public void upgradeMove() {
+ upgradeMovementSpeedCommandEmitter.send(new UpgradeMovementSpeedCommand(Float.parseFloat(upgradeMoveCost)));
+ }
+
+ public void updateMove() {
+ playerRepository.updateMoveSpeed(getCurrentPlayer().getMoveSpeedMultiplier() - Float.parseFloat(upgradeMultiplier));
+ }
+
+ public void upgradeCollect() {
+ upgradeCollectRateCommandEmitter.send(new UpgradeCollectRateCommand(Float.parseFloat(upgradeMoveCost)));
+ }
+
+ public void updateCollect() {
+ playerRepository.updateCollectRate(getCurrentPlayer().getCollectRateMultiplier() - Float.parseFloat(upgradeMultiplier));
+ }
+
+ public void upgradeStamina() {
+ upgradeStaminaCommandEmitter.send(new UpgradeStaminaCommand(Float.parseFloat(upgradeMoveCost)));
+ }
+
+ public void updateStamina() {
+ playerRepository.updateStamina(getCurrentPlayer().getStaminaMultiplier() - Float.parseFloat(upgradeMultiplier));
+ }
+
+ public void pay(Float newMoney) {
+ itemRepository.fillInventory(ItemAggregate.ResourceType.MONEY, newMoney);
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/HelloWorldResource.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/HelloWorldResource.java
new file mode 100644
index 0000000..9f9cb70
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/HelloWorldResource.java
@@ -0,0 +1,19 @@
+package fr.epita.assistants.item_producer.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/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/ItemProducerResource.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/ItemProducerResource.java
new file mode 100644
index 0000000..fcebee9
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/rest/ItemProducerResource.java
@@ -0,0 +1,154 @@
+package fr.epita.assistants.item_producer.presentation.rest;
+
+import fr.epita.assistants.common.api.request.MoveRequest;
+import fr.epita.assistants.common.api.request.StartRequest;
+import fr.epita.assistants.common.api.response.MoveResponse;
+import fr.epita.assistants.common.api.response.StartResponse;
+import fr.epita.assistants.common.utils.ErrorInfo;
+import fr.epita.assistants.item_producer.converter.ItemProducerConverter;
+import fr.epita.assistants.item_producer.domain.service.ItemProducerService;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+@Path("/")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+public class ItemProducerResource {
+ @Inject
+ ItemProducerService itemProducerService;
+
+ @Path("/")
+ @GET
+ public Response getInventory() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running"));
+ else
+ rb = Response.ok(ItemProducerConverter.EntityToResponse(itemProducerService.getAllItems()));
+ return rb.build();
+ }
+
+ @Path("player")
+ @GET
+ public Response getPlayer() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running"));
+ else
+ rb = Response.ok(ItemProducerConverter.EntityToResponse(itemProducerService.getCurrentPlayer()));
+ return rb.build();
+ }
+ @Path("start")
+ @POST
+ public Response start(StartRequest startRequest) {
+ StartResponse r = ItemProducerConverter.EntityToResponse(itemProducerService.startGame(ItemProducerConverter.Start(startRequest)));
+ Response.ResponseBuilder res;
+ if (r == null)
+ res = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Bad request for /start"));
+ else
+ res = Response.ok(r);
+ return res.build();
+ }
+ @Path("upgrades")
+ @GET
+ public Response getUpgrades() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running"));
+ else
+ rb = Response.ok(ItemProducerConverter.EntityToResponse(itemProducerService.getUpgradeCosts()));
+ return rb.build();
+ }
+
+ @Path("collect")
+ @POST
+ public Response collect() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running"));
+ else if (!itemProducerService.canCollect())
+ rb = Response.status(Response.Status.TOO_MANY_REQUESTS).entity(new ErrorInfo("Input too early, wait " +
+ "before trying to move again"));
+ else {
+ StartResponse rep = ItemProducerConverter.EntityToResponse(itemProducerService.collect());
+ if (rep == null)
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Can't collect on this tile"));
+ else
+ rb = Response.ok(rep);
+ }
+ return rb.build();
+ }
+
+ @Path("move")
+ @POST
+ public Response move(MoveRequest moveRequest) {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running"));
+ else if (!itemProducerService.canMove())
+ rb = Response.status(Response.Status.TOO_MANY_REQUESTS).entity(new ErrorInfo("Input too early, wait " +
+ "before trying to move again"));
+ else {
+ MoveResponse rep = ItemProducerConverter.EntityToResponse(itemProducerService.move(moveRequest.getDirection()));
+ if (rep == null)
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Tried to move out of bounds " +
+ "(or maybe you felt like you were Jesus)"));
+ else
+ rb = Response.ok(rep);
+ }
+ return rb.build();
+ }
+
+ @Path("upgrade/collect")
+ @PATCH
+ public Response upgradeCollect() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running."));
+ else if (itemProducerService.getMoney() == null)
+ rb = Response.status(Response.Status.NOT_FOUND).entity(new ErrorInfo("No money was found."));
+ else if (itemProducerService.getMoney() < itemProducerService.getUpgradeCosts().getUpgradeCollectCost())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("You are poor."));
+ else {
+ itemProducerService.upgradeCollect();
+ rb = Response.noContent();
+ }
+ return rb.build();
+ }
+
+ @Path("upgrade/move")
+ @PATCH
+ public Response upgradeMove() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running."));
+ else if (itemProducerService.getMoney() == null)
+ rb = Response.status(Response.Status.NOT_FOUND).entity(new ErrorInfo("No money was found."));
+ else if (itemProducerService.getMoney() < itemProducerService.getUpgradeCosts().getUpgradeMoveCost())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("You are poor."));
+ else {
+ itemProducerService.upgradeMove();
+ rb = Response.noContent();
+ }
+ return rb.build();
+ }
+
+ @Path("upgrade/stamina")
+ @PATCH
+ public Response upgradeStamina() {
+ Response.ResponseBuilder rb;
+ if (!itemProducerService.isGameRunning())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Game is not running."));
+ else if (itemProducerService.getMoney() == null)
+ rb = Response.status(Response.Status.NOT_FOUND).entity(new ErrorInfo("No money was found."));
+ else if (itemProducerService.getMoney() < itemProducerService.getUpgradeCosts().getUpgradeStaminaCost())
+ rb = Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("You are poor."));
+ else {
+ itemProducerService.upgradeStamina();
+ rb = Response.noContent();
+ }
+ return rb.build();
+ }
+}
diff --git a/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/subscriber/AggregateSubscriber.java b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/subscriber/AggregateSubscriber.java
new file mode 100644
index 0000000..c6f3231
--- /dev/null
+++ b/jws/epibazaar/item-producer/src/main/java/fr/epita/assistants/item_producer/presentation/subscriber/AggregateSubscriber.java
@@ -0,0 +1,47 @@
+package fr.epita.assistants.item_producer.presentation.subscriber;
+
+import fr.epita.assistants.common.aggregate.ItemAggregate;
+import fr.epita.assistants.common.aggregate.ResetInventoryAggregate;
+import fr.epita.assistants.common.aggregate.UpgradeItemProducerAggregate;
+import fr.epita.assistants.item_producer.domain.service.ItemProducerService;
+import io.smallrye.reactive.messaging.annotations.Broadcast;
+import jakarta.inject.Inject;
+import org.eclipse.microprofile.reactive.messaging.Incoming;
+
+public class AggregateSubscriber {
+ @Inject
+ ItemProducerService itemProducerService;
+
+ @Broadcast
+ @Incoming("reset-inventory-aggregate")
+ public void commandListener(ResetInventoryAggregate aggregate) {
+ itemProducerService.clearItems(aggregate);
+ }
+
+ @Broadcast
+ @Incoming("collect-item-aggregate")
+ public void commandListener(ItemAggregate agr) {
+ itemProducerService.collectItem(agr);
+ }
+
+ @Broadcast
+ @Incoming("upgrade-collect-rate-aggregate")
+ public void collectCommandListener(UpgradeItemProducerAggregate agr) {
+ itemProducerService.pay(agr.getNewMoney());
+ itemProducerService.updateCollect();
+ }
+
+ @Broadcast
+ @Incoming("upgrade-movement-speed-aggregate")
+ public void moveCommandListener(UpgradeItemProducerAggregate agr) {
+ itemProducerService.pay(agr.getNewMoney());
+ itemProducerService.updateMove();
+ }
+
+ @Broadcast
+ @Incoming("upgrade-stamina-aggregate")
+ public void staminaCommandListener(UpgradeItemProducerAggregate agr) {
+ itemProducerService.pay(agr.getNewMoney());
+ itemProducerService.updateStamina();
+ }
+}