Skip to content

Commit

Permalink
Merge pull request #19 from vavarm/18-link-frontend-and-backend
Browse files Browse the repository at this point in the history
18 link frontend and backend
  • Loading branch information
vavarm committed Mar 25, 2024
2 parents da71149 + 590e2e1 commit 476e4f0
Show file tree
Hide file tree
Showing 20 changed files with 196 additions and 45 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ sonar {
}

dependencies {
implementation 'io.quarkus:quarkus-smallrye-reactive-messaging-mqtt'
implementation 'io.quarkus:quarkus-smallrye-openapi'
implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
implementation 'io.quarkus:quarkus-arc'
implementation 'io.quarkus:quarkus-resteasy-reactive-jackson'
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
testImplementation 'io.quarkus:quarkus-junit5'
testImplementation 'io.rest-assured:rest-assured'
testImplementation "io.quarkus:quarkus-jacoco"
Expand Down
111 changes: 83 additions & 28 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ function App() {

const [startTime, setStartTime] = useState(Date.now())

const [gameField, setGameField] = useState({size: {x: 0, y: 0}, nbGarages: 0, nbGasStations: 0})

const [pseudoField, setPseudoField] = useState('')

const [pseudo, setPseudo] = useState('')

const [game, setGame] = useState({x: 0, y: 0, garages: [], gasStations: [], vehicles: []})
const [game, setGame] = useState({size: {x: 0, y: 0}, garages: [], gasStations: [], vehicles: []})
// game with x, y, garages, gasStations, vehicles
/* const [game, setGame] = useState(
{
Expand All @@ -41,14 +43,8 @@ function App() {

const createGame = async () => {
try {
const response = await axios.post(`${backendUrl}/game`, {
x: 10,
y: 10,
})
const response = await axios.post(`${backendUrl}/game`, gameField)
console.log(response.data)
setGame(prevState =>
({...prevState, x: response.data.x, y: response.data.y, garages: [], gasStations: [], vehicles: []})
)
} catch (error) {
console.error(error)
}
Expand All @@ -66,8 +62,9 @@ function App() {

const createVehicle = async () => {
axios.post(`${backendUrl}/vehicle`, {
pseudo: pseudoField,
}).then(response => {
pseudo: pseudoField
}
).then(response => {
console.log(response.data)
setPseudo(response.data.pseudo)
}).catch(error => {
Expand Down Expand Up @@ -117,6 +114,16 @@ function App() {
});
}

const checkIfPlayerIsDead = (data) => {
if (!pseudo) return;
//get all pseudos
const pseudos = data.vehicles.map(vehicle => vehicle.pseudo);
//check if the pseudo is in the list
if (!pseudos.includes(pseudo)) {
setPseudo('');
}
}

useEffect(() => {
mqttConnect()
}, []);
Expand All @@ -130,6 +137,7 @@ function App() {
mqttClient.on('message', (topic, message) => {
console.log(topic, message.toString())
const data = JSON.parse(message.toString())
checkIfPlayerIsDead(data)
setGame(data)
})
}
Expand All @@ -148,17 +156,64 @@ function App() {

return (
<div className="App" style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100vh', width: '100vw'}}>
{ game.x === 0 &&
<div>
{ game.size.x === 0 &&
<>
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
}}>
<span>Game width</span>
<input type={"number"} value={gameField.size.x} onChange={(event) => setGameField({
...gameField,
size: {x: event.target.value, y: gameField.size.y}
})} placeholder="Size x"/>
</div>
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
}}>
<span>Game height</span>
<input type={"number"} value={gameField.size.y} onChange={(event) => setGameField({
...gameField,
size: {x: gameField.size.x, y: event.target.value}
})} placeholder="Size y"/>
</div>
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
}}>
<span>Number of garages</span>
<input type={"number"} value={gameField.nbGarages}
onChange={(event) => setGameField({...gameField, nbGarages: event.target.value})}
placeholder="Number of garages"/>
</div>
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
}}>
<span>Number of gas stations</span>
<input type={"number"} value={gameField.nbGasStations}
onChange={(event) => setGameField({...gameField, nbGasStations: event.target.value})}
placeholder="Number of gas stations"/>
</div>
<button onClick={createGame}>Create New Game</button>
</div>
<button onClick={getGame}>Join Game</button>
</>
}
{pseudo.length !== 0 ?
<div>
<h1>Your pseudo: {pseudo}</h1>
</div>
:
game.x !== 0 &&
game.size.x !== 0 &&
<div>
<input
type="text"
Expand All @@ -170,45 +225,45 @@ function App() {
</div>
}
<div className="game" style={{flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: `100%`}}>
{game.x !== 0 &&
Array.from({length: game.y}, (_, i) =>
<div key={i} className="row" style={{display: 'flex', flexDirection: 'row', justifyContent: "center", width: `100%`, height: `calc(90% / ${game.y})`}}>
{Array.from({length: game.x}, (_, j) =>
<div key={j} className="cell" style={{height: `100%`, width: `calc(90% / ${game.x})`, display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid black'}}>
{game.size.x !== 0 &&
Array.from({length: game.size.y}, (_, i) =>
<div key={i} className="row" style={{display: 'flex', flexDirection: 'row', justifyContent: "center", width: `100%`, height: `calc(90% / ${game.size.y})`}}>
{Array.from({length: game.size.x}, (_, j) =>
<div key={j} className="cell" style={{height: `100%`, width: `calc(90% / ${game.size.x})`, display: 'flex', justifyContent: 'center', alignItems: 'center', border: '1px solid black'}}>
{
// if garage, then display a garage emote and the pseudo of all the vehicles in the garage
// else if gas station, then display a gas station emote and the pseudo of all the vehicles in the gas station
// else if vehicle, then display a vehicle emote
// else display nothing
}
{
game.garages.some(garage => garage.x === j && garage.y === i) ?
game.garages.some(garage => garage.position.x === j && garage.position.y === i) ?
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
🏠
<div>{game.vehicles.filter(vehicle => vehicle.x === j && vehicle.y === i).map(vehicle => vehicle.pseudo).join(', ')}</div>
<div>{game.vehicles.filter(vehicle => vehicle.position.x === j && vehicle.position.y === i).map(vehicle => vehicle.pseudo).join(', ')}</div>
</div>
:
game.gasStations.some(gasStation => gasStation.x === j && gasStation.y === i) ?
game.gasStations.some(gasStation => gasStation.position.x === j && gasStation.position.y === i) ?
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
<div>{game.vehicles.filter(vehicle => vehicle.x === j && vehicle.y === i).map(vehicle => vehicle.pseudo).join(', ')}</div>
<div>{game.vehicles.filter(vehicle => vehicle.position.x === j && vehicle.position.y === i).map(vehicle => vehicle.pseudo).join(', ')}</div>
</div>
:
game.vehicles.some(vehicle => vehicle.x === j && vehicle.y === i) ?
game.vehicles.some(vehicle => vehicle.position.x === j && vehicle.position.y === i) ?
<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
{
game.vehicles.find(vehicle => vehicle.x === j && vehicle.y === i).direction === "UP" ?
game.vehicles.find(vehicle => vehicle.position.x === j && vehicle.position.y === i).direction === "UP" ?
'⬆️'
:
game.vehicles.find(vehicle => vehicle.x === j && vehicle.y === i).direction === "RIGHT" ?
game.vehicles.find(vehicle => vehicle.position.x === j && vehicle.position.y === i).direction === "RIGHT" ?
'➡️'
:
game.vehicles.find(vehicle => vehicle.x === j && vehicle.y === i).direction === "DOWN" ?
game.vehicles.find(vehicle => vehicle.position.x === j && vehicle.position.y === i).direction === "DOWN" ?
'⬇️'
:
'⬅️'
}
<div>{game.vehicles.find(vehicle => vehicle.x === j && vehicle.y === i).pseudo}</div>
<div>{game.vehicles.find(vehicle => vehicle.position.x === j && vehicle.position.y === i).pseudo}</div>
</div>
:
null
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#Gradle properties
#Fri Mar 01 13:00:39 CET 2024
#Mon Mar 25 07:55:06 CET 2024
quarkusPlatformArtifactId=quarkus-bom
quarkusPlatformGroupId=io.quarkus.platform
quarkusPlatformVersion=3.8.1
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
11 changes: 9 additions & 2 deletions src/main/java/org/acme/ctrl/GameController.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
package org.acme.ctrl;

import io.quarkus.logging.Log;
import io.smallrye.reactive.messaging.providers.extension.EmitterImpl;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.acme.dto.CreateGameDTO;
import org.acme.model.Game;
import org.acme.svc.GameService;
import org.acme.svc.MQTTService;
import org.acme.svc.impl.GameServiceImpl;
import org.acme.svc.impl.MQTTServiceImpl;

@Path("/game")
public class GameController {

private final GameService gameService;

private final MQTTService mqttService;

@Inject
public GameController() {
this.gameService = new GameServiceImpl();
this.mqttService = new MQTTServiceImpl();
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createGame(CreateGameDTO createGameDTO){
// TODO : envoyer avec MQTT
Log.info("Creating game with size: x=" + createGameDTO.getSize().getx() + " y=" + createGameDTO.getSize().gety());
if ( gameService.createGame(createGameDTO) ) {
mqttService.sendGameState();
return Response.status(201).entity(createGameDTO).build();
}
return Response.status(400).build();
Expand All @@ -34,10 +41,10 @@ public Response createGame(CreateGameDTO createGameDTO){
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getGameState(){
// TODO : envoyer avec MQTT
Log.info("Getting game state");
String gameState = gameService.getGameState();
if (gameState != null) {
mqttService.sendGameState();
return Response.status(200).entity(gameState).build();
}
return Response.status(500).build();
Expand Down
18 changes: 12 additions & 6 deletions src/main/java/org/acme/ctrl/VehicleController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,34 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.acme.common.MoveState;
import org.acme.dto.CreateVehicleDTO;
import org.acme.dto.MoveVehicleDTO;
import org.acme.svc.MQTTService;
import org.acme.svc.VehicleService;
import org.acme.svc.impl.MQTTServiceImpl;
import org.acme.svc.impl.VehicleServiceImpl;

@Path("/vehicle")
public class VehicleController {

private final VehicleService vehicleService;

private final MQTTService mqttService;

@Inject
public VehicleController() {
vehicleService = new VehicleServiceImpl();
mqttService = new MQTTServiceImpl();
}

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createVehicle(String pseudo){
// TODO : envoyer avec MQTT
Log.info("Creating vehicle with pseudo: " + pseudo);
if ( vehicleService.createVehicle(pseudo) ) {
return Response.status(201).entity(pseudo).build();
public Response createVehicle(CreateVehicleDTO dto){
Log.info("Creating vehicle with pseudo: " + dto.getPseudo());
if ( vehicleService.createVehicle(dto.getPseudo()) ) {
mqttService.sendGameState();
return Response.status(201).entity(dto).build();
}
return Response.status(400).build();
}
Expand All @@ -36,11 +42,11 @@ public Response createVehicle(String pseudo){
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response moveVehicle(MoveVehicleDTO moveVehicleDTO){
// TODO : envoyer avec MQTT
Log.info("Moving vehicle with pseudo: " + moveVehicleDTO.getPseudo() + " in direction: " + moveVehicleDTO.getDirection());
MoveState moveState = vehicleService.moveVehicle(moveVehicleDTO);
Log.info("Move state: " + moveState);
if (moveState == MoveState.SUCCESS) {
mqttService.sendGameState();
return Response.status(200).entity(moveState).build();
}
return Response.status(400).build();
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/acme/dto/CreateVehicleDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.acme.dto;

import org.acme.common.Direction;

public class CreateVehicleDTO {
private String pseudo;

public CreateVehicleDTO() {
this.pseudo = "";
}

public CreateVehicleDTO(String pseudo) {
this.pseudo = pseudo;
}

public String getPseudo() {
return pseudo;
}

public void setPseudo(String pseudo) {
this.pseudo = pseudo;
}
}
2 changes: 1 addition & 1 deletion src/main/java/org/acme/model/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public int hashCode() {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\"Game\":{");
sb.append("{");
sb.append("\"size\":{");
sb.append("\"x\":").append(size.getx());
sb.append(", ");
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/acme/svc/MQTTService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.acme.svc;

public interface MQTTService {

public void sendGameState();

}
Loading

0 comments on commit 476e4f0

Please sign in to comment.