From 65a7ef3e5fb7f115b87854fc47ae49a793bcf225 Mon Sep 17 00:00:00 2001 From: eric <3024947@stud.hs-mannheim.de> Date: Sun, 10 Aug 2025 23:11:24 +0200 Subject: [PATCH 1/2] refresh knopf entfern --- src/main/resources/public/game.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/public/game.html b/src/main/resources/public/game.html index 2c4e32a..2bb9718 100644 --- a/src/main/resources/public/game.html +++ b/src/main/resources/public/game.html @@ -189,7 +189,6 @@

Teilnehmer

-
From 5531b57018650e5150a76d9be469765e731018a1 Mon Sep 17 00:00:00 2001 From: eric <3024947@stud.hs-mannheim.de> Date: Mon, 11 Aug 2025 19:06:39 +0200 Subject: [PATCH 2/2] troubleshooting kram --- .../Roullette/controller/GameController.java | 23 ++++++-- .../Roullette/service/SpotifyAuthService.java | 58 +++++++++++++++++-- .../websocket/GameWebSocketHandler.java | 35 ++++++----- src/main/resources/public/js/game.js | 3 + 4 files changed, 91 insertions(+), 28 deletions(-) diff --git a/src/main/java/eric/Roullette/controller/GameController.java b/src/main/java/eric/Roullette/controller/GameController.java index 9fc42d9..b752532 100644 --- a/src/main/java/eric/Roullette/controller/GameController.java +++ b/src/main/java/eric/Roullette/controller/GameController.java @@ -23,6 +23,7 @@ package eric.Roullette.controller; import java.util.Map; // import java.util.Objects; // import java.util.UUID; + import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; // import java.util.concurrent.TimeUnit; @@ -32,7 +33,9 @@ public class GameController { private final GameWebSocketHandler webSocketHandler; private final OkHttpClient httpClient = new OkHttpClient(); private String accessToken = ""; - private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GameController.class); + private Map userAccessTokens = new ConcurrentHashMap<>(); + // Map + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GameController.class); public GameController(Javalin app, GameService gs, SpotifyAuthService sas, GameWebSocketHandler wsHandler) { this.gameService = gs; @@ -50,21 +53,28 @@ public class GameController { ctx.status(400).result("username fehlt"); return; } - var accessToken = authService.getAccessTokenForUser(username); + // spieler in map hinzufügen + + String playerAccessToken = null; + if(!userAccessTokens.containsKey(username)) { + playerAccessToken = authService.getAccessTokenForUser(username); + if (playerAccessToken != null) { + userAccessTokens.put(username, playerAccessToken); + } + } + if (accessToken == null) { ctx.status(401).result("Zugriffstoken fehlt oder ist ungültig"); return; } - setToken(accessToken); + var devices = authService.getDevices(accessToken); ctx.json(devices); }); } - private void setToken(String accessToken) { - this.accessToken = accessToken; - } + @SuppressWarnings("unchecked") private void createGame(Context ctx) throws InterruptedException { Map body = (Map) ctx.bodyAsClass(Map.class); @@ -144,6 +154,7 @@ public class GameController { try { //String accessToken = authService.getAccessTokenForUser(username); + String accessToken = userAccessTokens.get(username); OkHttpClient client = httpClient; String trackId = trackUri.split(":")[2]; Request getTrack = new Request.Builder() diff --git a/src/main/java/eric/Roullette/service/SpotifyAuthService.java b/src/main/java/eric/Roullette/service/SpotifyAuthService.java index 17cd358..cb62c98 100644 --- a/src/main/java/eric/Roullette/service/SpotifyAuthService.java +++ b/src/main/java/eric/Roullette/service/SpotifyAuthService.java @@ -20,7 +20,7 @@ import java.net.URI; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import static com.neovisionaries.i18n.CountryCode.DE; +//import static com.neovisionaries.i18n.CountryCode.DE; public class SpotifyAuthService { private final String clientId; @@ -38,18 +38,27 @@ public class SpotifyAuthService { public URI getAuthorizationUri(String user) { System.out.println("Erstelle Auth-URL für Benutzer: " + user); // Temporäre API-Instanz nur für die Erstellung der Auth-URL + String scope = "user-read-recently-played user-library-read user-modify-playback-state user-read-playback-state streaming user-read-private"; + // + SpotifyApi tempApi = new SpotifyApi.Builder() .setClientId(clientId) .setClientSecret(clientSecret) .setRedirectUri(redirectUri) .build(); + //überprüfe, ob der nutzer ein Premium-User ist return tempApi.authorizationCodeUri() - .scope("user-read-recently-played user-library-read user-read-playback-state user-modify-playback-state streaming") + .scope(scope) .state(user) // Der Benutzername wird im State mitgegeben + .show_dialog(true) .build() .execute(); } +// public boolean isPremiumUser(SpotifyApi api) throws IOException, SpotifyWebApiException, ParseException { +// var user = api.getCurrentUsersProfile().build().execute(); +// return "premium".equalsIgnoreCase(String.valueOf(user.getProduct())); +// } public void exchangeCode(String code, String user) throws IOException, ParseException, SpotifyWebApiException { // Erstellt eine neue, dedizierte API-Instanz für diesen Benutzer @@ -63,6 +72,8 @@ public class SpotifyAuthService { AuthorizationCodeCredentials creds = userApi.authorizationCode(code).build().execute(); userApi.setAccessToken(creds.getAccessToken()); userApi.setRefreshToken(creds.getRefreshToken()); + System.out.println("Granted scopes: " + creds.getScope()); // wichtig fürs Debugging + // Speichert die fertig konfigurierte API-Instanz für den Benutzer userApis.put(user, userApi); @@ -70,26 +81,57 @@ public class SpotifyAuthService { public List getRecentTracks(String user) { System.out.println("Hole kürzlich gespielte Tracks für Benutzer: " + user); - int limit = 2; + int limit = 50; SpotifyApi userApi = userApis.get(user); if (userApi == null) { - System.err.println("Kein SpotifyApi-Client für Benutzer gefunden: " + user); + System.out.println("Kein SpotifyApi-Client für Benutzer gefunden: " + user); return Collections.emptyList(); } + System.out.println("SpotifyApi-Client für Benutzer gefunden: " + user); + System.out.println("AccessToken: " + userApi.getAccessToken()); + System.out.println("RefreshToken: " + userApi.getRefreshToken()); + try { + System.out.println("Hole Profil für Benutzer: " + user); + // Hole das Profil des Benutzers, um den Account-Typ zu überprüfen + var profile = userApi.getCurrentUsersProfile().build().execute(); + System.out.println("Account-Typ: " + profile.getProduct()); + + System.out.println("Erstelle Anfrage für kürzlich gespielte Tracks..."); + if (userApi.getRefreshToken() == null) { + System.out.println("Refresh Token für Benutzer " + user + " ist nicht gesetzt."); + } + + System.out.println("Refresh Token für Benutzer " + user + " ist gesetzt."); + if( userApi.getAccessToken() == null) { + System.out.println("Access Token für Benutzer " + user + " ist nicht gesetzt."); + return Collections.emptyList(); + } + + System.out.println("Access Token für Benutzer " + user + " ist gesetzt."); + + GetCurrentUsersRecentlyPlayedTracksRequest request = userApi.getCurrentUsersRecentlyPlayedTracks() .limit(limit) .build(); + // Führe die Anfrage aus und erhalte die Ergebnisse + System.out.println("Führe paging Anfrage aus..."); PagingCursorbased history = request.execute(); + System.out.println("Paging Anfrage erfolgreich ausgeführt."); + // Überprüfe, ob die Ergebnisse leer sind + System.out.println("Überprüfe, ob Ergebnisse vorhanden sind..."); if (history == null || history.getItems() == null) { return Collections.emptyList(); } + System.out.println("Verarbeite kürzlich gespielte Tracks..."); + // Extrahiere die URIs der kürzlich gespielten Tracks List recentTracks = Arrays.stream(history.getItems()) .map(item -> item.getTrack().getUri()) .distinct() .toList(); + System.out.println("Gefundene kürzlich gespielte Tracks: " + recentTracks.size()); if (recentTracks.size() < limit) { int newLimit = limit - recentTracks.size(); @@ -106,7 +148,14 @@ public class SpotifyAuthService { recentTracks.addAll(savedTracks2.subList(0, Math.min(newLimit, savedTracks2.size()))); } } + System.out.println("Endgültige Anzahl kürzlich gespielter Tracks: " + recentTracks.size()); return recentTracks.subList(0, Math.min(limit, recentTracks.size())); +// } catch (se.michaelthelin.spotify.exceptions.detailed.ForbiddenException e) { +// System.out.println("ForbiddenException: " + e.getMessage()); +// System.out.println("Möglicherweise hat der Benutzer keine Berechtigung, kürzlich gespielte Tracks abzurufen."); +// +// +// return Collections.emptyList(); } catch (IOException | SpotifyWebApiException | ParseException e) { e.printStackTrace(); return Collections.emptyList(); @@ -197,6 +246,7 @@ public class SpotifyAuthService { .build(); try (Response resp = client.newCall(req).execute()) { if (!resp.isSuccessful()) return List.of(); + assert resp.body() != null; String body = resp.body().string(); // Parsen, z.B. mit Jackson var node = new ObjectMapper().readTree(body); diff --git a/src/main/java/eric/Roullette/websocket/GameWebSocketHandler.java b/src/main/java/eric/Roullette/websocket/GameWebSocketHandler.java index 45b5e16..dff62d1 100644 --- a/src/main/java/eric/Roullette/websocket/GameWebSocketHandler.java +++ b/src/main/java/eric/Roullette/websocket/GameWebSocketHandler.java @@ -22,11 +22,11 @@ public class GameWebSocketHandler { // Spiel-ID → (Username → deren Guess) private final Map> currentGuesses = new ConcurrentHashMap<>(); - private final Map> trackInfoCache = new ConcurrentHashMap<>(); - private final Map> allTracksCache = new ConcurrentHashMap<>(); +// private final Map> trackInfoCache = new ConcurrentHashMap<>(); +// private final Map> allTracksCache = new ConcurrentHashMap<>(); //Map> - private Map>> playerTracksCache = new ConcurrentHashMap<>(); - private Map>> playerTrackInfoCache = new ConcurrentHashMap<>(); + //private Map>> playerTracksCache = new ConcurrentHashMap<>(); + private Map>> playerTrackInfoCache = new ConcurrentHashMap<>(); public GameWebSocketHandler(GameService gameService) { this.service = gameService; @@ -77,9 +77,7 @@ public class GameWebSocketHandler { } case "requestPlayers" -> service.broadcastPlayers(gameId); - case "next-round" -> { - nextround(gameId); - } + case "next-round" -> nextround(gameId); case "start-round" -> { var currentGame = service.getOrCreateGame(gameId); if (currentGame.players().isEmpty()) return; @@ -94,10 +92,10 @@ public class GameWebSocketHandler { service.startRound(gameId, allTracks); } // Trackinfos für alle Spieler sammeln - Map> allTrackInfos = service.getTrackInfos(allPlayerTracks); + //Map> allTrackInfos = service.getTrackInfos(allPlayerTracks); // Cache für Trackinfos pro Spiel-ID - playerTrackInfoCache.put(gameId, allTrackInfos); - System.out.println("TrackInfosCache für Spiel " + gameId + " hat " + allTrackInfos.size() + " Spieler (rundenstart)"); + //playerTrackInfoCache.put(gameId, allTrackInfos); + //System.out.println("TrackInfosCache für Spiel " + gameId + " hat " + allTrackInfos.size() + " Spieler (rundenstart)"); broadcastRoundStart(gameId); } } @@ -168,7 +166,7 @@ private void broadcastRoundResult(String gameId) { // Prüfe auf Gewinner String winner = scores.entrySet().stream() - .filter(e -> e.getValue() >= 30) + .filter(e -> e.getValue() >= 6) .map(Map.Entry::getKey) .findFirst() .orElse(null); @@ -182,14 +180,15 @@ private void broadcastRoundResult(String gameId) { broadcastToAll(gameId, winMsg); game.scores().replaceAll((user , pts) -> 0); // Reset Scores für alle Spieler - }else{ - // nächste Runde starten - // ... -// new Thread(() -> { -// try { Thread.sleep(2000); } catch (InterruptedException ignored) {} -// nextround(gameId); -// }).start(); } +// else{ +// // nächste Runde starten +// // ... +//// new Thread(() -> { +//// try { Thread.sleep(2000); } catch (InterruptedException ignored) {} +//// nextround(gameId); +//// }).start(); +// } } /** Hilfsmethode: Sendet eine Nachricht an alle WebSocket-Sessions eines Spiels. */ diff --git a/src/main/resources/public/js/game.js b/src/main/resources/public/js/game.js index ee93bbb..e8b1964 100644 --- a/src/main/resources/public/js/game.js +++ b/src/main/resources/public/js/game.js @@ -301,7 +301,10 @@ function handleRoundResult({ scores, guesses, owner }) { // 8) Spielende -> Start-Button zurück function handleGameEnd({ winner }) { + const nextBtn = document.getElementById("nextRound"); resultP.textContent = `🎉 ${winner} hat gewonnen!`; + nextBtn.hidden = true; + nextBtn.disabled = true; setTimeout(() => { startBtn.hidden = false; startBtn.disabled = false;