Skip to content

Commit

Permalink
Merge pull request #47 from PaulKreft/persist-multiplayer-games
Browse files Browse the repository at this point in the history
Persist multiplayer games
  • Loading branch information
PaulKreft authored Feb 22, 2024
2 parents e107eed + e15e950 commit 0cdbbee
Show file tree
Hide file tree
Showing 28 changed files with 262 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,15 @@ public String handleException(UsernameNotFoundException exception) {
return exception.getMessage();
}

@ExceptionHandler({LobbyNotFoundException.class})
@ExceptionHandler({LobbyGoneException.class})
@ResponseStatus(HttpStatus.GONE)
public String handleException(LobbyGoneException exception) {
return exception.getMessage();
}

@ExceptionHandler({RequestQueueNotFoundException.class})
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handleException(LobbyNotFoundException exception) {
public String handleException(RequestQueueNotFoundException exception) {
return exception.getMessage();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.neuefische.paulkreft.backend.exception;

public class LobbyGoneException extends RuntimeException {
public LobbyGoneException(String errorMessage) {
super(errorMessage);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.neuefische.paulkreft.backend.exception;

public class RequestQueueNotFoundException extends RuntimeException {
public RequestQueueNotFoundException(String errorMessage) {
super(errorMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package de.neuefische.paulkreft.backend.game.controller;
package de.neuefische.paulkreft.backend.game.classic.controller;

import de.neuefische.paulkreft.backend.game.model.Game;
import de.neuefische.paulkreft.backend.game.model.GameCreate;
import de.neuefische.paulkreft.backend.game.service.GameService;
import de.neuefische.paulkreft.backend.game.classic.model.Game;
import de.neuefische.paulkreft.backend.game.classic.model.GameCreate;
import de.neuefische.paulkreft.backend.game.classic.service.GameService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/games")
@RequestMapping("/api/game")
public class GameController {
private final GameService gameService;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.neuefische.paulkreft.backend.game.model;
package de.neuefische.paulkreft.backend.game.classic.model;

import org.springframework.data.annotation.Id;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.neuefische.paulkreft.backend.game.model;
package de.neuefische.paulkreft.backend.game.classic.model;

import java.time.Instant;
import java.util.List;
Expand All @@ -11,7 +11,6 @@ public record GameCreate(
int duration,
List<String> configuration
) {

public Game withIdAndCreatedAt(String id, Instant createdAt) {
return new Game(id, this.userId, this.type, this.difficulty, this.isSuccess, this.duration, this.configuration, createdAt);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.neuefische.paulkreft.backend.game.repository;
package de.neuefische.paulkreft.backend.game.classic.repository;

import de.neuefische.paulkreft.backend.game.model.Game;
import de.neuefische.paulkreft.backend.game.classic.model.Game;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package de.neuefische.paulkreft.backend.game.service;
package de.neuefische.paulkreft.backend.game.classic.service;

import de.neuefische.paulkreft.backend.game.model.Game;
import de.neuefische.paulkreft.backend.game.model.GameCreate;
import de.neuefische.paulkreft.backend.game.repository.GameRepo;
import de.neuefische.paulkreft.backend.service.IdService;
import de.neuefische.paulkreft.backend.service.TimeService;
import de.neuefische.paulkreft.backend.game.classic.model.Game;
import de.neuefische.paulkreft.backend.game.classic.model.GameCreate;
import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo;
import de.neuefische.paulkreft.backend.utils.service.IdService;
import de.neuefische.paulkreft.backend.utils.service.TimeService;
import org.springframework.stereotype.Service;

import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.neuefische.paulkreft.backend.game.multiplayer.controller;

import de.neuefische.paulkreft.backend.game.multiplayer.model.MultiplayerGame;
import de.neuefische.paulkreft.backend.game.multiplayer.model.MultiplayerGameCreate;
import de.neuefische.paulkreft.backend.game.multiplayer.service.MultiplayerService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/game/multiplayer")
public class MultiplayerController {
private final MultiplayerService multiplayerService;

public MultiplayerController(MultiplayerService multiplayerService) {
this.multiplayerService = multiplayerService;
}

@PostMapping
public MultiplayerGame createMultiplayerGame(@RequestBody MultiplayerGameCreate multiplayerGameCreate) {
return multiplayerService.createGame(multiplayerGameCreate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package de.neuefische.paulkreft.backend.game.multiplayer.model;

import org.springframework.data.annotation.Id;

import java.time.Instant;
import java.util.List;

public record MultiplayerGame(
@Id
String id,
List<String> playerIds,
int difficulty,
Integer streakToWin,
String winnerId,
List<String> loserIds,
Integer wonInMilliseconds,
Instant createdAt
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.neuefische.paulkreft.backend.game.multiplayer.model;

import java.time.Instant;
import java.util.List;

public record MultiplayerGameCreate(
List<String> playerIds,
int difficulty,
Integer streakToWin,
String winnerId,
List<String> loserIds,
Integer wonInMilliseconds
) {
public MultiplayerGame withIdAndCreatedAt(String id, Instant createdAt) {
return new MultiplayerGame(id, this.playerIds, this.difficulty, this.streakToWin, this.winnerId, this.loserIds, this.wonInMilliseconds, createdAt);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package de.neuefische.paulkreft.backend.game.multiplayer.repository;

import de.neuefische.paulkreft.backend.game.multiplayer.model.MultiplayerGame;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MultiplayerGameRepo extends MongoRepository<MultiplayerGame, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.neuefische.paulkreft.backend.game.multiplayer.service;

import de.neuefische.paulkreft.backend.game.multiplayer.model.MultiplayerGame;
import de.neuefische.paulkreft.backend.game.multiplayer.model.MultiplayerGameCreate;
import de.neuefische.paulkreft.backend.game.multiplayer.repository.MultiplayerGameRepo;
import de.neuefische.paulkreft.backend.utils.service.IdService;
import de.neuefische.paulkreft.backend.utils.service.TimeService;
import org.springframework.stereotype.Service;

@Service
public class MultiplayerService {
private final MultiplayerGameRepo multiplayerGameRepo;
private final IdService idService;
private final TimeService timeService;

public MultiplayerService(MultiplayerGameRepo multiplayerGameRepo, IdService idService, TimeService timeService) {
this.multiplayerGameRepo = multiplayerGameRepo;
this.idService = idService;
this.timeService = timeService;
}

public MultiplayerGame createGame(MultiplayerGameCreate multiplayerGameCreate) {
return multiplayerGameRepo.save(multiplayerGameCreate.withIdAndCreatedAt(idService.generateUUID(), timeService.getNow()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import de.neuefische.paulkreft.backend.exception.LobbyNotFoundException;
import de.neuefische.paulkreft.backend.exception.RequestQueueNotFoundException;
import de.neuefische.paulkreft.backend.lobby.model.Lobby;
import de.neuefische.paulkreft.backend.lobby.service.LobbyService;
import de.neuefische.paulkreft.backend.user.model.Player;
Expand All @@ -27,11 +27,11 @@ public DeferredResult<Lobby> getGameUpdate(@PathVariable String id) {
ConcurrentLinkedQueue<DeferredResult<Lobby>> queue = this.queuedRequests.get(id);

if (queue == null) {
throw new LobbyNotFoundException("Lobby does not exist in database");
throw new RequestQueueNotFoundException("Cannot resolve request");
}

DeferredResult<Lobby> updatedLobby = new DeferredResult<>();
updatedLobby.onTimeout(() -> queue.remove(updatedLobby));
updatedLobby.onTimeout(() -> resolveRequest(lobbyService.getLobbyById(id)));
queue.add(updatedLobby);
return updatedLobby;
}
Expand Down Expand Up @@ -97,7 +97,7 @@ public void resolveRequest(Lobby lobby) {
ConcurrentLinkedQueue<DeferredResult<Lobby>> queue = this.queuedRequests.get(lobby.id());

if (queue == null) {
throw new LobbyNotFoundException("Lobby does not exist in database");
throw new RequestQueueNotFoundException("Cannot resolve request");
}

for (DeferredResult<Lobby> defResult : queue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import de.neuefische.paulkreft.backend.exception.LobbyNotFoundException;
import de.neuefische.paulkreft.backend.exception.LobbyGoneException;
import de.neuefische.paulkreft.backend.exception.PlayerNotPartOfLobbyException;
import de.neuefische.paulkreft.backend.lobby.model.Lobby;
import de.neuefische.paulkreft.backend.lobby.repository.LobbyRepo;
Expand All @@ -24,13 +24,13 @@ public Lobby createLobby(Lobby lobby) {
}

public Lobby getLobbyById(String id) {
return lobbyRepo.findById(id).orElseThrow(() -> new LobbyNotFoundException("Could not find lobby"));
return lobbyRepo.findById(id).orElseThrow(() -> new LobbyGoneException("Could not find lobby"));
}


public Lobby updateLobby(Lobby lobby) {
if (!lobbyRepo.existsById(lobby.id())) {
throw new LobbyNotFoundException("Could not find lobby");
throw new LobbyGoneException("Could not find lobby");
}

return lobbyRepo.save(lobby);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package de.neuefische.paulkreft.backend.user.service;

import de.neuefische.paulkreft.backend.exception.GithubEmailNotFoundException;
import de.neuefische.paulkreft.backend.game.model.Game;
import de.neuefische.paulkreft.backend.game.repository.GameRepo;
import de.neuefische.paulkreft.backend.game.classic.model.Game;
import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo;
import de.neuefische.paulkreft.backend.github.service.GithubService;
import de.neuefische.paulkreft.backend.service.IdService;
import de.neuefische.paulkreft.backend.service.TimeService;
import de.neuefische.paulkreft.backend.utils.service.IdService;
import de.neuefische.paulkreft.backend.utils.service.TimeService;
import de.neuefische.paulkreft.backend.user.model.ScoreMap;
import de.neuefische.paulkreft.backend.user.model.Statistics;
import de.neuefische.paulkreft.backend.user.model.User;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.neuefische.paulkreft.backend.service;
package de.neuefische.paulkreft.backend.utils.service;

import org.springframework.stereotype.Service;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.neuefische.paulkreft.backend.service;
package de.neuefische.paulkreft.backend.utils.service;

import org.springframework.stereotype.Service;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package de.neuefische.paulkreft.backend.game.controller;

import de.neuefische.paulkreft.backend.game.model.Game;
import de.neuefische.paulkreft.backend.game.repository.GameRepo;
import de.neuefische.paulkreft.backend.service.IdService;
import de.neuefische.paulkreft.backend.service.TimeService;
import de.neuefische.paulkreft.backend.game.classic.model.Game;
import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo;
import de.neuefische.paulkreft.backend.utils.service.IdService;
import de.neuefische.paulkreft.backend.utils.service.TimeService;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -48,7 +48,7 @@ void createGameTest_whenGameCreateGiven_thenReturnGame() throws Exception {
when(idService.generateUUID()).thenReturn("gameId");

// Given, when and then
mockMvc.perform(MockMvcRequestBuilders.post("/api/games")
mockMvc.perform(MockMvcRequestBuilders.post("/api/game")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
Expand Down Expand Up @@ -93,7 +93,7 @@ void getGamesByUserIdTest_whenOneMatchingGameInDB_thenReturnMatchingGame() throw
gameRepo.save(testGame2);

// When
mockMvc.perform(MockMvcRequestBuilders.get("/api/games/user/User1"))
mockMvc.perform(MockMvcRequestBuilders.get("/api/game/user/User1"))
// Then
.andExpect(status().isOk())
.andExpect(content().json("""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package de.neuefische.paulkreft.backend.game.service;

import de.neuefische.paulkreft.backend.game.model.Game;
import de.neuefische.paulkreft.backend.game.model.GameCreate;
import de.neuefische.paulkreft.backend.game.repository.GameRepo;
import de.neuefische.paulkreft.backend.service.IdService;
import de.neuefische.paulkreft.backend.service.TimeService;
import de.neuefische.paulkreft.backend.game.classic.model.Game;
import de.neuefische.paulkreft.backend.game.classic.model.GameCreate;
import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo;
import de.neuefische.paulkreft.backend.game.classic.service.GameService;
import de.neuefische.paulkreft.backend.utils.service.IdService;
import de.neuefische.paulkreft.backend.utils.service.TimeService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

Expand Down
Loading

0 comments on commit 0cdbbee

Please sign in to comment.