From a8fcaeca5e22d81ece1138290cd1db03bcd1d760 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Thu, 22 Feb 2024 11:50:43 +0100 Subject: [PATCH 01/18] folder structure --- .../{user => statistic}/model/ScoreMap.java | 2 +- .../{user => statistic}/model/Statistics.java | 2 +- .../statistic/service/StatisticService.java | 131 ++++++++++++++++++ .../user/controller/UserController.java | 2 +- .../backend/user/service/UserService.java | 121 +--------------- .../service/StatisticServiceTest.java | 96 +++++++++++++ .../backend/user/service/UserServiceTest.java | 86 +----------- 7 files changed, 239 insertions(+), 201 deletions(-) rename backend/src/main/java/de/neuefische/paulkreft/backend/{user => statistic}/model/ScoreMap.java (62%) rename backend/src/main/java/de/neuefische/paulkreft/backend/{user => statistic}/model/Statistics.java (79%) create mode 100644 backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java create mode 100644 backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/model/ScoreMap.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/ScoreMap.java similarity index 62% rename from backend/src/main/java/de/neuefische/paulkreft/backend/user/model/ScoreMap.java rename to backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/ScoreMap.java index 16a98d4..1d791aa 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/model/ScoreMap.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/ScoreMap.java @@ -1,4 +1,4 @@ -package de.neuefische.paulkreft.backend.user.model; +package de.neuefische.paulkreft.backend.statistic.model; public record ScoreMap( Double easy, diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/model/Statistics.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/Statistics.java similarity index 79% rename from backend/src/main/java/de/neuefische/paulkreft/backend/user/model/Statistics.java rename to backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/Statistics.java index c29bd46..74cd8ca 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/model/Statistics.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/Statistics.java @@ -1,4 +1,4 @@ -package de.neuefische.paulkreft.backend.user.model; +package de.neuefische.paulkreft.backend.statistic.model; public record Statistics( ScoreMap longestWinningStreak, diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java new file mode 100644 index 0000000..2cfbd2b --- /dev/null +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -0,0 +1,131 @@ +package de.neuefische.paulkreft.backend.statistic.service; + +import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; +import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; +import de.neuefische.paulkreft.backend.statistic.model.Statistics; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.*; + + + +@Service +@RequiredArgsConstructor +public class StatisticService { + private final GameRepo gameRepo; + + private static final int EASY = 1; + private static final int MEDIUM = 2; + private static final int HARD = 4; + + public Statistics getUserStatistics(String id) { + List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); + + List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); + List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); + List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); + + ScoreMap longestWinningStreaks = getLongestWinningStreaks(easyGames, mediumGames, hardGames); + ScoreMap longestLosingStreaks = getLongestLosingStreaks(easyGames, mediumGames, hardGames); + ScoreMap totalGames = getTotalGames(easyGames, mediumGames, hardGames); + ScoreMap totalGamesWon = getGamesWon(easyGames, mediumGames, hardGames); + ScoreMap fastestSolve = getFastestSolves(easyGames, mediumGames, hardGames); + ScoreMap averageDuration = getAverageDurations(easyGames, mediumGames, hardGames); + + return new Statistics(longestWinningStreaks, longestLosingStreaks, totalGames, totalGamesWon, fastestSolve, averageDuration); + } + + + private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { + List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); + List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); + List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); + + Double averageDurationEasy = !easyDurations.isEmpty() ? easyDurations.stream().mapToDouble(v -> v).sum() / easyDurations.size() : null; + Double averageDurationMedium = !mediumDurations.isEmpty() ? mediumDurations.stream().mapToDouble(v -> v).sum() : null; + Double averageDurationHard = !hardDurations.isEmpty() ? hardDurations.stream().mapToDouble(v -> v).sum() : null; + + return new ScoreMap(averageDurationEasy, averageDurationMedium, averageDurationHard); + } + + private ScoreMap getFastestSolves(List easyGames, List mediumGames, List hardGames) { + List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); + List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); + List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); + + Double fastestSolveEasy = !easyDurations.isEmpty() ? Collections.min(easyDurations) : null; + Double fastestSolveMedium = !mediumDurations.isEmpty() ? Collections.min(mediumDurations) : null; + Double fastestSolveHard = !hardDurations.isEmpty() ? Collections.min(hardDurations) : null; + + return new ScoreMap(fastestSolveEasy, fastestSolveMedium, fastestSolveHard); + } + + private ScoreMap getTotalGames(List easyGames, List mediumGames, List hardGames) { + return new ScoreMap((double) easyGames.size(), (double) mediumGames.size(), (double) hardGames.size()); + } + + private ScoreMap getGamesWon(List easyGames, List mediumGames, List hardGames) { + return new ScoreMap((double) easyGames.stream().filter(Game::isSuccess).toList().size(), (double) mediumGames.stream().filter(Game::isSuccess).toList().size(), (double) hardGames.stream().filter(Game::isSuccess).toList().size()); + } + + private ScoreMap getLongestWinningStreaks(List easyGames, List mediumGames, List hardGames) { + Map easyStreaks = getStreaks(easyGames); + Map mediumStreaks = getStreaks(mediumGames); + Map hardStreaks = getStreaks(hardGames); + + + return new ScoreMap(easyStreaks.get("win"), mediumStreaks.get("win"), hardStreaks.get("win")); + } + + private ScoreMap getLongestLosingStreaks(List easyGames, List mediumGames, List hardGames) { + Map easyStreaks = getStreaks(easyGames); + Map mediumStreaks = getStreaks(mediumGames); + Map hardStreaks = getStreaks(hardGames); + + + return new ScoreMap(easyStreaks.get("lose"), mediumStreaks.get("lose"), hardStreaks.get("lose")); + } + + private Map getStreaks(List games) { + Map streaks = new HashMap<>(); + + List winningStreaks = new ArrayList<>(); + List losingStreaks = new ArrayList<>(); + + double winningStreak = 0; + double losingStreak = 0; + + for (Game game : games) { + if (game.isSuccess()) { + winningStreak++; + if (losingStreak != 0) { + losingStreaks.add(losingStreak); + losingStreak = 0; + } + continue; + } + + losingStreak++; + if (winningStreak != 0) { + winningStreaks.add(winningStreak); + winningStreak = 0; + } + } + + if (winningStreak != 0) { + winningStreaks.add(winningStreak); + } + + if (losingStreak != 0) { + losingStreaks.add(losingStreak); + } + + + streaks.put("win", !winningStreaks.isEmpty() ? Collections.max(winningStreaks) : 0.0); + streaks.put("lose", !losingStreaks.isEmpty() ? Collections.max(losingStreaks) : 0.0); + + return streaks; + } +} diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java b/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java index bdadf09..74c3034 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.user.controller; -import de.neuefische.paulkreft.backend.user.model.Statistics; +import de.neuefische.paulkreft.backend.statistic.model.Statistics; import de.neuefische.paulkreft.backend.user.model.User; import de.neuefische.paulkreft.backend.user.model.UserGet; import de.neuefische.paulkreft.backend.user.service.UserService; diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java index adafe31..91f2a5b 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java @@ -1,13 +1,11 @@ package de.neuefische.paulkreft.backend.user.service; import de.neuefische.paulkreft.backend.exception.GithubEmailNotFoundException; -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.statistic.model.Statistics; +import de.neuefische.paulkreft.backend.statistic.service.StatisticService; 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; import de.neuefische.paulkreft.backend.user.model.UserGet; import de.neuefische.paulkreft.backend.user.repository.UsersRepo; @@ -21,22 +19,18 @@ import java.security.Principal; import java.time.Instant; -import java.util.*; @Service @RequiredArgsConstructor public class UserService { private final UsersRepo usersRepo; - private final GameRepo gameRepo; + + private final StatisticService statisticService; private final IdService idService; private final TimeService timeService; private final GithubService githubService; - private static final int EASY = 1; - private static final int MEDIUM = 2; - private static final int HARD = 4; - public UserGet getLoggedInUser(Principal user, HttpServletRequest request) { if (user == null) { return null; @@ -104,112 +98,7 @@ public boolean existsByEmail(String email) { } public Statistics getStatistics(String id) { - List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); - - List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); - List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); - List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); - - ScoreMap longestWinningStreaks = getLongestWinningStreaks(easyGames, mediumGames, hardGames); - ScoreMap longestLosingStreaks = getLongestLosingStreaks(easyGames, mediumGames, hardGames); - ScoreMap totalGames = getTotalGames(easyGames, mediumGames, hardGames); - ScoreMap totalGamesWon = getGamesWon(easyGames, mediumGames, hardGames); - ScoreMap fastestSolve = getFastestSolves(easyGames, mediumGames, hardGames); - ScoreMap averageDuration = getAverageDurations(easyGames, mediumGames, hardGames); - - return new Statistics(longestWinningStreaks, longestLosingStreaks, totalGames, totalGamesWon, fastestSolve, averageDuration); - } - - - private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { - List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); - List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); - List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); - - Double averageDurationEasy = !easyDurations.isEmpty() ? easyDurations.stream().mapToDouble(v -> v).sum() / easyDurations.size() : null; - Double averageDurationMedium = !mediumDurations.isEmpty() ? mediumDurations.stream().mapToDouble(v -> v).sum() : null; - Double averageDurationHard = !hardDurations.isEmpty() ? hardDurations.stream().mapToDouble(v -> v).sum() : null; - - return new ScoreMap(averageDurationEasy, averageDurationMedium, averageDurationHard); - } - - private ScoreMap getFastestSolves(List easyGames, List mediumGames, List hardGames) { - List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); - List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); - List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); - - Double fastestSolveEasy = !easyDurations.isEmpty() ? Collections.min(easyDurations) : null; - Double fastestSolveMedium = !mediumDurations.isEmpty() ? Collections.min(mediumDurations) : null; - Double fastestSolveHard = !hardDurations.isEmpty() ? Collections.min(hardDurations) : null; - - return new ScoreMap(fastestSolveEasy, fastestSolveMedium, fastestSolveHard); - } - - private ScoreMap getTotalGames(List easyGames, List mediumGames, List hardGames) { - return new ScoreMap((double) easyGames.size(), (double) mediumGames.size(), (double) hardGames.size()); - } - - private ScoreMap getGamesWon(List easyGames, List mediumGames, List hardGames) { - return new ScoreMap((double) easyGames.stream().filter(Game::isSuccess).toList().size(), (double) mediumGames.stream().filter(Game::isSuccess).toList().size(), (double) hardGames.stream().filter(Game::isSuccess).toList().size()); - } - - private ScoreMap getLongestWinningStreaks(List easyGames, List mediumGames, List hardGames) { - Map easyStreaks = getStreaks(easyGames); - Map mediumStreaks = getStreaks(mediumGames); - Map hardStreaks = getStreaks(hardGames); - - - return new ScoreMap(easyStreaks.get("win"), mediumStreaks.get("win"), hardStreaks.get("win")); - } - - private ScoreMap getLongestLosingStreaks(List easyGames, List mediumGames, List hardGames) { - Map easyStreaks = getStreaks(easyGames); - Map mediumStreaks = getStreaks(mediumGames); - Map hardStreaks = getStreaks(hardGames); - - - return new ScoreMap(easyStreaks.get("lose"), mediumStreaks.get("lose"), hardStreaks.get("lose")); - } - - private Map getStreaks(List games) { - Map streaks = new HashMap<>(); - - List winningStreaks = new ArrayList<>(); - List losingStreaks = new ArrayList<>(); - - double winningStreak = 0; - double losingStreak = 0; - - for (Game game : games) { - if (game.isSuccess()) { - winningStreak++; - if (losingStreak != 0) { - losingStreaks.add(losingStreak); - losingStreak = 0; - } - continue; - } - - losingStreak++; - if (winningStreak != 0) { - winningStreaks.add(winningStreak); - winningStreak = 0; - } - } - - if (winningStreak != 0) { - winningStreaks.add(winningStreak); - } - - if (losingStreak != 0) { - losingStreaks.add(losingStreak); - } - - - streaks.put("win", !winningStreaks.isEmpty() ? Collections.max(winningStreaks) : 0.0); - streaks.put("lose", !losingStreaks.isEmpty() ? Collections.max(losingStreaks) : 0.0); - - return streaks; + return statisticService.getUserStatistics(id); } } diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java new file mode 100644 index 0000000..2397c60 --- /dev/null +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java @@ -0,0 +1,96 @@ +package de.neuefische.paulkreft.backend.statistic.service; + +import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; +import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; +import de.neuefische.paulkreft.backend.statistic.model.Statistics; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.time.Instant; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +class StatisticServiceTest { + @Test + void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { + // Given + GameRepo gameRepo = Mockito.mock(GameRepo.class); + + StatisticService statisticService = new StatisticService(gameRepo); + + + Game game1 = new Game("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); + Game game2 = new Game("51e74bcd-d341-4ac9-8311-2513a86e9261", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 8515, List.of("#05a928", "#adbb2f", "#0c58b8", "#5244d0", "#f3a747", "#fa56d7"), Instant.parse("2024-02-09T15:19:09.388Z")); + Game game3 = new Game("b6bd5d8b-42c6-4efc-985f-dfc48e2df7e0", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#53accc", "#ac5333", "#3ed3ab", "#c12c54", "#6a13b4", "#95ec4b"), Instant.parse("2024-02-09T15:19:13.671Z")); + Game game4 = new Game("25fefbca-6d74-408f-aaa3-397e37a19764", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 5000, List.of("#4a4b01", "#b5b4fe", "#7d8b42", "#960ba7", "#8274bd", "#69f458"), Instant.parse("2024-02-09T15:19:23.261Z")); + Game game5 = new Game("641730f8-0654-4912-ae4f-37bbd64d4a86", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 16616, List.of("#099c93", "#c2a995", "#c51a5f", "#f6636c", "#3d566a", "#3ae5a0"), Instant.parse("2024-02-09T16:13:23.514Z")); + Game game6 = new Game("066cfbb8-c4f4-45d8-9af5-e65970e11f5c", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 8578, List.of("#8e4392", "#9532a1", "#8e1e9e", "#3e6697", "#71bc6d", "#c19968", "#6acd5e", "#71e161"), Instant.parse("2024-02-09T16:13:37.306Z")); + Game game7 = new Game("11b7aabb-2261-48a0-8ce0-1c30d7d13dc8", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 16699, List.of("#1d9dbd", "#c32605", "#3cd9fa", "#e26242", "#177ca5", "#ea622e", "#e8835a", "#159dd1"), Instant.parse("2024-02-09T16:13:55.319Z")); + Game game8 = new Game("8fa85a56-1a78-48ff-b5f1-172f75475b0a", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#de02b8", "#60317a", "#5ce92d", "#9fce85", "#e67e12", "#e254b5", "#1981ed", "#227da2", "#a316d2", "#dd825d", "#21fd47", "#1dab4a"), Instant.parse("2024-02-09T16:14:15.221Z")); + Game game9 = new Game("c15f9b9a-71d9-49e4-82e4-cbb9007358af", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#c19615", "#efde72", "#4f40fb", "#e26b51", "#3e69ea", "#5ee08c", "#5f3394", "#1d94ae", "#10218d", "#a0cc6b", "#a11f73", "#b0bf04"), Instant.parse("2024-02-09T16:14:25.192Z")); + Game game10 = new Game("3cd692e8-f028-4e72-a92d-ed69dd4c6a94", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#9b01c2", "#5450f6", "#2a0cb1", "#195378", "#fd1b5b", "#02e4a4", "#d5f34e", "#77f5fc", "#e6ac87", "#64fe3d", "#abaf09", "#880a03"), Instant.parse("2024-02-09T16:14:49.157Z")); + Game game11 = new Game("efdb3e28-78fa-4abe-9328-df77cfeb1186", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#1fb50d", "#855303", "#c542b0", "#1177e3", "#620463", "#986046", "#3abd4f", "#e04af2", "#9dfb9c", "#ee881c", "#679fb9", "#7aacfc"), Instant.parse("2024-02-09T16:14:53.990Z")); + Game game12 = new Game("b91f14e0-086e-402b-9823-16a55278f713", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, true, 15833, List.of("#84211c", "#7bdee3", "#350e34", "#762766", "#8cbf63", "#be7b12", "#caf1cb", "#73409c", "#89d899", "#a773ff", "#4184ed", "#588c00"), Instant.parse("2024-02-09T16:15:10.996Z")); + Game game13 = new Game("42e62761-2c95-488a-885b-ee2c012ab1dc", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#75ce6b", "#5dbaf4", "#a2450b", "#c65e86", "#39a179", "#8a3194"), Instant.parse("2024-02-09T16:16:53.418Z")); + Game game14 = new Game("26c84fe4-b77b-4858-83e1-5a3a4499fabe", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3851, List.of("#1b43bc", "#023e44", "#fdc1bb", "#e4bc43", "#5c8731", "#a378ce"), Instant.parse("2024-02-09T16:16:58.237Z")); + Game game15 = new Game("42ede063-4bcd-4e14-a091-80ab6a98285f", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#aba965", "#37e2c7", "#1fe8eb", "#e01714", "#54569a", "#c81d38"), Instant.parse("2024-02-09T16:17:05.101Z")); + Game game16 = new Game("16c3ba8c-c7f4-4089-8719-2d3d5b8bab99", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3750, List.of("#74f523", "#3a928c", "#06085c", "#8b0adc", "#c56d73", "#f9f7a3"), Instant.parse("2024-02-09T16:17:10.384Z")); + Game game17 = new Game("60aa46f9-feaf-4ca4-99b1-a6685a3712d7", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#5efe36", "#e93efa", "#16c105", "#a101c9", "#a5a045", "#5a5fba"), Instant.parse("2024-02-09T16:17:12.851Z")); + Game game18 = new Game("8bc70a24-2e44-4b78-a333-8e6a486e8f21", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3632, List.of("#8ed974", "#d00308", "#71268b", "#2ffcf7", "#095bf0", "#f6a40f"), Instant.parse("2024-02-09T16:17:17.570Z")); + Game game19 = new Game("0c88bce7-4232-4f1f-8bdc-013658874091", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 6700, List.of("#8bd278", "#67dd65", "#9abd98", "#98229a", "#742d87", "#654267"), Instant.parse("2024-02-09T16:17:25.085Z")); + Game game20 = new Game("04fe2411-6be3-4d92-b5a8-06d8386f0cc1", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff"), Instant.parse("2024-02-09T16:23:37.832Z")); + Game game21 = new Game("7824747f-97d4-415f-a6f4-080906b78c79", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, false, 0, List.of("#695cdd", "#522f88", "#96a322", "#add077", "#f56853", "#d6656c", "#299a93", "#0a97ac"), Instant.parse("2024-02-09T16:25:45.317Z")); + + List games = List.of(game1, game2, game3, game4, game5, game6, game7, game8, game9, game10, game11, game12, game13, game14, game15, game16, game17, game18, game19, game20, game21); + + when(gameRepo.findAllByUserIdOrderByCreatedAtAsc(any())).thenReturn(games); + + Statistics expected = new Statistics( + new ScoreMap(2.0, 2.0, 1.0), + new ScoreMap(1.0, 1.0, 4.0), + new ScoreMap(12.0, 3.0, 6.0), + new ScoreMap(7.0, 2.0, 1.0), + new ScoreMap(3632.0, 8578.0, 15833.0), + new ScoreMap(6866.285714285715, 25277.0, 15833.0) + ); + + // When + Statistics actual = statisticService.getUserStatistics(""); + + // Then + assertNotNull(actual); + assertEquals(expected.longestWinningStreak().easy(), actual.longestWinningStreak().easy()); + assertEquals(expected.longestWinningStreak().medium(), actual.longestWinningStreak().medium()); + assertEquals(expected.longestWinningStreak().hard(), actual.longestWinningStreak().hard()); + + assertEquals(expected.longestLosingStreak().easy(), actual.longestLosingStreak().easy()); + assertEquals(expected.longestLosingStreak().medium(), actual.longestLosingStreak().medium()); + assertEquals(expected.longestLosingStreak().hard(), actual.longestLosingStreak().hard()); + + assertEquals(expected.gamesPlayed().easy(), actual.gamesPlayed().easy()); + assertEquals(expected.gamesPlayed().medium(), actual.gamesPlayed().medium()); + assertEquals(expected.gamesPlayed().hard(), actual.gamesPlayed().hard()); + + assertEquals(expected.gamesWon().easy(), actual.gamesWon().easy()); + assertEquals(expected.gamesWon().medium(), actual.gamesWon().medium()); + assertEquals(expected.gamesWon().hard(), actual.gamesWon().hard()); + + assertEquals(expected.fastestSolve().easy(), actual.fastestSolve().easy()); + assertEquals(expected.fastestSolve().medium(), actual.fastestSolve().medium()); + assertEquals(expected.fastestSolve().hard(), actual.fastestSolve().hard()); + + assertEquals(expected.averageTime().easy(), actual.averageTime().easy()); + assertEquals(expected.averageTime().medium(), actual.averageTime().medium()); + assertEquals(expected.averageTime().hard(), actual.averageTime().hard()); + + assertEquals(expected, actual); + verify(gameRepo, times(1)).findAllByUserIdOrderByCreatedAtAsc(any()); + verifyNoMoreInteractions(gameRepo); + } + +} \ No newline at end of file diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java index b100eb5..197082d 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java @@ -3,10 +3,11 @@ 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.statistic.service.StatisticService; 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.statistic.model.ScoreMap; +import de.neuefische.paulkreft.backend.statistic.model.Statistics; import de.neuefische.paulkreft.backend.user.model.User; import de.neuefische.paulkreft.backend.user.model.UserGet; import de.neuefische.paulkreft.backend.user.repository.UsersRepo; @@ -35,18 +36,15 @@ class UserServiceTest { private GithubService githubService; - private GameRepo gameRepo; - private User testUser; @BeforeEach public void instantiateTestUser() { usersRepo = Mockito.mock(UsersRepo.class); - gameRepo = Mockito.mock(GameRepo.class); idService = Mockito.mock(IdService.class); timeService = Mockito.mock(TimeService.class); githubService = Mockito.mock(GithubService.class); - userService = new UserService(usersRepo, gameRepo, idService, timeService, githubService); + userService = new UserService(usersRepo, Mockito.mock(StatisticService.class), idService, timeService, githubService); testUser = new User("Some UUID", "Some Name", "someemail@soem.de", "", Instant.now(), Instant.now()); } @@ -189,80 +187,4 @@ void existsByEmailTest_whenCheckNonExistingUser_returnFalse() { verify(usersRepo, times(1)).existsUserByEmail(nonExistingEmail); verifyNoMoreInteractions(idService, usersRepo, timeService, githubService); } - - - @Test - void getStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { - // Given - Game game1 = new Game("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); - Game game2 = new Game("51e74bcd-d341-4ac9-8311-2513a86e9261", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 8515, List.of("#05a928", "#adbb2f", "#0c58b8", "#5244d0", "#f3a747", "#fa56d7"), Instant.parse("2024-02-09T15:19:09.388Z")); - Game game3 = new Game("b6bd5d8b-42c6-4efc-985f-dfc48e2df7e0", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#53accc", "#ac5333", "#3ed3ab", "#c12c54", "#6a13b4", "#95ec4b"), Instant.parse("2024-02-09T15:19:13.671Z")); - Game game4 = new Game("25fefbca-6d74-408f-aaa3-397e37a19764", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 5000, List.of("#4a4b01", "#b5b4fe", "#7d8b42", "#960ba7", "#8274bd", "#69f458"), Instant.parse("2024-02-09T15:19:23.261Z")); - Game game5 = new Game("641730f8-0654-4912-ae4f-37bbd64d4a86", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 16616, List.of("#099c93", "#c2a995", "#c51a5f", "#f6636c", "#3d566a", "#3ae5a0"), Instant.parse("2024-02-09T16:13:23.514Z")); - Game game6 = new Game("066cfbb8-c4f4-45d8-9af5-e65970e11f5c", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 8578, List.of("#8e4392", "#9532a1", "#8e1e9e", "#3e6697", "#71bc6d", "#c19968", "#6acd5e", "#71e161"), Instant.parse("2024-02-09T16:13:37.306Z")); - Game game7 = new Game("11b7aabb-2261-48a0-8ce0-1c30d7d13dc8", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 16699, List.of("#1d9dbd", "#c32605", "#3cd9fa", "#e26242", "#177ca5", "#ea622e", "#e8835a", "#159dd1"), Instant.parse("2024-02-09T16:13:55.319Z")); - Game game8 = new Game("8fa85a56-1a78-48ff-b5f1-172f75475b0a", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#de02b8", "#60317a", "#5ce92d", "#9fce85", "#e67e12", "#e254b5", "#1981ed", "#227da2", "#a316d2", "#dd825d", "#21fd47", "#1dab4a"), Instant.parse("2024-02-09T16:14:15.221Z")); - Game game9 = new Game("c15f9b9a-71d9-49e4-82e4-cbb9007358af", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#c19615", "#efde72", "#4f40fb", "#e26b51", "#3e69ea", "#5ee08c", "#5f3394", "#1d94ae", "#10218d", "#a0cc6b", "#a11f73", "#b0bf04"), Instant.parse("2024-02-09T16:14:25.192Z")); - Game game10 = new Game("3cd692e8-f028-4e72-a92d-ed69dd4c6a94", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#9b01c2", "#5450f6", "#2a0cb1", "#195378", "#fd1b5b", "#02e4a4", "#d5f34e", "#77f5fc", "#e6ac87", "#64fe3d", "#abaf09", "#880a03"), Instant.parse("2024-02-09T16:14:49.157Z")); - Game game11 = new Game("efdb3e28-78fa-4abe-9328-df77cfeb1186", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#1fb50d", "#855303", "#c542b0", "#1177e3", "#620463", "#986046", "#3abd4f", "#e04af2", "#9dfb9c", "#ee881c", "#679fb9", "#7aacfc"), Instant.parse("2024-02-09T16:14:53.990Z")); - Game game12 = new Game("b91f14e0-086e-402b-9823-16a55278f713", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, true, 15833, List.of("#84211c", "#7bdee3", "#350e34", "#762766", "#8cbf63", "#be7b12", "#caf1cb", "#73409c", "#89d899", "#a773ff", "#4184ed", "#588c00"), Instant.parse("2024-02-09T16:15:10.996Z")); - Game game13 = new Game("42e62761-2c95-488a-885b-ee2c012ab1dc", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#75ce6b", "#5dbaf4", "#a2450b", "#c65e86", "#39a179", "#8a3194"), Instant.parse("2024-02-09T16:16:53.418Z")); - Game game14 = new Game("26c84fe4-b77b-4858-83e1-5a3a4499fabe", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3851, List.of("#1b43bc", "#023e44", "#fdc1bb", "#e4bc43", "#5c8731", "#a378ce"), Instant.parse("2024-02-09T16:16:58.237Z")); - Game game15 = new Game("42ede063-4bcd-4e14-a091-80ab6a98285f", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#aba965", "#37e2c7", "#1fe8eb", "#e01714", "#54569a", "#c81d38"), Instant.parse("2024-02-09T16:17:05.101Z")); - Game game16 = new Game("16c3ba8c-c7f4-4089-8719-2d3d5b8bab99", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3750, List.of("#74f523", "#3a928c", "#06085c", "#8b0adc", "#c56d73", "#f9f7a3"), Instant.parse("2024-02-09T16:17:10.384Z")); - Game game17 = new Game("60aa46f9-feaf-4ca4-99b1-a6685a3712d7", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#5efe36", "#e93efa", "#16c105", "#a101c9", "#a5a045", "#5a5fba"), Instant.parse("2024-02-09T16:17:12.851Z")); - Game game18 = new Game("8bc70a24-2e44-4b78-a333-8e6a486e8f21", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3632, List.of("#8ed974", "#d00308", "#71268b", "#2ffcf7", "#095bf0", "#f6a40f"), Instant.parse("2024-02-09T16:17:17.570Z")); - Game game19 = new Game("0c88bce7-4232-4f1f-8bdc-013658874091", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 6700, List.of("#8bd278", "#67dd65", "#9abd98", "#98229a", "#742d87", "#654267"), Instant.parse("2024-02-09T16:17:25.085Z")); - Game game20 = new Game("04fe2411-6be3-4d92-b5a8-06d8386f0cc1", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff"), Instant.parse("2024-02-09T16:23:37.832Z")); - Game game21 = new Game("7824747f-97d4-415f-a6f4-080906b78c79", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, false, 0, List.of("#695cdd", "#522f88", "#96a322", "#add077", "#f56853", "#d6656c", "#299a93", "#0a97ac"), Instant.parse("2024-02-09T16:25:45.317Z")); - - List games = List.of(game1, game2, game3, game4, game5, game6, game7, game8, game9, game10, game11, game12, game13, game14, game15, game16, game17, game18, game19, game20, game21); - - when(gameRepo.findAllByUserIdOrderByCreatedAtAsc(any())).thenReturn(games); - - Statistics expected = new Statistics( - new ScoreMap(2.0, 2.0, 1.0), - new ScoreMap(1.0, 1.0, 4.0), - new ScoreMap(12.0, 3.0, 6.0), - new ScoreMap(7.0, 2.0, 1.0), - new ScoreMap(3632.0, 8578.0, 15833.0), - new ScoreMap(6866.285714285715, 25277.0, 15833.0) - ); - - // When - Statistics actual = userService.getStatistics(""); - - // Then - assertNotNull(actual); - assertEquals(expected.longestWinningStreak().easy(), actual.longestWinningStreak().easy()); - assertEquals(expected.longestWinningStreak().medium(), actual.longestWinningStreak().medium()); - assertEquals(expected.longestWinningStreak().hard(), actual.longestWinningStreak().hard()); - - assertEquals(expected.longestLosingStreak().easy(), actual.longestLosingStreak().easy()); - assertEquals(expected.longestLosingStreak().medium(), actual.longestLosingStreak().medium()); - assertEquals(expected.longestLosingStreak().hard(), actual.longestLosingStreak().hard()); - - assertEquals(expected.gamesPlayed().easy(), actual.gamesPlayed().easy()); - assertEquals(expected.gamesPlayed().medium(), actual.gamesPlayed().medium()); - assertEquals(expected.gamesPlayed().hard(), actual.gamesPlayed().hard()); - - assertEquals(expected.gamesWon().easy(), actual.gamesWon().easy()); - assertEquals(expected.gamesWon().medium(), actual.gamesWon().medium()); - assertEquals(expected.gamesWon().hard(), actual.gamesWon().hard()); - - assertEquals(expected.fastestSolve().easy(), actual.fastestSolve().easy()); - assertEquals(expected.fastestSolve().medium(), actual.fastestSolve().medium()); - assertEquals(expected.fastestSolve().hard(), actual.fastestSolve().hard()); - - assertEquals(expected.averageTime().easy(), actual.averageTime().easy()); - assertEquals(expected.averageTime().medium(), actual.averageTime().medium()); - assertEquals(expected.averageTime().hard(), actual.averageTime().hard()); - - assertEquals(expected, actual); - verify(gameRepo, times(1)).findAllByUserIdOrderByCreatedAtAsc(any()); - verifyNoMoreInteractions(idService, usersRepo, timeService, githubService, gameRepo); - } - - - } From 1059802749de02763625f2d9aec775972e989624 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Thu, 22 Feb 2024 14:57:11 +0100 Subject: [PATCH 02/18] add button for 1v1 lobby to distinguish from group lobby --- frontend/src/components/LobbyEntrance.tsx | 31 +++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/LobbyEntrance.tsx b/frontend/src/components/LobbyEntrance.tsx index 56ffdce..3312d0f 100644 --- a/frontend/src/components/LobbyEntrance.tsx +++ b/frontend/src/components/LobbyEntrance.tsx @@ -44,23 +44,18 @@ export const LobbyEntrance: React.FC = ({ user }) => { }; const handleKeyDownOnInput = (event: React.KeyboardEvent): void => { - if(event.key === "Enter") { + if (event.key === "Enter") { joinLobby(); } - } + }; return (
-
- -
+
+
Enter a lobby
+
setLobbyId(event.target.value)} @@ -74,6 +69,20 @@ export const LobbyEntrance: React.FC = ({ user }) => { Join
+
+ + +
); From 22c9a0aea04252e877824625faad620aea846f20 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 10:00:39 +0100 Subject: [PATCH 03/18] rename Statistics class to ClassicStatistics --- .../model/{Statistics.java => ClassicStatistics.java} | 2 +- .../backend/statistic/service/StatisticService.java | 6 +++--- .../paulkreft/backend/user/controller/UserController.java | 4 ++-- .../paulkreft/backend/user/service/UserService.java | 4 ++-- .../backend/statistic/service/StatisticServiceTest.java | 6 +++--- .../paulkreft/backend/user/service/UserServiceTest.java | 5 ----- 6 files changed, 11 insertions(+), 16 deletions(-) rename backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/{Statistics.java => ClassicStatistics.java} (88%) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/Statistics.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/ClassicStatistics.java similarity index 88% rename from backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/Statistics.java rename to backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/ClassicStatistics.java index 74cd8ca..583730a 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/Statistics.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/ClassicStatistics.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.statistic.model; -public record Statistics( +public record ClassicStatistics( ScoreMap longestWinningStreak, ScoreMap longestLosingStreak, ScoreMap gamesPlayed, diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java index 2cfbd2b..d341976 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -3,7 +3,7 @@ import de.neuefische.paulkreft.backend.game.classic.model.Game; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; -import de.neuefische.paulkreft.backend.statistic.model.Statistics; +import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,7 +20,7 @@ public class StatisticService { private static final int MEDIUM = 2; private static final int HARD = 4; - public Statistics getUserStatistics(String id) { + public ClassicStatistics getUserStatistics(String id) { List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); @@ -34,7 +34,7 @@ public Statistics getUserStatistics(String id) { ScoreMap fastestSolve = getFastestSolves(easyGames, mediumGames, hardGames); ScoreMap averageDuration = getAverageDurations(easyGames, mediumGames, hardGames); - return new Statistics(longestWinningStreaks, longestLosingStreaks, totalGames, totalGamesWon, fastestSolve, averageDuration); + return new ClassicStatistics(longestWinningStreaks, longestLosingStreaks, totalGames, totalGamesWon, fastestSolve, averageDuration); } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java b/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java index 74c3034..39d29f0 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.user.controller; -import de.neuefische.paulkreft.backend.statistic.model.Statistics; +import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; import de.neuefische.paulkreft.backend.user.model.User; import de.neuefische.paulkreft.backend.user.model.UserGet; import de.neuefische.paulkreft.backend.user.service.UserService; @@ -27,7 +27,7 @@ public UserGet updateUser(@RequestBody User user) { } @GetMapping("{id}/statistics") - public Statistics getUserStatistics(@PathVariable String id) { + public ClassicStatistics getUserStatistics(@PathVariable String id) { return userService.getStatistics(id); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java index 91f2a5b..afb5845 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java @@ -2,7 +2,7 @@ import de.neuefische.paulkreft.backend.exception.GithubEmailNotFoundException; import de.neuefische.paulkreft.backend.github.service.GithubService; -import de.neuefische.paulkreft.backend.statistic.model.Statistics; +import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; import de.neuefische.paulkreft.backend.statistic.service.StatisticService; import de.neuefische.paulkreft.backend.utils.service.IdService; import de.neuefische.paulkreft.backend.utils.service.TimeService; @@ -97,7 +97,7 @@ public boolean existsByEmail(String email) { return usersRepo.existsUserByEmail(email); } - public Statistics getStatistics(String id) { + public ClassicStatistics getStatistics(String id) { return statisticService.getUserStatistics(id); } } diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java index 2397c60..cd80e2c 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java @@ -3,7 +3,7 @@ import de.neuefische.paulkreft.backend.game.classic.model.Game; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; -import de.neuefische.paulkreft.backend.statistic.model.Statistics; +import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -50,7 +50,7 @@ void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { when(gameRepo.findAllByUserIdOrderByCreatedAtAsc(any())).thenReturn(games); - Statistics expected = new Statistics( + ClassicStatistics expected = new ClassicStatistics( new ScoreMap(2.0, 2.0, 1.0), new ScoreMap(1.0, 1.0, 4.0), new ScoreMap(12.0, 3.0, 6.0), @@ -60,7 +60,7 @@ void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { ); // When - Statistics actual = statisticService.getUserStatistics(""); + ClassicStatistics actual = statisticService.getUserStatistics(""); // Then assertNotNull(actual); diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java index 197082d..26c3504 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/user/service/UserServiceTest.java @@ -1,13 +1,9 @@ package de.neuefische.paulkreft.backend.user.service; -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.statistic.service.StatisticService; import de.neuefische.paulkreft.backend.utils.service.IdService; import de.neuefische.paulkreft.backend.utils.service.TimeService; -import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; -import de.neuefische.paulkreft.backend.statistic.model.Statistics; import de.neuefische.paulkreft.backend.user.model.User; import de.neuefische.paulkreft.backend.user.model.UserGet; import de.neuefische.paulkreft.backend.user.repository.UsersRepo; @@ -18,7 +14,6 @@ import java.security.Principal; import java.time.Instant; -import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; From 628ad257bda1d0e2f2aeaa2564263603f9d15467 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 10:30:54 +0100 Subject: [PATCH 04/18] rename Game class to ClassicGame --- .../classic/controller/GameController.java | 6 +-- .../model/{Game.java => ClassicGame.java} | 2 +- .../game/classic/model/GameCreate.java | 4 +- .../game/classic/repository/GameRepo.java | 8 ++-- .../game/classic/service/GameService.java | 6 +-- .../statistic/service/StatisticService.java | 28 +++++------ ...ClassicGameControllerIntegrationTest.java} | 8 ++-- ...eTest.java => ClassicGameServiceTest.java} | 16 +++---- .../service/StatisticServiceTest.java | 48 +++++++++---------- 9 files changed, 63 insertions(+), 63 deletions(-) rename backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/{Game.java => ClassicGame.java} (93%) rename backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/{GameControllerIntegrationTest.java => ClassicGameControllerIntegrationTest.java} (92%) rename backend/src/test/java/de/neuefische/paulkreft/backend/game/service/{GameServiceTest.java => ClassicGameServiceTest.java} (73%) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java index de6b244..e786968 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.classic.controller; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; import de.neuefische.paulkreft.backend.game.classic.model.GameCreate; import de.neuefische.paulkreft.backend.game.classic.service.GameService; import org.springframework.web.bind.annotation.*; @@ -17,12 +17,12 @@ public GameController(GameService gameService) { } @PostMapping - public Game createGame(@RequestBody GameCreate gameCreate) { + public ClassicGame createGame(@RequestBody GameCreate gameCreate) { return gameService.createGame(gameCreate); } @GetMapping("/user/{userId}") - public List getGamesByUserId(@PathVariable String userId) { + public List getGamesByUserId(@PathVariable String userId) { return gameService.getGamesByUserId(userId); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/Game.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/ClassicGame.java similarity index 93% rename from backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/Game.java rename to backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/ClassicGame.java index 1f0d57e..159c53f 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/Game.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/ClassicGame.java @@ -5,7 +5,7 @@ import java.time.Instant; import java.util.List; -public record Game( +public record ClassicGame( @Id String id, String userId, diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java index 3106177..eca1d8d 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java @@ -11,7 +11,7 @@ public record GameCreate( int duration, List 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); + public ClassicGame withIdAndCreatedAt(String id, Instant createdAt) { + return new ClassicGame(id, this.userId, this.type, this.difficulty, this.isSuccess, this.duration, this.configuration, createdAt); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java index 7bd14a2..ef8d113 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java @@ -1,13 +1,13 @@ package de.neuefische.paulkreft.backend.game.classic.repository; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository -public interface GameRepo extends MongoRepository { - List findAllByUserId(String id); - List findAllByUserIdOrderByCreatedAtAsc(String id); +public interface GameRepo extends MongoRepository { + List findAllByUserId(String id); + List findAllByUserIdOrderByCreatedAtAsc(String id); } \ No newline at end of file diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java index 9d1a22c..0a8eacb 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.classic.service; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; 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; @@ -21,11 +21,11 @@ public GameService(GameRepo gameRepo, IdService idService, TimeService timeServi this.timeService = timeService; } - public Game createGame(GameCreate gameCreate) { + public ClassicGame createGame(GameCreate gameCreate) { return gameRepo.save(gameCreate.withIdAndCreatedAt(idService.generateUUID(), timeService.getNow())); } - public List getGamesByUserId(String userId) { + public List getGamesByUserId(String userId) { return gameRepo.findAllByUserId(userId); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java index d341976..2570b23 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.statistic.service; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; @@ -21,11 +21,11 @@ public class StatisticService { private static final int HARD = 4; public ClassicStatistics getUserStatistics(String id) { - List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); + List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); - List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); - List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); - List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); + List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); + List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); + List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); ScoreMap longestWinningStreaks = getLongestWinningStreaks(easyGames, mediumGames, hardGames); ScoreMap longestLosingStreaks = getLongestLosingStreaks(easyGames, mediumGames, hardGames); @@ -38,7 +38,7 @@ public ClassicStatistics getUserStatistics(String id) { } - private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); @@ -50,7 +50,7 @@ private ScoreMap getAverageDurations(List easyGames, List mediumGame return new ScoreMap(averageDurationEasy, averageDurationMedium, averageDurationHard); } - private ScoreMap getFastestSolves(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getFastestSolves(List easyGames, List mediumGames, List hardGames) { List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); @@ -62,15 +62,15 @@ private ScoreMap getFastestSolves(List easyGames, List mediumGames, return new ScoreMap(fastestSolveEasy, fastestSolveMedium, fastestSolveHard); } - private ScoreMap getTotalGames(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getTotalGames(List easyGames, List mediumGames, List hardGames) { return new ScoreMap((double) easyGames.size(), (double) mediumGames.size(), (double) hardGames.size()); } - private ScoreMap getGamesWon(List easyGames, List mediumGames, List hardGames) { - return new ScoreMap((double) easyGames.stream().filter(Game::isSuccess).toList().size(), (double) mediumGames.stream().filter(Game::isSuccess).toList().size(), (double) hardGames.stream().filter(Game::isSuccess).toList().size()); + private ScoreMap getGamesWon(List easyGames, List mediumGames, List hardGames) { + return new ScoreMap((double) easyGames.stream().filter(ClassicGame::isSuccess).toList().size(), (double) mediumGames.stream().filter(ClassicGame::isSuccess).toList().size(), (double) hardGames.stream().filter(ClassicGame::isSuccess).toList().size()); } - private ScoreMap getLongestWinningStreaks(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getLongestWinningStreaks(List easyGames, List mediumGames, List hardGames) { Map easyStreaks = getStreaks(easyGames); Map mediumStreaks = getStreaks(mediumGames); Map hardStreaks = getStreaks(hardGames); @@ -79,7 +79,7 @@ private ScoreMap getLongestWinningStreaks(List easyGames, List mediu return new ScoreMap(easyStreaks.get("win"), mediumStreaks.get("win"), hardStreaks.get("win")); } - private ScoreMap getLongestLosingStreaks(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getLongestLosingStreaks(List easyGames, List mediumGames, List hardGames) { Map easyStreaks = getStreaks(easyGames); Map mediumStreaks = getStreaks(mediumGames); Map hardStreaks = getStreaks(hardGames); @@ -88,7 +88,7 @@ private ScoreMap getLongestLosingStreaks(List easyGames, List medium return new ScoreMap(easyStreaks.get("lose"), mediumStreaks.get("lose"), hardStreaks.get("lose")); } - private Map getStreaks(List games) { + private Map getStreaks(List games) { Map streaks = new HashMap<>(); List winningStreaks = new ArrayList<>(); @@ -97,7 +97,7 @@ private Map getStreaks(List games) { double winningStreak = 0; double losingStreak = 0; - for (Game game : games) { + for (ClassicGame game : games) { if (game.isSuccess()) { winningStreak++; if (losingStreak != 0) { diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/GameControllerIntegrationTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java similarity index 92% rename from backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/GameControllerIntegrationTest.java rename to backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java index fdff2a4..0d4969e 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/GameControllerIntegrationTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.controller; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; 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; @@ -25,7 +25,7 @@ @SpringBootTest @AutoConfigureMockMvc -class GameControllerIntegrationTest { +class ClassicGameControllerIntegrationTest { @Autowired private MockMvc mockMvc; @@ -87,8 +87,8 @@ void createGameTest_whenGameCreateGiven_thenReturnGame() throws Exception { void getGamesByUserIdTest_whenOneMatchingGameInDB_thenReturnMatchingGame() throws Exception { // Given Instant now = Instant.parse("2016-06-09T00:00:00Z"); - Game testGame = new Game("1", "User1", "Type", 1, true, 10, List.of("#FFFFFF"), now); - Game testGame2 = new Game("2", "User2", "Type", 1, true, 10, Collections.emptyList(), now); + ClassicGame testGame = new ClassicGame("1", "User1", "Type", 1, true, 10, List.of("#FFFFFF"), now); + ClassicGame testGame2 = new ClassicGame("2", "User2", "Type", 1, true, 10, Collections.emptyList(), now); gameRepo.save(testGame); gameRepo.save(testGame2); diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/GameServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java similarity index 73% rename from backend/src/test/java/de/neuefische/paulkreft/backend/game/service/GameServiceTest.java rename to backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java index 50224e7..bdb2a73 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/GameServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.service; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; 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; @@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; -class GameServiceTest { +class ClassicGameServiceTest { private final GameRepo gameRepo = mock(GameRepo.class); private final IdService idService = mock(IdService.class); @@ -35,32 +35,32 @@ void createGame_shouldSaveGame() { GameCreate mockGame = mock(GameCreate.class); Instant now = Instant.now(); - Game expectedGame = new Game("1", "User1", "Type", 1, true, 10, Collections.emptyList(), now); + ClassicGame expectedGame = new ClassicGame("1", "User1", "Type", 1, true, 10, Collections.emptyList(), now); GameCreate gameCreate = new GameCreate("User1", "Type", 1, true, 10, Collections.emptyList()); when(idService.generateUUID()).thenReturn("1"); when(timeService.getNow()).thenReturn(now); when(mockGame.withIdAndCreatedAt("1", now)).thenReturn(expectedGame); - when(gameRepo.save(any(Game.class))).thenReturn(expectedGame); + when(gameRepo.save(any(ClassicGame.class))).thenReturn(expectedGame); // When - Game savedGame = gameService.createGame(gameCreate); + ClassicGame savedGame = gameService.createGame(gameCreate); // Then assertEquals(expectedGame, savedGame); - verify(gameRepo, times(1)).save(any(Game.class)); + verify(gameRepo, times(1)).save(any(ClassicGame.class)); } @Test void getGamesByUserId_shouldReturnGames() { // Given String userId = "User1"; - List expectedGames = Collections.singletonList(new Game("1", userId, "Type", 1, true, 10, Collections.emptyList(), Instant.now())); + List expectedGames = Collections.singletonList(new ClassicGame("1", userId, "Type", 1, true, 10, Collections.emptyList(), Instant.now())); when(gameRepo.findAllByUserId(userId)).thenReturn(expectedGames); // When - List actualGames = gameService.getGamesByUserId(userId); + List actualGames = gameService.getGamesByUserId(userId); // Then assertEquals(expectedGames, actualGames); diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java index cd80e2c..d1bb9b2 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.statistic.service; -import de.neuefische.paulkreft.backend.game.classic.model.Game; +import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; @@ -24,29 +24,29 @@ void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { StatisticService statisticService = new StatisticService(gameRepo); - Game game1 = new Game("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); - Game game2 = new Game("51e74bcd-d341-4ac9-8311-2513a86e9261", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 8515, List.of("#05a928", "#adbb2f", "#0c58b8", "#5244d0", "#f3a747", "#fa56d7"), Instant.parse("2024-02-09T15:19:09.388Z")); - Game game3 = new Game("b6bd5d8b-42c6-4efc-985f-dfc48e2df7e0", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#53accc", "#ac5333", "#3ed3ab", "#c12c54", "#6a13b4", "#95ec4b"), Instant.parse("2024-02-09T15:19:13.671Z")); - Game game4 = new Game("25fefbca-6d74-408f-aaa3-397e37a19764", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 5000, List.of("#4a4b01", "#b5b4fe", "#7d8b42", "#960ba7", "#8274bd", "#69f458"), Instant.parse("2024-02-09T15:19:23.261Z")); - Game game5 = new Game("641730f8-0654-4912-ae4f-37bbd64d4a86", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 16616, List.of("#099c93", "#c2a995", "#c51a5f", "#f6636c", "#3d566a", "#3ae5a0"), Instant.parse("2024-02-09T16:13:23.514Z")); - Game game6 = new Game("066cfbb8-c4f4-45d8-9af5-e65970e11f5c", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 8578, List.of("#8e4392", "#9532a1", "#8e1e9e", "#3e6697", "#71bc6d", "#c19968", "#6acd5e", "#71e161"), Instant.parse("2024-02-09T16:13:37.306Z")); - Game game7 = new Game("11b7aabb-2261-48a0-8ce0-1c30d7d13dc8", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 16699, List.of("#1d9dbd", "#c32605", "#3cd9fa", "#e26242", "#177ca5", "#ea622e", "#e8835a", "#159dd1"), Instant.parse("2024-02-09T16:13:55.319Z")); - Game game8 = new Game("8fa85a56-1a78-48ff-b5f1-172f75475b0a", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#de02b8", "#60317a", "#5ce92d", "#9fce85", "#e67e12", "#e254b5", "#1981ed", "#227da2", "#a316d2", "#dd825d", "#21fd47", "#1dab4a"), Instant.parse("2024-02-09T16:14:15.221Z")); - Game game9 = new Game("c15f9b9a-71d9-49e4-82e4-cbb9007358af", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#c19615", "#efde72", "#4f40fb", "#e26b51", "#3e69ea", "#5ee08c", "#5f3394", "#1d94ae", "#10218d", "#a0cc6b", "#a11f73", "#b0bf04"), Instant.parse("2024-02-09T16:14:25.192Z")); - Game game10 = new Game("3cd692e8-f028-4e72-a92d-ed69dd4c6a94", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#9b01c2", "#5450f6", "#2a0cb1", "#195378", "#fd1b5b", "#02e4a4", "#d5f34e", "#77f5fc", "#e6ac87", "#64fe3d", "#abaf09", "#880a03"), Instant.parse("2024-02-09T16:14:49.157Z")); - Game game11 = new Game("efdb3e28-78fa-4abe-9328-df77cfeb1186", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#1fb50d", "#855303", "#c542b0", "#1177e3", "#620463", "#986046", "#3abd4f", "#e04af2", "#9dfb9c", "#ee881c", "#679fb9", "#7aacfc"), Instant.parse("2024-02-09T16:14:53.990Z")); - Game game12 = new Game("b91f14e0-086e-402b-9823-16a55278f713", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, true, 15833, List.of("#84211c", "#7bdee3", "#350e34", "#762766", "#8cbf63", "#be7b12", "#caf1cb", "#73409c", "#89d899", "#a773ff", "#4184ed", "#588c00"), Instant.parse("2024-02-09T16:15:10.996Z")); - Game game13 = new Game("42e62761-2c95-488a-885b-ee2c012ab1dc", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#75ce6b", "#5dbaf4", "#a2450b", "#c65e86", "#39a179", "#8a3194"), Instant.parse("2024-02-09T16:16:53.418Z")); - Game game14 = new Game("26c84fe4-b77b-4858-83e1-5a3a4499fabe", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3851, List.of("#1b43bc", "#023e44", "#fdc1bb", "#e4bc43", "#5c8731", "#a378ce"), Instant.parse("2024-02-09T16:16:58.237Z")); - Game game15 = new Game("42ede063-4bcd-4e14-a091-80ab6a98285f", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#aba965", "#37e2c7", "#1fe8eb", "#e01714", "#54569a", "#c81d38"), Instant.parse("2024-02-09T16:17:05.101Z")); - Game game16 = new Game("16c3ba8c-c7f4-4089-8719-2d3d5b8bab99", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3750, List.of("#74f523", "#3a928c", "#06085c", "#8b0adc", "#c56d73", "#f9f7a3"), Instant.parse("2024-02-09T16:17:10.384Z")); - Game game17 = new Game("60aa46f9-feaf-4ca4-99b1-a6685a3712d7", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#5efe36", "#e93efa", "#16c105", "#a101c9", "#a5a045", "#5a5fba"), Instant.parse("2024-02-09T16:17:12.851Z")); - Game game18 = new Game("8bc70a24-2e44-4b78-a333-8e6a486e8f21", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3632, List.of("#8ed974", "#d00308", "#71268b", "#2ffcf7", "#095bf0", "#f6a40f"), Instant.parse("2024-02-09T16:17:17.570Z")); - Game game19 = new Game("0c88bce7-4232-4f1f-8bdc-013658874091", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 6700, List.of("#8bd278", "#67dd65", "#9abd98", "#98229a", "#742d87", "#654267"), Instant.parse("2024-02-09T16:17:25.085Z")); - Game game20 = new Game("04fe2411-6be3-4d92-b5a8-06d8386f0cc1", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff"), Instant.parse("2024-02-09T16:23:37.832Z")); - Game game21 = new Game("7824747f-97d4-415f-a6f4-080906b78c79", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, false, 0, List.of("#695cdd", "#522f88", "#96a322", "#add077", "#f56853", "#d6656c", "#299a93", "#0a97ac"), Instant.parse("2024-02-09T16:25:45.317Z")); - - List games = List.of(game1, game2, game3, game4, game5, game6, game7, game8, game9, game10, game11, game12, game13, game14, game15, game16, game17, game18, game19, game20, game21); + ClassicGame game1 = new ClassicGame("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); + ClassicGame game2 = new ClassicGame("51e74bcd-d341-4ac9-8311-2513a86e9261", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 8515, List.of("#05a928", "#adbb2f", "#0c58b8", "#5244d0", "#f3a747", "#fa56d7"), Instant.parse("2024-02-09T15:19:09.388Z")); + ClassicGame game3 = new ClassicGame("b6bd5d8b-42c6-4efc-985f-dfc48e2df7e0", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#53accc", "#ac5333", "#3ed3ab", "#c12c54", "#6a13b4", "#95ec4b"), Instant.parse("2024-02-09T15:19:13.671Z")); + ClassicGame game4 = new ClassicGame("25fefbca-6d74-408f-aaa3-397e37a19764", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 5000, List.of("#4a4b01", "#b5b4fe", "#7d8b42", "#960ba7", "#8274bd", "#69f458"), Instant.parse("2024-02-09T15:19:23.261Z")); + ClassicGame game5 = new ClassicGame("641730f8-0654-4912-ae4f-37bbd64d4a86", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 16616, List.of("#099c93", "#c2a995", "#c51a5f", "#f6636c", "#3d566a", "#3ae5a0"), Instant.parse("2024-02-09T16:13:23.514Z")); + ClassicGame game6 = new ClassicGame("066cfbb8-c4f4-45d8-9af5-e65970e11f5c", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 8578, List.of("#8e4392", "#9532a1", "#8e1e9e", "#3e6697", "#71bc6d", "#c19968", "#6acd5e", "#71e161"), Instant.parse("2024-02-09T16:13:37.306Z")); + ClassicGame game7 = new ClassicGame("11b7aabb-2261-48a0-8ce0-1c30d7d13dc8", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 16699, List.of("#1d9dbd", "#c32605", "#3cd9fa", "#e26242", "#177ca5", "#ea622e", "#e8835a", "#159dd1"), Instant.parse("2024-02-09T16:13:55.319Z")); + ClassicGame game8 = new ClassicGame("8fa85a56-1a78-48ff-b5f1-172f75475b0a", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#de02b8", "#60317a", "#5ce92d", "#9fce85", "#e67e12", "#e254b5", "#1981ed", "#227da2", "#a316d2", "#dd825d", "#21fd47", "#1dab4a"), Instant.parse("2024-02-09T16:14:15.221Z")); + ClassicGame game9 = new ClassicGame("c15f9b9a-71d9-49e4-82e4-cbb9007358af", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#c19615", "#efde72", "#4f40fb", "#e26b51", "#3e69ea", "#5ee08c", "#5f3394", "#1d94ae", "#10218d", "#a0cc6b", "#a11f73", "#b0bf04"), Instant.parse("2024-02-09T16:14:25.192Z")); + ClassicGame game10 = new ClassicGame("3cd692e8-f028-4e72-a92d-ed69dd4c6a94", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#9b01c2", "#5450f6", "#2a0cb1", "#195378", "#fd1b5b", "#02e4a4", "#d5f34e", "#77f5fc", "#e6ac87", "#64fe3d", "#abaf09", "#880a03"), Instant.parse("2024-02-09T16:14:49.157Z")); + ClassicGame game11 = new ClassicGame("efdb3e28-78fa-4abe-9328-df77cfeb1186", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#1fb50d", "#855303", "#c542b0", "#1177e3", "#620463", "#986046", "#3abd4f", "#e04af2", "#9dfb9c", "#ee881c", "#679fb9", "#7aacfc"), Instant.parse("2024-02-09T16:14:53.990Z")); + ClassicGame game12 = new ClassicGame("b91f14e0-086e-402b-9823-16a55278f713", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, true, 15833, List.of("#84211c", "#7bdee3", "#350e34", "#762766", "#8cbf63", "#be7b12", "#caf1cb", "#73409c", "#89d899", "#a773ff", "#4184ed", "#588c00"), Instant.parse("2024-02-09T16:15:10.996Z")); + ClassicGame game13 = new ClassicGame("42e62761-2c95-488a-885b-ee2c012ab1dc", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#75ce6b", "#5dbaf4", "#a2450b", "#c65e86", "#39a179", "#8a3194"), Instant.parse("2024-02-09T16:16:53.418Z")); + ClassicGame game14 = new ClassicGame("26c84fe4-b77b-4858-83e1-5a3a4499fabe", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3851, List.of("#1b43bc", "#023e44", "#fdc1bb", "#e4bc43", "#5c8731", "#a378ce"), Instant.parse("2024-02-09T16:16:58.237Z")); + ClassicGame game15 = new ClassicGame("42ede063-4bcd-4e14-a091-80ab6a98285f", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#aba965", "#37e2c7", "#1fe8eb", "#e01714", "#54569a", "#c81d38"), Instant.parse("2024-02-09T16:17:05.101Z")); + ClassicGame game16 = new ClassicGame("16c3ba8c-c7f4-4089-8719-2d3d5b8bab99", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3750, List.of("#74f523", "#3a928c", "#06085c", "#8b0adc", "#c56d73", "#f9f7a3"), Instant.parse("2024-02-09T16:17:10.384Z")); + ClassicGame game17 = new ClassicGame("60aa46f9-feaf-4ca4-99b1-a6685a3712d7", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#5efe36", "#e93efa", "#16c105", "#a101c9", "#a5a045", "#5a5fba"), Instant.parse("2024-02-09T16:17:12.851Z")); + ClassicGame game18 = new ClassicGame("8bc70a24-2e44-4b78-a333-8e6a486e8f21", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3632, List.of("#8ed974", "#d00308", "#71268b", "#2ffcf7", "#095bf0", "#f6a40f"), Instant.parse("2024-02-09T16:17:17.570Z")); + ClassicGame game19 = new ClassicGame("0c88bce7-4232-4f1f-8bdc-013658874091", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 6700, List.of("#8bd278", "#67dd65", "#9abd98", "#98229a", "#742d87", "#654267"), Instant.parse("2024-02-09T16:17:25.085Z")); + ClassicGame game20 = new ClassicGame("04fe2411-6be3-4d92-b5a8-06d8386f0cc1", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff"), Instant.parse("2024-02-09T16:23:37.832Z")); + ClassicGame game21 = new ClassicGame("7824747f-97d4-415f-a6f4-080906b78c79", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, false, 0, List.of("#695cdd", "#522f88", "#96a322", "#add077", "#f56853", "#d6656c", "#299a93", "#0a97ac"), Instant.parse("2024-02-09T16:25:45.317Z")); + + List games = List.of(game1, game2, game3, game4, game5, game6, game7, game8, game9, game10, game11, game12, game13, game14, game15, game16, game17, game18, game19, game20, game21); when(gameRepo.findAllByUserIdOrderByCreatedAtAsc(any())).thenReturn(games); From 06567bb67fd4cbe5fb33748598cae16945c7e136 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 10:44:47 +0100 Subject: [PATCH 05/18] add capacity property to Lobby models --- .../de/neuefische/paulkreft/backend/lobby/model/Lobby.java | 3 ++- .../lobby/controller/LobbyControllerIntegrationTest.java | 2 +- frontend/src/types/Lobby.ts | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/model/Lobby.java b/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/model/Lobby.java index 3f739eb..9ccbe15 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/model/Lobby.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/model/Lobby.java @@ -20,6 +20,7 @@ public record Lobby( List losers, Integer streakToWin, Integer timeToBeat, - Instant lastGameStarted + Instant lastGameStarted, + Integer capacity ) { } diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java index 46b655e..cbd2574 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java @@ -38,7 +38,7 @@ class LobbyControllerIntegrationTest { public void instantiateTestLobby() { Player host = new Player("1", "Paul"); Player participant = new Player("2", "Soso"); - testLobby = new Lobby("1", host, List.of(host, participant), false, false, 4, null, List.of(), 3, null, null); + testLobby = new Lobby("1", host, List.of(host, participant), false, false, 4, null, List.of(), 3, null, null, false); } diff --git a/frontend/src/types/Lobby.ts b/frontend/src/types/Lobby.ts index bd438f7..f466dc9 100644 --- a/frontend/src/types/Lobby.ts +++ b/frontend/src/types/Lobby.ts @@ -13,4 +13,5 @@ export type Lobby = { streakToWin: number; timeToBeat?: number; lastGameStarted?: Date; + capacity?: number; }; From cb0b4124b544c35bd46b7e550903d2627eaf5cd6 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 10:45:19 +0100 Subject: [PATCH 06/18] pass capacity when creating lobby --- frontend/src/components/LobbyEntrance.tsx | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/LobbyEntrance.tsx b/frontend/src/components/LobbyEntrance.tsx index 3312d0f..c71e3cb 100644 --- a/frontend/src/components/LobbyEntrance.tsx +++ b/frontend/src/components/LobbyEntrance.tsx @@ -11,6 +11,8 @@ type MultiPlayerProps = { const EASY = 1; +const DUEL_CAPACITY = 2; + export const LobbyEntrance: React.FC = ({ user }) => { const [lobbyId, setLobbyId] = useState(""); @@ -22,7 +24,7 @@ export const LobbyEntrance: React.FC = ({ user }) => { const currentPlayer: Player = { id: user.id, name: user.name }; - const createLobby = (): void => { + const createLobby = (capacity: number | null = null): void => { const lobbyId = Math.ceil(Math.random() * 1000000).toString(); const lobby: Lobby = { @@ -34,6 +36,7 @@ export const LobbyEntrance: React.FC = ({ user }) => { difficulty: EASY, losers: [], streakToWin: 3, + ...(capacity && { capacity }), }; axios.post("/api/lobby", lobby).then(() => navigate(`/multiplayer/lobby/${lobbyId}`)); @@ -51,7 +54,7 @@ export const LobbyEntrance: React.FC = ({ user }) => { return (
-
+
Enter a lobby
= ({ user }) => { Join
-
+
From 7c3e4e31e1f5eba850c093cb0fa6ee85115e6d2f Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 10:47:16 +0100 Subject: [PATCH 07/18] fix error in test - wrong attribute type was passed --- .../lobby/controller/LobbyControllerIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java index cbd2574..c139291 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/lobby/controller/LobbyControllerIntegrationTest.java @@ -38,7 +38,7 @@ class LobbyControllerIntegrationTest { public void instantiateTestLobby() { Player host = new Player("1", "Paul"); Player participant = new Player("2", "Soso"); - testLobby = new Lobby("1", host, List.of(host, participant), false, false, 4, null, List.of(), 3, null, null, false); + testLobby = new Lobby("1", host, List.of(host, participant), false, false, 4, null, List.of(), 3, null, null, null); } From 42b20db642621703bf783908c4353ec1d06d630f Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 11:06:29 +0100 Subject: [PATCH 08/18] undo rename of Game to ClassicGame, because it did not make sense --- .../classic/controller/GameController.java | 6 +-- .../model/{ClassicGame.java => Game.java} | 2 +- .../game/classic/model/GameCreate.java | 4 +- .../game/classic/repository/GameRepo.java | 8 ++-- .../game/classic/service/GameService.java | 6 +-- .../statistic/service/StatisticService.java | 28 +++++------ .../ClassicGameControllerIntegrationTest.java | 6 +-- .../game/service/ClassicGameServiceTest.java | 14 +++--- .../service/StatisticServiceTest.java | 48 +++++++++---------- 9 files changed, 61 insertions(+), 61 deletions(-) rename backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/{ClassicGame.java => Game.java} (93%) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java index e786968..de6b244 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/controller/GameController.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.classic.controller; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +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.*; @@ -17,12 +17,12 @@ public GameController(GameService gameService) { } @PostMapping - public ClassicGame createGame(@RequestBody GameCreate gameCreate) { + public Game createGame(@RequestBody GameCreate gameCreate) { return gameService.createGame(gameCreate); } @GetMapping("/user/{userId}") - public List getGamesByUserId(@PathVariable String userId) { + public List getGamesByUserId(@PathVariable String userId) { return gameService.getGamesByUserId(userId); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/ClassicGame.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/Game.java similarity index 93% rename from backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/ClassicGame.java rename to backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/Game.java index 159c53f..1f0d57e 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/ClassicGame.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/Game.java @@ -5,7 +5,7 @@ import java.time.Instant; import java.util.List; -public record ClassicGame( +public record Game( @Id String id, String userId, diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java index eca1d8d..3106177 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/model/GameCreate.java @@ -11,7 +11,7 @@ public record GameCreate( int duration, List configuration ) { - public ClassicGame withIdAndCreatedAt(String id, Instant createdAt) { - return new ClassicGame(id, this.userId, this.type, this.difficulty, this.isSuccess, this.duration, this.configuration, createdAt); + public Game withIdAndCreatedAt(String id, Instant createdAt) { + return new Game(id, this.userId, this.type, this.difficulty, this.isSuccess, this.duration, this.configuration, createdAt); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java index ef8d113..7bd14a2 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/repository/GameRepo.java @@ -1,13 +1,13 @@ package de.neuefische.paulkreft.backend.game.classic.repository; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +import de.neuefische.paulkreft.backend.game.classic.model.Game; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository -public interface GameRepo extends MongoRepository { - List findAllByUserId(String id); - List findAllByUserIdOrderByCreatedAtAsc(String id); +public interface GameRepo extends MongoRepository { + List findAllByUserId(String id); + List findAllByUserIdOrderByCreatedAtAsc(String id); } \ No newline at end of file diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java index 0a8eacb..9d1a22c 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/classic/service/GameService.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.classic.service; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +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; @@ -21,11 +21,11 @@ public GameService(GameRepo gameRepo, IdService idService, TimeService timeServi this.timeService = timeService; } - public ClassicGame createGame(GameCreate gameCreate) { + public Game createGame(GameCreate gameCreate) { return gameRepo.save(gameCreate.withIdAndCreatedAt(idService.generateUUID(), timeService.getNow())); } - public List getGamesByUserId(String userId) { + public List getGamesByUserId(String userId) { return gameRepo.findAllByUserId(userId); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java index 2570b23..d341976 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.statistic.service; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +import de.neuefische.paulkreft.backend.game.classic.model.Game; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; @@ -21,11 +21,11 @@ public class StatisticService { private static final int HARD = 4; public ClassicStatistics getUserStatistics(String id) { - List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); + List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); - List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); - List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); - List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); + List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); + List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); + List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); ScoreMap longestWinningStreaks = getLongestWinningStreaks(easyGames, mediumGames, hardGames); ScoreMap longestLosingStreaks = getLongestLosingStreaks(easyGames, mediumGames, hardGames); @@ -38,7 +38,7 @@ public ClassicStatistics getUserStatistics(String id) { } - private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); @@ -50,7 +50,7 @@ private ScoreMap getAverageDurations(List easyGames, List easyGames, List mediumGames, List hardGames) { + private ScoreMap getFastestSolves(List easyGames, List mediumGames, List hardGames) { List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List hardDurations = hardGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); @@ -62,15 +62,15 @@ private ScoreMap getFastestSolves(List easyGames, List return new ScoreMap(fastestSolveEasy, fastestSolveMedium, fastestSolveHard); } - private ScoreMap getTotalGames(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getTotalGames(List easyGames, List mediumGames, List hardGames) { return new ScoreMap((double) easyGames.size(), (double) mediumGames.size(), (double) hardGames.size()); } - private ScoreMap getGamesWon(List easyGames, List mediumGames, List hardGames) { - return new ScoreMap((double) easyGames.stream().filter(ClassicGame::isSuccess).toList().size(), (double) mediumGames.stream().filter(ClassicGame::isSuccess).toList().size(), (double) hardGames.stream().filter(ClassicGame::isSuccess).toList().size()); + private ScoreMap getGamesWon(List easyGames, List mediumGames, List hardGames) { + return new ScoreMap((double) easyGames.stream().filter(Game::isSuccess).toList().size(), (double) mediumGames.stream().filter(Game::isSuccess).toList().size(), (double) hardGames.stream().filter(Game::isSuccess).toList().size()); } - private ScoreMap getLongestWinningStreaks(List easyGames, List mediumGames, List hardGames) { + private ScoreMap getLongestWinningStreaks(List easyGames, List mediumGames, List hardGames) { Map easyStreaks = getStreaks(easyGames); Map mediumStreaks = getStreaks(mediumGames); Map hardStreaks = getStreaks(hardGames); @@ -79,7 +79,7 @@ private ScoreMap getLongestWinningStreaks(List easyGames, List easyGames, List mediumGames, List hardGames) { + private ScoreMap getLongestLosingStreaks(List easyGames, List mediumGames, List hardGames) { Map easyStreaks = getStreaks(easyGames); Map mediumStreaks = getStreaks(mediumGames); Map hardStreaks = getStreaks(hardGames); @@ -88,7 +88,7 @@ private ScoreMap getLongestLosingStreaks(List easyGames, List getStreaks(List games) { + private Map getStreaks(List games) { Map streaks = new HashMap<>(); List winningStreaks = new ArrayList<>(); @@ -97,7 +97,7 @@ private Map getStreaks(List games) { double winningStreak = 0; double losingStreak = 0; - for (ClassicGame game : games) { + for (Game game : games) { if (game.isSuccess()) { winningStreak++; if (losingStreak != 0) { diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java index 0d4969e..4ea8e09 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/game/controller/ClassicGameControllerIntegrationTest.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.controller; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +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; @@ -87,8 +87,8 @@ void createGameTest_whenGameCreateGiven_thenReturnGame() throws Exception { void getGamesByUserIdTest_whenOneMatchingGameInDB_thenReturnMatchingGame() throws Exception { // Given Instant now = Instant.parse("2016-06-09T00:00:00Z"); - ClassicGame testGame = new ClassicGame("1", "User1", "Type", 1, true, 10, List.of("#FFFFFF"), now); - ClassicGame testGame2 = new ClassicGame("2", "User2", "Type", 1, true, 10, Collections.emptyList(), now); + Game testGame = new Game("1", "User1", "Type", 1, true, 10, List.of("#FFFFFF"), now); + Game testGame2 = new Game("2", "User2", "Type", 1, true, 10, Collections.emptyList(), now); gameRepo.save(testGame); gameRepo.save(testGame2); diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java index bdb2a73..b6a57fb 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/game/service/ClassicGameServiceTest.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.game.service; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +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; @@ -35,32 +35,32 @@ void createGame_shouldSaveGame() { GameCreate mockGame = mock(GameCreate.class); Instant now = Instant.now(); - ClassicGame expectedGame = new ClassicGame("1", "User1", "Type", 1, true, 10, Collections.emptyList(), now); + Game expectedGame = new Game("1", "User1", "Type", 1, true, 10, Collections.emptyList(), now); GameCreate gameCreate = new GameCreate("User1", "Type", 1, true, 10, Collections.emptyList()); when(idService.generateUUID()).thenReturn("1"); when(timeService.getNow()).thenReturn(now); when(mockGame.withIdAndCreatedAt("1", now)).thenReturn(expectedGame); - when(gameRepo.save(any(ClassicGame.class))).thenReturn(expectedGame); + when(gameRepo.save(any(Game.class))).thenReturn(expectedGame); // When - ClassicGame savedGame = gameService.createGame(gameCreate); + Game savedGame = gameService.createGame(gameCreate); // Then assertEquals(expectedGame, savedGame); - verify(gameRepo, times(1)).save(any(ClassicGame.class)); + verify(gameRepo, times(1)).save(any(Game.class)); } @Test void getGamesByUserId_shouldReturnGames() { // Given String userId = "User1"; - List expectedGames = Collections.singletonList(new ClassicGame("1", userId, "Type", 1, true, 10, Collections.emptyList(), Instant.now())); + List expectedGames = Collections.singletonList(new Game("1", userId, "Type", 1, true, 10, Collections.emptyList(), Instant.now())); when(gameRepo.findAllByUserId(userId)).thenReturn(expectedGames); // When - List actualGames = gameService.getGamesByUserId(userId); + List actualGames = gameService.getGamesByUserId(userId); // Then assertEquals(expectedGames, actualGames); diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java index d1bb9b2..cd80e2c 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java @@ -1,6 +1,6 @@ package de.neuefische.paulkreft.backend.statistic.service; -import de.neuefische.paulkreft.backend.game.classic.model.ClassicGame; +import de.neuefische.paulkreft.backend.game.classic.model.Game; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; @@ -24,29 +24,29 @@ void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { StatisticService statisticService = new StatisticService(gameRepo); - ClassicGame game1 = new ClassicGame("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); - ClassicGame game2 = new ClassicGame("51e74bcd-d341-4ac9-8311-2513a86e9261", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 8515, List.of("#05a928", "#adbb2f", "#0c58b8", "#5244d0", "#f3a747", "#fa56d7"), Instant.parse("2024-02-09T15:19:09.388Z")); - ClassicGame game3 = new ClassicGame("b6bd5d8b-42c6-4efc-985f-dfc48e2df7e0", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#53accc", "#ac5333", "#3ed3ab", "#c12c54", "#6a13b4", "#95ec4b"), Instant.parse("2024-02-09T15:19:13.671Z")); - ClassicGame game4 = new ClassicGame("25fefbca-6d74-408f-aaa3-397e37a19764", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 5000, List.of("#4a4b01", "#b5b4fe", "#7d8b42", "#960ba7", "#8274bd", "#69f458"), Instant.parse("2024-02-09T15:19:23.261Z")); - ClassicGame game5 = new ClassicGame("641730f8-0654-4912-ae4f-37bbd64d4a86", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 16616, List.of("#099c93", "#c2a995", "#c51a5f", "#f6636c", "#3d566a", "#3ae5a0"), Instant.parse("2024-02-09T16:13:23.514Z")); - ClassicGame game6 = new ClassicGame("066cfbb8-c4f4-45d8-9af5-e65970e11f5c", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 8578, List.of("#8e4392", "#9532a1", "#8e1e9e", "#3e6697", "#71bc6d", "#c19968", "#6acd5e", "#71e161"), Instant.parse("2024-02-09T16:13:37.306Z")); - ClassicGame game7 = new ClassicGame("11b7aabb-2261-48a0-8ce0-1c30d7d13dc8", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 16699, List.of("#1d9dbd", "#c32605", "#3cd9fa", "#e26242", "#177ca5", "#ea622e", "#e8835a", "#159dd1"), Instant.parse("2024-02-09T16:13:55.319Z")); - ClassicGame game8 = new ClassicGame("8fa85a56-1a78-48ff-b5f1-172f75475b0a", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#de02b8", "#60317a", "#5ce92d", "#9fce85", "#e67e12", "#e254b5", "#1981ed", "#227da2", "#a316d2", "#dd825d", "#21fd47", "#1dab4a"), Instant.parse("2024-02-09T16:14:15.221Z")); - ClassicGame game9 = new ClassicGame("c15f9b9a-71d9-49e4-82e4-cbb9007358af", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#c19615", "#efde72", "#4f40fb", "#e26b51", "#3e69ea", "#5ee08c", "#5f3394", "#1d94ae", "#10218d", "#a0cc6b", "#a11f73", "#b0bf04"), Instant.parse("2024-02-09T16:14:25.192Z")); - ClassicGame game10 = new ClassicGame("3cd692e8-f028-4e72-a92d-ed69dd4c6a94", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#9b01c2", "#5450f6", "#2a0cb1", "#195378", "#fd1b5b", "#02e4a4", "#d5f34e", "#77f5fc", "#e6ac87", "#64fe3d", "#abaf09", "#880a03"), Instant.parse("2024-02-09T16:14:49.157Z")); - ClassicGame game11 = new ClassicGame("efdb3e28-78fa-4abe-9328-df77cfeb1186", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#1fb50d", "#855303", "#c542b0", "#1177e3", "#620463", "#986046", "#3abd4f", "#e04af2", "#9dfb9c", "#ee881c", "#679fb9", "#7aacfc"), Instant.parse("2024-02-09T16:14:53.990Z")); - ClassicGame game12 = new ClassicGame("b91f14e0-086e-402b-9823-16a55278f713", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, true, 15833, List.of("#84211c", "#7bdee3", "#350e34", "#762766", "#8cbf63", "#be7b12", "#caf1cb", "#73409c", "#89d899", "#a773ff", "#4184ed", "#588c00"), Instant.parse("2024-02-09T16:15:10.996Z")); - ClassicGame game13 = new ClassicGame("42e62761-2c95-488a-885b-ee2c012ab1dc", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#75ce6b", "#5dbaf4", "#a2450b", "#c65e86", "#39a179", "#8a3194"), Instant.parse("2024-02-09T16:16:53.418Z")); - ClassicGame game14 = new ClassicGame("26c84fe4-b77b-4858-83e1-5a3a4499fabe", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3851, List.of("#1b43bc", "#023e44", "#fdc1bb", "#e4bc43", "#5c8731", "#a378ce"), Instant.parse("2024-02-09T16:16:58.237Z")); - ClassicGame game15 = new ClassicGame("42ede063-4bcd-4e14-a091-80ab6a98285f", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#aba965", "#37e2c7", "#1fe8eb", "#e01714", "#54569a", "#c81d38"), Instant.parse("2024-02-09T16:17:05.101Z")); - ClassicGame game16 = new ClassicGame("16c3ba8c-c7f4-4089-8719-2d3d5b8bab99", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3750, List.of("#74f523", "#3a928c", "#06085c", "#8b0adc", "#c56d73", "#f9f7a3"), Instant.parse("2024-02-09T16:17:10.384Z")); - ClassicGame game17 = new ClassicGame("60aa46f9-feaf-4ca4-99b1-a6685a3712d7", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#5efe36", "#e93efa", "#16c105", "#a101c9", "#a5a045", "#5a5fba"), Instant.parse("2024-02-09T16:17:12.851Z")); - ClassicGame game18 = new ClassicGame("8bc70a24-2e44-4b78-a333-8e6a486e8f21", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3632, List.of("#8ed974", "#d00308", "#71268b", "#2ffcf7", "#095bf0", "#f6a40f"), Instant.parse("2024-02-09T16:17:17.570Z")); - ClassicGame game19 = new ClassicGame("0c88bce7-4232-4f1f-8bdc-013658874091", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 6700, List.of("#8bd278", "#67dd65", "#9abd98", "#98229a", "#742d87", "#654267"), Instant.parse("2024-02-09T16:17:25.085Z")); - ClassicGame game20 = new ClassicGame("04fe2411-6be3-4d92-b5a8-06d8386f0cc1", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff"), Instant.parse("2024-02-09T16:23:37.832Z")); - ClassicGame game21 = new ClassicGame("7824747f-97d4-415f-a6f4-080906b78c79", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, false, 0, List.of("#695cdd", "#522f88", "#96a322", "#add077", "#f56853", "#d6656c", "#299a93", "#0a97ac"), Instant.parse("2024-02-09T16:25:45.317Z")); - - List games = List.of(game1, game2, game3, game4, game5, game6, game7, game8, game9, game10, game11, game12, game13, game14, game15, game16, game17, game18, game19, game20, game21); + Game game1 = new Game("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); + Game game2 = new Game("51e74bcd-d341-4ac9-8311-2513a86e9261", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 8515, List.of("#05a928", "#adbb2f", "#0c58b8", "#5244d0", "#f3a747", "#fa56d7"), Instant.parse("2024-02-09T15:19:09.388Z")); + Game game3 = new Game("b6bd5d8b-42c6-4efc-985f-dfc48e2df7e0", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#53accc", "#ac5333", "#3ed3ab", "#c12c54", "#6a13b4", "#95ec4b"), Instant.parse("2024-02-09T15:19:13.671Z")); + Game game4 = new Game("25fefbca-6d74-408f-aaa3-397e37a19764", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 5000, List.of("#4a4b01", "#b5b4fe", "#7d8b42", "#960ba7", "#8274bd", "#69f458"), Instant.parse("2024-02-09T15:19:23.261Z")); + Game game5 = new Game("641730f8-0654-4912-ae4f-37bbd64d4a86", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 16616, List.of("#099c93", "#c2a995", "#c51a5f", "#f6636c", "#3d566a", "#3ae5a0"), Instant.parse("2024-02-09T16:13:23.514Z")); + Game game6 = new Game("066cfbb8-c4f4-45d8-9af5-e65970e11f5c", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 8578, List.of("#8e4392", "#9532a1", "#8e1e9e", "#3e6697", "#71bc6d", "#c19968", "#6acd5e", "#71e161"), Instant.parse("2024-02-09T16:13:37.306Z")); + Game game7 = new Game("11b7aabb-2261-48a0-8ce0-1c30d7d13dc8", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, true, 16699, List.of("#1d9dbd", "#c32605", "#3cd9fa", "#e26242", "#177ca5", "#ea622e", "#e8835a", "#159dd1"), Instant.parse("2024-02-09T16:13:55.319Z")); + Game game8 = new Game("8fa85a56-1a78-48ff-b5f1-172f75475b0a", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#de02b8", "#60317a", "#5ce92d", "#9fce85", "#e67e12", "#e254b5", "#1981ed", "#227da2", "#a316d2", "#dd825d", "#21fd47", "#1dab4a"), Instant.parse("2024-02-09T16:14:15.221Z")); + Game game9 = new Game("c15f9b9a-71d9-49e4-82e4-cbb9007358af", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#c19615", "#efde72", "#4f40fb", "#e26b51", "#3e69ea", "#5ee08c", "#5f3394", "#1d94ae", "#10218d", "#a0cc6b", "#a11f73", "#b0bf04"), Instant.parse("2024-02-09T16:14:25.192Z")); + Game game10 = new Game("3cd692e8-f028-4e72-a92d-ed69dd4c6a94", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#9b01c2", "#5450f6", "#2a0cb1", "#195378", "#fd1b5b", "#02e4a4", "#d5f34e", "#77f5fc", "#e6ac87", "#64fe3d", "#abaf09", "#880a03"), Instant.parse("2024-02-09T16:14:49.157Z")); + Game game11 = new Game("efdb3e28-78fa-4abe-9328-df77cfeb1186", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#1fb50d", "#855303", "#c542b0", "#1177e3", "#620463", "#986046", "#3abd4f", "#e04af2", "#9dfb9c", "#ee881c", "#679fb9", "#7aacfc"), Instant.parse("2024-02-09T16:14:53.990Z")); + Game game12 = new Game("b91f14e0-086e-402b-9823-16a55278f713", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, true, 15833, List.of("#84211c", "#7bdee3", "#350e34", "#762766", "#8cbf63", "#be7b12", "#caf1cb", "#73409c", "#89d899", "#a773ff", "#4184ed", "#588c00"), Instant.parse("2024-02-09T16:15:10.996Z")); + Game game13 = new Game("42e62761-2c95-488a-885b-ee2c012ab1dc", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#75ce6b", "#5dbaf4", "#a2450b", "#c65e86", "#39a179", "#8a3194"), Instant.parse("2024-02-09T16:16:53.418Z")); + Game game14 = new Game("26c84fe4-b77b-4858-83e1-5a3a4499fabe", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3851, List.of("#1b43bc", "#023e44", "#fdc1bb", "#e4bc43", "#5c8731", "#a378ce"), Instant.parse("2024-02-09T16:16:58.237Z")); + Game game15 = new Game("42ede063-4bcd-4e14-a091-80ab6a98285f", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#aba965", "#37e2c7", "#1fe8eb", "#e01714", "#54569a", "#c81d38"), Instant.parse("2024-02-09T16:17:05.101Z")); + Game game16 = new Game("16c3ba8c-c7f4-4089-8719-2d3d5b8bab99", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3750, List.of("#74f523", "#3a928c", "#06085c", "#8b0adc", "#c56d73", "#f9f7a3"), Instant.parse("2024-02-09T16:17:10.384Z")); + Game game17 = new Game("60aa46f9-feaf-4ca4-99b1-a6685a3712d7", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#5efe36", "#e93efa", "#16c105", "#a101c9", "#a5a045", "#5a5fba"), Instant.parse("2024-02-09T16:17:12.851Z")); + Game game18 = new Game("8bc70a24-2e44-4b78-a333-8e6a486e8f21", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 3632, List.of("#8ed974", "#d00308", "#71268b", "#2ffcf7", "#095bf0", "#f6a40f"), Instant.parse("2024-02-09T16:17:17.570Z")); + Game game19 = new Game("0c88bce7-4232-4f1f-8bdc-013658874091", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, true, 6700, List.of("#8bd278", "#67dd65", "#9abd98", "#98229a", "#742d87", "#654267"), Instant.parse("2024-02-09T16:17:25.085Z")); + Game game20 = new Game("04fe2411-6be3-4d92-b5a8-06d8386f0cc1", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 4, false, 0, List.of("#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff", "#000000", "#ffffff"), Instant.parse("2024-02-09T16:23:37.832Z")); + Game game21 = new Game("7824747f-97d4-415f-a6f4-080906b78c79", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 2, false, 0, List.of("#695cdd", "#522f88", "#96a322", "#add077", "#f56853", "#d6656c", "#299a93", "#0a97ac"), Instant.parse("2024-02-09T16:25:45.317Z")); + + List games = List.of(game1, game2, game3, game4, game5, game6, game7, game8, game9, game10, game11, game12, game13, game14, game15, game16, game17, game18, game19, game20, game21); when(gameRepo.findAllByUserIdOrderByCreatedAtAsc(any())).thenReturn(games); From 14d8d4270d2db33f41fe78e25f4034b90320e354 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 15:21:56 +0100 Subject: [PATCH 09/18] add capacity to lobby; add totalPlayers to MultiplayerGame --- .../backend/exception/GlobalExceptionHandler.java | 6 ++++++ .../backend/exception/LobbyCapacityExceededException.java | 7 +++++++ .../backend/game/multiplayer/model/MultiplayerGame.java | 3 ++- .../game/multiplayer/model/MultiplayerGameCreate.java | 7 ++++--- .../paulkreft/backend/lobby/service/LobbyService.java | 5 +++++ frontend/src/components/LobbyEntrance.tsx | 5 ++++- frontend/src/components/MultiplayerSession.tsx | 5 ++++- frontend/src/types/MultiplayerGame.ts | 3 ++- 8 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 backend/src/main/java/de/neuefische/paulkreft/backend/exception/LobbyCapacityExceededException.java diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/exception/GlobalExceptionHandler.java b/backend/src/main/java/de/neuefische/paulkreft/backend/exception/GlobalExceptionHandler.java index 5297c93..96d69c3 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/exception/GlobalExceptionHandler.java @@ -72,4 +72,10 @@ public String handleException(RequestQueueNotFoundException exception) { public String handleException(PlayerNotPartOfLobbyException exception) { return exception.getMessage(); } + + @ExceptionHandler({LobbyCapacityExceededException.class}) + @ResponseStatus(HttpStatus.CONFLICT) + public String handleException(LobbyCapacityExceededException exception) { + return exception.getMessage(); + } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/exception/LobbyCapacityExceededException.java b/backend/src/main/java/de/neuefische/paulkreft/backend/exception/LobbyCapacityExceededException.java new file mode 100644 index 0000000..97316ad --- /dev/null +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/exception/LobbyCapacityExceededException.java @@ -0,0 +1,7 @@ +package de.neuefische.paulkreft.backend.exception; + +public class LobbyCapacityExceededException extends RuntimeException { + public LobbyCapacityExceededException(String errorMessage) { + super(errorMessage); + } +} diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGame.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGame.java index 82f037c..eb038a2 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGame.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGame.java @@ -11,9 +11,10 @@ public record MultiplayerGame( List playerIds, int difficulty, Integer streakToWin, - String winnerId, + List winnerIds, List loserIds, Integer wonInMilliseconds, + int totalPlayers, Instant createdAt ) { } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java index 68ea22e..6b2a03b 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java @@ -7,11 +7,12 @@ public record MultiplayerGameCreate( List playerIds, int difficulty, Integer streakToWin, - String winnerId, + List winnerId, List loserIds, - Integer wonInMilliseconds + Integer wonInMilliseconds, + int totalPlayers ) { public MultiplayerGame withIdAndCreatedAt(String id, Instant createdAt) { - return new MultiplayerGame(id, this.playerIds, this.difficulty, this.streakToWin, this.winnerId, this.loserIds, this.wonInMilliseconds, createdAt); + return new MultiplayerGame(id, this.playerIds, this.difficulty, this.streakToWin, this.winnerId, this.loserIds, this.wonInMilliseconds, this.totalPlayers , createdAt); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/service/LobbyService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/service/LobbyService.java index d5f126d..c50ca9e 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/service/LobbyService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/lobby/service/LobbyService.java @@ -4,6 +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.LobbyCapacityExceededException; import de.neuefische.paulkreft.backend.exception.LobbyGoneException; import de.neuefische.paulkreft.backend.exception.PlayerNotPartOfLobbyException; import de.neuefische.paulkreft.backend.lobby.model.Lobby; @@ -43,6 +44,10 @@ public Lobby joinLobby(String id, @RequestBody Player player) { return lobby; } + if (lobby.capacity() != null && lobby.players().size() == lobby.capacity()) { + throw new LobbyCapacityExceededException("This lobby is full"); + } + lobby.players().add(player); return lobbyRepo.save(lobby); } diff --git a/frontend/src/components/LobbyEntrance.tsx b/frontend/src/components/LobbyEntrance.tsx index c71e3cb..e236efd 100644 --- a/frontend/src/components/LobbyEntrance.tsx +++ b/frontend/src/components/LobbyEntrance.tsx @@ -43,7 +43,10 @@ export const LobbyEntrance: React.FC = ({ user }) => { }; const joinLobby = (): void => { - axios.put(`/api/lobby/${lobbyId}/join`, currentPlayer).then(() => navigate(`/multiplayer/lobby/${lobbyId}`)); + axios + .put(`/api/lobby/${lobbyId}/join`, currentPlayer) + .then(() => navigate(`/multiplayer/lobby/${lobbyId}`)) + .catch((error) => console.log(error)); }; const handleKeyDownOnInput = (event: React.KeyboardEvent): void => { diff --git a/frontend/src/components/MultiplayerSession.tsx b/frontend/src/components/MultiplayerSession.tsx index 950c164..604cf73 100644 --- a/frontend/src/components/MultiplayerSession.tsx +++ b/frontend/src/components/MultiplayerSession.tsx @@ -25,6 +25,7 @@ export const MultiplayerSession: React.FC = ({ user }) => { const [isGameOver, setIsGameOver] = useState(false); const [isSavedToDatabase, setIsSavedToDatabase] = useState(false); + const [totalPlayers, setTotalPlayers] = useState(2); useEffect(() => { if (lobby?.losers.length && lobby.winner && lobby.losers.length >= lobby.players.length - 1) { @@ -37,9 +38,10 @@ export const MultiplayerSession: React.FC = ({ user }) => { playerIds: lobby.players.map((player) => player.id), difficulty: lobby.difficulty, streakToWin: lobby.streakToWin, - winnerId: lobby.winner.id, + winnerIds: [lobby.winner.id], loserIds: lobby.losers.map((loser) => loser.id), wonInMilliseconds: lobby.timeToBeat, + totalPlayers }) .then(() => setIsSavedToDatabase(true)) .catch((error) => console.log(error)); @@ -100,6 +102,7 @@ export const MultiplayerSession: React.FC = ({ user }) => { }) .then((response) => { setLobby(response.data); + setTotalPlayers(lobby ? lobby.players.length : 0); }); }; diff --git a/frontend/src/types/MultiplayerGame.ts b/frontend/src/types/MultiplayerGame.ts index aa3228b..d14ea57 100644 --- a/frontend/src/types/MultiplayerGame.ts +++ b/frontend/src/types/MultiplayerGame.ts @@ -3,8 +3,9 @@ export type MultiplayerGame = { playerIds: string[]; difficulty: number; streakToWin: number; - winnerId: string; + winnerId: string[]; loserIds: string[]; wonInMilliseconds: number; + totalPlayers: number; createdAt?: string; }; From a3b299f3b0854c8942928c6f09175721191e6f78 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 16:06:17 +0100 Subject: [PATCH 10/18] fix frontend - backend attribute naming incompatibility --- .../backend/game/multiplayer/model/MultiplayerGameCreate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java index 6b2a03b..3e5e7ed 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/model/MultiplayerGameCreate.java @@ -7,12 +7,12 @@ public record MultiplayerGameCreate( List playerIds, int difficulty, Integer streakToWin, - List winnerId, + List winnerIds, List loserIds, Integer wonInMilliseconds, int totalPlayers ) { public MultiplayerGame withIdAndCreatedAt(String id, Instant createdAt) { - return new MultiplayerGame(id, this.playerIds, this.difficulty, this.streakToWin, this.winnerId, this.loserIds, this.wonInMilliseconds, this.totalPlayers , createdAt); + return new MultiplayerGame(id, this.playerIds, this.difficulty, this.streakToWin, this.winnerIds, this.loserIds, this.wonInMilliseconds, this.totalPlayers , createdAt); } } From 80eec2fba87d01fe13b42aa43984896245bdcb13 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 17:22:07 +0100 Subject: [PATCH 11/18] fix multiplayer game duplicate save bug --- .../src/components/MultiplayerSession.tsx | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/MultiplayerSession.tsx b/frontend/src/components/MultiplayerSession.tsx index 604cf73..9c67753 100644 --- a/frontend/src/components/MultiplayerSession.tsx +++ b/frontend/src/components/MultiplayerSession.tsx @@ -30,28 +30,38 @@ export const MultiplayerSession: React.FC = ({ user }) => { useEffect(() => { if (lobby?.losers.length && lobby.winner && lobby.losers.length >= lobby.players.length - 1) { setIsGameOver(true); - - lobby.host.id === player.id && - !isSavedToDatabase && - axios - .post("/api/game/multiplayer", { - playerIds: lobby.players.map((player) => player.id), - difficulty: lobby.difficulty, - streakToWin: lobby.streakToWin, - winnerIds: [lobby.winner.id], - loserIds: lobby.losers.map((loser) => loser.id), - wonInMilliseconds: lobby.timeToBeat, - totalPlayers - }) - .then(() => setIsSavedToDatabase(true)) - .catch((error) => console.log(error)); - return; } setIsGameOver(false); - setIsSavedToDatabase(false); }, [lobby?.losers, lobby?.players]); + useEffect(() => { + if (!isGameOver) { + setIsSavedToDatabase(false); + } + + if (!lobby?.winner) { + return; + } + + lobby.host.id === player.id && + !isSavedToDatabase && + axios + .post("/api/game/multiplayer", { + playerIds: lobby.players.map((player) => player.id), + difficulty: lobby.difficulty, + streakToWin: lobby.streakToWin, + winnerIds: [lobby.winner.id], + loserIds: lobby.losers.map((loser) => loser.id), + wonInMilliseconds: lobby.timeToBeat, + totalPlayers, + }) + .then(() => { + setIsSavedToDatabase(true); + }) + .catch((error) => console.log(error)); + }, [isGameOver]); + useEffect(() => { axios.get(`/api/lobby/${id}`).then((response) => { setLobby(response.data); From 85a73b45dbbf455dc1c7aa1b14551d5e16a92193 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 17:24:51 +0100 Subject: [PATCH 12/18] remove unnecessary state variable --- frontend/src/components/MultiplayerSession.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/MultiplayerSession.tsx b/frontend/src/components/MultiplayerSession.tsx index 9c67753..1953c65 100644 --- a/frontend/src/components/MultiplayerSession.tsx +++ b/frontend/src/components/MultiplayerSession.tsx @@ -24,7 +24,6 @@ export const MultiplayerSession: React.FC = ({ user }) => { const [startTime, setStartTime] = useState(); const [isGameOver, setIsGameOver] = useState(false); - const [isSavedToDatabase, setIsSavedToDatabase] = useState(false); const [totalPlayers, setTotalPlayers] = useState(2); useEffect(() => { @@ -37,7 +36,7 @@ export const MultiplayerSession: React.FC = ({ user }) => { useEffect(() => { if (!isGameOver) { - setIsSavedToDatabase(false); + return; } if (!lobby?.winner) { @@ -45,7 +44,6 @@ export const MultiplayerSession: React.FC = ({ user }) => { } lobby.host.id === player.id && - !isSavedToDatabase && axios .post("/api/game/multiplayer", { playerIds: lobby.players.map((player) => player.id), @@ -56,9 +54,7 @@ export const MultiplayerSession: React.FC = ({ user }) => { wonInMilliseconds: lobby.timeToBeat, totalPlayers, }) - .then(() => { - setIsSavedToDatabase(true); - }) + .then(() => {}) .catch((error) => console.log(error)); }, [isGameOver]); From 9a67b6a91c3b571b4aa82d06082070ecc90acc1e Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 18:07:16 +0100 Subject: [PATCH 13/18] provide basic duel statistics in backend --- .../repository/MultiplayerGameRepo.java | 3 ++ .../statistic/model/DuelStatistics.java | 9 ++++++ .../statistic/service/StatisticService.java | 29 ++++++++++++++++--- .../user/controller/UserController.java | 10 +++++-- .../backend/user/service/UserService.java | 8 +++-- .../service/StatisticServiceTest.java | 8 +++-- 6 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/DuelStatistics.java diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java index 2b37dfc..8aadf8e 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java @@ -4,6 +4,9 @@ import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface MultiplayerGameRepo extends MongoRepository { + List findAllByTotalPlayersAndPlayerIdsOrderByCreatedAtAsc(int totalPlayers, List playerIds); } \ No newline at end of file diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/DuelStatistics.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/DuelStatistics.java new file mode 100644 index 0000000..59c5140 --- /dev/null +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/model/DuelStatistics.java @@ -0,0 +1,9 @@ +package de.neuefische.paulkreft.backend.statistic.model; + +public record DuelStatistics( + String player, + String opponent, + ScoreMap gamesPlayed, + ScoreMap gamesWon +) { +} diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java index d341976..36ad67c 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -2,26 +2,31 @@ import de.neuefische.paulkreft.backend.game.classic.model.Game; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; -import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; +import de.neuefische.paulkreft.backend.game.multiplayer.model.MultiplayerGame; +import de.neuefische.paulkreft.backend.game.multiplayer.repository.MultiplayerGameRepo; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; +import de.neuefische.paulkreft.backend.statistic.model.DuelStatistics; +import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.*; - @Service @RequiredArgsConstructor public class StatisticService { private final GameRepo gameRepo; + private final MultiplayerGameRepo multiplayerGameRepo; private static final int EASY = 1; private static final int MEDIUM = 2; private static final int HARD = 4; - public ClassicStatistics getUserStatistics(String id) { - List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); + private static final int DUEL_TOTAL_PLAYERS = 2; + + public ClassicStatistics getUserClassicStatistics(String id) { + List games = gameRepo.findAllByUserId(id); List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); @@ -38,6 +43,22 @@ public ClassicStatistics getUserStatistics(String id) { } + public DuelStatistics getUserDuelStatistics(String id, String opponentId) { + List games = multiplayerGameRepo.findAllByTotalPlayersAndPlayerIdsOrderByCreatedAtAsc(DUEL_TOTAL_PLAYERS, List.of(id, opponentId)); + + + List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); + List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); + List hardGames = games.stream().filter(game -> game.difficulty() == HARD).toList(); + + double easyGamesWon = easyGames.stream().filter(game -> game.winnerIds().contains(id)).toList().size(); + double mediumGamesWon = mediumGames.stream().filter(game -> game.winnerIds().contains(id)).toList().size(); + double hardGamesWon = hardGames.stream().filter(game -> game.winnerIds().contains(id)).toList().size(); + + return new DuelStatistics(id, opponentId, new ScoreMap((double) easyGames.size(), (double) mediumGames.size(), (double) hardGames.size()), new ScoreMap(easyGamesWon, mediumGamesWon, hardGamesWon)); + } + + private ScoreMap getAverageDurations(List easyGames, List mediumGames, List hardGames) { List easyDurations = easyGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); List mediumDurations = mediumGames.stream().map(game -> Double.valueOf(game.duration())).filter(d -> d != 0).toList(); diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java b/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java index 39d29f0..8278675 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/user/controller/UserController.java @@ -1,6 +1,7 @@ package de.neuefische.paulkreft.backend.user.controller; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; +import de.neuefische.paulkreft.backend.statistic.model.DuelStatistics; import de.neuefische.paulkreft.backend.user.model.User; import de.neuefische.paulkreft.backend.user.model.UserGet; import de.neuefische.paulkreft.backend.user.service.UserService; @@ -27,7 +28,12 @@ public UserGet updateUser(@RequestBody User user) { } @GetMapping("{id}/statistics") - public ClassicStatistics getUserStatistics(@PathVariable String id) { - return userService.getStatistics(id); + public ClassicStatistics getUserClassicStatistics(@PathVariable String id) { + return userService.getClassicStatistics(id); + } + + @GetMapping("{id}/statistics/duel") + public DuelStatistics getUserDuelStatistics(@PathVariable String id, @RequestParam String opponentId) { + return userService.getDuelStatistics(id, opponentId); } } diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java index afb5845..2eb03fb 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/user/service/UserService.java @@ -3,6 +3,7 @@ import de.neuefische.paulkreft.backend.exception.GithubEmailNotFoundException; import de.neuefische.paulkreft.backend.github.service.GithubService; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; +import de.neuefische.paulkreft.backend.statistic.model.DuelStatistics; import de.neuefische.paulkreft.backend.statistic.service.StatisticService; import de.neuefische.paulkreft.backend.utils.service.IdService; import de.neuefische.paulkreft.backend.utils.service.TimeService; @@ -97,8 +98,11 @@ public boolean existsByEmail(String email) { return usersRepo.existsUserByEmail(email); } - public ClassicStatistics getStatistics(String id) { - return statisticService.getUserStatistics(id); + public ClassicStatistics getClassicStatistics(String id) { + return statisticService.getUserClassicStatistics(id); + } + public DuelStatistics getDuelStatistics(String id, String opponentId) { + return statisticService.getUserDuelStatistics(id, opponentId); } } diff --git a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java index cd80e2c..19edd1a 100644 --- a/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java +++ b/backend/src/test/java/de/neuefische/paulkreft/backend/statistic/service/StatisticServiceTest.java @@ -2,6 +2,7 @@ import de.neuefische.paulkreft.backend.game.classic.model.Game; import de.neuefische.paulkreft.backend.game.classic.repository.GameRepo; +import de.neuefische.paulkreft.backend.game.multiplayer.repository.MultiplayerGameRepo; import de.neuefische.paulkreft.backend.statistic.model.ScoreMap; import de.neuefische.paulkreft.backend.statistic.model.ClassicStatistics; import org.junit.jupiter.api.Test; @@ -17,11 +18,12 @@ class StatisticServiceTest { @Test - void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { + void getUserClassicStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { // Given GameRepo gameRepo = Mockito.mock(GameRepo.class); + MultiplayerGameRepo multiplayerGameRepo = Mockito.mock(MultiplayerGameRepo.class); - StatisticService statisticService = new StatisticService(gameRepo); + StatisticService statisticService = new StatisticService(gameRepo, multiplayerGameRepo); Game game1 = new Game("7b6cc6c8-b98f-428a-bee5-2e4e804901cd", "f39e6614-8132-4f8e-bd98-6fdf50fed3b0", "", 1, false, 0, List.of("#f1da9b", "#bb463d", "#0e2564", "#237dc9", "#44b9c2", "#dc8236"), Instant.parse("2024-02-09T15:18:59.426Z")); @@ -60,7 +62,7 @@ void getUserStatisticsTest_whenAllStatisticsCalculable_returnCorrectValues() { ); // When - ClassicStatistics actual = statisticService.getUserStatistics(""); + ClassicStatistics actual = statisticService.getUserClassicStatistics(""); // Then assertNotNull(actual); From a064099312f25aa75c9ee9702b0c1e5f0dbae35d Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 18:50:18 +0100 Subject: [PATCH 14/18] add DuelStatistic model in frontend --- frontend/src/types/DuelStatistics.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 frontend/src/types/DuelStatistics.ts diff --git a/frontend/src/types/DuelStatistics.ts b/frontend/src/types/DuelStatistics.ts new file mode 100644 index 0000000..67eb947 --- /dev/null +++ b/frontend/src/types/DuelStatistics.ts @@ -0,0 +1,6 @@ +import {ScoreMap} from "./ScoreMap.ts"; + +export type DuelStatistics = { + gamesPlayed: ScoreMap; + gamesWon: ScoreMap; +} \ No newline at end of file From 8b39884238b2f38717a631a8eafe415062fcfccb Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 18:51:38 +0100 Subject: [PATCH 15/18] fix db retrieval method --- .../game/multiplayer/repository/MultiplayerGameRepo.java | 2 +- .../paulkreft/backend/statistic/service/StatisticService.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java index 8aadf8e..fb98cab 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/game/multiplayer/repository/MultiplayerGameRepo.java @@ -8,5 +8,5 @@ @Repository public interface MultiplayerGameRepo extends MongoRepository { - List findAllByTotalPlayersAndPlayerIdsOrderByCreatedAtAsc(int totalPlayers, List playerIds); + List findAllByTotalPlayersAndPlayerIdsIsContainingOrderByCreatedAtAsc(int totalPlayers, List playerIds); } \ No newline at end of file diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java index 36ad67c..0eb624e 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -44,8 +44,7 @@ public ClassicStatistics getUserClassicStatistics(String id) { public DuelStatistics getUserDuelStatistics(String id, String opponentId) { - List games = multiplayerGameRepo.findAllByTotalPlayersAndPlayerIdsOrderByCreatedAtAsc(DUEL_TOTAL_PLAYERS, List.of(id, opponentId)); - + List games = multiplayerGameRepo.findAllByTotalPlayersAndPlayerIdsIsContainingOrderByCreatedAtAsc(DUEL_TOTAL_PLAYERS, List.of(id, opponentId)); List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); From e05974ab000c94887e994bb6a76d71606470205c Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 18:53:25 +0100 Subject: [PATCH 16/18] get and show duel record in (duel) multiplayer lobby --- frontend/src/components/MultiplayerLobby.tsx | 49 ++++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/MultiplayerLobby.tsx b/frontend/src/components/MultiplayerLobby.tsx index 8f64a8e..9bb38d7 100644 --- a/frontend/src/components/MultiplayerLobby.tsx +++ b/frontend/src/components/MultiplayerLobby.tsx @@ -1,8 +1,10 @@ import { Spinner } from "./Spinner.tsx"; -import React, { ChangeEvent } from "react"; +import React, { ChangeEvent, useEffect, useState } from "react"; import { Player } from "../types/Player.ts"; import { Lobby } from "../types/Lobby.ts"; import copyToClipBoardIconUrl from "./../assets/copy-to-clipboard-icon.svg"; +import axios from "axios"; +import { DuelStatistics } from "../types/DuelStatistics.ts"; type MultiplayerLobbyProps = { lobby: Lobby; @@ -16,6 +18,9 @@ const EASY = 1; const MEDIUM = 2; const HARD = 4; +const DUEL_CAPACITY = 2; +const DUEL_TOTAL_PLAYERS = 2; + export const MultiplayerLobby: React.FC = ({ lobby, player, @@ -23,6 +28,26 @@ export const MultiplayerLobby: React.FC = ({ onChangeDifficulty, startGame, }) => { + const [duelStatistics, setDuelStatistics] = useState(); + + useEffect(() => { + if (lobby.capacity === DUEL_CAPACITY && lobby.players.length === DUEL_TOTAL_PLAYERS) { + const opponent: Player | undefined = lobby.players.find((opponent) => opponent.id != player.id); + if (!opponent) { + return; + } + + const opponentId: string = opponent.id; + + axios.get(`/api/user/${player.id}/statistics/duel?opponentId=${opponentId}`).then((response) => + setDuelStatistics({ + gamesPlayed: response.data.gamesPlayed, + gamesWon: response.data.gamesWon, + }), + ); + } + }, [lobby.players]); + return (
@@ -41,11 +66,11 @@ export const MultiplayerLobby: React.FC = ({ {lobby.host.id !== player.id && (
- Streak to win + Streak to win {lobby.streakToWin ?? "1"}
- Difficulty + Difficulty {lobby.difficulty === 1 ? "Easy" : lobby.difficulty === 2 ? "Medium" : "Hard"} @@ -53,10 +78,24 @@ export const MultiplayerLobby: React.FC = ({
)} -
+ {duelStatistics && ( +
+ Record + + {duelStatistics.gamesWon[lobby.difficulty === 1 ? "easy" : lobby.difficulty === 2 ? "medium" : "hard"]}{" "} + -{" "} + {duelStatistics.gamesPlayed[ + lobby.difficulty === 1 ? "easy" : lobby.difficulty === 2 ? "medium" : "hard" + ] - + duelStatistics.gamesWon[lobby.difficulty === 1 ? "easy" : lobby.difficulty === 2 ? "medium" : "hard"]} + +
+ )} + +
{lobby.players.map((player) => (
-
{player.name}
+
{player.name}
))} From dde6512dcbd617fe2943a0dadae4b349c4fb18df Mon Sep 17 00:00:00 2001 From: paulkreft Date: Fri, 23 Feb 2024 19:04:38 +0100 Subject: [PATCH 17/18] fix unintended changes --- .../paulkreft/backend/statistic/service/StatisticService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java index 0eb624e..ea17d39 100644 --- a/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java +++ b/backend/src/main/java/de/neuefische/paulkreft/backend/statistic/service/StatisticService.java @@ -26,7 +26,7 @@ public class StatisticService { private static final int DUEL_TOTAL_PLAYERS = 2; public ClassicStatistics getUserClassicStatistics(String id) { - List games = gameRepo.findAllByUserId(id); + List games = gameRepo.findAllByUserIdOrderByCreatedAtAsc(id); List easyGames = games.stream().filter(game -> game.difficulty() == EASY).toList(); List mediumGames = games.stream().filter(game -> game.difficulty() == MEDIUM).toList(); From 19b614a243899669a9a5d170c1dfe4be306acc51 Mon Sep 17 00:00:00 2001 From: paulkreft Date: Sun, 25 Feb 2024 19:35:18 +0100 Subject: [PATCH 18/18] add loading state for login / signup --- frontend/src/components/EmailLogin.tsx | 15 ++++++++++++--- frontend/src/components/EmailSignUp.tsx | 18 +++++++++++------- frontend/src/components/Login.tsx | 14 +++++++++++++- frontend/src/components/SignUp.tsx | 14 +++++++++++++- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/EmailLogin.tsx b/frontend/src/components/EmailLogin.tsx index 1019fad..f364f50 100644 --- a/frontend/src/components/EmailLogin.tsx +++ b/frontend/src/components/EmailLogin.tsx @@ -1,12 +1,13 @@ import React, { FormEvent, useEffect, useState } from "react"; import { cn } from "../lib/utils.ts"; +import {Spinner} from "./Spinner.tsx"; type EmailLoginProps = { login: (email: string, password: string) => void; }; export const EmailLogin: React.FC = ({ login }) => { - const [isSigningUp, setIsSigningUp] = useState(false); + const [isLoggingIn, setIsLoggingIn] = useState(false); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); @@ -26,10 +27,18 @@ export const EmailLogin: React.FC = ({ login }) => { const loginWithEmail = (event: FormEvent) => { event.preventDefault(); - setIsSigningUp(true); + setIsLoggingIn(true); login(email, password); }; + if (isLoggingIn) { + return ( +
+ +
+ ); + } + return (
@@ -76,7 +85,7 @@ export const EmailLogin: React.FC = ({ login }) => { diff --git a/frontend/src/components/EmailSignUp.tsx b/frontend/src/components/EmailSignUp.tsx index cb5b725..67b1405 100644 --- a/frontend/src/components/EmailSignUp.tsx +++ b/frontend/src/components/EmailSignUp.tsx @@ -1,6 +1,7 @@ import React, { FormEvent, useEffect, useState } from "react"; import { cn } from "../lib/utils.ts"; import axios from "axios"; +import { Spinner } from "./Spinner.tsx"; type EmailSignUpProps = { login: (email: string, password: string) => void; @@ -37,6 +38,14 @@ export const EmailSignUp: React.FC = ({ login }) => { .catch((e) => console.log(e)); }; + if (isSigningUp) { + return ( +
+ +
+ ); + } + return (
@@ -54,9 +63,7 @@ export const EmailSignUp: React.FC = ({ login }) => { onChange={(event) => setEmail(event.target.value)} required /> -
+
Invalid email format
@@ -73,10 +80,7 @@ export const EmailSignUp: React.FC = ({ login }) => { required />
Invalid password format
diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx index 8737128..517a5ea 100644 --- a/frontend/src/components/Login.tsx +++ b/frontend/src/components/Login.tsx @@ -1,14 +1,26 @@ import githubMarkUrl from "./../assets/github-mark.png"; import { Link } from "react-router-dom"; +import { Spinner } from "./Spinner.tsx"; +import { useState } from "react"; export default function Login() { + const [isLoading, setIsLoading] = useState(false); + const link = import.meta.env.PROD ? "/oauth2/authorization/github" : "http://localhost:8080/oauth2/authorization/github"; + if (isLoading) { + return ( +
+ +
+ ); + } + return (