diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /jws | |
Diffstat (limited to 'jws')
110 files changed, 4609 insertions, 0 deletions
diff --git a/jws/.gitignore b/jws/.gitignore new file mode 100644 index 0000000..163b215 --- /dev/null +++ b/jws/.gitignore @@ -0,0 +1,7 @@ +flake.lock +*.tar +.idea/ +target/ +*.iml +test/ +viewer/ diff --git a/jws/database/pom.xml b/jws/database/pom.xml new file mode 100644 index 0000000..4f79f2b --- /dev/null +++ b/jws/database/pom.xml @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>fr.epita.assistants</groupId> + <artifactId>database</artifactId> + <version>1.0</version> + + <properties> + <maven.compiler.release>21</maven.compiler.release> + <maven.compiler.source>21</maven.compiler.source> + <maven.compiler.target>21</maven.compiler.target> + + <compiler-plugin.version>3.13.0</compiler-plugin.version> + <maven.compiler.parameters>true</maven.compiler.parameters> + + <versions.maven-surefire-plugin>2.22.2</versions.maven-surefire-plugin> + <versions.maven-jar-plugin>3.4.1</versions.maven-jar-plugin> + <versions.maven-install-plugin>3.1.2</versions.maven-install-plugin> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id> + <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> + <quarkus.platform.version>3.16.1</quarkus.platform.version> + + + <skipITs>true</skipITs> + + <surefire.reportsDirectory>${project.build.directory}/surefire-reports</surefire.reportsDirectory> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>${quarkus.platform.group-id}</groupId> + <artifactId>${quarkus.platform.artifact-id}</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy-jackson</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-arc</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-quartz</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-smallrye-openapi</artifactId> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.30</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + </dependency> + <dependency> + <groupId>com.tngtech.archunit</groupId> + <artifactId>archunit-junit5</artifactId> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>io.github.classgraph</groupId> + <artifactId>classgraph</artifactId> + <version>4.8.179</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.smallrye.reactive</groupId> + <artifactId>smallrye-reactive-messaging-in-memory</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.awaitility</groupId> + <artifactId>awaitility</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.26.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-jdbc-postgresql</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-hibernate-orm-panache</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>${versions.maven-jar-plugin}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> + +</project> diff --git a/jws/database/src/main/java/fr/epita/assistants/data/model/CourseModel.java b/jws/database/src/main/java/fr/epita/assistants/data/model/CourseModel.java new file mode 100644 index 0000000..4be0261 --- /dev/null +++ b/jws/database/src/main/java/fr/epita/assistants/data/model/CourseModel.java @@ -0,0 +1,17 @@ +package fr.epita.assistants.data.model; + +import jakarta.persistence.*; + +import java.util.List; + +@Entity +@Table(name = "course_model") +public class CourseModel { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + public long id; + public String name; + @ElementCollection @CollectionTable(name = "course_model_tags", joinColumns = @JoinColumn(name = "course_id")) + public List<String> tag; + @OneToMany(mappedBy = "courseModel") + public List<StudentModel> students; +} diff --git a/jws/database/src/main/java/fr/epita/assistants/data/model/StudentModel.java b/jws/database/src/main/java/fr/epita/assistants/data/model/StudentModel.java new file mode 100644 index 0000000..9d82559 --- /dev/null +++ b/jws/database/src/main/java/fr/epita/assistants/data/model/StudentModel.java @@ -0,0 +1,15 @@ +package fr.epita.assistants.data.model; + +import jakarta.persistence.*; + +@Entity +@Table(name = "student_model") +public class StudentModel { + public String name; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + public long id; + + @ManyToOne + @JoinColumn(name = "course_id") + public CourseModel courseModel; +} diff --git a/jws/database/src/main/resources/application.properties b/jws/database/src/main/resources/application.properties new file mode 100644 index 0000000..8d1ceb2 --- /dev/null +++ b/jws/database/src/main/resources/application.properties @@ -0,0 +1,24 @@ +# DEV +%dev.quarkus.http.port=8082 +%dev.quarkus.hibernate-orm.database.default-schema=${epita.group.id} +%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:courses} +%dev.quarkus.flyway.create-schemas=true +%dev.quarkus.flyway.schemas=${epita.group.id} + +%dev.quarkus.swagger-ui.enable=true +quarkus.swagger-ui.always-include=true +quarkus.swagger-ui.theme=material + +# DB +quarkus.datasource.username=${DB_USERNAME:postgres} +quarkus.datasource.password=${DB_PASSWORD:postgres} +quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:courses} +quarkus.datasource.jdbc.transaction-isolation-level=read-uncommitted + +epita.group.id=courses +epita.random=0 + +quarkus.hibernate-orm.database.generation=${DATABASE_DB_GENERATION:update} + +quarkus.devservices.enabled=false +quarkus.http.cors=true diff --git a/jws/endpoints/pom.xml b/jws/endpoints/pom.xml new file mode 100644 index 0000000..fc67629 --- /dev/null +++ b/jws/endpoints/pom.xml @@ -0,0 +1,186 @@ +<?xml version="1.0"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + + <groupId>fr.epita.assistants</groupId> + <artifactId>endpoints</artifactId> + <version>1.0</version> + + <properties> + <maven.compiler.release>21</maven.compiler.release> + <maven.compiler.source>21</maven.compiler.source> + <maven.compiler.target>21</maven.compiler.target> + + <compiler-plugin.version>3.13.0</compiler-plugin.version> + <maven.compiler.parameters>true</maven.compiler.parameters> + + <versions.maven-surefire-plugin>3.0.0-M5</versions.maven-surefire-plugin> + <versions.maven-jar-plugin>3.4.1</versions.maven-jar-plugin> + <versions.maven-install-plugin>3.1.2</versions.maven-install-plugin> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id> + <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> + <quarkus.platform.version>3.17.5</quarkus.platform.version> + + <skipITs>true</skipITs> + + <surefire.reportsDirectory>${project.build.directory}/surefire-reports</surefire.reportsDirectory> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>${quarkus.platform.group-id}</groupId> + <artifactId>${quarkus.platform.artifact-id}</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest</artifactId> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.30</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.eclipse.microprofile.openapi</groupId> + <artifactId>microprofile-openapi-api</artifactId> + <version>4.0.2</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-jackson</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-smallrye-openapi</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.26.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit-platform</artifactId> + <version>${versions.maven-surefire-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-api</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>${versions.maven-jar-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <version>${versions.maven-install-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.7.0</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>${quarkus.platform.group-id}</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + <goal>native-image-agent</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>true</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner + </native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <skipITs>false</skipITs> + <quarkus.native.enabled>true</quarkus.native.enabled> + </properties> + </profile> + </profiles> + +</project> diff --git a/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/Endpoints.java b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/Endpoints.java new file mode 100644 index 0000000..cd4a49f --- /dev/null +++ b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/Endpoints.java @@ -0,0 +1,35 @@ +package fr.epita.assistants.presentation.rest; + +import fr.epita.assistants.presentation.rest.request.ReverseRequest; +import fr.epita.assistants.presentation.rest.response.HelloResponse; +import fr.epita.assistants.presentation.rest.response.ReverseResponse; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.Response; + +@Path("/") +public class Endpoints { + @GET + @Path("hello/{name}") + public Response hello(@PathParam("name") String name) { + Response.ResponseBuilder res = Response.ok(new HelloResponse(name)); + if (name == null || name.isEmpty()) + res.status(Response.Status.BAD_REQUEST); + return res.build(); + } + + @POST + @Path("reverse") + public Response reverse(ReverseRequest request) { + if (request == null || request.getContent() == null) { + Response.ResponseBuilder res = Response.status(Response.Status.BAD_REQUEST); + return res.build(); + } + Response.ResponseBuilder res = Response.ok(new ReverseResponse(request.getContent())); + if (request.getContent().isEmpty()) + res.status(Response.Status.BAD_REQUEST); + return res.build(); + } +} diff --git a/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/HelloWorldEndpoint.java b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/HelloWorldEndpoint.java new file mode 100644 index 0000000..4f8a59d --- /dev/null +++ b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/HelloWorldEndpoint.java @@ -0,0 +1,15 @@ +package fr.epita.assistants.presentation.rest; + +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; + +@Path("/") +@Consumes(MediaType.TEXT_PLAIN) +@Produces(MediaType.TEXT_PLAIN) +public class HelloWorldEndpoint { + @Path("/") + @GET + public String helloWorld() { + return "Hello World!"; + } +} diff --git a/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/request/ReverseRequest.java b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/request/ReverseRequest.java new file mode 100644 index 0000000..0a8fc7d --- /dev/null +++ b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/request/ReverseRequest.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.presentation.rest.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class ReverseRequest { + String content; +} diff --git a/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/response/HelloResponse.java b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/response/HelloResponse.java new file mode 100644 index 0000000..2dbc9d0 --- /dev/null +++ b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/response/HelloResponse.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.presentation.rest.response; + +import lombok.Getter; + +@Getter +public class HelloResponse { + String content; + + public HelloResponse(String content) { + this.content = "hello " + content; + } +} diff --git a/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/response/ReverseResponse.java b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/response/ReverseResponse.java new file mode 100644 index 0000000..3f1bb9e --- /dev/null +++ b/jws/endpoints/src/main/java/fr/epita/assistants/presentation/rest/response/ReverseResponse.java @@ -0,0 +1,14 @@ +package fr.epita.assistants.presentation.rest.response; + +import lombok.Getter; + +@Getter +public class ReverseResponse { + String original; + String reversed; + + public ReverseResponse(String original) { + this.original = original; + this.reversed = new StringBuilder(original).reverse().toString(); + } +} diff --git a/jws/endpoints/src/main/resources/application.properties b/jws/endpoints/src/main/resources/application.properties new file mode 100644 index 0000000..b3b3d13 --- /dev/null +++ b/jws/endpoints/src/main/resources/application.properties @@ -0,0 +1,7 @@ +%dev.quarkus.http.port=8082 +%dev.quarkus.swagger-ui.enable=true + +quarkus.log.category."org.apache.kafka".level=WARN +quarkus.devservices.enabled=false + +quarkus.http.cors=true diff --git a/jws/endpoints/src/main/resources/openapi.yaml b/jws/endpoints/src/main/resources/openapi.yaml new file mode 100644 index 0000000..7e8ac48 --- /dev/null +++ b/jws/endpoints/src/main/resources/openapi.yaml @@ -0,0 +1,80 @@ +--- +openapi: 3.1.0 +tags: +- name: Greeting +- name: String Operations +servers: + - url: http://localhost:8082/ +components: + schemas: + HelloResponse: + type: object + properties: + content: + type: string + example: "hello test" + ReverseRequest: + type: object + properties: + content: + type: string + example: "hello\ntest" + ReverseResponse: + type: object + properties: + original: + type: string + example: "hello\ntest" + reversed: + type: string + example: "tset\nolleh" +paths: + /hello/{name}: + get: + summary: Greet by name + description: "Returns a greeting message in the format `hello {name}` using\ + \ the provided name." + tags: + - Greeting + parameters: + - name: name + in: path + required: true + schema: + type: string + responses: + "200": + description: Greeting message returned successfully. + content: + application/json: + schema: + $ref: "#/components/schemas/HelloResponse" + "400": + description: "Bad request: The name parameter is null or empty." + /reverse: + post: + summary: Reverse a string + description: "Accepts a JSON request containing a string, reverses the string,\ + \ and returns both the original and reversed versions." + tags: + - String Operations + requestBody: + description: JSON object containing the string to be reversed. + content: + application/json: + schema: + $ref: "#/components/schemas/ReverseRequest" + required: true + responses: + "200": + description: Reversed string returned successfully. + content: + application/json: + schema: + $ref: "#/components/schemas/ReverseResponse" + "400": + description: "Bad request: Request body is null or the string content is\ + \ null or empty." +info: + title: endpoints API + version: "1.0" diff --git a/jws/epibazaar/common/pom.xml b/jws/epibazaar/common/pom.xml new file mode 100644 index 0000000..c1de2b7 --- /dev/null +++ b/jws/epibazaar/common/pom.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.epita.assistants</groupId> + <artifactId>epibazaar</artifactId> + <version>1.0.0</version> + </parent> + <artifactId>common</artifactId> + <version>1.0.0</version> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> +</project> diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/ItemAggregate.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/ItemAggregate.java new file mode 100644 index 0000000..2c21136 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/ItemAggregate.java @@ -0,0 +1,71 @@ +package fr.epita.assistants.common.aggregate; + +import fr.epita.assistants.common.utils.ItemInfo; +import io.smallrye.common.constraint.NotNull; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Value; + +import java.util.HashMap; +import java.util.Map; + +@Value +public class ItemAggregate { + @NotNull + public ResourceType type; + @NotNull + public Float quantity; + @Getter + @AllArgsConstructor + public enum ResourceType { + MONEY(new ItemInfo() + .withCollectable(false) + .withWalkable(false) + .withCollectQuantity(0) + .withPrice(null) + .withValue('M') + ), + GROUND(new ItemInfo() + .withCollectable(false) + .withWalkable(true) + .withCollectQuantity(0) + .withPrice(null) + .withValue('G') + ), + WATER(new ItemInfo() + .withCollectable(false) + .withWalkable(false) + .withCollectQuantity(0) + .withPrice(null) + .withValue('O') + ), + ROCK(new ItemInfo() + .withCollectable(true) + .withWalkable(true) + .withCollectQuantity(3) + .withPrice(3f) + .withValue('R') + ), + WOOD(new ItemInfo() + .withCollectable(true) + .withWalkable(true) + .withCollectQuantity(5) + .withPrice(2f) + .withValue('W') + ); + + private static final Map<Character, ResourceType> lookup = new HashMap<>(); + + static { + for (ResourceType entity : ResourceType.values()) { + lookup.put(entity.getItemInfo().getValue(), entity); + } + } + + private final ItemInfo itemInfo; + + public static ResourceType getResource(Character c) { + return lookup.get(c); + } + } +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/ResetInventoryAggregate.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/ResetInventoryAggregate.java new file mode 100644 index 0000000..a044af6 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/ResetInventoryAggregate.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.aggregate; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +import java.util.List; + +@Value +public class ResetInventoryAggregate { + @NotNull + List<ItemAggregate> items; +}
\ No newline at end of file diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/SellItemAggregate.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/SellItemAggregate.java new file mode 100644 index 0000000..f0d478c --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/SellItemAggregate.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.aggregate; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +import java.util.List; + +@Value +public class SellItemAggregate { + @NotNull + List<ItemAggregate> items; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/SyncInventoryAggregate.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/SyncInventoryAggregate.java new file mode 100644 index 0000000..1c7e489 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/SyncInventoryAggregate.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.aggregate; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +import java.util.List; + +@Value +public class SyncInventoryAggregate { + @NotNull + List<ItemAggregate> items; +}
\ No newline at end of file diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/UpgradeItemProducerAggregate.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/UpgradeItemProducerAggregate.java new file mode 100644 index 0000000..c977061 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/UpgradeItemProducerAggregate.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.aggregate; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class UpgradeItemProducerAggregate { + @NotNull + Float newMoney; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/UpgradeShopAggregate.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/UpgradeShopAggregate.java new file mode 100644 index 0000000..09aa31c --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/aggregate/UpgradeShopAggregate.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.aggregate; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class UpgradeShopAggregate { + @NotNull + Integer shopId; + @NotNull + Float newMoney; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/ItemRequest.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/ItemRequest.java new file mode 100644 index 0000000..b84667b --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/ItemRequest.java @@ -0,0 +1,13 @@ +package fr.epita.assistants.common.api.request; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import lombok.AllArgsConstructor; +import lombok.Getter; + + +@Getter +@AllArgsConstructor +public class ItemRequest { + float quantity; + ItemAggregate.ResourceType type; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/ItemsRequest.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/ItemsRequest.java new file mode 100644 index 0000000..ff873db --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/ItemsRequest.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.api.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class ItemsRequest { + List<ItemRequest> itemsRequest; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/MoveRequest.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/MoveRequest.java new file mode 100644 index 0000000..745fa2b --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/MoveRequest.java @@ -0,0 +1,11 @@ +package fr.epita.assistants.common.api.request; + +import fr.epita.assistants.common.utils.Direction; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class MoveRequest { + Direction direction; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/StartRequest.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/StartRequest.java new file mode 100644 index 0000000..275cd27 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/request/StartRequest.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.api.request; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class StartRequest { + String mapPath; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ItemResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ItemResponse.java new file mode 100644 index 0000000..f5cfcc0 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ItemResponse.java @@ -0,0 +1,13 @@ +package fr.epita.assistants.common.api.response; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ItemResponse { + long id; + float quantity; + ItemAggregate.ResourceType type; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ItemsResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ItemsResponse.java new file mode 100644 index 0000000..919b4e6 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ItemsResponse.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class ItemsResponse { + List<ItemResponse> itemsResponse; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/MoveResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/MoveResponse.java new file mode 100644 index 0000000..3b7d8cc --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/MoveResponse.java @@ -0,0 +1,11 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class MoveResponse { + int posX; + int posY; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/PlayerResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/PlayerResponse.java new file mode 100644 index 0000000..b852f27 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/PlayerResponse.java @@ -0,0 +1,18 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +@AllArgsConstructor +public class PlayerResponse { + int posX; + int posY; + LocalDateTime lastMove; + LocalDateTime lastCollect; + float moveSpeedMultiplier; + float staminaMultiplier; + float collectRateMultiplier; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopPriceResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopPriceResponse.java new file mode 100644 index 0000000..59cf22e --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopPriceResponse.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ShopPriceResponse { + float shopPrice; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopResponse.java new file mode 100644 index 0000000..c168df5 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopResponse.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ShopResponse { + int id; + float priceMultiplier; + float upgradePrice; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopsResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopsResponse.java new file mode 100644 index 0000000..f2a114b --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/ShopsResponse.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class ShopsResponse { + List<ShopResponse> shops; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/StartResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/StartResponse.java new file mode 100644 index 0000000..463564c --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/StartResponse.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class StartResponse { + List<List<String>> map; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/UpgradeCostResponse.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/UpgradeCostResponse.java new file mode 100644 index 0000000..19557a1 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/api/response/UpgradeCostResponse.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.api.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class UpgradeCostResponse { + float upgradeCollectCost; + float upgradeMoveCost; + float upgradeStaminaCost; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/CollectItemCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/CollectItemCommand.java new file mode 100644 index 0000000..94752cc --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/CollectItemCommand.java @@ -0,0 +1,14 @@ +package fr.epita.assistants.common.command; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +import static fr.epita.assistants.common.aggregate.ItemAggregate.ResourceType; + +@Value +public class CollectItemCommand { + @NotNull + ResourceType type; + @NotNull + Float collectRateMultiplier; +}
\ No newline at end of file diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/CreateShopCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/CreateShopCommand.java new file mode 100644 index 0000000..f5e56e5 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/CreateShopCommand.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.command; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class CreateShopCommand { + @NotNull + public Float price; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/ResetInventoryCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/ResetInventoryCommand.java new file mode 100644 index 0000000..c2bdfc3 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/ResetInventoryCommand.java @@ -0,0 +1,11 @@ +package fr.epita.assistants.common.command; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + +@JsonInclude(NON_NULL) +public class ResetInventoryCommand { + public ResetInventoryCommand() { + } +}
\ No newline at end of file diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/SellItemCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/SellItemCommand.java new file mode 100644 index 0000000..aaa8c0b --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/SellItemCommand.java @@ -0,0 +1,15 @@ +package fr.epita.assistants.common.command; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +import java.util.List; + +@Value +public class SellItemCommand { + @NotNull + List<ItemAggregate> items; + @NotNull + Float priceMultiplier; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/SyncInventoryCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/SyncInventoryCommand.java new file mode 100644 index 0000000..d077093 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/SyncInventoryCommand.java @@ -0,0 +1,11 @@ +package fr.epita.assistants.common.command; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + +@JsonInclude(NON_NULL) +public class SyncInventoryCommand { + public SyncInventoryCommand() { + } +}
\ No newline at end of file diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeCollectRateCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeCollectRateCommand.java new file mode 100644 index 0000000..de0feaf --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeCollectRateCommand.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.command; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class UpgradeCollectRateCommand { + @NotNull + Float price; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeMovementSpeedCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeMovementSpeedCommand.java new file mode 100644 index 0000000..ce3504c --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeMovementSpeedCommand.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.command; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class UpgradeMovementSpeedCommand { + @NotNull + Float price; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeShopPriceCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeShopPriceCommand.java new file mode 100644 index 0000000..9fa68a1 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeShopPriceCommand.java @@ -0,0 +1,12 @@ +package fr.epita.assistants.common.command; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class UpgradeShopPriceCommand { + @NotNull + Integer shopId; + @NotNull + Float price; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeStaminaCommand.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeStaminaCommand.java new file mode 100644 index 0000000..de4fa7e --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/command/UpgradeStaminaCommand.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.command; + +import io.smallrye.common.constraint.NotNull; +import lombok.Value; + +@Value +public class UpgradeStaminaCommand { + @NotNull + Float price; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/Direction.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/Direction.java new file mode 100644 index 0000000..815016c --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/Direction.java @@ -0,0 +1,15 @@ +package fr.epita.assistants.common.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum Direction { + UP(new Point(0, -1)), + DOWN(new Point(0, 1)), + RIGHT(new Point(1, 0)), + LEFT(new Point(-1, 0)); + + private final Point point; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/ErrorInfo.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/ErrorInfo.java new file mode 100644 index 0000000..cd1a2d4 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/ErrorInfo.java @@ -0,0 +1,10 @@ +package fr.epita.assistants.common.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class ErrorInfo { + private String message; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/ItemInfo.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/ItemInfo.java new file mode 100644 index 0000000..02d40fb --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/ItemInfo.java @@ -0,0 +1,20 @@ +package fr.epita.assistants.common.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.With; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@With +public class ItemInfo { + private boolean isCollectable; + private boolean isWalkable; + + private char value; + + private int collectQuantity; + private Float price; +} diff --git a/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/Point.java b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/Point.java new file mode 100644 index 0000000..f9ebcf8 --- /dev/null +++ b/jws/epibazaar/common/src/main/java/fr/epita/assistants/common/utils/Point.java @@ -0,0 +1,13 @@ +package fr.epita.assistants.common.utils; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Setter +@Getter +public class Point { + private int posX; + private int posY; +} diff --git a/jws/epibazaar/common/src/main/resources/application.properties b/jws/epibazaar/common/src/main/resources/application.properties new file mode 100644 index 0000000..9db5e48 --- /dev/null +++ b/jws/epibazaar/common/src/main/resources/application.properties @@ -0,0 +1,3 @@ +quarkus.devservices.enabled=true +quarkus.kafka.devservices.image-name=reg.undercloud.cri.epita.fr/docker/redpandadata/redpanda:v24.1.2 +%test.quarkus.devservices.enabled=false diff --git a/jws/epibazaar/inventory/pom.xml b/jws/epibazaar/inventory/pom.xml new file mode 100644 index 0000000..b8af7c8 --- /dev/null +++ b/jws/epibazaar/inventory/pom.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.epita.assistants</groupId> + <artifactId>epibazaar</artifactId> + <version>1.0.0</version> + </parent> + + <artifactId>inventory</artifactId> + <version>1.0.0</version> + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-messaging-kafka</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-jdbc-postgresql</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-hibernate-orm-panache</artifactId> + </dependency> + <dependency> + <groupId>fr.epita.assistants</groupId> + <artifactId>common</artifactId> + <version>1.0.0</version> + <scope>compile</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> +</project> diff --git a/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/converter/InventoryConverter.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/converter/InventoryConverter.java new file mode 100644 index 0000000..62c7994 --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/converter/InventoryConverter.java @@ -0,0 +1,24 @@ +package fr.epita.assistants.inventory.converter; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.common.api.response.ItemResponse; +import fr.epita.assistants.common.api.response.ItemsResponse; +import fr.epita.assistants.inventory.data.model.ItemModel; +import fr.epita.assistants.inventory.domain.entity.ItemEntity; +import fr.epita.assistants.inventory.domain.entity.ItemsEntity; + +public class InventoryConverter { + public static ItemAggregate updatedItem(ItemModel item) { + return new ItemAggregate(item.getType(), item.getQuantity()); + } + + 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(InventoryConverter::EntityToResponse).toList()); + } +} diff --git a/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/data/model/ItemModel.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/data/model/ItemModel.java new file mode 100644 index 0000000..29a182b --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/data/model/ItemModel.java @@ -0,0 +1,25 @@ +package fr.epita.assistants.inventory.data.model; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.persistence.*; +import lombok.*; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Setter +@Table(name = "item") +public class ItemModel { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + Long id; + Float quantity; + @Enumerated(value = EnumType.STRING) + ItemAggregate.ResourceType type; + + public ItemModel(float quantity, ItemAggregate.ResourceType type) { + this.quantity = quantity; + this.type = type; + } +} diff --git a/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/data/repository/ItemRepository.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/data/repository/ItemRepository.java new file mode 100644 index 0000000..129c815 --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/data/repository/ItemRepository.java @@ -0,0 +1,48 @@ +package fr.epita.assistants.inventory.data.repository; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.inventory.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.Optional; + +@ApplicationScoped +public class ItemRepository implements PanacheRepository<ItemModel> { + + @Transactional + public void clearDB() { + deleteAll(); + } + + @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 ItemModel addItem(ItemAggregate.ResourceType type, Float amount) { + ItemModel res = new ItemModel(amount, type); + persist(res); + return res; + } + + // amount should already be the updated amount + @Transactional + public ItemModel fillInventory(ItemAggregate.ResourceType type, Float amount) { + update("quantity = ?1 where type = ?2", amount, type); + return new ItemModel(amount, type); + } + + @Transactional + public List<ItemModel> getMoney() { + return find("where type = ?1", ItemAggregate.ResourceType.MONEY).stream().toList(); + } +} diff --git a/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/entity/ItemEntity.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/entity/ItemEntity.java new file mode 100644 index 0000000..028d09e --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/entity/ItemEntity.java @@ -0,0 +1,13 @@ +package fr.epita.assistants.inventory.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/inventory/src/main/java/fr/epita/assistants/inventory/domain/entity/ItemsEntity.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/entity/ItemsEntity.java new file mode 100644 index 0000000..c0a96ac --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/entity/ItemsEntity.java @@ -0,0 +1,13 @@ +package fr.epita.assistants.inventory.domain.entity; + +import fr.epita.assistants.inventory.domain.entity.ItemEntity; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.List; + +@Getter +@AllArgsConstructor +public class ItemsEntity { + List<ItemEntity> items; +} diff --git a/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/service/InventoryService.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/service/InventoryService.java new file mode 100644 index 0000000..fc25abf --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/domain/service/InventoryService.java @@ -0,0 +1,59 @@ +package fr.epita.assistants.inventory.domain.service; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.common.aggregate.ResetInventoryAggregate; +import fr.epita.assistants.common.command.CollectItemCommand; +import fr.epita.assistants.inventory.converter.InventoryConverter; +import fr.epita.assistants.inventory.data.model.ItemModel; +import fr.epita.assistants.inventory.data.repository.ItemRepository; +import fr.epita.assistants.inventory.domain.entity.ItemEntity; +import fr.epita.assistants.inventory.domain.entity.ItemsEntity; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.util.List; +import java.util.Optional; + +@ApplicationScoped +public class InventoryService { + @Inject + ItemRepository itemRepository; + + public ResetInventoryAggregate resetInventory() { + ResetInventoryAggregate res = + new ResetInventoryAggregate(itemRepository.getItems().stream().map(m -> new ItemAggregate(m.getType() + , m.getQuantity())).toList()); + itemRepository.clearDB(); + return res; + } + + public ItemAggregate collectItem(CollectItemCommand cmd) { + Optional<ItemModel> item = itemRepository.exists(cmd.getType()); + if (item.isPresent()) { + ItemModel updated = itemRepository.fillInventory(cmd.getType(), + cmd.getCollectRateMultiplier() * cmd.getType().getItemInfo().getCollectQuantity() + item.get().getQuantity()); + return InventoryConverter.updatedItem(updated); + } else { + ItemModel newItem = itemRepository.addItem(cmd.getType(), + cmd.getCollectRateMultiplier() * cmd.getType().getItemInfo().getCollectQuantity()); + return InventoryConverter.updatedItem(newItem); + } + } + + public ItemsEntity getAllItems() { + return new ItemsEntity(itemRepository.getItems().stream().map(m -> new ItemEntity(m.getId(), + m.getQuantity(), m.getType())).toList()); + } + + public Double getMoney() { + List<ItemModel> entries = itemRepository.getMoney(); + if (entries.isEmpty()) + return null; + return entries.stream().mapToDouble(m -> m.getQuantity().doubleValue()).sum(); + } + + public Float pay(Float price) { + itemRepository.fillInventory(ItemAggregate.ResourceType.MONEY, getMoney().floatValue() - price); + return getMoney().floatValue(); + } +} diff --git a/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/presentation/subscriber/CommandSubscriber.java b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/presentation/subscriber/CommandSubscriber.java new file mode 100644 index 0000000..3a95a3a --- /dev/null +++ b/jws/epibazaar/inventory/src/main/java/fr/epita/assistants/inventory/presentation/subscriber/CommandSubscriber.java @@ -0,0 +1,59 @@ +package fr.epita.assistants.inventory.presentation.subscriber; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.common.aggregate.ResetInventoryAggregate; +import fr.epita.assistants.common.aggregate.SyncInventoryAggregate; +import fr.epita.assistants.common.aggregate.UpgradeItemProducerAggregate; +import fr.epita.assistants.common.command.*; +import fr.epita.assistants.inventory.domain.service.InventoryService; +import io.smallrye.reactive.messaging.annotations.Broadcast; +import jakarta.inject.Inject; +import org.eclipse.microprofile.reactive.messaging.Incoming; +import org.eclipse.microprofile.reactive.messaging.Outgoing; + +public class CommandSubscriber { + @Inject + InventoryService inventoryService; + + @Broadcast + @Incoming("reset-inventory-command") + @Outgoing("reset-inventory-aggregate") + public ResetInventoryAggregate commandListener(ResetInventoryCommand cmd) { + return inventoryService.resetInventory(); + } + + @Broadcast + @Incoming("collect-item-command") + @Outgoing("collect-item-aggregate") + public ItemAggregate commandListener(CollectItemCommand cmd) { + return inventoryService.collectItem(cmd); + } + + @Broadcast + @Incoming("sync-inventory-command") + @Outgoing("sync-inventory-aggregate") + public SyncInventoryAggregate commandListener(SyncInventoryCommand cmd) { + return new SyncInventoryAggregate(inventoryService.getAllItems().getItems().stream().map(e -> new ItemAggregate(e.getType(), e.getQuantity())).toList()); + } + + @Broadcast + @Incoming("upgrade-collect-rate-command") + @Outgoing("upgrade-collect-rate-aggregate") + public UpgradeItemProducerAggregate commandListener(UpgradeCollectRateCommand cmd) { + return new UpgradeItemProducerAggregate(inventoryService.pay(cmd.getPrice())); + } + + @Broadcast + @Incoming("upgrade-movement-speed-command") + @Outgoing("upgrade-movement-speed-aggregate") + public UpgradeItemProducerAggregate commandListener(UpgradeMovementSpeedCommand cmd) { + return new UpgradeItemProducerAggregate(inventoryService.pay(cmd.getPrice())); + } + + @Broadcast + @Incoming("upgrade-stamina-command") + @Outgoing("upgrade-stamina-aggregate") + public UpgradeItemProducerAggregate commandListener(UpgradeStaminaCommand cmd) { + return new UpgradeItemProducerAggregate(inventoryService.pay(cmd.getPrice())); + } +} diff --git a/jws/epibazaar/inventory/src/main/resources/application.properties b/jws/epibazaar/inventory/src/main/resources/application.properties new file mode 100644 index 0000000..fedcdd0 --- /dev/null +++ b/jws/epibazaar/inventory/src/main/resources/application.properties @@ -0,0 +1,11 @@ +%dev.quarkus.http.port=8999 +quarkus.datasource.db-kind=postgresql +quarkus.datasource.username=postgres +quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/inventory?currentSchema=public +quarkus.transaction-manager.default-transaction-timeout=3000s +quarkus.hibernate-orm.log.queries-slower-than-ms=200 +quarkus.hibernate-orm.database.generation=drop-and-create + +quarkus.kafka.devservices.image-name=reg.undercloud.cri.epita.fr/docker/redpandadata/redpanda:v24.1.2 +quarkus.devservices.enabled=true +%test.quarkus.devservices.enabled=false diff --git a/jws/epibazaar/inventory/src/main/resources/db/migration/V1__Init.sql b/jws/epibazaar/inventory/src/main/resources/db/migration/V1__Init.sql new file mode 100644 index 0000000..3c1e091 --- /dev/null +++ b/jws/epibazaar/inventory/src/main/resources/db/migration/V1__Init.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS "item" +( + id SERIAL PRIMARY KEY NOT NULL, + + type VARCHAR(64) NOT NULL, + quantity FLOAT NOT NULL +); diff --git a/jws/epibazaar/item-producer/.env b/jws/epibazaar/item-producer/.env new file mode 100644 index 0000000..9b1af1e --- /dev/null +++ b/jws/epibazaar/item-producer/.env @@ -0,0 +1,7 @@ +JWS_TICK_DURATION=100 +JWS_DELAY_COLLECT=3 +JWS_DELAY_MOVEMENT=2 +JWS_UPGRADE_COLLECT_COST=50.0 +JWS_UPGRADE_MOVE_COST=27.5 +JWS_UPGRADE_STAMINA_COST=32.25 +JWS_UPGRADE_MULTIPLIER=1.15
\ No newline at end of file diff --git a/jws/epibazaar/item-producer/pom.xml b/jws/epibazaar/item-producer/pom.xml new file mode 100644 index 0000000..bea50b4 --- /dev/null +++ b/jws/epibazaar/item-producer/pom.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.epita.assistants</groupId> + <artifactId>epibazaar</artifactId> + <version>1.0.0</version> + </parent> + + <artifactId>item-producer</artifactId> + <version>1.0.0</version> + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-messaging-kafka</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-jdbc-postgresql</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-hibernate-orm-panache</artifactId> + </dependency> + <dependency> + <groupId>fr.epita.assistants</groupId> + <artifactId>common</artifactId> + <version>1.0.0</version> + <scope>compile</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> +</project> 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(); + } +} diff --git a/jws/epibazaar/item-producer/src/main/resources/application.properties b/jws/epibazaar/item-producer/src/main/resources/application.properties new file mode 100644 index 0000000..498479f --- /dev/null +++ b/jws/epibazaar/item-producer/src/main/resources/application.properties @@ -0,0 +1,13 @@ +%dev.quarkus.http.port=8081 +quarkus.datasource.db-kind=postgresql +quarkus.datasource.username=postgres +quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/item_producer?currentSchema=public +quarkus.transaction-manager.default-transaction-timeout=3000s +quarkus.hibernate-orm.log.queries-slower-than-ms=200 +quarkus.http.cors=true +quarkus.http.cors.origins=* +quarkus.hibernate-orm.database.generation=drop-and-create + +quarkus.kafka.devservices.image-name=reg.undercloud.cri.epita.fr/docker/redpandadata/redpanda:v24.1.2 +quarkus.devservices.enabled=true +%test.quarkus.devservices.enabled=false diff --git a/jws/epibazaar/item-producer/src/main/resources/db/migration/V1__Init.sql b/jws/epibazaar/item-producer/src/main/resources/db/migration/V1__Init.sql new file mode 100644 index 0000000..0eede01 --- /dev/null +++ b/jws/epibazaar/item-producer/src/main/resources/db/migration/V1__Init.sql @@ -0,0 +1,25 @@ +CREATE TABLE IF NOT EXISTS "game" +( + id SERIAL PRIMARY KEY NOT NULL, + map TEXT NOT NULL +); + +CREATE TABLE IF NOT EXISTS "item" +( + id SERIAL PRIMARY KEY NOT NULL, + + type VARCHAR(64) NOT NULL, + quantity FLOAT NOT NULL +); + +CREATE TABLE IF NOT EXISTS "player" +( + id SERIAL PRIMARY KEY NOT NULL, + pos_x INTEGER NOT NULL, + pos_y INTEGER NOT NULL, + last_move TIMESTAMP, + last_collect TIMESTAMP, + move_speed_multiplier FLOAT NOT NULL, + stamina_multiplier FLOAT NOT NULL, + collect_rate_multiplier FLOAT NOT NULL +); diff --git a/jws/epibazaar/item-producer/src/main/resources/maps/custom.epimap b/jws/epibazaar/item-producer/src/main/resources/maps/custom.epimap new file mode 100644 index 0000000..5b510f3 --- /dev/null +++ b/jws/epibazaar/item-producer/src/main/resources/maps/custom.epimap @@ -0,0 +1,16 @@ +2G4R3W5G2R +5G3W4R2G2W +6R3G2W5G +3W5G6R2W +4G3R4W5G +2W5R3G4W2G +6G4R3W3G +4R6G3W3R +5G2W5R4G +3W5R4G3W1G +2G6W3R5G +4W5G3R4W +3G4R5W4G +5R3G6W2R +2W5G4R5W +9G7G
\ No newline at end of file diff --git a/jws/epibazaar/item-producer/src/main/resources/maps/huge.epimap b/jws/epibazaar/item-producer/src/main/resources/maps/huge.epimap new file mode 100644 index 0000000..d8384bd --- /dev/null +++ b/jws/epibazaar/item-producer/src/main/resources/maps/huge.epimap @@ -0,0 +1,30 @@ +9G9G9G3G +8G3W3R2G2R2G2W1R4G1R2G +7G2W1G3R1W1G1R1W2G1R1G1R1G1R1G2W2R1G +1G1W4G1R1G1W1R5G2R4G1R1W1R2G1W3G +1G1W1R2G2R1G1W2R3G2W2G2O3G2R3G1W1G +1G1W1G2W7G4O3G2O3R3G2W1G +1G1R4G1R3G1R3G2O3G2O2R3G2W2G +4G3R3G3R8O3R2G1W3G +4G3R1G5R4O2G1W2R1G2R5G +4G9R1G3O9G4G +5G4R2W2O1R5O2G3W1R5G +3G4R2G8O1G7W1G2W2G +3G1R1G2R1G1W9O1W2G1R2W6G +1G1R1G2R2G1R1W1G6O4W9O1G +1G4R1G2R1W1G3O1G2O5W1G7O1G +1G1W2R1W1G1R1G2W3O2R1O4W1G1R7O1G +5G3W3G2O1G1W1G3W1G1W1G7O1G +1G2R2G2W4R2O3G3W1R1G1W1G1R5O1G +1G1W1R1G2R4W1R1G1R1G3R2W5G5O1G +1G2R2G1R2W1R2G6R1W1G9O1O1G +2G2W9R2R3W2G9O1G +6G3W2G4R3W2G2O1W6O1G +1G3R2G3W2G3R1G3W2R2O1R6O1G +1G3R1G1W3R2W1R2G2W1G3R2O1R1O1G1O1G1W1O1G +3G2W1G2R1G2R2G2W3G1R1W2G2R1G1W1G1R1O1G +3G1W1R3G2R4G1R2G1W1G1R2W2R1G1W3R1G +1G4W1G3R2W3G2R3W1R2W3R1G2R2G +2G3W1G2R6G2R2G2R1G1W1G2W1G1R1G1W1G +2G3W1G1W1G4W9G1G2R1W1G2R2G +9G9G9G3G
\ No newline at end of file diff --git a/jws/epibazaar/item-producer/src/main/resources/maps/pretty.epimap b/jws/epibazaar/item-producer/src/main/resources/maps/pretty.epimap new file mode 100644 index 0000000..3699c22 --- /dev/null +++ b/jws/epibazaar/item-producer/src/main/resources/maps/pretty.epimap @@ -0,0 +1,16 @@ +9G7G +2G6O3G4R1G +2G5O4G3R2G +2G4O4G3W2G1G +2G3O4G5W1G1G +2G3O3G5W3G +2G3G4W4G3R +2G3R3G4W3O1G +1G2R3G4W4O2G +1G3G3W6O3G +1G2W4G5O4G +1G2W3G4R3G3G +1G3R4G4R1G3G +1G5R4G4R2G +1G5R3G6G1G +9G7G diff --git a/jws/epibazaar/item-producer/src/main/resources/openapi.yaml b/jws/epibazaar/item-producer/src/main/resources/openapi.yaml new file mode 100644 index 0000000..16e0465 --- /dev/null +++ b/jws/epibazaar/item-producer/src/main/resources/openapi.yaml @@ -0,0 +1,287 @@ +--- +openapi: 3.1.0 +tags: +- name: Game Management +- name: Player Actions +- name: Upgrades +paths: + /: + get: + summary: Retrieve all inventory resources + description: Fetch all resources currently available in the inventory. + x-quarkus-openapi-method-ref: m98752433_-1109396335 + tags: + - Game Management + responses: + "200": + description: Resources successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/ItemsResponse" + "400": + description: The game is not running. + servers: + - url: http://localhost:8081/ + /collect: + post: + summary: Collect resources + description: Collect the resource available on the player's current tile. + x-quarkus-openapi-method-ref: m98752433_799402137 + tags: + - Player Actions + responses: + "200": + description: Resource successfully collected and sent to inventory. + content: + application/json: + schema: + $ref: "#/components/schemas/StartResponse" + "400": + description: Invalid tile or the game is not running. + "429": + description: Player has recently collected and must wait before collecting + again. + servers: + - url: http://localhost:8081/ + /move: + post: + summary: Move player + description: "Move the player in the specified direction (left, right, up, or\ + \ down)." + x-quarkus-openapi-method-ref: m98752433_-1586243046 + tags: + - Player Actions + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/MoveRequest" + required: true + responses: + "200": + description: Player successfully moved. + content: + application/json: + schema: + $ref: "#/components/schemas/MoveResponse" + "400": + description: Invalid direction or the game is not running. + "429": + description: Player has recently moved and must wait before moving again. + servers: + - url: http://localhost:8081/ + /player: + get: + summary: Retrieve player information + description: Fetch information about the current player. + x-quarkus-openapi-method-ref: m98752433_-1988770431 + tags: + - Game Management + responses: + "200": + description: Player information successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/PlayerResponse" + "400": + description: The game is not running. + servers: + - url: http://localhost:8081/ + /start: + post: + summary: Start the game + description: Initialize and start the item-producer game. Synchronizes the database + with the `Inventory` service. + x-quarkus-openapi-method-ref: m98752433_677674067 + tags: + - Game Management + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/StartRequest" + required: true + responses: + "200": + description: The game started successfully. + content: + application/json: + schema: + $ref: "#/components/schemas/StartResponse" + "400": + description: Invalid `path` provided. + servers: + - url: http://localhost:8081/ + /upgrade/collect: + patch: + summary: Upgrade collection rate + description: Increase the amount of resources collected per action. + x-quarkus-openapi-method-ref: m98752433_274012880 + tags: + - Upgrades + responses: + "204": + description: Collection rate upgrade successfully applied. + "400": + description: Insufficient funds or the game is not running. + "404": + description: The money was not found. + servers: + - url: http://localhost:8081/ + /upgrade/move: + patch: + summary: Upgrade move speed + description: Decrease the tick rate required for the player to move. + x-quarkus-openapi-method-ref: m98752433_1889564488 + tags: + - Upgrades + responses: + "204": + description: Move speed upgrade successfully applied. + "400": + description: Insufficient funds or the game is not running. + "404": + description: The money was not found. + servers: + - url: http://localhost:8081/ + /upgrade/stamina: + patch: + summary: Upgrade stamina + description: Decrease the tick rate required to collect resources. + x-quarkus-openapi-method-ref: m98752433_-1142370765 + tags: + - Upgrades + responses: + "204": + description: Stamina upgrade successfully applied. + "400": + description: Insufficient funds or the game is not running. + "404": + description: The money was not found. + servers: + - url: http://localhost:8081/ + /upgrades: + get: + summary: Retrieve upgrade costs + description: Fetch the costs of all available upgrades. + x-quarkus-openapi-method-ref: m98752433_-99503618 + tags: + - Game Management + responses: + "200": + description: Upgrade costs successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/UpgradeCostResponse" + "400": + description: The game is not running. + servers: + - url: http://localhost:8081/ +components: + schemas: + Direction: + type: string + enum: + - UP + - DOWN + - RIGHT + - LEFT + ItemResponse: + type: object + properties: + id: + type: integer + format: int32 + quantity: + type: number + format: float + type: + $ref: "#/components/schemas/ResourceType" + ItemsResponse: + type: object + properties: + itemsResponse: + type: array + items: + $ref: "#/components/schemas/ItemResponse" + LocalDateTime: + type: string + format: date-time + examples: + - 2022-03-10T12:15:50 + MoveRequest: + type: object + properties: + direction: + $ref: "#/components/schemas/Direction" + MoveResponse: + type: object + properties: + posX: + type: integer + format: int32 + posY: + type: integer + format: int32 + PlayerResponse: + type: object + properties: + posX: + type: integer + format: int32 + posY: + type: integer + format: int32 + lastMove: + $ref: "#/components/schemas/LocalDateTime" + lastCollect: + $ref: "#/components/schemas/LocalDateTime" + moveSpeedMultiplier: + type: number + format: float + staminaMultiplier: + type: number + format: float + collectRateMultiplier: + type: number + format: float + ResourceType: + type: string + enum: + - MONEY + - GROUND + - WATER + - ROCK + - WOOD + StartRequest: + type: object + properties: + mapPath: + type: string + StartResponse: + type: object + properties: + map: + type: array + items: + type: array + items: + $ref: "#/components/schemas/ResourceType" + UpgradeCostResponse: + type: object + properties: + upgradeCollectCost: + type: number + format: float + upgradeMoveCost: + type: number + format: float + upgradeStaminaCost: + type: number + format: float +info: + title: item-producer API + version: 1.0.0 diff --git a/jws/epibazaar/pom.xml b/jws/epibazaar/pom.xml new file mode 100644 index 0000000..c0ed297 --- /dev/null +++ b/jws/epibazaar/pom.xml @@ -0,0 +1,359 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>fr.epita.assistants</groupId> + <artifactId>epibazaar</artifactId> + <version>1.0.0</version> + <packaging>pom</packaging> + + <modules> + <module>common</module> + <module>item-producer</module> + <module>inventory</module> + <module>shop</module> + </modules> + + <properties> + <maven.compiler.release>21</maven.compiler.release> + <maven.compiler.source>21</maven.compiler.source> + <maven.compiler.target>21</maven.compiler.target> + + <compiler-plugin.version>3.13.0</compiler-plugin.version> + <maven.compiler.parameters>true</maven.compiler.parameters> + + <versions.maven-surefire-plugin>3.0.0-M5</versions.maven-surefire-plugin> + <versions.maven-jar-plugin>3.4.1</versions.maven-jar-plugin> + <versions.maven-install-plugin>3.1.2</versions.maven-install-plugin> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id> + <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> + <quarkus.platform.version>3.17.5</quarkus.platform.version> + + <skipITs>true</skipITs> + <surefire.reportsDirectory>${project.build.directory}../../target/surefire-reports</surefire.reportsDirectory> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>${quarkus.platform.group-id}</groupId> + <artifactId>${quarkus.platform.artifact-id}</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-jackson</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-jackson-deployment</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-arc</artifactId> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.36</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>io.smallrye.reactive</groupId> + <artifactId>smallrye-reactive-messaging-in-memory</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.awaitility</groupId> + <artifactId>awaitility</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.26.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-kotlin</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-messaging-kafka-deployment</artifactId> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + </dependency> + + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5-properties</artifactId> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + </dependency> + <dependency> + <groupId>org.opentest4j</groupId> + <artifactId>opentest4j</artifactId> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>org.apiguardian</groupId> + <artifactId>apiguardian-api</artifactId> + <version>1.1.2</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit-platform</artifactId> + <version>${versions.maven-surefire-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>common-java5</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-shared-utils</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-api</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>3.17.5</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>${versions.maven-jar-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <version>${versions.maven-install-plugin}</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-kotlin-deployment</artifactId> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-commons</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-repository-metadata</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-registry</artifactId> + <version>2.0.6</version> + </dependency> + <dependency> + <groupId>classworlds</groupId> + <artifactId>classworlds</artifactId> + <version>1.1-alpha-2</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>3.17.5</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-smallrye-openapi</artifactId> + </dependency> + <dependency> + <groupId>com.tngtech.archunit</groupId> + <artifactId>archunit-junit5</artifactId> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>io.github.classgraph</groupId> + <artifactId>classgraph</artifactId> + <version>4.8.179</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <version>3.3.1</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.7.1</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.7.0</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + <annotationProcessorPaths> + <path> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.36</version> + </path> + </annotationProcessorPaths> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> +</project> diff --git a/jws/epibazaar/shop/.env b/jws/epibazaar/shop/.env new file mode 100644 index 0000000..c83ee7f --- /dev/null +++ b/jws/epibazaar/shop/.env @@ -0,0 +1,4 @@ +JWS_SHOP_PRICE=17.5 +JWS_UPGRADE_PRICE_COST=28.5 +JWS_UPGRADE_MULTIPLIER=1.15 +JWS_MAX_SHOP_QUANTITY=8
\ No newline at end of file diff --git a/jws/epibazaar/shop/pom.xml b/jws/epibazaar/shop/pom.xml new file mode 100644 index 0000000..6d07d08 --- /dev/null +++ b/jws/epibazaar/shop/pom.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>fr.epita.assistants</groupId> + <artifactId>epibazaar</artifactId> + <version>1.0.0</version> + </parent> + + <artifactId>shop</artifactId> + <version>1.0.0</version> + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-messaging-kafka</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-jdbc-postgresql</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-hibernate-orm-panache</artifactId> + </dependency> + <dependency> + <groupId>fr.epita.assistants</groupId> + <artifactId>common</artifactId> + <version>1.0.0</version> + <scope>compile</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> +</project> diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/converter/ShopConverter.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/converter/ShopConverter.java new file mode 100644 index 0000000..1b3e8cb --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/converter/ShopConverter.java @@ -0,0 +1,24 @@ +package fr.epita.assistants.shop.converter; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.common.aggregate.ResetInventoryAggregate; +import fr.epita.assistants.shop.data.model.ItemModel; +import jakarta.enterprise.context.ApplicationScoped; + +import java.util.HashMap; +import java.util.Map; + +@ApplicationScoped +public class ShopConverter { + 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 ItemAggregate updatedItem(ItemModel item) { + return new ItemAggregate(item.getType(), item.getQuantity()); + } +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/model/ItemModel.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/model/ItemModel.java new file mode 100644 index 0000000..a16f7bc --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/model/ItemModel.java @@ -0,0 +1,28 @@ +package fr.epita.assistants.shop.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; + } +}
\ No newline at end of file diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/model/ShopModel.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/model/ShopModel.java new file mode 100644 index 0000000..5f1c3ff --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/model/ShopModel.java @@ -0,0 +1,18 @@ +package fr.epita.assistants.shop.data.model; +import jakarta.persistence.*; +import lombok.*; + +import java.time.LocalDateTime; + +@Getter +@Setter +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "shop") +public class ShopModel { + Float priceMultiplier; + Float upgradePrice; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + Integer id; +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/repository/ItemRepository.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/repository/ItemRepository.java new file mode 100644 index 0000000..c471eb4 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/repository/ItemRepository.java @@ -0,0 +1,39 @@ +package fr.epita.assistants.shop.data.repository; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.shop.data.model.ItemModel; +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.transaction.Transactional; + +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 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); + } +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/repository/ShopRepository.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/repository/ShopRepository.java new file mode 100644 index 0000000..1bc7c78 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/data/repository/ShopRepository.java @@ -0,0 +1,30 @@ +package fr.epita.assistants.shop.data.repository; + +import fr.epita.assistants.common.api.request.StartRequest; +import fr.epita.assistants.common.api.response.StartResponse; +import fr.epita.assistants.common.utils.ErrorInfo; +import fr.epita.assistants.shop.converter.ShopConverter; +import fr.epita.assistants.shop.data.model.ShopModel; +import fr.epita.assistants.shop.domain.service.ShopService; +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response; + +@ApplicationScoped +public class ShopRepository implements PanacheRepository<ShopModel> { + @Transactional + public void clearDB() { + deleteAll(); + } + @Transactional + public void addEntry(Float priceMultiplier, Float upgradePriceCost) { + ShopModel shop = new ShopModel(); + shop.setUpgradePrice(upgradePriceCost); + shop.setPriceMultiplier(priceMultiplier); + persist(shop); + } +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/entity/ErwenEntity.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/entity/ErwenEntity.java new file mode 100644 index 0000000..3bb22f1 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/entity/ErwenEntity.java @@ -0,0 +1,4 @@ +package fr.epita.assistants.shop.domain.entity; + +public class ErwenEntity { +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/entity/StartEntity.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/entity/StartEntity.java new file mode 100644 index 0000000..d26ac90 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/entity/StartEntity.java @@ -0,0 +1,9 @@ +package fr.epita.assistants.shop.domain.entity; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class StartEntity { +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/service/ErwenService.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/service/ErwenService.java new file mode 100644 index 0000000..b7e8ad7 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/service/ErwenService.java @@ -0,0 +1,4 @@ +package fr.epita.assistants.shop.domain.service; + +public class ErwenService { +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/service/ShopService.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/service/ShopService.java new file mode 100644 index 0000000..06ed11c --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/domain/service/ShopService.java @@ -0,0 +1,79 @@ +package fr.epita.assistants.shop.domain.service; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.common.aggregate.ResetInventoryAggregate; +import fr.epita.assistants.common.aggregate.SyncInventoryAggregate; +import fr.epita.assistants.common.command.CollectItemCommand; +import fr.epita.assistants.common.command.ResetInventoryCommand; +import fr.epita.assistants.common.command.SyncInventoryCommand; +import fr.epita.assistants.shop.converter.ShopConverter; +import fr.epita.assistants.shop.data.model.ItemModel; +import fr.epita.assistants.shop.data.repository.ItemRepository; +import fr.epita.assistants.shop.data.repository.ShopRepository; +import io.smallrye.reactive.messaging.annotations.Broadcast; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.reactive.messaging.Channel; +import org.eclipse.microprofile.reactive.messaging.Emitter; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@ApplicationScoped +public class ShopService { + @ConfigProperty(name = "JWS_SHOP_PRICE") + String shopPrice; + @ConfigProperty(name = "JWS_UPGRADE_PRICE_COST") + String upgradePriceCost; + @Inject + ItemRepository itemRepository; + @Inject + ShopRepository shopRepository; + + @Inject + @Channel("sync-inventory-command") + @Broadcast + Emitter<SyncInventoryCommand> syncInventoryCommandEmitter; + + public void clearItems(ResetInventoryAggregate items) { + itemRepository.deleteItems(ShopConverter.DeleteItems(items)); + } + + 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 void startShop() { + shopRepository.clearDB(); + shopRepository.addEntry(1f, Float.parseFloat(upgradePriceCost)); + syncInventoryCommandEmitter.send(new SyncInventoryCommand()); + } + + @Transactional + public void updateItems(SyncInventoryAggregate agr) { + for (ItemAggregate item : agr.getItems()) { + Optional<ItemModel> it = itemRepository.exists(item.getType()); + if (it.isPresent()) { + itemRepository.fillInventory(item.getType(), item.getQuantity() + it.get().getQuantity()); + } else { + itemRepository.addItem(item.getType(), item.getQuantity()); + } + } + } + + public void pay(Float newMoney) { + itemRepository.fillInventory(ItemAggregate.ResourceType.MONEY, newMoney); + } +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/rest/HelloWorldResource.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/rest/HelloWorldResource.java new file mode 100644 index 0000000..e384c22 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/rest/HelloWorldResource.java @@ -0,0 +1,19 @@ +package fr.epita.assistants.shop.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/shop/src/main/java/fr/epita/assistants/shop/presentation/rest/ShopResource.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/rest/ShopResource.java new file mode 100644 index 0000000..71719d1 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/rest/ShopResource.java @@ -0,0 +1,63 @@ +package fr.epita.assistants.shop.presentation.rest; + +import fr.epita.assistants.common.api.request.ItemsRequest; +import fr.epita.assistants.common.api.request.StartRequest; +import fr.epita.assistants.common.utils.ErrorInfo; +import fr.epita.assistants.shop.domain.service.ShopService; +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 ShopResource { + private final ShopService shopService; + + @jakarta.inject.Inject + public ShopResource(ShopService shopService) { + this.shopService = shopService; + } + + @Path("/") + @GET + public Response getRoot() { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } + @Path("/") + @POST + public Response postRoot() { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } + @Path("resources") + @GET + public Response resources() { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } + @Path("start") + @POST + public Response start() { + shopService.startShop(); + return Response.status(Response.Status.NO_CONTENT).build(); + } + @Path("price") + @GET + public Response price() { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } + @Path("{id}") + @POST + public Response getShop(@PathParam("id") int id) { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } + @Path("sell/{id}") + @PATCH + public Response sellItems(@PathParam("id") int id, ItemsRequest itemsRequest) { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } + @Path("upgrade/price/{id}") + @PATCH + public Response upgradeShop(@PathParam("id") int id) { + return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorInfo("Not implemented")).build(); + } +} diff --git a/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/subscriber/AggregateSubscriber.java b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/subscriber/AggregateSubscriber.java new file mode 100644 index 0000000..26247b9 --- /dev/null +++ b/jws/epibazaar/shop/src/main/java/fr/epita/assistants/shop/presentation/subscriber/AggregateSubscriber.java @@ -0,0 +1,41 @@ +package fr.epita.assistants.shop.presentation.subscriber; + +import fr.epita.assistants.common.aggregate.ItemAggregate; +import fr.epita.assistants.common.aggregate.ResetInventoryAggregate; +import fr.epita.assistants.common.aggregate.SyncInventoryAggregate; +import fr.epita.assistants.common.aggregate.UpgradeItemProducerAggregate; +import fr.epita.assistants.common.command.CollectItemCommand; +import fr.epita.assistants.shop.domain.service.ShopService; +import io.smallrye.reactive.messaging.annotations.Broadcast; +import jakarta.inject.Inject; +import org.eclipse.microprofile.reactive.messaging.Incoming; +import org.eclipse.microprofile.reactive.messaging.Outgoing; + +public class AggregateSubscriber { + @Inject + ShopService shopService; + + @Broadcast + @Incoming("sync-inventory-aggregate") + public void commandListener(SyncInventoryAggregate aggregate) { + shopService.updateItems(aggregate); + } + + @Broadcast + @Incoming("upgrade-collect-rate-aggregate") + public void collectCommandListener(UpgradeItemProducerAggregate agr) { + shopService.pay(agr.getNewMoney()); + } + + @Broadcast + @Incoming("upgrade-movement-speed-aggregate") + public void moveCommandListener(UpgradeItemProducerAggregate agr) { + shopService.pay(agr.getNewMoney()); + } + + @Broadcast + @Incoming("upgrade-stamina-aggregate") + public void staminaCommandListener(UpgradeItemProducerAggregate agr) { + shopService.pay(agr.getNewMoney()); + } +} diff --git a/jws/epibazaar/shop/src/main/resources/application.properties b/jws/epibazaar/shop/src/main/resources/application.properties new file mode 100644 index 0000000..e2fa130 --- /dev/null +++ b/jws/epibazaar/shop/src/main/resources/application.properties @@ -0,0 +1,13 @@ +%dev.quarkus.http.port=8082 +quarkus.datasource.db-kind=postgresql +quarkus.datasource.username=postgres +quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/shop?currentSchema=public +quarkus.transaction-manager.default-transaction-timeout=3000s +quarkus.hibernate-orm.log.queries-slower-than-ms=200 +quarkus.http.cors=true +quarkus.http.cors.origins=* +quarkus.hibernate-orm.database.generation=drop-and-create + +quarkus.kafka.devservices.image-name=reg.undercloud.cri.epita.fr/docker/redpandadata/redpanda:v24.1.2 +quarkus.devservices.enabled=true +%test.quarkus.devservices.enabled=false diff --git a/jws/epibazaar/shop/src/main/resources/db/migration/V1__Init.sql b/jws/epibazaar/shop/src/main/resources/db/migration/V1__Init.sql new file mode 100644 index 0000000..0161cb5 --- /dev/null +++ b/jws/epibazaar/shop/src/main/resources/db/migration/V1__Init.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS "shop" +( + id SERIAL PRIMARY KEY NOT NULL, + + price_multiplier FLOAT NOT NULL, + upgrade_price FLOAT NOT NULL +); + +CREATE TABLE IF NOT EXISTS "item" +( + id SERIAL PRIMARY KEY NOT NULL, + + type VARCHAR(64) NOT NULL, + quantity FLOAT NOT NULL +); diff --git a/jws/epibazaar/shop/src/main/resources/openapi.yaml b/jws/epibazaar/shop/src/main/resources/openapi.yaml new file mode 100644 index 0000000..7b6928f --- /dev/null +++ b/jws/epibazaar/shop/src/main/resources/openapi.yaml @@ -0,0 +1,242 @@ +--- +openapi: 3.1.0 +tags: +- name: Game Management +- name: Inventory Management +- name: Shop Management +- name: Shop Operations +- name: Shop Upgrades +components: + schemas: + ItemRequest: + type: object + properties: + quantity: + type: number + format: float + type: + $ref: "#/components/schemas/ResourceType" + ItemResponse: + type: object + properties: + id: + type: integer + format: int32 + quantity: + type: number + format: float + type: + $ref: "#/components/schemas/ResourceType" + ItemsRequest: + type: object + properties: + itemsRequest: + type: array + items: + $ref: "#/components/schemas/ItemRequest" + ItemsResponse: + type: object + properties: + itemsResponse: + type: array + items: + $ref: "#/components/schemas/ItemResponse" + ResourceType: + type: string + enum: + - MONEY + - GROUND + - WATER + - ROCK + - WOOD + ShopPriceResponse: + type: object + properties: + shopPrice: + type: number + format: float + ShopResponse: + type: object + properties: + id: + type: integer + format: int32 + priceMultiplier: + type: number + format: float + upgradePrice: + type: number + format: float + ShopsResponse: + type: object + properties: + shops: + type: array + items: + $ref: "#/components/schemas/ShopResponse" +paths: + /: + get: + summary: Get all shops. + description: Retrieves all available shops. + x-quarkus-openapi-method-ref: m869844210_-222983088 + tags: + - Shop Management + responses: + "200": + description: The shops were successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/ShopsResponse" + "400": + description: The game is not running. + servers: + - url: http://localhost:8082/ + post: + summary: Create a new shop. + description: Creates a new shop. + x-quarkus-openapi-method-ref: m869844210_1764851887 + tags: + - Shop Management + responses: + "204": + description: The shop creation request was successfully sent. + "400": + description: "The game has reached its max capacity, you do not have enough\ + \ money, or the game is not running." + "404": + description: No money item found. + servers: + - url: http://localhost:8082/ + /price: + get: + summary: Get the current shop price. + description: Retrieves the current shop price. + x-quarkus-openapi-method-ref: m869844210_-271831484 + tags: + - Shop Management + responses: + "200": + description: The shop price was successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/ShopPriceResponse" + "400": + description: The game is not running. + servers: + - url: http://localhost:8082/ + /resources: + get: + summary: Retrieve available resources in inventory. + description: Fetch all resources currently available in the inventory. + x-quarkus-openapi-method-ref: m911209932_-1184004262 + tags: + - Inventory Management + responses: + "200": + description: The resources were successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/ItemsResponse" + "400": + description: The game is not running or the request is invalid. + servers: + - url: http://localhost:8082/ + /sell/{id}: + patch: + summary: Sell items to a client. + description: Processes the sale of items to a client. + x-quarkus-openapi-method-ref: m869844210_-1356306674 + tags: + - Shop Operations + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int32 + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/ItemsRequest" + required: true + responses: + "204": + description: The sell request was successfully sent. + "400": + description: "You do not have enough resources, an item is not sellable,\ + \ an amount is invalid, or the game is not running." + "404": + description: The shop or an item was not found. + servers: + - url: http://localhost:8082/ + /start: + post: + summary: Start the game. + description: Starts the game by sending a Kafka command. + x-quarkus-openapi-method-ref: m869844210_1873672464 + tags: + - Game Management + responses: + "204": + description: The game started successfully. + servers: + - url: http://localhost:8082/ + /upgrade/price/{id}: + patch: + summary: Upgrade the resource price for a specific shop. + description: Increases the resource price for a specific shop. + x-quarkus-openapi-method-ref: m869844210_-999917025 + tags: + - Shop Upgrades + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int32 + responses: + "204": + description: The price upgrade request was successfully sent. + "400": + description: You do not have enough money or the game is not running. + "404": + description: The shop was not found or the money was not found. + servers: + - url: http://localhost:8082/ + /{id}: + get: + summary: Get a specific shop. + description: Retrieves details of a specific shop. + x-quarkus-openapi-method-ref: m869844210_868322035 + tags: + - Shop Management + parameters: + - name: id + in: path + required: true + schema: + type: integer + format: int32 + responses: + "200": + description: The shop was successfully retrieved. + content: + application/json: + schema: + $ref: "#/components/schemas/ShopResponse" + "400": + description: The game is not running or the ID is not valid. + "404": + description: The shop was not found. + servers: + - url: http://localhost:8082/ +info: + title: shop API + version: 1.0.0 diff --git a/jws/epibazaar/viewer.tar.gz b/jws/epibazaar/viewer.tar.gz Binary files differnew file mode 100644 index 0000000..01be4e4 --- /dev/null +++ b/jws/epibazaar/viewer.tar.gz diff --git a/jws/flake.nix b/jws/flake.nix new file mode 100644 index 0000000..6bf8d07 --- /dev/null +++ b/jws/flake.nix @@ -0,0 +1,29 @@ +{ + description = "Java 2027"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + }; + in + with pkgs; + { + devShell = mkShell { + buildInputs = [ + jdk21_headless + postgresql + quarkus + maven + nodejs_22 + ]; + }; + } + ); +} diff --git a/jws/kafka/pom.xml b/jws/kafka/pom.xml new file mode 100644 index 0000000..35c8c59 --- /dev/null +++ b/jws/kafka/pom.xml @@ -0,0 +1,332 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>fr.epita.assistants</groupId> + <artifactId>kafka</artifactId> + <version>1.0.0</version> + + <properties> + <maven.compiler.release>21</maven.compiler.release> + <maven.compiler.source>21</maven.compiler.source> + <maven.compiler.target>21</maven.compiler.target> + + <compiler-plugin.version>3.13.0</compiler-plugin.version> + <maven.compiler.parameters>true</maven.compiler.parameters> + + <versions.maven-surefire-plugin>3.0.0-M5</versions.maven-surefire-plugin> + <versions.maven-jar-plugin>3.4.1</versions.maven-jar-plugin> + <versions.maven-install-plugin>3.1.2</versions.maven-install-plugin> + + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id> + <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id> + <quarkus.platform.version>3.17.5</quarkus.platform.version> + + <skipITs>true</skipITs> + + <surefire.reportsDirectory>${project.build.directory}/surefire-reports</surefire.reportsDirectory> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>${quarkus.platform.group-id}</groupId> + <artifactId>${quarkus.platform.artifact-id}</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-jackson</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-jackson-deployment</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-smallrye-reactive-messaging-kafka</artifactId> + <version>3.15.2</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-messaging-kafka</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-arc</artifactId> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.36</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>io.smallrye.reactive</groupId> + <artifactId>smallrye-reactive-messaging-in-memory</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.awaitility</groupId> + <artifactId>awaitility</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <version>3.26.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpmime</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-kotlin</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-messaging-kafka-deployment</artifactId> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom</artifactId> + <version>${quarkus.platform.version}</version> + <type>pom</type> + </dependency> + + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5-properties</artifactId> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + </dependency> + <dependency> + <groupId>org.opentest4j</groupId> + <artifactId>opentest4j</artifactId> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>org.apiguardian</groupId> + <artifactId>apiguardian-api</artifactId> + <version>1.1.2</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit-platform</artifactId> + <version>${versions.maven-surefire-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>common-java5</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-shared-utils</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-api</artifactId> + <version>3.5.2</version> + </dependency> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>3.17.5</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>${versions.maven-jar-plugin}</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-install-plugin</artifactId> + <version>${versions.maven-install-plugin}</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-rest-kotlin-deployment</artifactId> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-commons</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-repository-metadata</artifactId> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-registry</artifactId> + <version>2.0.6</version> + </dependency> + <dependency> + <groupId>classworlds</groupId> + <artifactId>classworlds</artifactId> + <version>1.1-alpha-2</version> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>3.17.5</version> + </dependency> + <dependency> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.7.0</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>fully.qualified.MainClass</mainClass> + </manifest> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </plugin> + <plugin> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-maven-plugin</artifactId> + <version>${quarkus.platform.version}</version> + <extensions>true</extensions> + <executions> + <execution> + <goals> + <goal>build</goal> + <goal>generate-code</goal> + <goal>generate-code-tests</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>${compiler-plugin.version}</version> + <configuration> + <parameters>${maven.compiler.parameters}</parameters> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <configuration> + <systemPropertyVariables> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>fetch-bom</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <dependencies> + <dependency> + <groupId>io.quarkus.platform</groupId> + <artifactId>quarkus-bom-quarkus-platform-properties</artifactId> + <version>3.17.5</version> + <type>properties</type> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + + <activation> + <property> + <name>native</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <version>${versions.maven-surefire-plugin}</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + <configuration> + <systemPropertyVariables> + <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path> + <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> + <maven.home>${maven.home}</maven.home> + </systemPropertyVariables> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + </profile> + </profiles> + +</project> diff --git a/jws/kafka/src/main/java/fr/epita/assistants/StringInfoProcessor.java b/jws/kafka/src/main/java/fr/epita/assistants/StringInfoProcessor.java new file mode 100644 index 0000000..b419623 --- /dev/null +++ b/jws/kafka/src/main/java/fr/epita/assistants/StringInfoProcessor.java @@ -0,0 +1,41 @@ +package fr.epita.assistants; + +import fr.epita.assistants.utils.StringInfo; +import io.smallrye.reactive.messaging.annotations.Broadcast; +import org.eclipse.microprofile.reactive.messaging.Incoming; +import org.eclipse.microprofile.reactive.messaging.Outgoing; + +public class StringInfoProcessor { + private boolean isPalindrome(String word) { + if (word == null) return false; + word = word.toLowerCase().strip(); + if (word.isEmpty()) return true; + for (int i = 0, j = word.length() - 1; i < j; i++, j--) { + while (word.charAt(i) == ' ') { + i++; + } + while (word.charAt(j) == ' ') { + j--; + } + if (word.charAt(i) != word.charAt(j)) return false; + } + return true; + } + + @Incoming("string-info-command") + @Outgoing("string-info-aggregate") + @Broadcast + public StringInfo process(String s) { + String tmp = s.toLowerCase(); + int v = 0; + int c = 0; + for (int i = 0; i < tmp.length(); i++) { + if (tmp.charAt(i) == 'a' || tmp.charAt(i) == 'e' || tmp.charAt(i) == 'i' || tmp.charAt(i) == 'o' || tmp.charAt(i) == 'u' || tmp.charAt(i) == 'y') + v++; + else if (tmp.charAt(i) <= 'z' && tmp.charAt(i) >= 'a') + c++; + } + return new StringInfo(s, v, c, isPalindrome(s)); + } + +}
\ No newline at end of file diff --git a/jws/kafka/src/main/java/fr/epita/assistants/StringInfoResource.java b/jws/kafka/src/main/java/fr/epita/assistants/StringInfoResource.java new file mode 100644 index 0000000..62a5d51 --- /dev/null +++ b/jws/kafka/src/main/java/fr/epita/assistants/StringInfoResource.java @@ -0,0 +1,25 @@ +package fr.epita.assistants; + +import io.smallrye.reactive.messaging.annotations.Broadcast; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.reactive.messaging.Channel; +import org.eclipse.microprofile.reactive.messaging.Emitter; + +import java.util.concurrent.CompletionStage; + +@Path("/send") +@Consumes +public class StringInfoResource { + @Inject + @Broadcast + @Channel("string-info-command") + Emitter<String> commandEmitter; + + @POST + public void send(String s) { + CompletionStage<Void> v = commandEmitter.send(s); + } +}
\ No newline at end of file diff --git a/jws/kafka/src/main/java/fr/epita/assistants/StringInfoSubscriber.java b/jws/kafka/src/main/java/fr/epita/assistants/StringInfoSubscriber.java new file mode 100644 index 0000000..c955270 --- /dev/null +++ b/jws/kafka/src/main/java/fr/epita/assistants/StringInfoSubscriber.java @@ -0,0 +1,13 @@ +package fr.epita.assistants; + +import fr.epita.assistants.utils.StringInfo; +import io.smallrye.reactive.messaging.annotations.Broadcast; +import org.eclipse.microprofile.reactive.messaging.Incoming; + +public class StringInfoSubscriber { + @Incoming("string-info-aggregate") + @Broadcast + public void subscribe(StringInfo si) { + System.out.println(si.toString()); + } +}
\ No newline at end of file diff --git a/jws/kafka/src/main/java/fr/epita/assistants/utils/StringInfo.java b/jws/kafka/src/main/java/fr/epita/assistants/utils/StringInfo.java new file mode 100644 index 0000000..c328ac3 --- /dev/null +++ b/jws/kafka/src/main/java/fr/epita/assistants/utils/StringInfo.java @@ -0,0 +1,13 @@ +package fr.epita.assistants.utils; + +import lombok.ToString; +import lombok.Value; + +@Value +@ToString +public class StringInfo { + String word; + Integer nbVowels; + Integer nbConsonants; + Boolean isPalindrome; +} diff --git a/jws/kafka/src/main/resources/application.properties b/jws/kafka/src/main/resources/application.properties new file mode 100644 index 0000000..9db5e48 --- /dev/null +++ b/jws/kafka/src/main/resources/application.properties @@ -0,0 +1,3 @@ +quarkus.devservices.enabled=true +quarkus.kafka.devservices.image-name=reg.undercloud.cri.epita.fr/docker/redpandadata/redpanda:v24.1.2 +%test.quarkus.devservices.enabled=false |
